IntpTrilinear3.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. // David Eberly, Geometric Tools, Redmond WA 98052
  2. // Copyright (c) 1998-2020
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // https://www.boost.org/LICENSE_1_0.txt
  5. // https://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
  6. // Version: 4.0.2019.08.13
  7. #pragma once
  8. #include <Mathematics/Logger.h>
  9. #include <array>
  10. // The interpolator is for uniformly spaced(x,y z)-values. The input samples
  11. // must be stored in lexicographical order to represent f(x,y,z); that is,
  12. // F[c + xBound*(r + yBound*s)] corresponds to f(x,y,z), where c is the index
  13. // corresponding to x, r is the index corresponding to y, and s is the index
  14. // corresponding to z.
  15. namespace WwiseGTE
  16. {
  17. template <typename Real>
  18. class IntpTrilinear3
  19. {
  20. public:
  21. // Construction.
  22. IntpTrilinear3(int xBound, int yBound, int zBound, Real xMin,
  23. Real xSpacing, Real yMin, Real ySpacing, Real zMin, Real zSpacing, Real const* F)
  24. :
  25. mXBound(xBound),
  26. mYBound(yBound),
  27. mZBound(zBound),
  28. mQuantity(xBound* yBound* zBound),
  29. mXMin(xMin),
  30. mXSpacing(xSpacing),
  31. mYMin(yMin),
  32. mYSpacing(ySpacing),
  33. mZMin(zMin),
  34. mZSpacing(zSpacing),
  35. mF(F)
  36. {
  37. // At least a 2x2x2 block of data points are needed to construct
  38. // the trilinear interpolation.
  39. LogAssert(xBound >= 2 && yBound >= 2 && zBound >= 2 && F != nullptr
  40. && xSpacing > (Real)0 && ySpacing > (Real)0 && zSpacing > (Real)0,
  41. "Invalid input.");
  42. mXMax = mXMin + mXSpacing * static_cast<Real>(mXBound - 1);
  43. mInvXSpacing = (Real)1 / mXSpacing;
  44. mYMax = mYMin + mYSpacing * static_cast<Real>(mYBound - 1);
  45. mInvYSpacing = (Real)1 / mYSpacing;
  46. mZMax = mZMin + mZSpacing * static_cast<Real>(mZBound - 1);
  47. mInvZSpacing = (Real)1 / mZSpacing;
  48. mBlend[0][0] = (Real)1;
  49. mBlend[0][1] = (Real)-1;
  50. mBlend[1][0] = (Real)0;
  51. mBlend[1][1] = (Real)1;
  52. }
  53. // Member access.
  54. inline int GetXBound() const
  55. {
  56. return mXBound;
  57. }
  58. inline int GetYBound() const
  59. {
  60. return mYBound;
  61. }
  62. inline int GetZBound() const
  63. {
  64. return mZBound;
  65. }
  66. inline int GetQuantity() const
  67. {
  68. return mQuantity;
  69. }
  70. inline Real const* GetF() const
  71. {
  72. return mF;
  73. }
  74. inline Real GetXMin() const
  75. {
  76. return mXMin;
  77. }
  78. inline Real GetXMax() const
  79. {
  80. return mXMax;
  81. }
  82. inline Real GetXSpacing() const
  83. {
  84. return mXSpacing;
  85. }
  86. inline Real GetYMin() const
  87. {
  88. return mYMin;
  89. }
  90. inline Real GetYMax() const
  91. {
  92. return mYMax;
  93. }
  94. inline Real GetYSpacing() const
  95. {
  96. return mYSpacing;
  97. }
  98. inline Real GetZMin() const
  99. {
  100. return mZMin;
  101. }
  102. inline Real GetZMax() const
  103. {
  104. return mZMax;
  105. }
  106. inline Real GetZSpacing() const
  107. {
  108. return mZSpacing;
  109. }
  110. // Evaluate the function and its derivatives. The functions clamp the
  111. // inputs to xmin <= x <= xmax, ymin <= y <= ymax and
  112. // zmin <= z <= zmax. The first operator is for function evaluation.
  113. // The second operator is for function or derivative evaluations. The
  114. // xOrder argument is the order of the x-derivative, the yOrder
  115. // argument is the order of the y-derivative, and the zOrder argument
  116. // is the order of the z-derivative. All orders are zero to get the
  117. // function value itself.
  118. Real operator()(Real x, Real y, Real z) const
  119. {
  120. // Compute x-index and clamp to image.
  121. Real xIndex = (x - mXMin) * mInvXSpacing;
  122. int ix = static_cast<int>(xIndex);
  123. if (ix < 0)
  124. {
  125. ix = 0;
  126. }
  127. else if (ix >= mXBound)
  128. {
  129. ix = mXBound - 1;
  130. }
  131. // Compute y-index and clamp to image.
  132. Real yIndex = (y - mYMin) * mInvYSpacing;
  133. int iy = static_cast<int>(yIndex);
  134. if (iy < 0)
  135. {
  136. iy = 0;
  137. }
  138. else if (iy >= mYBound)
  139. {
  140. iy = mYBound - 1;
  141. }
  142. // Compute z-index and clamp to image.
  143. Real zIndex = (z - mZMin) * mInvZSpacing;
  144. int iz = static_cast<int>(zIndex);
  145. if (iz < 0)
  146. {
  147. iz = 0;
  148. }
  149. else if (iz >= mZBound)
  150. {
  151. iz = mZBound - 1;
  152. }
  153. std::array<Real, 2> U;
  154. U[0] = (Real)1;
  155. U[1] = xIndex - ix;
  156. std::array<Real, 2> V;
  157. V[0] = (Real)1;
  158. V[1] = yIndex - iy;
  159. std::array<Real, 2> W;
  160. W[0] = (Real)1;
  161. W[1] = zIndex - iz;
  162. // Compute P = M*U, Q = M*V, R = M*W.
  163. std::array<Real, 2> P, Q, R;
  164. for (int row = 0; row < 2; ++row)
  165. {
  166. P[row] = (Real)0;
  167. Q[row] = (Real)0;
  168. R[row] = (Real)0;
  169. for (int col = 0; col < 2; ++col)
  170. {
  171. P[row] += mBlend[row][col] * U[col];
  172. Q[row] += mBlend[row][col] * V[col];
  173. R[row] += mBlend[row][col] * W[col];
  174. }
  175. }
  176. // compute the tensor product (M*U)(M*V)(M*W)*D where D is the 2x2x2
  177. // subimage containing (x,y,z)
  178. Real result = (Real)0;
  179. for (int slice = 0; slice < 2; ++slice)
  180. {
  181. int zClamp = iz + slice;
  182. if (zClamp >= mZBound)
  183. {
  184. zClamp = mZBound - 1;
  185. }
  186. for (int row = 0; row < 2; ++row)
  187. {
  188. int yClamp = iy + row;
  189. if (yClamp >= mYBound)
  190. {
  191. yClamp = mYBound - 1;
  192. }
  193. for (int col = 0; col < 2; ++col)
  194. {
  195. int xClamp = ix + col;
  196. if (xClamp >= mXBound)
  197. {
  198. xClamp = mXBound - 1;
  199. }
  200. result += P[col] * Q[row] * R[slice] *
  201. mF[xClamp + mXBound * (yClamp + mYBound * zClamp)];
  202. }
  203. }
  204. }
  205. return result;
  206. }
  207. Real operator()(int xOrder, int yOrder, int zOrder, Real x, Real y, Real z) const
  208. {
  209. // Compute x-index and clamp to image.
  210. Real xIndex = (x - mXMin) * mInvXSpacing;
  211. int ix = static_cast<int>(xIndex);
  212. if (ix < 0)
  213. {
  214. ix = 0;
  215. }
  216. else if (ix >= mXBound)
  217. {
  218. ix = mXBound - 1;
  219. }
  220. // Compute y-index and clamp to image.
  221. Real yIndex = (y - mYMin) * mInvYSpacing;
  222. int iy = static_cast<int>(yIndex);
  223. if (iy < 0)
  224. {
  225. iy = 0;
  226. }
  227. else if (iy >= mYBound)
  228. {
  229. iy = mYBound - 1;
  230. }
  231. // Compute z-index and clamp to image.
  232. Real zIndex = (z - mZMin) * mInvZSpacing;
  233. int iz = static_cast<int>(zIndex);
  234. if (iz < 0)
  235. {
  236. iz = 0;
  237. }
  238. else if (iz >= mZBound)
  239. {
  240. iz = mZBound - 1;
  241. }
  242. std::array<Real, 2> U;
  243. Real dx, xMult;
  244. switch (xOrder)
  245. {
  246. case 0:
  247. dx = xIndex - ix;
  248. U[0] = (Real)1;
  249. U[1] = dx;
  250. xMult = (Real)1;
  251. break;
  252. case 1:
  253. dx = xIndex - ix;
  254. U[0] = (Real)0;
  255. U[1] = (Real)1;
  256. xMult = mInvXSpacing;
  257. break;
  258. default:
  259. return (Real)0;
  260. }
  261. std::array<Real, 2> V;
  262. Real dy, yMult;
  263. switch (yOrder)
  264. {
  265. case 0:
  266. dy = yIndex - iy;
  267. V[0] = (Real)1;
  268. V[1] = dy;
  269. yMult = (Real)1;
  270. break;
  271. case 1:
  272. dy = yIndex - iy;
  273. V[0] = (Real)0;
  274. V[1] = (Real)1;
  275. yMult = mInvYSpacing;
  276. break;
  277. default:
  278. return (Real)0;
  279. }
  280. std::array<Real, 2> W;
  281. Real dz, zMult;
  282. switch (zOrder)
  283. {
  284. case 0:
  285. dz = zIndex - iz;
  286. W[0] = (Real)1;
  287. W[1] = dz;
  288. zMult = (Real)1;
  289. break;
  290. case 1:
  291. dz = zIndex - iz;
  292. W[0] = (Real)0;
  293. W[1] = (Real)1;
  294. zMult = mInvZSpacing;
  295. break;
  296. default:
  297. return (Real)0;
  298. }
  299. // Compute P = M*U, Q = M*V, and R = M*W.
  300. std::array<Real, 2> P, Q, R;
  301. for (int row = 0; row < 2; ++row)
  302. {
  303. P[row] = (Real)0;
  304. Q[row] = (Real)0;
  305. R[row] = (Real)0;
  306. for (int col = 0; col < 2; ++col)
  307. {
  308. P[row] += mBlend[row][col] * U[col];
  309. Q[row] += mBlend[row][col] * V[col];
  310. R[row] += mBlend[row][col] * W[col];
  311. }
  312. }
  313. // Compute the tensor product (M*U)(M*V)(M*W)*D where D is the 2x2x2
  314. // subimage containing (x,y,z).
  315. Real result = (Real)0;
  316. for (int slice = 0; slice < 2; ++slice)
  317. {
  318. int zClamp = iz + slice;
  319. if (zClamp >= mZBound)
  320. {
  321. zClamp = mZBound - 1;
  322. }
  323. for (int row = 0; row < 2; ++row)
  324. {
  325. int yClamp = iy + row;
  326. if (yClamp >= mYBound)
  327. {
  328. yClamp = mYBound - 1;
  329. }
  330. for (int col = 0; col < 2; ++col)
  331. {
  332. int xClamp = ix + col;
  333. if (xClamp >= mXBound)
  334. {
  335. xClamp = mXBound - 1;
  336. }
  337. result += P[col] * Q[row] * R[slice] *
  338. mF[xClamp + mXBound * (yClamp + mYBound * zClamp)];
  339. }
  340. }
  341. }
  342. result *= xMult * yMult * zMult;
  343. return result;
  344. }
  345. private:
  346. int mXBound, mYBound, mZBound, mQuantity;
  347. Real mXMin, mXMax, mXSpacing, mInvXSpacing;
  348. Real mYMin, mYMax, mYSpacing, mInvYSpacing;
  349. Real mZMin, mZMax, mZSpacing, mInvZSpacing;
  350. Real const* mF;
  351. std::array<std::array<Real, 2>, 2> mBlend;
  352. };
  353. }