Cuberite
A lightweight, fast and extensible game server for Minecraft
LinearUpscale.h
Go to the documentation of this file.
1 
2 // LinearUpscale.h
3 
4 // Declares the functions for linearly upscaling arrays
5 
6 /*
7 Upscaling means that the array is divided into same-size "cells", and each cell is
8 linearly interpolated between its corners. The array's dimensions are therefore
9 1 + CellSize * NumCells, for each direction.
10 
11 Upscaling is more efficient than linear interpolation, because the cell sizes are integral
12 and therefore the cells' boundaries are on the array points.
13 
14 However, upscaling usually requires generating the "1 +" in each direction.
15 
16 Upscaling is implemented in templates, so that it's compatible with multiple datatypes.
17 Therefore, there is no cpp file.
18 
19 InPlace upscaling works on a single array and assumes that the values to work on have already
20 been interspersed into the array to the cell boundaries.
21 Specifically, a_Array[x * AnchorStepX + y * AnchorStepY] contains the anchor value.
22 
23 Regular upscaling takes two arrays and "moves" the input from src to dst; src is expected packed.
24 */
25 
26 
27 
28 
34 template <
35  int SizeX, int SizeY, // Dimensions of the array
36  int AnchorStepX, int AnchorStepY,
37  typename TYPE
38 >
39 void LinearUpscale2DArrayInPlace(TYPE * a_Array)
40 {
41  // First interpolate columns where the anchor points are:
42  int LastYCell = SizeY - AnchorStepY;
43  for (int y = 0; y < LastYCell; y += AnchorStepY)
44  {
45  int Idx = SizeX * y;
46  for (int x = 0; x < SizeX; x += AnchorStepX)
47  {
48  TYPE StartValue = a_Array[Idx];
49  TYPE EndValue = a_Array[Idx + SizeX * AnchorStepY];
50  TYPE Diff = EndValue - StartValue;
51  for (int CellY = 1; CellY < AnchorStepY; CellY++)
52  {
53  a_Array[Idx + SizeX * CellY] = StartValue + Diff * CellY / AnchorStepY;
54  } // for CellY
55  Idx += AnchorStepX;
56  } // for x
57  } // for y
58 
59  // Now interpolate in rows, each row has values in the anchor columns
60  int LastXCell = SizeX - AnchorStepX;
61  for (int y = 0; y < SizeY; y++)
62  {
63  int Idx = SizeX * y;
64  for (int x = 0; x < LastXCell; x += AnchorStepX)
65  {
66  TYPE StartValue = a_Array[Idx];
67  TYPE EndValue = a_Array[Idx + AnchorStepX];
68  TYPE Diff = EndValue - StartValue;
69  for (int CellX = 1; CellX < AnchorStepX; CellX++)
70  {
71  a_Array[Idx + CellX] = StartValue + CellX * Diff / AnchorStepX;
72  } // for CellY
73  Idx += AnchorStepX;
74  }
75  }
76 }
77 
78 
79 
80 
81 
86 template <typename TYPE> void LinearUpscale2DArray(
87  TYPE * a_Src,
88  int a_SrcSizeX, int a_SrcSizeY,
89  TYPE * a_Dst,
90  int a_UpscaleX, int a_UpscaleY
91 )
92 {
93  // For optimization reasons, we're storing the upscaling ratios in a fixed-size arrays of these sizes
94  // Feel free to enlarge them if needed, but keep in mind that they're on the stack
95  const int MAX_UPSCALE_X = 129;
96  const int MAX_UPSCALE_Y = 129;
97 
98  ASSERT(a_Src != nullptr);
99  ASSERT(a_Dst != nullptr);
100  ASSERT(a_SrcSizeX > 0);
101  ASSERT(a_SrcSizeY > 0);
102  ASSERT(a_UpscaleX > 0);
103  ASSERT(a_UpscaleY > 0);
104  ASSERT(a_UpscaleX < MAX_UPSCALE_X);
105  ASSERT(a_UpscaleY < MAX_UPSCALE_Y);
106 
107  // Pre-calculate the upscaling ratios:
108  TYPE RatioX[MAX_UPSCALE_X];
109  TYPE RatioY[MAX_UPSCALE_Y];
110  for (int x = 0; x <= a_UpscaleX; x++)
111  {
112  RatioX[x] = static_cast<TYPE>(x) / a_UpscaleX;
113  }
114  for (int y = 0; y <= a_UpscaleY; y++)
115  {
116  RatioY[y] = static_cast<TYPE>(y) / a_UpscaleY;
117  }
118 
119  // Interpolate each XY cell:
120  int DstSizeX = (a_SrcSizeX - 1) * a_UpscaleX + 1;
121  #ifdef _DEBUG
122  int DstSizeY = (a_SrcSizeY - 1) * a_UpscaleY + 1;
123  #endif
124  for (int y = 0; y < (a_SrcSizeY - 1); y++)
125  {
126  int DstY = y * a_UpscaleY;
127  int idx = y * a_SrcSizeX;
128  for (int x = 0; x < (a_SrcSizeX - 1); x++, idx++)
129  {
130  int DstX = x * a_UpscaleX;
131  TYPE LoXLoY = a_Src[idx];
132  TYPE LoXHiY = a_Src[idx + a_SrcSizeX];
133  TYPE HiXLoY = a_Src[idx + 1];
134  TYPE HiXHiY = a_Src[idx + 1 + a_SrcSizeX];
135  for (int CellY = 0; CellY <= a_UpscaleY; CellY++)
136  {
137  int DestIdx = (DstY + CellY) * DstSizeX + DstX;
138  ASSERT(DestIdx + a_UpscaleX < DstSizeX * DstSizeY);
139  TYPE LoXInY = LoXLoY + (LoXHiY - LoXLoY) * RatioY[CellY];
140  TYPE HiXInY = HiXLoY + (HiXHiY - HiXLoY) * RatioY[CellY];
141  for (int CellX = 0; CellX <= a_UpscaleX; CellX++, DestIdx++)
142  {
143  a_Dst[DestIdx] = LoXInY + (HiXInY - LoXInY) * RatioX[CellX];
144  }
145  } // for CellY
146  } // for x
147  } // for y
148 }
149 
150 
151 
152 
153 
158 template <typename TYPE> void LinearUpscale3DArray(
159  TYPE * a_Src,
160  int a_SrcSizeX, int a_SrcSizeY, int a_SrcSizeZ,
161  TYPE * a_Dst,
162  int a_UpscaleX, int a_UpscaleY, int a_UpscaleZ
163 )
164 {
165  // For optimization reasons, we're storing the upscaling ratios in a fixed-size arrays of these sizes
166  // Feel free to enlarge them if needed, but keep in mind that they're on the stack
167  const int MAX_UPSCALE_X = 128;
168  const int MAX_UPSCALE_Y = 128;
169  const int MAX_UPSCALE_Z = 128;
170 
171  ASSERT(a_Src != nullptr);
172  ASSERT(a_Dst != nullptr);
173  ASSERT(a_SrcSizeX > 0);
174  ASSERT(a_SrcSizeY > 0);
175  ASSERT(a_SrcSizeZ > 0);
176  ASSERT(a_UpscaleX > 0);
177  ASSERT(a_UpscaleY > 0);
178  ASSERT(a_UpscaleZ > 0);
179  ASSERT(a_UpscaleX <= MAX_UPSCALE_X);
180  ASSERT(a_UpscaleY <= MAX_UPSCALE_Y);
181  ASSERT(a_UpscaleZ <= MAX_UPSCALE_Z);
182 
183  // Pre-calculate the upscaling ratios:
184  TYPE RatioX[MAX_UPSCALE_X];
185  TYPE RatioY[MAX_UPSCALE_Y];
186  TYPE RatioZ[MAX_UPSCALE_Z];
187  for (int x = 0; x <= a_UpscaleX; x++)
188  {
189  RatioX[x] = static_cast<TYPE>(x) / a_UpscaleX;
190  }
191  for (int y = 0; y <= a_UpscaleY; y++)
192  {
193  RatioY[y] = static_cast<TYPE>(y) / a_UpscaleY;
194  }
195  for (int z = 0; z <= a_UpscaleZ; z++)
196  {
197  RatioZ[z] = static_cast<TYPE>(z) / a_UpscaleZ;
198  }
199 
200  // Interpolate each XYZ cell:
201  int DstSizeX = (a_SrcSizeX - 1) * a_UpscaleX + 1;
202  int DstSizeY = (a_SrcSizeY - 1) * a_UpscaleY + 1;
203  #ifdef _DEBUG
204  int DstSizeZ = (a_SrcSizeZ - 1) * a_UpscaleZ + 1;
205  #endif
206  for (int z = 0; z < (a_SrcSizeZ - 1); z++)
207  {
208  int DstZ = z * a_UpscaleZ;
209  for (int y = 0; y < (a_SrcSizeY - 1); y++)
210  {
211  int DstY = y * a_UpscaleY;
212  int idx = y * a_SrcSizeX + z * a_SrcSizeX * a_SrcSizeY;
213  for (int x = 0; x < (a_SrcSizeX - 1); x++, idx++)
214  {
215  int DstX = x * a_UpscaleX;
216  TYPE LoXLoYLoZ = a_Src[idx];
217  TYPE LoXLoYHiZ = a_Src[idx + a_SrcSizeX * a_SrcSizeY];
218  TYPE LoXHiYLoZ = a_Src[idx + a_SrcSizeX];
219  TYPE LoXHiYHiZ = a_Src[idx + a_SrcSizeX + a_SrcSizeX * a_SrcSizeY];
220  TYPE HiXLoYLoZ = a_Src[idx + 1];
221  TYPE HiXLoYHiZ = a_Src[idx + 1 + a_SrcSizeX * a_SrcSizeY];
222  TYPE HiXHiYLoZ = a_Src[idx + 1 + a_SrcSizeX];
223  TYPE HiXHiYHiZ = a_Src[idx + 1 + a_SrcSizeX + a_SrcSizeX * a_SrcSizeY];
224  for (int CellZ = 0; CellZ <= a_UpscaleZ; CellZ++)
225  {
226  TYPE LoXLoYInZ = LoXLoYLoZ + (LoXLoYHiZ - LoXLoYLoZ) * RatioZ[CellZ];
227  TYPE LoXHiYInZ = LoXHiYLoZ + (LoXHiYHiZ - LoXHiYLoZ) * RatioZ[CellZ];
228  TYPE HiXLoYInZ = HiXLoYLoZ + (HiXLoYHiZ - HiXLoYLoZ) * RatioZ[CellZ];
229  TYPE HiXHiYInZ = HiXHiYLoZ + (HiXHiYHiZ - HiXHiYLoZ) * RatioZ[CellZ];
230  for (int CellY = 0; CellY <= a_UpscaleY; CellY++)
231  {
232  int DestIdx = (DstZ + CellZ) * DstSizeX * DstSizeY + (DstY + CellY) * DstSizeX + DstX;
233  ASSERT(DestIdx + a_UpscaleX < DstSizeX * DstSizeY * DstSizeZ);
234  TYPE LoXInY = LoXLoYInZ + (LoXHiYInZ - LoXLoYInZ) * RatioY[CellY];
235  TYPE HiXInY = HiXLoYInZ + (HiXHiYInZ - HiXLoYInZ) * RatioY[CellY];
236  for (int CellX = 0; CellX <= a_UpscaleX; CellX++, DestIdx++)
237  {
238  a_Dst[DestIdx] = LoXInY + (HiXInY - LoXInY) * RatioX[CellX];
239  }
240  } // for CellY
241  } // for CellZ
242  } // for x
243  } // for y
244  } // for z
245 }
246 
247 
248 
249 
250 
#define ASSERT(x)
Definition: Globals.h:335
void LinearUpscale2DArrayInPlace(TYPE *a_Array)
Linearly interpolates values in the array between the equidistant anchor points (upscales).
Definition: LinearUpscale.h:39
void LinearUpscale3DArray(TYPE *a_Src, int a_SrcSizeX, int a_SrcSizeY, int a_SrcSizeZ, TYPE *a_Dst, int a_UpscaleX, int a_UpscaleY, int a_UpscaleZ)
Linearly interpolates values in the array between the equidistant anchor points (upscales).
void LinearUpscale2DArray(TYPE *a_Src, int a_SrcSizeX, int a_SrcSizeY, TYPE *a_Dst, int a_UpscaleX, int a_UpscaleY)
Linearly interpolates values in the array between the equidistant anchor points (upscales).
Definition: LinearUpscale.h:86
T Diff(T a_Val1, T a_Val2)
Definition: Defines.h:965