Cuberite
A lightweight, fast and extensible game server for Minecraft
LinearInterpolation.cpp
Go to the documentation of this file.
1 
2 // LinearInterpolation.cpp
3 
4 // Implements methods for linear interpolation over 1D, 2D and 3D arrays
5 
6 #include "Globals.h"
7 #include "LinearInterpolation.h"
8 
9 
10 
11 
12 
13 /*
14 // Perform an automatic test upon program start (use breakpoints to debug):
15 
16 extern void Debug3DNoise(float * a_Noise, int a_SizeX, int a_SizeY, int a_SizeZ, const AString & a_FileNameBase);
17 
18 class Test
19 {
20 public:
21  Test(void)
22  {
23  // DoTest1();
24  DoTest2();
25  }
26 
27 
28  void DoTest1(void)
29  {
30  float In[8] = {0, 1, 2, 3, 1, 2, 2, 2};
31  float Out[3 * 3 * 3];
32  LinearInterpolate1DArray(In, 4, Out, 9);
33  LinearInterpolate2DArray(In, 2, 2, Out, 3, 3);
34  LinearInterpolate3DArray(In, 2, 2, 2, Out, 3, 3, 3);
35  LOGD("Out[0]: %f", Out[0]);
36  }
37 
38 
39  void DoTest2(void)
40  {
41  float In[3 * 3 * 3];
42  for (size_t i = 0; i < ARRAYCOUNT(In); i++)
43  {
44  In[i] = (float)(i % 5);
45  }
46  float Out[15 * 16 * 17];
47  LinearInterpolate3DArray(In, 3, 3, 3, Out, 15, 16, 17);
48  Debug3DNoise(Out, 15, 16, 17, "LERP test");
49  }
50 } gTest;
51 //*/
52 
53 
54 
55 
56 
57 // Puts linearly interpolated values from one array into another array. 1D version
59  float * a_Src,
60  int a_SrcSizeX,
61  float * a_Dst,
62  int a_DstSizeX
63 )
64 {
65  a_Dst[0] = a_Src[0];
66  int DstSizeXm1 = a_DstSizeX - 1;
67  int SrcSizeXm1 = a_SrcSizeX - 1;
68  float fDstSizeXm1 = static_cast<float>(DstSizeXm1);
69  float fSrcSizeXm1 = static_cast<float>(SrcSizeXm1);
70  for (int x = 1; x < DstSizeXm1; x++)
71  {
72  int SrcIdx = x * SrcSizeXm1 / DstSizeXm1;
73  float ValLo = a_Src[SrcIdx];
74  float ValHi = a_Src[SrcIdx + 1];
75  float Ratio = static_cast<float>(x) * fSrcSizeXm1 / fDstSizeXm1 - SrcIdx;
76  a_Dst[x] = ValLo + (ValHi - ValLo) * Ratio;
77  }
78  a_Dst[a_DstSizeX - 1] = a_Src[a_SrcSizeX - 1];
79 }
80 
81 
82 
83 
84 
85 // Puts linearly interpolated values from one array into another array. 2D version
87  float * a_Src,
88  int a_SrcSizeX, int a_SrcSizeY,
89  float * a_Dst,
90  int a_DstSizeX, int a_DstSizeY
91 )
92 {
93  ASSERT(a_DstSizeX > 0);
94  ASSERT(a_DstSizeX < MAX_INTERPOL_SIZEX);
95  ASSERT(a_DstSizeY > 0);
96  ASSERT(a_DstSizeY < MAX_INTERPOL_SIZEY);
97 
98  // Calculate interpolation ratios and src indices along each axis:
99  float RatioX[MAX_INTERPOL_SIZEX];
100  float RatioY[MAX_INTERPOL_SIZEY];
101  int SrcIdxX[MAX_INTERPOL_SIZEX];
102  int SrcIdxY[MAX_INTERPOL_SIZEY];
103  for (int x = 1; x < a_DstSizeX; x++)
104  {
105  SrcIdxX[x] = x * (a_SrcSizeX - 1) / (a_DstSizeX - 1);
106  RatioX[x] = (static_cast<float>(x * (a_SrcSizeX - 1)) / (a_DstSizeX - 1)) - SrcIdxX[x];
107  }
108  for (int y = 1; y < a_DstSizeY; y++)
109  {
110  SrcIdxY[y] = y * (a_SrcSizeY - 1) / (a_DstSizeY - 1);
111  RatioY[y] = (static_cast<float>(y * (a_SrcSizeY - 1)) / (a_DstSizeY - 1)) - SrcIdxY[y];
112  }
113 
114  // Special values at the ends. Notice especially the last indices being (size - 2) with ratio set to 1, to avoid index overflow:
115  SrcIdxX[0] = 0;
116  RatioX[0] = 0;
117  SrcIdxY[0] = 0;
118  RatioY[0] = 0;
119  SrcIdxX[a_DstSizeX - 1] = a_SrcSizeX - 2;
120  RatioX[a_DstSizeX - 1] = 1;
121  SrcIdxY[a_DstSizeY - 1] = a_SrcSizeY - 2;
122  RatioY[a_DstSizeY - 1] = 1;
123 
124  // Output all the dst array values using the indices and ratios:
125  int idx = 0;
126  for (int y = 0; y < a_DstSizeY; y++)
127  {
128  int idxLoY = a_SrcSizeX * SrcIdxY[y];
129  int idxHiY = a_SrcSizeX * (SrcIdxY[y] + 1);
130  float ry = RatioY[y];
131  for (int x = 0; x < a_DstSizeX; x++)
132  {
133  // The four src corners of the current "cell":
134  float LoXLoY = a_Src[SrcIdxX[x] + idxLoY];
135  float HiXLoY = a_Src[SrcIdxX[x] + 1 + idxLoY];
136  float LoXHiY = a_Src[SrcIdxX[x] + idxHiY];
137  float HiXHiY = a_Src[SrcIdxX[x] + 1 + idxHiY];
138 
139  // Linear interpolation along the X axis:
140  float InterpXLoY = LoXLoY + (HiXLoY - LoXLoY) * RatioX[x];
141  float InterpXHiY = LoXHiY + (HiXHiY - LoXHiY) * RatioX[x];
142 
143  // Linear interpolation along the Y axis:
144  a_Dst[idx] = InterpXLoY + (InterpXHiY - InterpXLoY) * ry;
145  idx += 1;
146  }
147  }
148 }
149 
150 
151 
152 
153 
155  float * a_Src,
156  int a_SrcSizeX, int a_SrcSizeY, int a_SrcSizeZ,
157  float * a_Dst,
158  int a_DstSizeX, int a_DstSizeY, int a_DstSizeZ
159 )
160 {
161  ASSERT(a_DstSizeX > 0);
162  ASSERT(a_DstSizeX < MAX_INTERPOL_SIZEX);
163  ASSERT(a_DstSizeY > 0);
164  ASSERT(a_DstSizeY < MAX_INTERPOL_SIZEY);
165  ASSERT(a_DstSizeZ > 0);
166  ASSERT(a_DstSizeZ < MAX_INTERPOL_SIZEZ);
167 
168  // Calculate interpolation ratios and src indices along each axis:
169  float RatioX[MAX_INTERPOL_SIZEX];
170  float RatioY[MAX_INTERPOL_SIZEY];
171  float RatioZ[MAX_INTERPOL_SIZEZ];
172  int SrcIdxX[MAX_INTERPOL_SIZEX];
173  int SrcIdxY[MAX_INTERPOL_SIZEY];
174  int SrcIdxZ[MAX_INTERPOL_SIZEZ];
175  for (int x = 1; x < a_DstSizeX; x++)
176  {
177  SrcIdxX[x] = x * (a_SrcSizeX - 1) / (a_DstSizeX - 1);
178  RatioX[x] = (static_cast<float>(x * (a_SrcSizeX - 1)) / (a_DstSizeX - 1)) - SrcIdxX[x];
179  }
180  for (int y = 1; y < a_DstSizeY; y++)
181  {
182  SrcIdxY[y] = y * (a_SrcSizeY - 1) / (a_DstSizeY - 1);
183  RatioY[y] = (static_cast<float>(y * (a_SrcSizeY - 1)) / (a_DstSizeY - 1)) - SrcIdxY[y];
184  }
185  for (int z = 1; z < a_DstSizeZ; z++)
186  {
187  SrcIdxZ[z] = z * (a_SrcSizeZ - 1) / (a_DstSizeZ - 1);
188  RatioZ[z] = (static_cast<float>(z * (a_SrcSizeZ - 1)) / (a_DstSizeZ - 1)) - SrcIdxZ[z];
189  }
190 
191  // Special values at the ends. Notice especially the last indices being (size - 2) with ratio set to 1, to avoid index overflow:
192  SrcIdxX[0] = 0;
193  RatioX[0] = 0;
194  SrcIdxY[0] = 0;
195  RatioY[0] = 0;
196  SrcIdxZ[0] = 0;
197  RatioZ[0] = 0;
198  SrcIdxX[a_DstSizeX - 1] = a_SrcSizeX - 2;
199  RatioX[a_DstSizeX - 1] = 1;
200  SrcIdxY[a_DstSizeY - 1] = a_SrcSizeY - 2;
201  RatioY[a_DstSizeY - 1] = 1;
202  SrcIdxZ[a_DstSizeZ - 1] = a_SrcSizeZ - 2;
203  RatioZ[a_DstSizeZ - 1] = 1;
204 
205  // Output all the dst array values using the indices and ratios:
206  int idx = 0;
207  for (int z = 0; z < a_DstSizeZ; z++)
208  {
209  int idxLoZ = a_SrcSizeX * a_SrcSizeY * SrcIdxZ[z];
210  int idxHiZ = a_SrcSizeX * a_SrcSizeY * (SrcIdxZ[z] + 1);
211  float rz = RatioZ[z];
212  for (int y = 0; y < a_DstSizeY; y++)
213  {
214  int idxLoY = a_SrcSizeX * SrcIdxY[y];
215  int idxHiY = a_SrcSizeX * (SrcIdxY[y] + 1);
216  float ry = RatioY[y];
217  for (int x = 0; x < a_DstSizeX; x++)
218  {
219  // The eight src corners of the current "cell":
220  float LoXLoYLoZ = a_Src[SrcIdxX[x] + idxLoY + idxLoZ];
221  float HiXLoYLoZ = a_Src[SrcIdxX[x] + 1 + idxLoY + idxLoZ];
222  float LoXHiYLoZ = a_Src[SrcIdxX[x] + idxHiY + idxLoZ];
223  float HiXHiYLoZ = a_Src[SrcIdxX[x] + 1 + idxHiY + idxLoZ];
224  float LoXLoYHiZ = a_Src[SrcIdxX[x] + idxLoY + idxHiZ];
225  float HiXLoYHiZ = a_Src[SrcIdxX[x] + 1 + idxLoY + idxHiZ];
226  float LoXHiYHiZ = a_Src[SrcIdxX[x] + idxHiY + idxHiZ];
227  float HiXHiYHiZ = a_Src[SrcIdxX[x] + 1 + idxHiY + idxHiZ];
228 
229  // Linear interpolation along the Z axis:
230  float LoXLoYInZ = LoXLoYLoZ + (LoXLoYHiZ - LoXLoYLoZ) * rz;
231  float HiXLoYInZ = HiXLoYLoZ + (HiXLoYHiZ - HiXLoYLoZ) * rz;
232  float LoXHiYInZ = LoXHiYLoZ + (LoXHiYHiZ - LoXHiYLoZ) * rz;
233  float HiXHiYInZ = HiXHiYLoZ + (HiXHiYHiZ - HiXHiYLoZ) * rz;
234 
235  // Linear interpolation along the Y axis:
236  float LoXInYInZ = LoXLoYInZ + (LoXHiYInZ - LoXLoYInZ) * ry;
237  float HiXInYInZ = HiXLoYInZ + (HiXHiYInZ - HiXLoYInZ) * ry;
238 
239  // Linear interpolation along the X axis:
240  a_Dst[idx] = LoXInYInZ + (HiXInYInZ - LoXInYInZ) * RatioX[x];
241  idx += 1;
242  } // for x
243  } // for y
244  } // for z
245 }
246 
247 
248 
249 
250 
#define ASSERT(x)
Definition: Globals.h:276
void LinearInterpolate2DArray(float *a_Src, int a_SrcSizeX, int a_SrcSizeY, float *a_Dst, int a_DstSizeX, int a_DstSizeY)
Puts linearly interpolated values from one array into another array.
void LinearInterpolate3DArray(float *a_Src, int a_SrcSizeX, int a_SrcSizeY, int a_SrcSizeZ, float *a_Dst, int a_DstSizeX, int a_DstSizeY, int a_DstSizeZ)
Puts linearly interpolated values from one array into another array.
void LinearInterpolate1DArray(float *a_Src, int a_SrcSizeX, float *a_Dst, int a_DstSizeX)
Puts linearly interpolated values from one array into another array.
const int MAX_INTERPOL_SIZEZ
Maximum Z-size of the interpolated array.
const int MAX_INTERPOL_SIZEY
Maximum Y-size of the interpolated array.
const int MAX_INTERPOL_SIZEX
Maximum X-size of the interpolated array.