Vector3.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  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.2020.01.10
  7. #pragma once
  8. #include <Mathematics/Vector.h>
  9. namespace WwiseGTE
  10. {
  11. // Template alias for convenience.
  12. template <typename Real>
  13. using Vector3 = Vector<3, Real>;
  14. // Cross, UnitCross, and DotCross have a template parameter N that should
  15. // be 3 or 4. The latter case supports affine vectors in 4D (last
  16. // component w = 0) when you want to use 4-tuples and 4x4 matrices for
  17. // affine algebra.
  18. // Compute the cross product using the formal determinant:
  19. // cross = det{{e0,e1,e2},{x0,x1,x2},{y0,y1,y2}}
  20. // = (x1*y2-x2*y1, x2*y0-x0*y2, x0*y1-x1*y0)
  21. // where e0 = (1,0,0), e1 = (0,1,0), e2 = (0,0,1), v0 = (x0,x1,x2), and
  22. // v1 = (y0,y1,y2).
  23. template <int N, typename Real>
  24. Vector<N, Real> Cross(Vector<N, Real> const& v0, Vector<N, Real> const& v1)
  25. {
  26. static_assert(N == 3 || N == 4, "Dimension must be 3 or 4.");
  27. Vector<N, Real> result;
  28. result.MakeZero();
  29. result[0] = v0[1] * v1[2] - v0[2] * v1[1];
  30. result[1] = v0[2] * v1[0] - v0[0] * v1[2];
  31. result[2] = v0[0] * v1[1] - v0[1] * v1[0];
  32. return result;
  33. }
  34. // Compute the normalized cross product.
  35. template <int N, typename Real>
  36. Vector<N, Real> UnitCross(Vector<N, Real> const& v0, Vector<N, Real> const& v1, bool robust = false)
  37. {
  38. static_assert(N == 3 || N == 4, "Dimension must be 3 or 4.");
  39. Vector<N, Real> unitCross = Cross(v0, v1);
  40. Normalize(unitCross, robust);
  41. return unitCross;
  42. }
  43. // Compute Dot((x0,x1,x2),Cross((y0,y1,y2),(z0,z1,z2)), the triple scalar
  44. // product of three vectors, where v0 = (x0,x1,x2), v1 = (y0,y1,y2), and
  45. // v2 is (z0,z1,z2).
  46. template <int N, typename Real>
  47. Real DotCross(Vector<N, Real> const& v0, Vector<N, Real> const& v1,
  48. Vector<N, Real> const& v2)
  49. {
  50. static_assert(N == 3 || N == 4, "Dimension must be 3 or 4.");
  51. return Dot(v0, Cross(v1, v2));
  52. }
  53. // Compute a right-handed orthonormal basis for the orthogonal complement
  54. // of the input vectors. The function returns the smallest length of the
  55. // unnormalized vectors computed during the process. If this value is
  56. // nearly zero, it is possible that the inputs are linearly dependent
  57. // (within numerical round-off errors). On input, numInputs must be 1 or
  58. // 2 and v[0] through v[numInputs-1] must be initialized. On output, the
  59. // vectors v[0] through v[2] form an orthonormal set.
  60. template <typename Real>
  61. Real ComputeOrthogonalComplement(int numInputs, Vector3<Real>* v, bool robust = false)
  62. {
  63. if (numInputs == 1)
  64. {
  65. if (std::fabs(v[0][0]) > std::fabs(v[0][1]))
  66. {
  67. v[1] = { -v[0][2], (Real)0, +v[0][0] };
  68. }
  69. else
  70. {
  71. v[1] = { (Real)0, +v[0][2], -v[0][1] };
  72. }
  73. numInputs = 2;
  74. }
  75. if (numInputs == 2)
  76. {
  77. v[2] = Cross(v[0], v[1]);
  78. return Orthonormalize<3, Real>(3, v, robust);
  79. }
  80. return (Real)0;
  81. }
  82. // Compute the barycentric coordinates of the point P with respect to the
  83. // tetrahedron <V0,V1,V2,V3>, P = b0*V0 + b1*V1 + b2*V2 + b3*V3, where
  84. // b0 + b1 + b2 + b3 = 1. The return value is 'true' iff {V0,V1,V2,V3} is
  85. // a linearly independent set. Numerically, this is measured by
  86. // |det[V0 V1 V2 V3]| <= epsilon. The values bary[] are valid only when
  87. // the return value is 'true' but set to zero when the return value is
  88. // 'false'.
  89. template <typename Real>
  90. bool ComputeBarycentrics(Vector3<Real> const& p, Vector3<Real> const& v0,
  91. Vector3<Real> const& v1, Vector3<Real> const& v2, Vector3<Real> const& v3,
  92. Real bary[4], Real epsilon = (Real)0)
  93. {
  94. // Compute the vectors relative to V3 of the tetrahedron.
  95. Vector3<Real> diff[4] = { v0 - v3, v1 - v3, v2 - v3, p - v3 };
  96. Real det = DotCross(diff[0], diff[1], diff[2]);
  97. if (det < -epsilon || det > epsilon)
  98. {
  99. Real invDet = ((Real)1) / det;
  100. bary[0] = DotCross(diff[3], diff[1], diff[2]) * invDet;
  101. bary[1] = DotCross(diff[3], diff[2], diff[0]) * invDet;
  102. bary[2] = DotCross(diff[3], diff[0], diff[1]) * invDet;
  103. bary[3] = (Real)1 - bary[0] - bary[1] - bary[2];
  104. return true;
  105. }
  106. for (int i = 0; i < 4; ++i)
  107. {
  108. bary[i] = (Real)0;
  109. }
  110. return false;
  111. }
  112. // Get intrinsic information about the input array of vectors. The return
  113. // value is 'true' iff the inputs are valid (numVectors > 0, v is not
  114. // null, and epsilon >= 0), in which case the class members are valid.
  115. template <typename Real>
  116. class IntrinsicsVector3
  117. {
  118. public:
  119. // The constructor sets the class members based on the input set.
  120. IntrinsicsVector3(int numVectors, Vector3<Real> const* v, Real inEpsilon)
  121. :
  122. epsilon(inEpsilon),
  123. dimension(0),
  124. maxRange((Real)0),
  125. origin{ (Real)0, (Real)0, (Real)0 },
  126. extremeCCW(false)
  127. {
  128. min[0] = (Real)0;
  129. min[1] = (Real)0;
  130. min[2] = (Real)0;
  131. direction[0] = { (Real)0, (Real)0, (Real)0 };
  132. direction[1] = { (Real)0, (Real)0, (Real)0 };
  133. direction[2] = { (Real)0, (Real)0, (Real)0 };
  134. extreme[0] = 0;
  135. extreme[1] = 0;
  136. extreme[2] = 0;
  137. extreme[3] = 0;
  138. if (numVectors > 0 && v && epsilon >= (Real)0)
  139. {
  140. // Compute the axis-aligned bounding box for the input vectors.
  141. // Keep track of the indices into 'vectors' for the current
  142. // min and max.
  143. int j, indexMin[3], indexMax[3];
  144. for (j = 0; j < 3; ++j)
  145. {
  146. min[j] = v[0][j];
  147. max[j] = min[j];
  148. indexMin[j] = 0;
  149. indexMax[j] = 0;
  150. }
  151. int i;
  152. for (i = 1; i < numVectors; ++i)
  153. {
  154. for (j = 0; j < 3; ++j)
  155. {
  156. if (v[i][j] < min[j])
  157. {
  158. min[j] = v[i][j];
  159. indexMin[j] = i;
  160. }
  161. else if (v[i][j] > max[j])
  162. {
  163. max[j] = v[i][j];
  164. indexMax[j] = i;
  165. }
  166. }
  167. }
  168. // Determine the maximum range for the bounding box.
  169. maxRange = max[0] - min[0];
  170. extreme[0] = indexMin[0];
  171. extreme[1] = indexMax[0];
  172. Real range = max[1] - min[1];
  173. if (range > maxRange)
  174. {
  175. maxRange = range;
  176. extreme[0] = indexMin[1];
  177. extreme[1] = indexMax[1];
  178. }
  179. range = max[2] - min[2];
  180. if (range > maxRange)
  181. {
  182. maxRange = range;
  183. extreme[0] = indexMin[2];
  184. extreme[1] = indexMax[2];
  185. }
  186. // The origin is either the vector of minimum x0-value, vector
  187. // of minimum x1-value, or vector of minimum x2-value.
  188. origin = v[extreme[0]];
  189. // Test whether the vector set is (nearly) a vector.
  190. if (maxRange <= epsilon)
  191. {
  192. dimension = 0;
  193. for (j = 0; j < 3; ++j)
  194. {
  195. extreme[j + 1] = extreme[0];
  196. }
  197. return;
  198. }
  199. // Test whether the vector set is (nearly) a line segment. We
  200. // need {direction[2],direction[3]} to span the orthogonal
  201. // complement of direction[0].
  202. direction[0] = v[extreme[1]] - origin;
  203. Normalize(direction[0], false);
  204. if (std::fabs(direction[0][0]) > std::fabs(direction[0][1]))
  205. {
  206. direction[1][0] = -direction[0][2];
  207. direction[1][1] = (Real)0;
  208. direction[1][2] = +direction[0][0];
  209. }
  210. else
  211. {
  212. direction[1][0] = (Real)0;
  213. direction[1][1] = +direction[0][2];
  214. direction[1][2] = -direction[0][1];
  215. }
  216. Normalize(direction[1], false);
  217. direction[2] = Cross(direction[0], direction[1]);
  218. // Compute the maximum distance of the points from the line
  219. // origin + t * direction[0].
  220. Real maxDistance = (Real)0;
  221. Real distance, dot;
  222. extreme[2] = extreme[0];
  223. for (i = 0; i < numVectors; ++i)
  224. {
  225. Vector3<Real> diff = v[i] - origin;
  226. dot = Dot(direction[0], diff);
  227. Vector3<Real> proj = diff - dot * direction[0];
  228. distance = Length(proj, false);
  229. if (distance > maxDistance)
  230. {
  231. maxDistance = distance;
  232. extreme[2] = i;
  233. }
  234. }
  235. if (maxDistance <= epsilon * maxRange)
  236. {
  237. // The points are (nearly) on the line
  238. // origin + t * direction[0].
  239. dimension = 1;
  240. extreme[2] = extreme[1];
  241. extreme[3] = extreme[1];
  242. return;
  243. }
  244. // Test whether the vector set is (nearly) a planar polygon.
  245. // The point v[extreme[2]] is farthest from the line:
  246. // origin + t * direction[0]. The vector
  247. // v[extreme[2]] - origin is not necessarily perpendicular to
  248. // direction[0], so project out the direction[0] component so
  249. // that the result is perpendicular to direction[0].
  250. direction[1] = v[extreme[2]] - origin;
  251. dot = Dot(direction[0], direction[1]);
  252. direction[1] -= dot * direction[0];
  253. Normalize(direction[1], false);
  254. // We need direction[2] to span the orthogonal complement of
  255. // {direction[0],direction[1]}.
  256. direction[2] = Cross(direction[0], direction[1]);
  257. // Compute the maximum distance of the points from the plane
  258. // origin+t0 * direction[0] + t1 * direction[1].
  259. maxDistance = (Real)0;
  260. Real maxSign = (Real)0;
  261. extreme[3] = extreme[0];
  262. for (i = 0; i < numVectors; ++i)
  263. {
  264. Vector3<Real> diff = v[i] - origin;
  265. distance = Dot(direction[2], diff);
  266. Real sign = (distance > (Real)0 ? (Real)1 :
  267. (distance < (Real)0 ? (Real)-1 : (Real)0));
  268. distance = std::fabs(distance);
  269. if (distance > maxDistance)
  270. {
  271. maxDistance = distance;
  272. maxSign = sign;
  273. extreme[3] = i;
  274. }
  275. }
  276. if (maxDistance <= epsilon * maxRange)
  277. {
  278. // The points are (nearly) on the plane
  279. // origin + t0 * direction[0] + t1 * direction[1].
  280. dimension = 2;
  281. extreme[3] = extreme[2];
  282. return;
  283. }
  284. dimension = 3;
  285. extremeCCW = (maxSign > (Real)0);
  286. return;
  287. }
  288. }
  289. // A nonnegative tolerance that is used to determine the intrinsic
  290. // dimension of the set.
  291. Real epsilon;
  292. // The intrinsic dimension of the input set, computed based on the
  293. // nonnegative tolerance mEpsilon.
  294. int dimension;
  295. // Axis-aligned bounding box of the input set. The maximum range is
  296. // the larger of max[0]-min[0], max[1]-min[1], and max[2]-min[2].
  297. Real min[3], max[3];
  298. Real maxRange;
  299. // Coordinate system. The origin is valid for any dimension d. The
  300. // unit-length direction vector is valid only for 0 <= i < d. The
  301. // extreme index is relative to the array of input points, and is also
  302. // valid only for 0 <= i < d. If d = 0, all points are effectively
  303. // the same, but the use of an epsilon may lead to an extreme index
  304. // that is not zero. If d = 1, all points effectively lie on a line
  305. // segment. If d = 2, all points effectively line on a plane. If
  306. // d = 3, the points are not coplanar.
  307. Vector3<Real> origin;
  308. Vector3<Real> direction[3];
  309. // The indices that define the maximum dimensional extents. The
  310. // values extreme[0] and extreme[1] are the indices for the points
  311. // that define the largest extent in one of the coordinate axis
  312. // directions. If the dimension is 2, then extreme[2] is the index
  313. // for the point that generates the largest extent in the direction
  314. // perpendicular to the line through the points corresponding to
  315. // extreme[0] and extreme[1]. Furthermore, if the dimension is 3,
  316. // then extreme[3] is the index for the point that generates the
  317. // largest extent in the direction perpendicular to the triangle
  318. // defined by the other extreme points. The tetrahedron formed by the
  319. // points V[extreme[0]], V[extreme[1]], V[extreme[2]], and
  320. // V[extreme[3]] is clockwise or counterclockwise, the condition
  321. // stored in extremeCCW.
  322. int extreme[4];
  323. bool extremeCCW;
  324. };
  325. }