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 
29 
30 #pragma once
31 
32 
33 
34 
35 
41 template <
42  int SizeX, int SizeY, // Dimensions of the array
43  int AnchorStepX, int AnchorStepY,
44  typename TYPE
45 >
46 void LinearUpscale2DArrayInPlace(TYPE * a_Array)
47 {
48  // First interpolate columns where the anchor points are:
49  int LastYCell = SizeY - AnchorStepY;
50  for (int y = 0; y < LastYCell; y += AnchorStepY)
51  {
52  int Idx = SizeX * y;
53  for (int x = 0; x < SizeX; x += AnchorStepX)
54  {
55  TYPE StartValue = a_Array[Idx];
56  TYPE EndValue = a_Array[Idx + SizeX * AnchorStepY];
57  TYPE Diff = EndValue - StartValue;
58  for (int CellY = 1; CellY < AnchorStepY; CellY++)
59  {
60  a_Array[Idx + SizeX * CellY] = StartValue + Diff * CellY / AnchorStepY;
61  } // for CellY
62  Idx += AnchorStepX;
63  } // for x
64  } // for y
65 
66  // Now interpolate in rows, each row has values in the anchor columns
67  int LastXCell = SizeX - AnchorStepX;
68  for (int y = 0; y < SizeY; y++)
69  {
70  int Idx = SizeX * y;
71  for (int x = 0; x < LastXCell; x += AnchorStepX)
72  {
73  TYPE StartValue = a_Array[Idx];
74  TYPE EndValue = a_Array[Idx + AnchorStepX];
75  TYPE Diff = EndValue - StartValue;
76  for (int CellX = 1; CellX < AnchorStepX; CellX++)
77  {
78  a_Array[Idx + CellX] = StartValue + CellX * Diff / AnchorStepX;
79  } // for CellY
80  Idx += AnchorStepX;
81  }
82  }
83 }
84 
85 
86 
87 
88 
93 template <typename TYPE> void LinearUpscale2DArray(
94  TYPE * a_Src,
95  int a_SrcSizeX, int a_SrcSizeY,
96  TYPE * a_Dst,
97  int a_UpscaleX, int a_UpscaleY
98 )
99 {
100  // For optimization reasons, we're storing the upscaling ratios in a fixed-size arrays of these sizes
101  // Feel free to enlarge them if needed, but keep in mind that they're on the stack
102  const int MAX_UPSCALE_X = 129;
103  const int MAX_UPSCALE_Y = 129;
104 
105  ASSERT(a_Src != nullptr);
106  ASSERT(a_Dst != nullptr);
107  ASSERT(a_SrcSizeX > 0);
108  ASSERT(a_SrcSizeY > 0);
109  ASSERT(a_UpscaleX > 0);
110  ASSERT(a_UpscaleY > 0);
111  ASSERT(a_UpscaleX < MAX_UPSCALE_X);
112  ASSERT(a_UpscaleY < MAX_UPSCALE_Y);
113 
114  // Pre-calculate the upscaling ratios:
115  TYPE RatioX[MAX_UPSCALE_X];
116  TYPE RatioY[MAX_UPSCALE_Y];
117  for (int x = 0; x <= a_UpscaleX; x++)
118  {
119  RatioX[x] = static_cast<TYPE>(x) / a_UpscaleX;
120  }
121  for (int y = 0; y <= a_UpscaleY; y++)
122  {
123  RatioY[y] = static_cast<TYPE>(y) / a_UpscaleY;
124  }
125 
126  const int DstSizeX = (a_SrcSizeX - 1) * a_UpscaleX + 1;
127  [[maybe_unused]] const int DstSizeY = (a_SrcSizeY - 1) * a_UpscaleY + 1;
128 
129  // Interpolate each XY cell:
130  for (int y = 0; y < (a_SrcSizeY - 1); y++)
131  {
132  int DstY = y * a_UpscaleY;
133  int idx = y * a_SrcSizeX;
134  for (int x = 0; x < (a_SrcSizeX - 1); x++, idx++)
135  {
136  int DstX = x * a_UpscaleX;
137  TYPE LoXLoY = a_Src[idx];
138  TYPE LoXHiY = a_Src[idx + a_SrcSizeX];
139  TYPE HiXLoY = a_Src[idx + 1];
140  TYPE HiXHiY = a_Src[idx + 1 + a_SrcSizeX];
141  for (int CellY = 0; CellY <= a_UpscaleY; CellY++)
142  {
143  int DestIdx = (DstY + CellY) * DstSizeX + DstX;
144  ASSERT(DestIdx + a_UpscaleX < DstSizeX * DstSizeY);
145  TYPE LoXInY = LoXLoY + (LoXHiY - LoXLoY) * RatioY[CellY];
146  TYPE HiXInY = HiXLoY + (HiXHiY - HiXLoY) * RatioY[CellY];
147  for (int CellX = 0; CellX <= a_UpscaleX; CellX++, DestIdx++)
148  {
149  a_Dst[DestIdx] = LoXInY + (HiXInY - LoXInY) * RatioX[CellX];
150  }
151  } // for CellY
152  } // for x
153  } // for y
154 }
155 
156 
157 
158 
159 
164 template <typename TYPE> void LinearUpscale3DArray(
165  TYPE * a_Src,
166  int a_SrcSizeX, int a_SrcSizeY, int a_SrcSizeZ,
167  TYPE * a_Dst,
168  int a_UpscaleX, int a_UpscaleY, int a_UpscaleZ
169 )
170 {
171  // For optimization reasons, we're storing the upscaling ratios in a fixed-size arrays of these sizes
172  // Feel free to enlarge them if needed, but keep in mind that they're on the stack
173  const int MAX_UPSCALE_X = 128;
174  const int MAX_UPSCALE_Y = 128;
175  const int MAX_UPSCALE_Z = 128;
176 
177  ASSERT(a_Src != nullptr);
178  ASSERT(a_Dst != nullptr);
179  ASSERT(a_SrcSizeX > 0);
180  ASSERT(a_SrcSizeY > 0);
181  ASSERT(a_SrcSizeZ > 0);
182  ASSERT(a_UpscaleX > 0);
183  ASSERT(a_UpscaleY > 0);
184  ASSERT(a_UpscaleZ > 0);
185  ASSERT(a_UpscaleX <= MAX_UPSCALE_X);
186  ASSERT(a_UpscaleY <= MAX_UPSCALE_Y);
187  ASSERT(a_UpscaleZ <= MAX_UPSCALE_Z);
188 
189  // Pre-calculate the upscaling ratios:
190  TYPE RatioX[MAX_UPSCALE_X];
191  TYPE RatioY[MAX_UPSCALE_Y];
192  TYPE RatioZ[MAX_UPSCALE_Z];
193  for (int x = 0; x <= a_UpscaleX; x++)
194  {
195  RatioX[x] = static_cast<TYPE>(x) / a_UpscaleX;
196  }
197  for (int y = 0; y <= a_UpscaleY; y++)
198  {
199  RatioY[y] = static_cast<TYPE>(y) / a_UpscaleY;
200  }
201  for (int z = 0; z <= a_UpscaleZ; z++)
202  {
203  RatioZ[z] = static_cast<TYPE>(z) / a_UpscaleZ;
204  }
205 
206  const int DstSizeX = (a_SrcSizeX - 1) * a_UpscaleX + 1;
207  const int DstSizeY = (a_SrcSizeY - 1) * a_UpscaleY + 1;
208  [[maybe_unused]] const int DstSizeZ = (a_SrcSizeZ - 1) * a_UpscaleZ + 1;
209 
210  // Interpolate each XYZ cell:
211  for (int z = 0; z < (a_SrcSizeZ - 1); z++)
212  {
213  int DstZ = z * a_UpscaleZ;
214  for (int y = 0; y < (a_SrcSizeY - 1); y++)
215  {
216  int DstY = y * a_UpscaleY;
217  int idx = y * a_SrcSizeX + z * a_SrcSizeX * a_SrcSizeY;
218  for (int x = 0; x < (a_SrcSizeX - 1); x++, idx++)
219  {
220  int DstX = x * a_UpscaleX;
221  TYPE LoXLoYLoZ = a_Src[idx];
222  TYPE LoXLoYHiZ = a_Src[idx + a_SrcSizeX * a_SrcSizeY];
223  TYPE LoXHiYLoZ = a_Src[idx + a_SrcSizeX];
224  TYPE LoXHiYHiZ = a_Src[idx + a_SrcSizeX + a_SrcSizeX * a_SrcSizeY];
225  TYPE HiXLoYLoZ = a_Src[idx + 1];
226  TYPE HiXLoYHiZ = a_Src[idx + 1 + a_SrcSizeX * a_SrcSizeY];
227  TYPE HiXHiYLoZ = a_Src[idx + 1 + a_SrcSizeX];
228  TYPE HiXHiYHiZ = a_Src[idx + 1 + a_SrcSizeX + a_SrcSizeX * a_SrcSizeY];
229  for (int CellZ = 0; CellZ <= a_UpscaleZ; CellZ++)
230  {
231  TYPE LoXLoYInZ = LoXLoYLoZ + (LoXLoYHiZ - LoXLoYLoZ) * RatioZ[CellZ];
232  TYPE LoXHiYInZ = LoXHiYLoZ + (LoXHiYHiZ - LoXHiYLoZ) * RatioZ[CellZ];
233  TYPE HiXLoYInZ = HiXLoYLoZ + (HiXLoYHiZ - HiXLoYLoZ) * RatioZ[CellZ];
234  TYPE HiXHiYInZ = HiXHiYLoZ + (HiXHiYHiZ - HiXHiYLoZ) * RatioZ[CellZ];
235  for (int CellY = 0; CellY <= a_UpscaleY; CellY++)
236  {
237  int DestIdx = (DstZ + CellZ) * DstSizeX * DstSizeY + (DstY + CellY) * DstSizeX + DstX;
238  ASSERT(DestIdx + a_UpscaleX < DstSizeX * DstSizeY * DstSizeZ);
239  TYPE LoXInY = LoXLoYInZ + (LoXHiYInZ - LoXLoYInZ) * RatioY[CellY];
240  TYPE HiXInY = HiXLoYInZ + (HiXHiYInZ - HiXLoYInZ) * RatioY[CellY];
241  for (int CellX = 0; CellX <= a_UpscaleX; CellX++, DestIdx++)
242  {
243  a_Dst[DestIdx] = LoXInY + (HiXInY - LoXInY) * RatioX[CellX];
244  }
245  } // for CellY
246  } // for CellZ
247  } // for x
248  } // for y
249  } // for z
250 }
251 
252 
253 
254 
255 
T Diff(T a_Val1, T a_Val2)
Definition: Defines.h:617
#define ASSERT(x)
Definition: Globals.h:276
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 LinearUpscale2DArrayInPlace(TYPE *a_Array)
Linearly interpolates values in the array between the equidistant anchor points (upscales).
Definition: LinearUpscale.h:46
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:93