当前位置:   article > 正文

【C++知识树】Vector.h&Geometry3D----三维空间向量计算几何算法汇总【ZENO、Blender、game-physics-cookbook、UE5、Godot】_c++三维向量

c++三维向量

ZENO----vec.h

  1. #pragma once
  2. #include <array>
  3. #include <cmath>
  4. #include <cstdint>
  5. #include <type_traits>
  6. #include <limits>
  7. namespace zeno {
  8. namespace _impl_vec {
  9. template <class T, class S>
  10. constexpr bool is_decay_same_v = std::is_same_v<std::decay_t<T>, std::decay_t<S>>;
  11. /* main class definition */
  12. template <size_t N, class T>
  13. struct vec : std::array<T, N> {
  14. vec() = default;
  15. explicit vec(T const &x) {
  16. for (size_t i = 0; i < N; i++) {
  17. (*this)[i] = x;
  18. }
  19. }
  20. vec(vec &&) = default;
  21. vec(vec const &) = default;
  22. vec &operator=(vec const &) = default;
  23. vec(std::array<T, N> const &a) {
  24. for (size_t i = 0; i < N; i++) {
  25. (*this)[i] = a[i];
  26. }
  27. }
  28. operator std::array<T, N>() const {
  29. std::array<T, N> res;
  30. for (size_t i = 0; i < N; i++) {
  31. res[i] = (*this)[i];
  32. }
  33. return res;
  34. }
  35. template <class S>
  36. explicit vec(vec<N, S> const &x) {
  37. for (size_t i = 0; i < N; i++) {
  38. (*this)[i] = T(x[i]);
  39. }
  40. }
  41. vec(std::initializer_list<T> const &x) {
  42. T val{};
  43. auto it = x.begin();
  44. for (size_t i = 0; i < N; i++) {
  45. if (it != x.end())
  46. val = *it++;
  47. (*this)[i] = val;
  48. }
  49. }
  50. vec(T const &x, T const &y) : vec{x, y} {}
  51. vec(T const &x, T const &y, T const &z) : vec{x, y, z} {}
  52. vec(T const &x, T const &y, T const &z, T const &w) : vec{x, y, z, w} {}
  53. template <class S>
  54. operator vec<N, S>() const {
  55. vec<N, S> res;
  56. for (size_t i = 0; i < N; i++) {
  57. res[i] = (*this)[i];
  58. }
  59. return res;
  60. }
  61. };
  62. /* type traits */
  63. template <class T>
  64. struct is_vec : std::false_type {
  65. static constexpr size_t _N = 1;
  66. };
  67. template <size_t N, class T>
  68. struct is_vec<vec<N, T>> : std::true_type {
  69. static constexpr size_t _N = N;
  70. };
  71. template <class T>
  72. inline constexpr bool is_vec_v = is_vec<std::decay_t<T>>::value;
  73. template <class T>
  74. inline constexpr size_t is_vec_n = is_vec<std::decay_t<T>>::_N;
  75. template <class T, class S>
  76. struct is_vec_promotable : std::false_type {
  77. using type = void;
  78. };
  79. template <class T, size_t N>
  80. struct is_vec_promotable<vec<N, T>, vec<N, T>> : std::true_type {
  81. using type = vec<N, T>;
  82. };
  83. template <class T, size_t N>
  84. struct is_vec_promotable<vec<N, T>, T> : std::true_type {
  85. using type = vec<N, T>;
  86. };
  87. template <class T, size_t N>
  88. struct is_vec_promotable<T, vec<N, T>> : std::true_type {
  89. using type = vec<N, T>;
  90. };
  91. template <class T>
  92. struct is_vec_promotable<T, T> : std::true_type {
  93. using type = T;
  94. };
  95. template <class T, class S>
  96. inline constexpr bool is_vec_promotable_v =
  97. is_vec_promotable<std::decay_t<T>, std::decay_t<S>>::value;
  98. template <class T, class S>
  99. using is_vec_promotable_t =
  100. typename is_vec_promotable<std::decay_t<T>, std::decay_t<S>>::type;
  101. template <class T, class S>
  102. struct is_vec_castable : std::false_type {};
  103. template <class T, size_t N>
  104. struct is_vec_castable<vec<N, T>, T> : std::true_type {};
  105. template <class T, size_t N>
  106. struct is_vec_castable<T, vec<N, T>> : std::false_type {};
  107. template <class T>
  108. struct is_vec_castable<T, T> : std::true_type {};
  109. template <class T, class S>
  110. inline constexpr bool is_vec_castable_v =
  111. is_vec_castable<std::decay_t<T>, std::decay_t<S>>::value;
  112. template <class T>
  113. struct decay_vec { using type = T; };
  114. template <size_t N, class T>
  115. struct decay_vec<vec<N, T>> { using type = T; };
  116. template <class T>
  117. using decay_vec_t = typename decay_vec<T>::type;
  118. /* converter functions */
  119. template <class T, std::enable_if_t<!is_vec_v<T>, bool> = true>
  120. inline auto vec_to_other(T const &a) {
  121. return a;
  122. }
  123. template <class OtherT, class T>
  124. inline auto vec_to_other(vec<2, T> const &a) {
  125. return OtherT(a[0], a[1]);
  126. }
  127. template <class OtherT, class T>
  128. inline auto vec_to_other(vec<3, T> const &a) {
  129. return OtherT(a[0], a[1], a[2]);
  130. }
  131. template <class OtherT, class T>
  132. inline auto vec_to_other(vec<4, T> const &a) {
  133. return OtherT(a[0], a[1], a[2], a[3]);
  134. }
  135. template <class OtherT, size_t N, class T>
  136. inline auto vec_to_other(vec<N, T> const &a) {
  137. OtherT res;
  138. for (size_t i = 0; i < N; i++) {
  139. res[i] = a[i];
  140. }
  141. return res;
  142. }
  143. template <size_t N, class OtherT>
  144. inline auto other_to_vec(OtherT const &x) {
  145. vec<N, std::decay_t<decltype(x[0])>> res;
  146. for (size_t i = 0; i < N; i++) {
  147. res[i] = x[i];
  148. }
  149. return res;
  150. }
  151. /* element-wise operations */
  152. template <size_t N, class T, class F>
  153. inline auto _vec_apply(F const &f, vec<N, T> const &a) {
  154. vec<N, decltype(f(a[0]))> res;
  155. for (size_t i = 0; i < N; i++) {
  156. res[i] = f(a[i]);
  157. }
  158. return res;
  159. }
  160. template <class T, class F, std::enable_if_t<!is_vec_v<T>, bool> = true>
  161. inline auto _vec_apply(F const &f, T const &a) {
  162. return f(a);
  163. }
  164. template <size_t N, class T, class S, class F>
  165. inline auto _vec_apply(F const &f, vec<N, T> const &a, vec<N, S> const &b) {
  166. vec<N, decltype(f(a[0], b[0]))> res;
  167. for (size_t i = 0; i < N; i++) {
  168. res[i] = f(a[i], b[i]);
  169. }
  170. return res;
  171. }
  172. template <size_t N, class T, class S, class F,
  173. std::enable_if_t<!is_vec_v<T>, bool> = true>
  174. inline auto _vec_apply(F const &f, T const &a, vec<N, S> const &b) {
  175. vec<N, decltype(f(a, b[0]))> res;
  176. for (size_t i = 0; i < N; i++) {
  177. res[i] = f(a, b[i]);
  178. }
  179. return res;
  180. }
  181. template <size_t N, class T, class S, class F,
  182. std::enable_if_t<!is_vec_v<S>, bool> = true>
  183. inline auto _vec_apply(F const &f, vec<N, T> const &a, S const &b) {
  184. vec<N, decltype(f(a[0], b))> res;
  185. for (size_t i = 0; i < N; i++) {
  186. res[i] = f(a[i], b);
  187. }
  188. return res;
  189. }
  190. template <class T, class S, class F,
  191. std::enable_if_t<!is_vec_v<T> && !is_vec_v<S>, bool> = true>
  192. inline auto _vec_apply(F const &f, T const &a, S const &b) {
  193. return f(a, b);
  194. }
  195. template <class T, class S>
  196. inline constexpr bool
  197. is__vec_apply_v = (is_vec_v<T> || is_vec_v<S>) &&
  198. (std::is_arithmetic_v<T> || std::is_arithmetic_v<S>
  199. || is_vec_n<T> == is_vec_n<S>);
  200. template <class T, class S, class F,
  201. std::enable_if_t<is__vec_apply_v<T, S>, bool> = true>
  202. inline auto _vec_apply(F const &f, T const &a, S const &b) {
  203. return f(a, b);
  204. }
  205. #define _PER_OP2(op) \
  206. template <class T, class S, \
  207. std::enable_if_t<is__vec_apply_v<T, S>, bool> = true, \
  208. decltype(std::declval<decay_vec_t<T>>() \
  209. op std::declval<decay_vec_t<S>>(), \
  210. true) = true> \
  211. inline auto operator op(T const &a, S const &b)->decltype(auto) { \
  212. return _vec_apply([](auto const &x, auto const &y) { return x op y; }, a, b); \
  213. }
  214. #define _PER_IOP2(op) \
  215. _PER_OP2(op) \
  216. template <size_t N, class T, class S, \
  217. std::enable_if_t<is__vec_apply_v<vec<N, T>, S>, bool> = true, \
  218. decltype(std::declval<vec<N, T>>() op std::declval<S>(), true) = \
  219. true> \
  220. inline vec<N, T> &operator op##=(vec<N, T> &a, S const &b) { \
  221. a = a op b; \
  222. return a; \
  223. }
  224. _PER_IOP2(+)
  225. _PER_IOP2(-)
  226. _PER_IOP2(*)
  227. _PER_IOP2(/)
  228. _PER_IOP2(%)
  229. _PER_IOP2(&)
  230. _PER_IOP2(|)
  231. _PER_IOP2(^)
  232. _PER_IOP2(>>)
  233. _PER_IOP2(<<)
  234. _PER_OP2(==)
  235. _PER_OP2(!=)
  236. _PER_OP2(<)
  237. _PER_OP2(>)
  238. _PER_OP2(<=)
  239. _PER_OP2(>=)
  240. _PER_OP2(&&)
  241. _PER_OP2(||)
  242. #undef _PER_IOP2
  243. #undef _PER_OP2
  244. #define _PER_OP1(op) \
  245. template <class T, std::enable_if_t<is_vec_v<T>, bool> = true, \
  246. decltype(op std::declval<decay_vec_t<T>>(), true) = true> \
  247. inline auto operator op(T const &a) { \
  248. return _vec_apply([](auto const &x) { return op x; }, a); \
  249. }
  250. _PER_OP1(+)
  251. _PER_OP1(-)
  252. _PER_OP1(~)
  253. _PER_OP1(!)
  254. #undef _PER_OP1
  255. #define _PER_FN2(func) \
  256. template <class T, class S, \
  257. decltype(std::declval<T>() + std::declval<S>(), true) = true> \
  258. inline auto func(T const &a, S const &b)->decltype(auto) { \
  259. return _vec_apply( \
  260. [](auto const &x, auto const &y) { \
  261. using promoted = decltype(x + y); \
  262. return (promoted)std::func((promoted)x, (promoted)y); \
  263. }, \
  264. a, b); \
  265. }
  266. _PER_FN2(atan2)
  267. _PER_FN2(pow)
  268. _PER_FN2(max)
  269. _PER_FN2(min)
  270. _PER_FN2(fmod)
  271. #undef _PER_FN2
  272. #define _PER_FN1(func) \
  273. template <class T> inline auto func(T const &a) { \
  274. return _vec_apply([](auto const &x) { return (decltype(x))std::func(x); }, a); \
  275. }
  276. _PER_FN1(abs)
  277. _PER_FN1(sqrt)
  278. _PER_FN1(sin)
  279. _PER_FN1(cos)
  280. _PER_FN1(tan)
  281. _PER_FN1(asin)
  282. _PER_FN1(acos)
  283. _PER_FN1(atan)
  284. _PER_FN1(exp)
  285. _PER_FN1(log)
  286. _PER_FN1(floor)
  287. _PER_FN1(ceil)
  288. #undef _PER_FN1
  289. template <class T>
  290. inline auto fract(T const &a) {
  291. return a - floor(a);
  292. }
  293. template <class T>
  294. inline auto ifloor(T const &a) {
  295. return toint(floor(a));
  296. }
  297. template <class To, class T>
  298. inline auto cast(T const &a) {
  299. return _vec_apply([](auto const &x) { return (To)x; }, a);
  300. }
  301. template <class T>
  302. inline auto toint(T const &a) {
  303. return cast<int, T>(a);
  304. }
  305. template <class T>
  306. inline auto tofloat(T const &a) {
  307. return cast<float, T>(a);
  308. }
  309. /* vector math functions */
  310. template <size_t N, class T>
  311. inline bool anytrue(vec<N, T> const &a) {
  312. bool ret = false;
  313. for (size_t i = 0; i < N; i++) {
  314. ret = ret || (bool)a[i];
  315. }
  316. return ret;
  317. }
  318. template <class T>
  319. inline bool anytrue(T const &a) {
  320. return (bool)a;
  321. }
  322. template <size_t N, class T>
  323. inline bool alltrue(vec<N, T> const &a) {
  324. bool ret = true;
  325. for (size_t i = 0; i < N; i++) {
  326. ret = ret && (bool)a[i];
  327. }
  328. return ret;
  329. }
  330. template <class T>
  331. inline bool alltrue(T const &a) {
  332. return (bool)a;
  333. }
  334. inline auto dot(float a, float b) { return a * b; }
  335. template <size_t N, class T, class S>
  336. inline auto dot(vec<N, T> const &a, vec<N, S> const &b) {
  337. std::decay_t<decltype(a[0] * b[0])> res(0);
  338. for (size_t i = 0; i < N; i++) {
  339. res += a[i] * b[i];
  340. }
  341. return res;
  342. }
  343. template <size_t N, class T>
  344. inline auto lengthSquared(vec<N, T> const &a) {
  345. std::decay_t<decltype(a[0])> res(0);
  346. for (size_t i = 0; i < N; i++) {
  347. res += a[i] * a[i];
  348. }
  349. return res;
  350. }
  351. template <size_t N, class T>
  352. inline auto length(vec<N, T> const &a) {
  353. std::decay_t<decltype(a[0])> res(0);
  354. for (size_t i = 0; i < N; i++) {
  355. res += a[i] * a[i];
  356. }
  357. return sqrt(res);
  358. }
  359. template <size_t N, class T>
  360. inline auto distance(vec<N, T> const &a, vec<N, T> const &b) {
  361. return length(b - a);
  362. }
  363. template <size_t N, class T>
  364. inline auto normalize(vec<N, T> const &a) {
  365. return a * (1 / length(a));
  366. }
  367. template <size_t N, class T>
  368. inline auto normalizeSafe(vec<N, T> const &a, T b = std::numeric_limits<T>::epsilon()) {
  369. return a * (1 / max(b, length(a)));
  370. }
  371. template <class T, class S>
  372. inline auto cross(vec<2, T> const &a, vec<2, S> const &b) {
  373. return a[0] * b[1] - b[0] * a[1];
  374. }
  375. template <class T, class S>
  376. inline auto cross(vec<3, T> const &a, vec<3, S> const &b) {
  377. return vec<3, decltype(a[0] * b[0])>(a[1] * b[2] - b[1] * a[2],
  378. a[2] * b[0] - b[2] * a[0],
  379. a[0] * b[1] - b[0] * a[1]);
  380. }
  381. /* generic helper functions */
  382. template <class T, class S, class F>
  383. inline auto mix(T const &a, S const &b, F const &f) {
  384. return a * (1 - f) + b * f;
  385. }
  386. template <class T, class S, class F>
  387. inline auto unmix(T const &a, S const &b, F const &f) {
  388. return (f - a) / (b - a);
  389. }
  390. template <class T, class S, class F>
  391. inline auto clamp(T const &x, S const &a, F const &b) {
  392. return min(max(x, a), b);
  393. }
  394. template <class T, class S>
  395. inline auto minmax(T const &a, S const &b) {
  396. return std::make_pair(min(a, b), max(a, b));
  397. }
  398. template <size_t N, class T, std::enable_if_t<!is_vec_v<T>, bool> = true>
  399. inline auto tovec(T const &x) {
  400. return vec<N, T>(x);
  401. }
  402. template <size_t N, class T>
  403. inline auto tovec(vec<N, T> const &x) { return x; }
  404. /* common type definitions */
  405. using vec2f = vec<2, float>;
  406. using vec2d = vec<2, double>;
  407. using vec2i = vec<2, int32_t>;
  408. using vec2l = vec<2, intptr_t>;
  409. using vec2h = vec<2, int16_t>;
  410. using vec2c = vec<2, int8_t>;
  411. using vec2b = vec<2, bool>;
  412. using vec2I = vec<2, uint32_t>;
  413. using vec2L = vec<2, uintptr_t>;
  414. using vec2Q = vec<2, uint64_t>;
  415. using vec2H = vec<2, uint16_t>;
  416. using vec2C = vec<2, uint8_t>;
  417. using vec3f = vec<3, float>;
  418. using vec3d = vec<3, double>;
  419. using vec3i = vec<3, int32_t>;
  420. using vec3l = vec<3, intptr_t>;
  421. using vec3h = vec<3, int16_t>;
  422. using vec3c = vec<3, int8_t>;
  423. using vec3b = vec<3, bool>;
  424. using vec3I = vec<3, uint32_t>;
  425. using vec3L = vec<3, uintptr_t>;
  426. using vec3Q = vec<3, uint64_t>;
  427. using vec3H = vec<3, uint16_t>;
  428. using vec3C = vec<3, uint8_t>;
  429. using vec4f = vec<4, float>;
  430. using vec4d = vec<4, double>;
  431. using vec4i = vec<4, int32_t>;
  432. using vec4l = vec<4, intptr_t>;
  433. using vec4h = vec<4, int16_t>;
  434. using vec4c = vec<4, int8_t>;
  435. using vec4b = vec<4, bool>;
  436. using vec4I = vec<4, uint32_t>;
  437. using vec4L = vec<4, uintptr_t>;
  438. using vec4Q = vec<4, uint64_t>;
  439. using vec4H = vec<4, uint16_t>;
  440. using vec4C = vec<4, uint8_t>;
  441. }
  442. using namespace _impl_vec;
  443. }
  444. /* specialization for structual-binding */
  445. namespace std {
  446. template <size_t N, class T>
  447. struct tuple_size<::zeno::vec<N, T>> : integral_constant<size_t, N> {
  448. };
  449. template <size_t I, size_t N, class T>
  450. struct tuple_element<I, ::zeno::vec<N, T>> {
  451. using type = enable_if_t<(I < N), T>;
  452. };
  453. template <size_t I, size_t N, class T>
  454. T const &get(::zeno::vec<N, T> const &t) {
  455. return t[I];
  456. }
  457. template <size_t I, size_t N, class T>
  458. T &get(::zeno::vec<N, T> &t) {
  459. return t[I];
  460. }
  461. template <size_t I, size_t N, class T>
  462. T &&get(::zeno::vec<N, T> &&t) {
  463. return std::move(t[I]);
  464. }
  465. }

game-physics-cookbook----Geometry3D.cpp

  1. #include "Geometry3D.h"
  2. #include <cmath>
  3. #include <cfloat>
  4. #include <list>
  5. #define CMP(x, y) \
  6. (fabsf(x - y) <= FLT_EPSILON * fmaxf(1.0f, fmaxf(fabsf(x), fabsf(y))))
  7. float Length(const Line& line) {
  8. return Magnitude(line.start - line.end);
  9. }
  10. float LengthSq(const Line& line) {
  11. return MagnitudeSq(line.start - line.end);
  12. }
  13. Ray FromPoints(const Point& from, const Point& to) {
  14. return Ray(
  15. from,
  16. Normalized(to - from)
  17. );
  18. }
  19. vec3 GetMin(const AABB& aabb) {
  20. vec3 p1 = aabb.position + aabb.size;
  21. vec3 p2 = aabb.position - aabb.size;
  22. return vec3(fminf(p1.x, p2.x), fminf(p1.y, p2.y), fminf(p1.z, p2.z));
  23. }
  24. vec3 GetMax(const AABB& aabb) {
  25. vec3 p1 = aabb.position + aabb.size;
  26. vec3 p2 = aabb.position - aabb.size;
  27. return vec3(fmaxf(p1.x, p2.x), fmaxf(p1.y, p2.y), fmaxf(p1.z, p2.z));
  28. }
  29. AABB FromMinMax(const vec3& min, const vec3& max) {
  30. return AABB((min + max) * 0.5f, (max - min) * 0.5f);
  31. }
  32. float PlaneEquation(const Point& point, const Plane& plane) {
  33. return Dot(point, plane.normal) - plane.distance;
  34. }
  35. float PlaneEquation(const Plane& plane, const Point& point) {
  36. return Dot(point, plane.normal) - plane.distance;
  37. }
  38. std::ostream& operator<<(std::ostream& os, const Line& shape) {
  39. os << "start: (" << shape.start.x << ", " << shape.start.y << ", " << shape.start.z << "), end: (";
  40. os << shape.end.x << ", " << shape.end.y << ", " << shape.end.z << ")";
  41. return os;
  42. }
  43. std::ostream& operator<<(std::ostream& os, const Ray& shape) {
  44. os << "origin: (" << shape.origin.x << ", " << shape.origin.y << ", " << shape.origin.z << "), ";
  45. os << "direction: (" << shape.direction.x << ", " << shape.direction.y << ", " << shape.direction.z << ")";
  46. return os;
  47. }
  48. std::ostream& operator<<(std::ostream& os, const Sphere& shape) {
  49. os << "position:" << shape.position.x << ", " << shape.position.y << ", " << shape.position.z << "), ";
  50. os << "radius: " << shape.radius;
  51. return os;
  52. }
  53. std::ostream& operator<<(std::ostream& os, const AABB& shape) {
  54. vec3 min = GetMin(shape);
  55. vec3 max = GetMax(shape);
  56. os << "min: (" << min.x << ", " << min.y << ", " << min.z << "), ";
  57. os << "max: (" << max.x << ", " << max.y << ", " << max.z << ")";
  58. return os;
  59. }
  60. std::ostream& operator<<(std::ostream& os, const Plane& shape) {
  61. os << "normal: (" << shape.normal.x << ", " << shape.normal.y << ", " << shape.normal.z << "), ";
  62. os << "distance: " << shape.distance;
  63. return os;
  64. }
  65. std::ostream& operator<<(std::ostream& os, const Triangle& shape) {
  66. os << "a: (" << shape.a.x << ", " << shape.a.y << ", " << shape.a.z << "), ";
  67. os << "b: (" << shape.b.x << ", " << shape.b.y << ", " << shape.b.z << "), ";
  68. os << "c: (" << shape.c.x << ", " << shape.c.y << ", " << shape.c.z << ")";
  69. return os;
  70. }
  71. std::ostream& operator<<(std::ostream& os, const OBB& shape) {
  72. os << "position:" << shape.position.x << ", " << shape.position.y << ", " << shape.position.z << "), ";
  73. os << "size:" << shape.size.x << ", " << shape.size.y << ", " << shape.size.z << "), ";
  74. os << "x basis:" << shape.orientation._11 << ", " << shape.orientation._21 << ", " << shape.orientation._31 << "), ";
  75. os << "y basis:" << shape.orientation._12 << ", " << shape.orientation._22 << ", " << shape.orientation._32 << "), ";
  76. os << "z basis:" << shape.orientation._13 << ", " << shape.orientation._23 << ", " << shape.orientation._33 << ")";
  77. return os;
  78. }
  79. bool PointInSphere(const Point& point, const Sphere& sphere) {
  80. return MagnitudeSq(point - sphere.position) < sphere.radius * sphere.radius;
  81. }
  82. bool PointOnPlane(const Point& point, const Plane& plane) {
  83. // This should probably use an epsilon!
  84. //return Dot(point, plane.normal) - plane.distance == 0.0f;
  85. return CMP(Dot(point, plane.normal) - plane.distance, 0.0f);
  86. }
  87. bool PointInAABB(const Point& point, const AABB& aabb) {
  88. Point min = GetMin(aabb);
  89. Point max = GetMax(aabb);
  90. if (point.x < min.x || point.y < min.y || point.z < min.z) {
  91. return false;
  92. }
  93. if (point.x > max.x || point.y > max.y || point.z > max.z) {
  94. return false;
  95. }
  96. return true;
  97. }
  98. bool PointInOBB(const Point& point, const OBB& obb) {
  99. vec3 dir = point - obb.position;
  100. for (int i = 0; i < 3; ++i) {
  101. const float* orientation = &obb.orientation.asArray[i * 3];
  102. vec3 axis(orientation[0], orientation[1], orientation[2]);
  103. float distance = Dot(dir, axis);
  104. if (distance > obb.size.asArray[i]) {
  105. return false;
  106. }
  107. if (distance < -obb.size.asArray[i]) {
  108. return false;
  109. }
  110. }
  111. return true;
  112. }
  113. Point ClosestPoint(const Sphere& sphere, const Point& point) {
  114. vec3 sphereToPoint = point - sphere.position;
  115. Normalize(sphereToPoint);
  116. sphereToPoint = sphereToPoint * sphere.radius;
  117. return sphereToPoint + sphere.position;
  118. }
  119. Point ClosestPoint(const AABB& aabb, const Point& point) {
  120. Point result = point;
  121. Point min = GetMin(aabb);
  122. Point max = GetMax(aabb);
  123. result.x = (result.x < min.x) ? min.x : result.x;
  124. result.y = (result.y < min.x) ? min.y : result.y;
  125. result.z = (result.z < min.x) ? min.z : result.z;
  126. result.x = (result.x > max.x) ? max.x : result.x;
  127. result.y = (result.y > max.x) ? max.y : result.y;
  128. result.z = (result.z > max.x) ? max.z : result.z;
  129. return result;
  130. }
  131. Point ClosestPoint(const OBB& obb, const Point& point) {
  132. Point result = obb.position;
  133. vec3 dir = point - obb.position;
  134. for (int i = 0; i < 3; ++i) {
  135. const float* orientation = &obb.orientation.asArray[i * 3];
  136. vec3 axis(orientation[0], orientation[1], orientation[2]);
  137. float distance = Dot(dir, axis);
  138. if (distance > obb.size.asArray[i]) {
  139. distance = obb.size.asArray[i];
  140. }
  141. if (distance < -obb.size.asArray[i]) {
  142. distance = -obb.size.asArray[i];
  143. }
  144. result = result + (axis * distance);
  145. }
  146. return result;
  147. }
  148. Point ClosestPoint(const Plane& plane, const Point& point) {
  149. // This works assuming plane.Normal is normalized, which it should be
  150. float distance = Dot(plane.normal, point) - plane.distance;
  151. // If the plane normal wasn't normalized, we'd need this:
  152. // distance = distance / DOT(plane.Normal, plane.Normal);
  153. return point - plane.normal * distance;
  154. }
  155. bool PointOnLine(const Point& point, const Line& line) {
  156. Point closest = ClosestPoint(line, point);
  157. float distanceSq = MagnitudeSq(closest - point);
  158. return CMP(distanceSq, 0.0f);
  159. }
  160. Point ClosestPoint(const Line& line, const Point& point) {
  161. vec3 lVec = line.end - line.start; // Line Vector
  162. // Project "point" onto the "Line Vector", computing:
  163. // closest(t) = start + t * (end - start)
  164. // T is how far along the line the projected point is
  165. float t = Dot(point - line.start, lVec) / Dot(lVec, lVec);
  166. // Clamp t to the 0 to 1 range
  167. t = fmaxf(t, 0.0f);
  168. t = fminf(t, 1.0f);
  169. // Return projected position of t
  170. return line.start + lVec * t;
  171. }
  172. bool PointOnRay(const Point& point, const Ray& ray) {
  173. if (point == ray.origin) {
  174. return true;
  175. }
  176. vec3 norm = point - ray.origin;
  177. Normalize(norm);
  178. float diff = Dot(norm, ray.direction); // Direction is normalized
  179. // If BOTH vectors point in the same direction, diff should be 1
  180. return CMP(diff, 1.0f);
  181. }
  182. Point ClosestPoint(const Ray& ray, const Point& point) {
  183. // Project point onto ray,
  184. float t = Dot(point - ray.origin, ray.direction);
  185. // Not needed if direction is normalized!
  186. // t /= Dot(ray.direction, ray.direction);
  187. // We only want to clamp t in the positive direction.
  188. // The ray extends infinatley in this direction!
  189. t = fmaxf(t, 0.0f);
  190. // Compute the projected position from the clamped t
  191. // Notice we multiply r.Normal by t, not AB.
  192. // This is becuase we want the ray in the direction
  193. // of the normal, which technically the line segment is
  194. // but this is much more explicit and easy to read.
  195. return Point(ray.origin + ray.direction * t);
  196. }
  197. bool PointInPlane(const Point& point, const Plane& plane) {
  198. return PointOnPlane(point, plane);
  199. }
  200. bool PointInLine(const Point& point, const Line& line) {
  201. return PointOnLine(point, line);
  202. }
  203. bool PointInRay(const Point& point, const Ray& ray) {
  204. return PointOnRay(point, ray);
  205. }
  206. bool ContainsPoint(const Sphere& sphere, const Point& point) {
  207. return PointInSphere(point, sphere);
  208. }
  209. bool ContainsPoint(const Point& point, const Sphere& sphere) {
  210. return PointInSphere(point, sphere);
  211. }
  212. bool ContainsPoint(const AABB& aabb, const Point& point) {
  213. return PointInAABB(point, aabb);
  214. }
  215. bool ContainsPoint(const Point& point, const AABB& aabb) {
  216. return PointInAABB(point, aabb);
  217. }
  218. bool ContainsPoint(const Point& point, const OBB& obb) {
  219. return PointInOBB(point, obb);
  220. }
  221. bool ContainsPoint(const OBB& obb, const Point& point) {
  222. return PointInOBB(point, obb);
  223. }
  224. bool ContainsPoint(const Point& point, const Plane& plane) {
  225. return PointOnPlane(point, plane);
  226. }
  227. bool ContainsPoint(const Plane& plane, const Point& point) {
  228. return PointOnPlane(point, plane);
  229. }
  230. bool ContainsPoint(const Point& point, const Line& line) {
  231. return PointOnLine(point, line);
  232. }
  233. bool ContainsPoint(const Line& line, const Point& point) {
  234. return PointOnLine(point, line);
  235. }
  236. bool ContainsPoint(const Point& point, const Ray& ray) {
  237. return PointOnRay(point, ray);
  238. }
  239. bool ContainsPoint(const Ray& ray, const Point& point) {
  240. return PointOnRay(point, ray);
  241. }
  242. Point ClosestPoint(const Point& point, const Sphere& sphere) {
  243. return ClosestPoint(sphere, point);
  244. }
  245. Point ClosestPoint(const Point& point, const AABB& aabb) {
  246. return ClosestPoint(aabb, point);
  247. }
  248. Point ClosestPoint(const Point& point, const OBB& obb) {
  249. return ClosestPoint(obb, point);
  250. }
  251. Point ClosestPoint(const Point& point, const Plane& plane) {
  252. return ClosestPoint(plane, point);
  253. }
  254. Point ClosestPoint(const Point& point, const Line& line) {
  255. return ClosestPoint(line, point);
  256. }
  257. Point ClosestPoint(const Point& point, const Ray& ray) {
  258. return ClosestPoint(ray, point);
  259. }
  260. Point ClosestPoint(const Point& p, const Triangle& t) {
  261. return ClosestPoint(t, p);
  262. }
  263. bool SphereSphere(const Sphere& s1, const Sphere& s2) {
  264. float radiiSum = s1.radius + s2.radius;
  265. float sqDistance = MagnitudeSq(s1.position - s2.position);
  266. return sqDistance < radiiSum * radiiSum;
  267. }
  268. bool SphereAABB(const Sphere& sphere, const AABB& aabb) {
  269. Point closestPoint = ClosestPoint(aabb, sphere.position);
  270. float distSq = MagnitudeSq(sphere.position - closestPoint);
  271. float radiusSq = sphere.radius * sphere.radius;
  272. return distSq < radiusSq;
  273. }
  274. bool SphereOBB(const Sphere& sphere, const OBB& obb) {
  275. Point closestPoint = ClosestPoint(obb, sphere.position);
  276. float distSq = MagnitudeSq(sphere.position - closestPoint);
  277. float radiusSq = sphere.radius * sphere.radius;
  278. return distSq < radiusSq;
  279. }
  280. bool SpherePlane(const Sphere& sphere, const Plane& plane) {
  281. Point closestPoint = ClosestPoint(plane, sphere.position);
  282. float distSq = MagnitudeSq(sphere.position - closestPoint);
  283. float radiusSq = sphere.radius * sphere.radius;
  284. return distSq < radiusSq;
  285. }
  286. bool AABBAABB(const AABB& aabb1, const AABB& aabb2) {
  287. Point aMin = GetMin(aabb1);
  288. Point aMax = GetMax(aabb1);
  289. Point bMin = GetMin(aabb2);
  290. Point bMax = GetMax(aabb2);
  291. return (aMin.x <= bMax.x && aMax.x >= bMin.x) &&
  292. (aMin.y <= bMax.y && aMax.y >= bMin.y) &&
  293. (aMin.z <= bMax.z && aMax.z >= bMin.z);
  294. }
  295. bool AABBOBB(const AABB& aabb, const OBB& obb) {
  296. const float* o = obb.orientation.asArray;
  297. vec3 test[15] = {
  298. vec3(1, 0, 0), // AABB axis 1
  299. vec3(0, 1, 0), // AABB axis 2
  300. vec3(0, 0, 1), // AABB axis 3
  301. vec3(o[0], o[1], o[2]),
  302. vec3(o[3], o[4], o[5]),
  303. vec3(o[6], o[7], o[8])
  304. };
  305. for (int i = 0; i < 3; ++i) { // Fill out rest of axis
  306. test[6 + i * 3 + 0] = Cross(test[i], test[0]);
  307. test[6 + i * 3 + 1] = Cross(test[i], test[1]);
  308. test[6 + i * 3 + 2] = Cross(test[i], test[2]);
  309. }
  310. for (int i = 0; i < 15; ++i) {
  311. if (!OverlapOnAxis(aabb, obb, test[i])) {
  312. return false; // Seperating axis found
  313. }
  314. }
  315. return true; // Seperating axis not found
  316. }
  317. bool OverlapOnAxis(const AABB& aabb, const OBB& obb, const vec3& axis) {
  318. Interval a = GetInterval(aabb, axis);
  319. Interval b = GetInterval(obb, axis);
  320. return ((b.min <= a.max) && (a.min <= b.max));
  321. }
  322. bool OverlapOnAxis(const OBB& obb1, const OBB& obb2, const vec3& axis) {
  323. Interval a = GetInterval(obb1, axis);
  324. Interval b = GetInterval(obb1, axis);
  325. return ((b.min <= a.max) && (a.min <= b.max));
  326. }
  327. bool OverlapOnAxis(const AABB& aabb, const Triangle& triangle, const vec3& axis) {
  328. Interval a = GetInterval(aabb, axis);
  329. Interval b = GetInterval(triangle, axis);
  330. return ((b.min <= a.max) && (a.min <= b.max));
  331. }
  332. bool OverlapOnAxis(const OBB& obb, const Triangle& triangle, const vec3& axis) {
  333. Interval a = GetInterval(obb, axis);
  334. Interval b = GetInterval(triangle, axis);
  335. return ((b.min <= a.max) && (a.min <= b.max));
  336. }
  337. bool OverlapOnAxis(const Triangle& t1, const Triangle& t2, const vec3& axis) {
  338. Interval a = GetInterval(t1, axis);
  339. Interval b = GetInterval(t2, axis);
  340. return ((b.min <= a.max) && (a.min <= b.max));
  341. }
  342. Interval GetInterval(const Triangle& triangle, const vec3& axis) {
  343. Interval result;
  344. result.min = Dot(axis, triangle.points[0]);
  345. result.max = result.min;
  346. for (int i = 1; i < 3; ++i) {
  347. float value = Dot(axis, triangle.points[i]);
  348. result.min = fminf(result.min, value);
  349. result.max = fmaxf(result.max, value);
  350. }
  351. return result;
  352. }
  353. Interval GetInterval(const OBB& obb, const vec3& axis) {
  354. vec3 vertex[8];
  355. vec3 C = obb.position; // OBB Center
  356. vec3 E = obb.size; // OBB Extents
  357. const float* o = obb.orientation.asArray;
  358. vec3 A[] = { // OBB Axis
  359. vec3(o[0], o[1], o[2]),
  360. vec3(o[3], o[4], o[5]),
  361. vec3(o[6], o[7], o[8]),
  362. };
  363. vertex[0] = C + A[0] * E[0] + A[1] * E[1] + A[2] * E[2];
  364. vertex[1] = C - A[0] * E[0] + A[1] * E[1] + A[2] * E[2];
  365. vertex[2] = C + A[0] * E[0] - A[1] * E[1] + A[2] * E[2];
  366. vertex[3] = C + A[0] * E[0] + A[1] * E[1] - A[2] * E[2];
  367. vertex[4] = C - A[0] * E[0] - A[1] * E[1] - A[2] * E[2];
  368. vertex[5] = C + A[0] * E[0] - A[1] * E[1] - A[2] * E[2];
  369. vertex[6] = C - A[0] * E[0] + A[1] * E[1] - A[2] * E[2];
  370. vertex[7] = C - A[0] * E[0] - A[1] * E[1] + A[2] * E[2];
  371. Interval result;
  372. result.min = result.max = Dot(axis, vertex[0]);
  373. for (int i = 1; i < 8; ++i) {
  374. float projection = Dot(axis, vertex[i]);
  375. result.min = (projection < result.min) ? projection : result.min;
  376. result.max = (projection > result.max) ? projection : result.max;
  377. }
  378. return result;
  379. }
  380. Interval GetInterval(const AABB& aabb, const vec3& axis) {
  381. vec3 i = GetMin(aabb);
  382. vec3 a = GetMax(aabb);
  383. vec3 vertex[8] = {
  384. vec3(i.x, a.y, a.z),
  385. vec3(i.x, a.y, i.z),
  386. vec3(i.x, i.y, a.z),
  387. vec3(i.x, i.y, i.z),
  388. vec3(a.x, a.y, a.z),
  389. vec3(a.x, a.y, i.z),
  390. vec3(a.x, i.y, a.z),
  391. vec3(a.x, i.y, i.z)
  392. };
  393. Interval result;
  394. result.min = result.max = Dot(axis, vertex[0]);
  395. for (int i = 1; i < 8; ++i) {
  396. float projection = Dot(axis, vertex[i]);
  397. result.min = (projection < result.min) ? projection : result.min;
  398. result.max = (projection > result.max) ? projection : result.max;
  399. }
  400. return result;
  401. }
  402. bool AABBPlane(const AABB& aabb, const Plane& plane) {
  403. // Project the half extents of the AABB onto the plane normal
  404. float pLen =aabb.size.x * fabsf(plane.normal.x) +
  405. aabb.size.y * fabsf(plane.normal.y) +
  406. aabb.size.z * fabsf(plane.normal.z);
  407. // Find the distance from the center of the AABB to the plane
  408. float dist = Dot(plane.normal, aabb.position) - plane.distance;
  409. // Intersection occurs if the distance falls within the projected side
  410. return fabsf(dist) <= pLen;
  411. }
  412. bool OBBOBB(const OBB& obb1, const OBB& obb2) {
  413. const float* o1 = obb1.orientation.asArray;
  414. const float* o2 = obb2.orientation.asArray;
  415. vec3 test[15] = {
  416. vec3(o1[0], o1[1], o1[2]),
  417. vec3(o1[3], o1[4], o1[5]),
  418. vec3(o1[6], o1[7], o1[8]),
  419. vec3(o2[0], o2[1], o2[2]),
  420. vec3(o2[3], o2[4], o2[5]),
  421. vec3(o2[6], o2[7], o2[8])
  422. };
  423. for (int i = 0; i < 3; ++i) { // Fill out rest of axis
  424. test[6 + i * 3 + 0] = Cross(test[i], test[0]);
  425. test[6 + i * 3 + 1] = Cross(test[i], test[1]);
  426. test[6 + i * 3 + 2] = Cross(test[i], test[2]);
  427. }
  428. for (int i = 0; i < 15; ++i) {
  429. if (!OverlapOnAxis(obb1, obb2, test[i])) {
  430. return false; // Seperating axis found
  431. }
  432. }
  433. return true; // Seperating axis not found
  434. }
  435. bool OBBPlane(const OBB& obb, const Plane& plane) {
  436. // Local variables for readability only
  437. const float* o = obb.orientation.asArray;
  438. vec3 rot[] = { // rotation / orientation
  439. vec3(o[0], o[1], o[2]),
  440. vec3(o[3], o[4], o[5]),
  441. vec3(o[6], o[7], o[8]),
  442. };
  443. vec3 normal = plane.normal;
  444. // Project the half extents of the AABB onto the plane normal
  445. float pLen =obb.size.x * fabsf(Dot(normal, rot[0])) +
  446. obb.size.y * fabsf(Dot(normal, rot[1])) +
  447. obb.size.z * fabsf(Dot(normal, rot[2]));
  448. // Find the distance from the center of the OBB to the plane
  449. float dist = Dot(plane.normal, obb.position) - plane.distance;
  450. // Intersection occurs if the distance falls within the projected side
  451. return fabsf(dist) <= pLen;
  452. }
  453. bool PlanePlane(const Plane& plane1, const Plane& plane2) {
  454. // Compute direction of intersection line
  455. vec3 d = Cross(plane1.normal, plane2.normal);
  456. // Check the length of the direction line
  457. // if the length is 0, no intersection happened
  458. return !(CMP(Dot(d, d), 0));
  459. // We could have used the dot product here, instead of the cross product
  460. }
  461. bool Raycast(const Sphere& sphere, const Ray& ray, RaycastResult* outResult) {
  462. ResetRaycastResult(outResult);
  463. vec3 e = sphere.position - ray.origin;
  464. float rSq = sphere.radius * sphere.radius;
  465. float eSq = MagnitudeSq(e);
  466. float a = Dot(e, ray.direction); // ray.direction is assumed to be normalized
  467. float bSq = /*sqrtf(*/eSq - (a * a)/*)*/;
  468. float f = sqrt(fabsf((rSq)- /*(b * b)*/bSq));
  469. // Assume normal intersection!
  470. float t = a - f;
  471. // No collision has happened
  472. if (rSq - (eSq - a * a) < 0.0f) {
  473. return false;
  474. }
  475. // Ray starts inside the sphere
  476. else if (eSq < rSq) {
  477. // Just reverse direction
  478. t = a + f;
  479. }
  480. if (outResult != 0) {
  481. outResult->t = t;
  482. outResult->hit = true;
  483. outResult->point = ray.origin + ray.direction * t;
  484. outResult->normal = Normalized(outResult->point - sphere.position);
  485. }
  486. return true;
  487. }
  488. bool Raycast(const OBB& obb, const Ray& ray, RaycastResult* outResult) {
  489. ResetRaycastResult(outResult);
  490. const float* o = obb.orientation.asArray;
  491. const float* size = obb.size.asArray;
  492. vec3 p = obb.position - ray.origin;
  493. vec3 X(o[0], o[1], o[2]);
  494. vec3 Y(o[3], o[4], o[5]);
  495. vec3 Z(o[6], o[7], o[8]);
  496. vec3 f(
  497. Dot(X, ray.direction),
  498. Dot(Y, ray.direction),
  499. Dot(Z, ray.direction)
  500. );
  501. vec3 e(
  502. Dot(X, p),
  503. Dot(Y, p),
  504. Dot(Z, p)
  505. );
  506. #if 1
  507. float t[6] = { 0, 0, 0, 0, 0, 0 };
  508. for (int i = 0; i < 3; ++i) {
  509. if (CMP(f[i], 0)) {
  510. if (-e[i] - size[i] > 0 || -e[i] + size[i] < 0) {
  511. return false;
  512. }
  513. f[i] = 0.00001f; // Avoid div by 0!
  514. }
  515. t[i * 2 + 0] = (e[i] + size[i]) / f[i]; // tmin[x, y, z]
  516. t[i * 2 + 1] = (e[i] - size[i]) / f[i]; // tmax[x, y, z]
  517. }
  518. float tmin = fmaxf(fmaxf(fminf(t[0], t[1]), fminf(t[2], t[3])), fminf(t[4], t[5]));
  519. float tmax = fminf(fminf(fmaxf(t[0], t[1]), fmaxf(t[2], t[3])), fmaxf(t[4], t[5]));
  520. #else
  521. // The above loop simplifies the below if statements
  522. // this is done to make sure the sample fits into the book
  523. if (CMP(f.x, 0)) {
  524. if (-e.x - obb.size.x > 0 || -e.x + obb.size.x < 0) {
  525. return -1;
  526. }
  527. f.x = 0.00001f; // Avoid div by 0!
  528. }
  529. else if (CMP(f.y, 0)) {
  530. if (-e.y - obb.size.y > 0 || -e.y + obb.size.y < 0) {
  531. return -1;
  532. }
  533. f.y = 0.00001f; // Avoid div by 0!
  534. }
  535. else if (CMP(f.z, 0)) {
  536. if (-e.z - obb.size.z > 0 || -e.z + obb.size.z < 0) {
  537. return -1;
  538. }
  539. f.z = 0.00001f; // Avoid div by 0!
  540. }
  541. float t1 = (e.x + obb.size.x) / f.x;
  542. float t2 = (e.x - obb.size.x) / f.x;
  543. float t3 = (e.y + obb.size.y) / f.y;
  544. float t4 = (e.y - obb.size.y) / f.y;
  545. float t5 = (e.z + obb.size.z) / f.z;
  546. float t6 = (e.z - obb.size.z) / f.z;
  547. float tmin = fmaxf(fmaxf(fminf(t1, t2), fminf(t3, t4)), fminf(t5, t6));
  548. float tmax = fminf(fminf(fmaxf(t1, t2), fmaxf(t3, t4)), fmaxf(t5, t6));
  549. #endif
  550. // if tmax < 0, ray is intersecting AABB
  551. // but entire AABB is behing it's origin
  552. if (tmax < 0) {
  553. return false;
  554. }
  555. // if tmin > tmax, ray doesn't intersect AABB
  556. if (tmin > tmax) {
  557. return false;
  558. }
  559. // If tmin is < 0, tmax is closer
  560. float t_result = tmin;
  561. if (tmin < 0.0f) {
  562. t_result = tmax;
  563. }
  564. if (outResult != 0) {
  565. outResult->hit = true;
  566. outResult->t = t_result;
  567. outResult->point = ray.origin + ray.direction * t_result;
  568. vec3 normals[] = {
  569. X, // +x
  570. X * -1.0f, // -x
  571. Y, // +y
  572. Y * -1.0f, // -y
  573. Z, // +z
  574. Z * -1.0f // -z
  575. };
  576. for (int i = 0; i < 6; ++i) {
  577. if (CMP(t_result, t[i])) {
  578. outResult->normal = Normalized(normals[i]);
  579. }
  580. }
  581. }
  582. return true;
  583. }
  584. void ResetRaycastResult(RaycastResult* outResult) {
  585. if (outResult != 0) {
  586. outResult->t = -1;
  587. outResult->hit = false;
  588. outResult->normal = vec3(0, 0, 1);
  589. outResult->point = vec3(0, 0, 0);
  590. }
  591. }
  592. bool Raycast(const AABB& aabb, const Ray& ray, RaycastResult* outResult) {
  593. ResetRaycastResult(outResult);
  594. vec3 min = GetMin(aabb);
  595. vec3 max = GetMax(aabb);
  596. // Any component of direction could be 0!
  597. // Address this by using a small number, close to
  598. // 0 in case any of directions components are 0
  599. float t1 = (min.x - ray.origin.x) / (CMP(ray.direction.x, 0.0f) ? 0.00001f : ray.direction.x);
  600. float t2 = (max.x - ray.origin.x) / (CMP(ray.direction.x, 0.0f) ? 0.00001f : ray.direction.x);
  601. float t3 = (min.y - ray.origin.y) / (CMP(ray.direction.y, 0.0f) ? 0.00001f : ray.direction.y);
  602. float t4 = (max.y - ray.origin.y) / (CMP(ray.direction.y, 0.0f) ? 0.00001f : ray.direction.y);
  603. float t5 = (min.z - ray.origin.z) / (CMP(ray.direction.z, 0.0f) ? 0.00001f : ray.direction.z);
  604. float t6 = (max.z - ray.origin.z) / (CMP(ray.direction.z, 0.0f) ? 0.00001f : ray.direction.z);
  605. float tmin = fmaxf(fmaxf(fminf(t1, t2), fminf(t3, t4)), fminf(t5, t6));
  606. float tmax = fminf(fminf(fmaxf(t1, t2), fmaxf(t3, t4)), fmaxf(t5, t6));
  607. // if tmax < 0, ray is intersecting AABB
  608. // but entire AABB is behing it's origin
  609. if (tmax < 0) {
  610. return false;
  611. }
  612. // if tmin > tmax, ray doesn't intersect AABB
  613. if (tmin > tmax) {
  614. return false;
  615. }
  616. float t_result = tmin;
  617. // If tmin is < 0, tmax is closer
  618. if (tmin < 0.0f) {
  619. t_result = tmax;
  620. }
  621. if (outResult != 0) {
  622. outResult->t = t_result;
  623. outResult->hit = true;
  624. outResult->point = ray.origin + ray.direction * t_result;
  625. vec3 normals[] = {
  626. vec3(-1, 0, 0),
  627. vec3(1, 0, 0),
  628. vec3(0, -1, 0),
  629. vec3(0, 1, 0),
  630. vec3(0, 0, -1),
  631. vec3(0, 0, 1)
  632. };
  633. float t[] = { t1, t2, t3, t4, t5, t6 };
  634. for (int i = 0; i < 6; ++i) {
  635. if (CMP(t_result, t[i])) {
  636. outResult->normal = normals[i];
  637. }
  638. }
  639. }
  640. return true;
  641. }
  642. bool Raycast(const Plane& plane, const Ray& ray, RaycastResult* outResult) {
  643. ResetRaycastResult(outResult);
  644. float nd = Dot(ray.direction, plane.normal);
  645. float pn = Dot(ray.origin, plane.normal);
  646. // nd must be negative, and not 0
  647. // if nd is positive, the ray and plane normals
  648. // point in the same direction. No intersection.
  649. if (nd >= 0.0f) {
  650. return false;
  651. }
  652. float t = (plane.distance - pn) / nd;
  653. // t must be positive
  654. if (t >= 0.0f) {
  655. if (outResult != 0) {
  656. outResult->t = t;
  657. outResult->hit = true;
  658. outResult->point = ray.origin + ray.direction * t;
  659. outResult->normal = Normalized(plane.normal);
  660. }
  661. return true;
  662. }
  663. return false;
  664. }
  665. bool Linetest(const Sphere& sphere, const Line& line) {
  666. Point closest = ClosestPoint(line, sphere.position);
  667. float distSq = MagnitudeSq(sphere.position - closest);
  668. return distSq <= (sphere.radius * sphere.radius);
  669. }
  670. bool Linetest(const Plane& plane, const Line& line) {
  671. vec3 ab = line.end - line.start;
  672. float nA = Dot(plane.normal, line.start);
  673. float nAB = Dot(plane.normal, ab);
  674. if (CMP(nAB, 0)) {
  675. return false;
  676. }
  677. float t = (plane.distance - nA) / nAB;
  678. return t >= 0.0f && t <= 1.0f;
  679. }
  680. bool Linetest(const AABB& aabb, const Line& line) {
  681. Ray ray;
  682. ray.origin = line.start;
  683. ray.direction = Normalized(line.end - line.start);
  684. RaycastResult raycast;
  685. if (!Raycast(aabb, ray, &raycast)) {
  686. return false;
  687. }
  688. float t = raycast.t;
  689. return t >= 0 && t * t <= LengthSq(line);
  690. }
  691. bool Linetest(const OBB& obb, const Line& line) {
  692. if (MagnitudeSq(line.end - line.start) < 0.0000001f) {
  693. return PointInOBB(line.start, obb);
  694. }
  695. Ray ray;
  696. ray.origin = line.start;
  697. ray.direction = Normalized(line.end - line.start);
  698. RaycastResult result;
  699. if (!Raycast(obb, ray, &result)) {
  700. return false;
  701. }
  702. float t = result.t;
  703. return t >= 0 && t * t <= LengthSq(line);
  704. }
  705. bool Raycast(const Ray& ray, const Sphere& sphere, RaycastResult* outResult) {
  706. return Raycast(sphere, ray, outResult);
  707. }
  708. bool Raycast(const Ray& ray, const AABB& aabb, RaycastResult* outResult) {
  709. return Raycast(aabb, ray, outResult);
  710. }
  711. bool Raycast(const Ray& ray, const OBB& obb, RaycastResult* outResult) {
  712. return Raycast(obb, ray, outResult);
  713. }
  714. bool Raycast(const Ray& ray, const Plane& plane, RaycastResult* outResult) {
  715. return Raycast(plane, ray, outResult);
  716. }
  717. bool Linetest(const Line& line, const Sphere& sphere) {
  718. return Linetest(sphere, line);
  719. }
  720. bool Linetest(const Line& line, const AABB& aabb) {
  721. return Linetest(aabb, line);
  722. }
  723. bool Linetest(const Line& line, const OBB& obb) {
  724. return Linetest(obb, line);
  725. }
  726. bool Linetest(const Line& line, const Plane& plane) {
  727. return Linetest(plane, line);
  728. }
  729. vec3 Centroid(const Triangle& t) {
  730. vec3 result;
  731. result.x = t.a.x + t.b.x + t.c.x;
  732. result.y = t.a.y + t.b.y + t.c.y;
  733. result.z = t.a.z + t.b.z + t.c.z;
  734. result = result * (1.0f / 3.0f);
  735. return result;
  736. }
  737. bool PointInTriangle(const Point& p, const Triangle& t) {
  738. // Move the triangle so that the point is
  739. // now at the origin of the triangle
  740. vec3 a = t.a - p;
  741. vec3 b = t.b - p;
  742. vec3 c = t.c - p;
  743. // The point should be moved too, so they are both
  744. // relative, but because we don't use p in the
  745. // equation anymore, we don't need it!
  746. // p -= p; // This would just equal the zero vector!
  747. vec3 normPBC = Cross(b, c); // Normal of PBC (u)
  748. vec3 normPCA = Cross(c, a); // Normal of PCA (v)
  749. vec3 normPAB = Cross(a, b); // Normal of PAB (w)
  750. // Test to see if the normals are facing
  751. // the same direction, return false if not
  752. if (Dot(normPBC, normPCA) < 0.0f) {
  753. return false;
  754. }
  755. else if (Dot(normPBC, normPAB) < 0.0f) {
  756. return false;
  757. }
  758. // All normals facing the same way, return true
  759. return true;
  760. }
  761. vec3 BarycentricOptimized(const Point& p, const Triangle& t) {
  762. vec3 v0 = t.b - t.a;
  763. vec3 v1 = t.c - t.a;
  764. vec3 v2 = p - t.a;
  765. float d00 = Dot(v0, v0);
  766. float d01 = Dot(v0, v1);
  767. float d11 = Dot(v1, v1);
  768. float d20 = Dot(v2, v0);
  769. float d21 = Dot(v2, v1);
  770. float denom = d00 * d11 - d01 * d01;
  771. if (CMP(denom, 0.0f)) {
  772. return vec3();
  773. }
  774. vec3 result;
  775. result.y = (d11 * d20 - d01 * d21) / denom;
  776. result.z = (d00 * d21 - d01 * d20) / denom;
  777. result.x = 1.0f - result.y - result.z;
  778. return result;
  779. }
  780. vec3 Barycentric(const Point& p, const Triangle& t) {
  781. vec3 ap = p - t.a;
  782. vec3 bp = p - t.b;
  783. vec3 cp = p - t.c;
  784. vec3 ab = t.b - t.a;
  785. vec3 ac = t.c - t.a;
  786. vec3 bc = t.c - t.b;
  787. vec3 cb = t.b - t.c;
  788. vec3 ca = t.a - t.c;
  789. vec3 v = ab - Project(ab, cb);
  790. float a = 1.0f - (Dot(v, ap) / Dot(v, ab));
  791. v = bc - Project(bc, ac);
  792. float b = 1.0f - (Dot(v, bp) / Dot(v, bc));
  793. v = ca - Project(ca, ab);
  794. float c = 1.0f - (Dot(v, cp) / Dot(v, ca));
  795. return vec3(a, b, c);
  796. }
  797. Plane FromTriangle(const Triangle& t) {
  798. Plane result;
  799. result.normal = Normalized(Cross(t.b - t.a, t.c - t.a));
  800. result.distance = Dot(result.normal, t.a);
  801. return result;
  802. }
  803. Point ClosestPoint(const Triangle& t, const Point& p) {
  804. Plane plane = FromTriangle(t);
  805. Point closest = ClosestPoint(plane, p);
  806. // Closest point was inside triangle
  807. if (PointInTriangle(closest, t)) {
  808. return closest;
  809. }
  810. Point c1 = ClosestPoint(Line(t.a, t.b), closest); // Line AB
  811. Point c2 = ClosestPoint(Line(t.b, t.c), closest); // Line BC
  812. Point c3 = ClosestPoint(Line(t.c, t.a), closest); // Line CA
  813. float magSq1 = MagnitudeSq(closest - c1);
  814. float magSq2 = MagnitudeSq(closest - c2);
  815. float magSq3 = MagnitudeSq(closest - c3);
  816. if (magSq1 < magSq2 && magSq1 < magSq3) {
  817. return c1;
  818. }
  819. else if (magSq2 < magSq1 && magSq2 < magSq3) {
  820. return c2;
  821. }
  822. return c3;
  823. }
  824. bool TriangleSphere(const Triangle& t, const Sphere& s) {
  825. Point closest = ClosestPoint(t, s.position);
  826. float magSq = MagnitudeSq(closest - s.position);
  827. return magSq <= s.radius * s.radius;
  828. }
  829. bool TriangleAABB(const Triangle& t, const AABB& a) {
  830. // Compute the edge vectors of the triangle (ABC)
  831. vec3 f0 = t.b - t.a;
  832. vec3 f1 = t.c - t.b;
  833. vec3 f2 = t.a - t.c;
  834. // Compute the face normals of the AABB
  835. vec3 u0(1.0f, 0.0f, 0.0f);
  836. vec3 u1(0.0f, 1.0f, 0.0f);
  837. vec3 u2(0.0f, 0.0f, 1.0f);
  838. vec3 test[13] = {
  839. // 3 Normals of AABB
  840. u0, // AABB Axis 1
  841. u1, // AABB Axis 2
  842. u2, // AABB Axis 3
  843. // 1 Normal of the Triangle
  844. Cross(f0, f1),
  845. // 9 Axis, cross products of all edges
  846. Cross(u0, f0),
  847. Cross(u0, f1),
  848. Cross(u0, f2),
  849. Cross(u1, f0),
  850. Cross(u1, f1),
  851. Cross(u1, f2),
  852. Cross(u2, f0),
  853. Cross(u2, f1),
  854. Cross(u2, f2)
  855. };
  856. for (int i = 0; i < 13; ++i) {
  857. if (!OverlapOnAxis(a, t, test[i])) {
  858. return false; // Seperating axis found
  859. }
  860. }
  861. return true; // Seperating axis not found
  862. }
  863. bool TriangleOBB(const Triangle& t, const OBB& o) {
  864. // Compute the edge vectors of the triangle (ABC)
  865. vec3 f0 = t.b - t.a;
  866. vec3 f1 = t.c - t.b;
  867. vec3 f2 = t.a - t.c;
  868. // Compute the face normals of the AABB
  869. const float* orientation = o.orientation.asArray;
  870. vec3 u0(orientation[0], orientation[1], orientation[2]);
  871. vec3 u1(orientation[3], orientation[4], orientation[5]);
  872. vec3 u2(orientation[6], orientation[7], orientation[8]);
  873. vec3 test[13] = {
  874. // 3 Normals of AABB
  875. u0, // AABB Axis 1
  876. u1, // AABB Axis 2
  877. u2, // AABB Axis 3
  878. // 1 Normal of the Triangle
  879. Cross(f0, f1),
  880. // 9 Axis, cross products of all edges
  881. Cross(u0, f0),
  882. Cross(u0, f1),
  883. Cross(u0, f2),
  884. Cross(u1, f0),
  885. Cross(u1, f1),
  886. Cross(u1, f2),
  887. Cross(u2, f0),
  888. Cross(u2, f1),
  889. Cross(u2, f2)
  890. };
  891. for (int i = 0; i < 13; ++i) {
  892. if (!OverlapOnAxis(o, t, test[i])) {
  893. return false; // Seperating axis found
  894. }
  895. }
  896. return true; // Seperating axis not found
  897. }
  898. bool TriangleTriangle(const Triangle& t1, const Triangle& t2) {
  899. #if 0
  900. vec3 axisToTest[] = {
  901. // Triangle 1, Normal
  902. SatCrossEdge(t1.a, t1.b, t1.b, t1.c),
  903. // Triangle 2, Normal
  904. SatCrossEdge(t2.a, t2.b, t2.b, t2.c),
  905. // Cross Product of edges
  906. SatCrossEdge(t2.a, t2.b, t1.a, t1.b),
  907. SatCrossEdge(t2.a, t2.b, t1.b, t1.c),
  908. SatCrossEdge(t2.a, t2.b, t1.c, t1.a),
  909. SatCrossEdge(t2.b, t2.c, t1.a, t1.b),
  910. SatCrossEdge(t2.b, t2.c, t1.b, t1.c),
  911. SatCrossEdge(t2.b, t2.c, t1.c, t1.a),
  912. SatCrossEdge(t2.c, t2.a, t1.a, t1.b),
  913. SatCrossEdge(t2.c, t2.a, t1.b, t1.c),
  914. SatCrossEdge(t2.c, t2.a, t1.c, t1.a),
  915. };
  916. #else
  917. vec3 t1_f0 = t1.b - t1.a; // Edge 0
  918. vec3 t1_f1 = t1.c - t1.b; // Edge 1
  919. vec3 t1_f2 = t1.a - t1.c; // Edge 2
  920. vec3 t2_f0 = t2.b - t2.a; // Edge 0
  921. vec3 t2_f1 = t2.c - t2.b; // Edge 1
  922. vec3 t2_f2 = t2.a - t2.c; // Edge 2
  923. vec3 axisToTest[] = {
  924. // Triangle 1, Normal
  925. Cross(t1_f0, t1_f1),
  926. // Triangle 2, Normal
  927. Cross(t2_f0, t2_f1),
  928. // Cross Product of edges
  929. Cross(t2_f0, t1_f0),
  930. Cross(t2_f0, t1_f1),
  931. Cross(t2_f0, t1_f2),
  932. Cross(t2_f1, t1_f0),
  933. Cross(t2_f1, t1_f1),
  934. Cross(t2_f1, t1_f2),
  935. Cross(t2_f2, t1_f0),
  936. Cross(t2_f2, t1_f1),
  937. Cross(t2_f2, t1_f2),
  938. };
  939. #endif
  940. for (int i = 0; i < 11; ++i) {
  941. if (!OverlapOnAxis(t1, t2, axisToTest[i])) {
  942. return false; // Seperating axis found
  943. }
  944. }
  945. return true; // Seperating axis not found
  946. }
  947. bool TriangleTriangleRobust(const Triangle& t1, const Triangle& t2) {
  948. vec3 axisToTest[] = {
  949. // Triangle 1, Normal
  950. SatCrossEdge(t1.a, t1.b, t1.b, t1.c),
  951. // Triangle 2, Normal
  952. SatCrossEdge(t2.a, t2.b, t2.b, t2.c),
  953. // Cross Product of edges
  954. SatCrossEdge(t2.a, t2.b, t1.a, t1.b),
  955. SatCrossEdge(t2.a, t2.b, t1.b, t1.c),
  956. SatCrossEdge(t2.a, t2.b, t1.c, t1.a),
  957. SatCrossEdge(t2.b, t2.c, t1.a, t1.b),
  958. SatCrossEdge(t2.b, t2.c, t1.b, t1.c),
  959. SatCrossEdge(t2.b, t2.c, t1.c, t1.a),
  960. SatCrossEdge(t2.c, t2.a, t1.a, t1.b),
  961. SatCrossEdge(t2.c, t2.a, t1.b, t1.c),
  962. SatCrossEdge(t2.c, t2.a, t1.c, t1.a),
  963. };
  964. for (int i = 0; i < 11; ++i) {
  965. if (!OverlapOnAxis(t1, t2, axisToTest[i])) {
  966. if (!CMP(MagnitudeSq(axisToTest[i]), 0)) {
  967. return false; // Seperating axis found
  968. }
  969. }
  970. }
  971. return true; // Seperating axis not found
  972. }
  973. vec3 SatCrossEdge(const vec3& a, const vec3& b, const vec3& c, const vec3& d) {
  974. vec3 ab = b - a;
  975. vec3 cd = d - c;
  976. vec3 result = Cross(ab, cd);
  977. if (!CMP(MagnitudeSq(result), 0)) { // Is ab and cd parallel?
  978. return result; // Not parallel!
  979. }
  980. else { // ab and cd are parallel
  981. // Get an axis perpendicular to AB
  982. vec3 axis = Cross(ab, c - a);
  983. result = Cross(ab, axis);
  984. if (!CMP(MagnitudeSq(result), 0)) { // Still parallel?
  985. return result; // Not parallel
  986. }
  987. }
  988. // New axis being tested is parallel too.
  989. // This means that a, b, c and d are on a line
  990. // Nothing we can do!
  991. return vec3();
  992. }
  993. Point debugRaycastResult;
  994. bool Raycast(const Triangle& triangle, const Ray& ray, RaycastResult* outResult) {
  995. ResetRaycastResult(outResult);
  996. Plane plane = FromTriangle(triangle);
  997. RaycastResult planeResult;
  998. if (!Raycast(plane, ray, &planeResult)) {
  999. return false;
  1000. }
  1001. float t = planeResult.t;
  1002. Point result = ray.origin + ray.direction * t;
  1003. vec3 barycentric = Barycentric(result, triangle);
  1004. if (barycentric.x >= 0.0f && barycentric.x <= 1.0f &&
  1005. barycentric.y >= 0.0f && barycentric.y <= 1.0f &&
  1006. barycentric.z >= 0.0f && barycentric.z <= 1.0f) {
  1007. if (outResult != 0) {
  1008. outResult->t = t;
  1009. outResult->hit = true;
  1010. outResult->point = ray.origin + ray.direction * t;
  1011. outResult->normal = plane.normal;
  1012. }
  1013. return true;
  1014. }
  1015. return false;
  1016. }
  1017. bool Linetest(const Triangle& triangle, const Line& line) {
  1018. Ray ray;
  1019. ray.origin = line.start;
  1020. ray.direction = Normalized(line.end - line.start);
  1021. RaycastResult raycast;
  1022. if (!Raycast(triangle, ray, &raycast)) {
  1023. return false;
  1024. }
  1025. float t = raycast.t;
  1026. return t >= 0 && t * t <= LengthSq(line);
  1027. }
  1028. void AccelerateMesh(Mesh& mesh) {
  1029. if (mesh.accelerator != 0) {
  1030. return;
  1031. }
  1032. vec3 min = mesh.vertices[0];
  1033. vec3 max = mesh.vertices[0];
  1034. for (int i = 1; i < mesh.numTriangles * 3; ++i) {
  1035. min.x = fminf(mesh.vertices[i].x, min.x);
  1036. min.y = fminf(mesh.vertices[i].y, min.y);
  1037. min.z = fminf(mesh.vertices[i].z, min.z);
  1038. max.x = fmaxf(mesh.vertices[i].x, max.x);
  1039. max.y = fmaxf(mesh.vertices[i].y, max.y);
  1040. max.z = fmaxf(mesh.vertices[i].z, max.z);
  1041. }
  1042. mesh.accelerator = new BVHNode();
  1043. mesh.accelerator->bounds = FromMinMax(min, max);
  1044. mesh.accelerator->children = 0;
  1045. mesh.accelerator->numTriangles = mesh.numTriangles;
  1046. mesh.accelerator->triangles = new int[mesh.numTriangles];
  1047. for (int i = 0; i < mesh.numTriangles; ++i) {
  1048. mesh.accelerator->triangles[i] = i;
  1049. }
  1050. SplitBVHNode(mesh.accelerator, mesh, 3);
  1051. }
  1052. void SplitBVHNode(BVHNode* node, const Mesh& model, int depth) {
  1053. if (depth-- <= 0) { // Decrements depth
  1054. return;
  1055. }
  1056. if (node->children == 0) {
  1057. // Only split if this node contains triangles
  1058. if (node->numTriangles > 0) {
  1059. node->children = new BVHNode[8];
  1060. vec3 c = node->bounds.position;
  1061. vec3 e = node->bounds.size *0.5f;
  1062. node->children[0].bounds = AABB(c + vec3(-e.x, +e.y, -e.z), e);
  1063. node->children[1].bounds = AABB(c + vec3(+e.x, +e.y, -e.z), e);
  1064. node->children[2].bounds = AABB(c + vec3(-e.x, +e.y, +e.z), e);
  1065. node->children[3].bounds = AABB(c + vec3(+e.x, +e.y, +e.z), e);
  1066. node->children[4].bounds = AABB(c + vec3(-e.x, -e.y, -e.z), e);
  1067. node->children[5].bounds = AABB(c + vec3(+e.x, -e.y, -e.z), e);
  1068. node->children[6].bounds = AABB(c + vec3(-e.x, -e.y, +e.z), e);
  1069. node->children[7].bounds = AABB(c + vec3(+e.x, -e.y, +e.z), e);
  1070. }
  1071. }
  1072. // If this node was just split
  1073. if (node->children != 0 && node->numTriangles > 0) {
  1074. for (int i = 0; i < 8; ++i) { // For each child
  1075. // Count how many triangles each child will contain
  1076. node->children[i].numTriangles = 0;
  1077. for (int j = 0; j < node->numTriangles; ++j) {
  1078. Triangle t = model.triangles[node->triangles[j]];
  1079. if (TriangleAABB(t, node->children[i].bounds)) {
  1080. node->children[i].numTriangles += 1;
  1081. }
  1082. }
  1083. if (node->children[i].numTriangles == 0) {
  1084. continue;
  1085. }
  1086. node->children[i].triangles = new int[node->children[i].numTriangles];
  1087. int index = 0; // Add the triangles in the new child arrau
  1088. for (int j = 0; j < node->numTriangles; ++j) {
  1089. Triangle t = model.triangles[node->triangles[j]];
  1090. if (TriangleAABB(t, node->children[i].bounds)) {
  1091. node->children[i].triangles[index++] = node->triangles[j];
  1092. }
  1093. }
  1094. }
  1095. node->numTriangles = 0;
  1096. delete[] node->triangles;
  1097. node->triangles = 0;
  1098. // Recurse
  1099. for (int i = 0; i < 8; ++i) {
  1100. SplitBVHNode(&node->children[i], model, depth);
  1101. }
  1102. }
  1103. }
  1104. void FreeBVHNode(BVHNode* node) {
  1105. if (node->children != 0) {
  1106. for (int i = 0; i < 8; ++i) {
  1107. FreeBVHNode(&node->children[i]);
  1108. }
  1109. delete[] node->children;
  1110. node->children = 0;
  1111. }
  1112. if (node->numTriangles != 0 || node->triangles != 0) {
  1113. delete[] node->triangles;
  1114. node->triangles = 0;
  1115. node->numTriangles = 0;
  1116. }
  1117. }
  1118. bool MeshAABB(const Mesh& mesh, const AABB& aabb) {
  1119. if (mesh.accelerator == 0) {
  1120. for (int i = 0; i < mesh.numTriangles; ++i) {
  1121. if (TriangleAABB(mesh.triangles[i], aabb)) {
  1122. return true;
  1123. }
  1124. }
  1125. }
  1126. else {
  1127. std::list<BVHNode*> toProcess;
  1128. toProcess.push_front(mesh.accelerator);
  1129. // Recursivley walk the BVH tree
  1130. while (!toProcess.empty()) {
  1131. BVHNode* iterator = *(toProcess.begin());
  1132. toProcess.erase(toProcess.begin());
  1133. if (iterator->numTriangles >= 0) {
  1134. // Iterate trough all triangles of the node
  1135. for (int i = 0; i < iterator->numTriangles; ++i) {
  1136. // Triangle indices in BVHNode index the mesh
  1137. if (TriangleAABB(mesh.triangles[iterator->triangles[i]], aabb)) {
  1138. return true;
  1139. }
  1140. }
  1141. }
  1142. if (iterator->children != 0) {
  1143. for (int i = 8 - 1; i >= 0; --i) {
  1144. // Only push children whos bounds intersect the test geometry
  1145. if (AABBAABB(iterator->children[i].bounds, aabb)) {
  1146. toProcess.push_front(&iterator->children[i]);
  1147. }
  1148. }
  1149. }
  1150. }
  1151. }
  1152. return false;
  1153. }
  1154. bool Linetest(const Mesh& mesh, const Line& line) {
  1155. if (mesh.accelerator == 0) {
  1156. for (int i = 0; i < mesh.numTriangles; ++i) {
  1157. if (Linetest(mesh.triangles[i], line)) {
  1158. return true;
  1159. }
  1160. }
  1161. }
  1162. else {
  1163. std::list<BVHNode*> toProcess;
  1164. toProcess.push_front(mesh.accelerator);
  1165. // Recursivley walk the BVH tree
  1166. while (!toProcess.empty()) {
  1167. BVHNode* iterator = *(toProcess.begin());
  1168. toProcess.erase(toProcess.begin());
  1169. if (iterator->numTriangles >= 0) {
  1170. // Iterate trough all triangles of the node
  1171. for (int i = 0; i < iterator->numTriangles; ++i) {
  1172. // Triangle indices in BVHNode index the mesh
  1173. if (Linetest(mesh.triangles[iterator->triangles[i]], line)) {
  1174. return true;
  1175. }
  1176. }
  1177. }
  1178. if (iterator->children != 0) {
  1179. for (int i = 8 - 1; i >= 0; --i) {
  1180. // Only push children whos bounds intersect the test geometry
  1181. if (Linetest(iterator->children[i].bounds, line)) {
  1182. toProcess.push_front(&iterator->children[i]);
  1183. }
  1184. }
  1185. }
  1186. }
  1187. }
  1188. return false;
  1189. }
  1190. bool MeshSphere(const Mesh& mesh, const Sphere& sphere) {
  1191. if (mesh.accelerator == 0) {
  1192. for (int i = 0; i < mesh.numTriangles; ++i) {
  1193. if (TriangleSphere(mesh.triangles[i], sphere)) {
  1194. return true;
  1195. }
  1196. }
  1197. }
  1198. else {
  1199. std::list<BVHNode*> toProcess;
  1200. toProcess.push_front(mesh.accelerator);
  1201. // Recursivley walk the BVH tree
  1202. while (!toProcess.empty()) {
  1203. BVHNode* iterator = *(toProcess.begin());
  1204. toProcess.erase(toProcess.begin());
  1205. if (iterator->numTriangles >= 0) {
  1206. // Iterate trough all triangles of the node
  1207. for (int i = 0; i < iterator->numTriangles; ++i) {
  1208. // Triangle indices in BVHNode index the mesh
  1209. if (TriangleSphere(mesh.triangles[iterator->triangles[i]], sphere)) {
  1210. return true;
  1211. }
  1212. }
  1213. }
  1214. if (iterator->children != 0) {
  1215. for (int i = 8 - 1; i >= 0; --i) {
  1216. // Only push children whos bounds intersect the test geometry
  1217. if (SphereAABB(sphere, iterator->children[i].bounds)) {
  1218. toProcess.push_front(&iterator->children[i]);
  1219. }
  1220. }
  1221. }
  1222. }
  1223. }
  1224. return false;
  1225. }
  1226. bool MeshOBB(const Mesh& mesh, const OBB& obb) {
  1227. if (mesh.accelerator == 0) {
  1228. for (int i = 0; i < mesh.numTriangles; ++i) {
  1229. if (TriangleOBB(mesh.triangles[i], obb)) {
  1230. return true;
  1231. }
  1232. }
  1233. }
  1234. else {
  1235. std::list<BVHNode*> toProcess;
  1236. toProcess.push_front(mesh.accelerator);
  1237. // Recursivley walk the BVH tree
  1238. while (!toProcess.empty()) {
  1239. BVHNode* iterator = *(toProcess.begin());
  1240. toProcess.erase(toProcess.begin());
  1241. if (iterator->numTriangles >= 0) {
  1242. // Iterate trough all triangles of the node
  1243. for (int i = 0; i < iterator->numTriangles; ++i) {
  1244. // Triangle indices in BVHNode index the mesh
  1245. if (TriangleOBB(mesh.triangles[iterator->triangles[i]], obb)) {
  1246. return true;
  1247. }
  1248. }
  1249. }
  1250. if (iterator->children != 0) {
  1251. for (int i = 8 - 1; i >= 0; --i) {
  1252. // Only push children whos bounds intersect the test geometry
  1253. if (AABBOBB(iterator->children[i].bounds, obb)) {
  1254. toProcess.push_front(&iterator->children[i]);
  1255. }
  1256. }
  1257. }
  1258. }
  1259. }
  1260. return false;
  1261. }
  1262. bool MeshPlane(const Mesh& mesh, const Plane& plane) {
  1263. if (mesh.accelerator == 0) {
  1264. for (int i = 0; i < mesh.numTriangles; ++i) {
  1265. if (TrianglePlane(mesh.triangles[i], plane)) {
  1266. return true;
  1267. }
  1268. }
  1269. }
  1270. else {
  1271. std::list<BVHNode*> toProcess;
  1272. toProcess.push_front(mesh.accelerator);
  1273. // Recursivley walk the BVH tree
  1274. while (!toProcess.empty()) {
  1275. BVHNode* iterator = *(toProcess.begin());
  1276. toProcess.erase(toProcess.begin());
  1277. if (iterator->numTriangles >= 0) {
  1278. // Iterate trough all triangles of the node
  1279. for (int i = 0; i < iterator->numTriangles; ++i) {
  1280. // Triangle indices in BVHNode index the mesh
  1281. if (TrianglePlane(mesh.triangles[iterator->triangles[i]], plane)) {
  1282. return true;
  1283. }
  1284. }
  1285. }
  1286. if (iterator->children != 0) {
  1287. for (int i = 8 - 1; i >= 0; --i) {
  1288. // Only push children whos bounds intersect the test geometry
  1289. if (AABBPlane(iterator->children[i].bounds, plane)) {
  1290. toProcess.push_front(&iterator->children[i]);
  1291. }
  1292. }
  1293. }
  1294. }
  1295. }
  1296. return false;
  1297. }
  1298. bool MeshTriangle(const Mesh& mesh, const Triangle& triangle) {
  1299. if (mesh.accelerator == 0) {
  1300. for (int i = 0; i < mesh.numTriangles; ++i) {
  1301. if (TriangleTriangle(mesh.triangles[i], triangle)) {
  1302. return true;
  1303. }
  1304. }
  1305. }
  1306. else {
  1307. std::list<BVHNode*> toProcess;
  1308. toProcess.push_front(mesh.accelerator);
  1309. // Recursivley walk the BVH tree
  1310. while (!toProcess.empty()) {
  1311. BVHNode* iterator = *(toProcess.begin());
  1312. toProcess.erase(toProcess.begin());
  1313. if (iterator->numTriangles >= 0) {
  1314. // Iterate trough all triangles of the node
  1315. for (int i = 0; i < iterator->numTriangles; ++i) {
  1316. // Triangle indices in BVHNode index the mesh
  1317. if (TriangleTriangle(mesh.triangles[iterator->triangles[i]], triangle)) {
  1318. return true;
  1319. }
  1320. }
  1321. }
  1322. if (iterator->children != 0) {
  1323. for (int i = 8 - 1; i >= 0; --i) {
  1324. // Only push children whos bounds intersect the test geometry
  1325. if (TriangleAABB(triangle, iterator->children[i].bounds)) {
  1326. toProcess.push_front(&iterator->children[i]);
  1327. }
  1328. }
  1329. }
  1330. }
  1331. }
  1332. return false;
  1333. }
  1334. float Raycast(const Mesh& mesh, const Ray& ray) {
  1335. return MeshRay(mesh, ray);
  1336. }
  1337. float Raycast(const Model& mesh, const Ray& ray) {
  1338. return ModelRay(mesh, ray);
  1339. }
  1340. float MeshRay(const Mesh& mesh, const Ray& ray) {
  1341. if (mesh.accelerator == 0) {
  1342. for (int i = 0; i < mesh.numTriangles; ++i) {
  1343. RaycastResult raycast;
  1344. Raycast(mesh.triangles[i], ray, &raycast);
  1345. float result = raycast.t;
  1346. if (result >= 0) {
  1347. return result;
  1348. }
  1349. }
  1350. }
  1351. else {
  1352. std::list<BVHNode*> toProcess;
  1353. toProcess.push_front(mesh.accelerator);
  1354. // Recursivley walk the BVH tree
  1355. while (!toProcess.empty()) {
  1356. BVHNode* iterator = *(toProcess.begin());
  1357. toProcess.erase(toProcess.begin());
  1358. if (iterator->numTriangles >= 0) {
  1359. // Iterate trough all triangles of the node
  1360. for (int i = 0; i < iterator->numTriangles; ++i) {
  1361. // Triangle indices in BVHNode index the mesh
  1362. RaycastResult raycast;
  1363. Raycast(mesh.triangles[iterator->triangles[i]], ray, &raycast);
  1364. float r = raycast.t;
  1365. if (r >= 0) {
  1366. return r;
  1367. }
  1368. }
  1369. }
  1370. if (iterator->children != 0) {
  1371. for (int i = 8 - 1; i >= 0; --i) {
  1372. // Only push children whos bounds intersect the test geometry
  1373. RaycastResult raycast;
  1374. Raycast(iterator->children[i].bounds, ray, &raycast);
  1375. if (raycast.t >= 0) {
  1376. toProcess.push_front(&iterator->children[i]);
  1377. }
  1378. }
  1379. }
  1380. }
  1381. }
  1382. return -1;
  1383. }
  1384. bool TrianglePlane(const Triangle& t, const Plane& p) {
  1385. float side1 = PlaneEquation(t.a, p);
  1386. float side2 = PlaneEquation(t.b, p);
  1387. float side3 = PlaneEquation(t.c, p);
  1388. // On Plane
  1389. if (CMP(side1, 0) && CMP(side2, 0) && CMP(side3, 0)) {
  1390. return true;
  1391. }
  1392. // Triangle in front of plane
  1393. if (side1 > 0 && side2 > 0 && side3 > 0) {
  1394. return false;
  1395. }
  1396. // Triangle behind plane
  1397. if (side1 < 0 && side2 < 0 && side3 < 0) {
  1398. return false;
  1399. }
  1400. return true; // Intersection
  1401. }
  1402. void Model::SetContent(Mesh* mesh) {
  1403. content = mesh;
  1404. if (content != 0) {
  1405. vec3 min = mesh->vertices[0];
  1406. vec3 max = mesh->vertices[0];
  1407. for (int i = 1; i < mesh->numTriangles * 3; ++i) {
  1408. min.x = fminf(mesh->vertices[i].x, min.x);
  1409. min.y = fminf(mesh->vertices[i].y, min.y);
  1410. min.z = fminf(mesh->vertices[i].z, min.z);
  1411. max.x = fmaxf(mesh->vertices[i].x, max.x);
  1412. max.y = fmaxf(mesh->vertices[i].y, max.y);
  1413. max.z = fmaxf(mesh->vertices[i].z, max.z);
  1414. }
  1415. bounds = FromMinMax(min, max);
  1416. }
  1417. }
  1418. mat4 GetWorldMatrix(const Model& model) {
  1419. mat4 translation = Translation(model.position);
  1420. mat4 rotation = Rotation(model.rotation.x, model.rotation.y, model.rotation.z);
  1421. mat4 localMat = /* Scale * */ rotation * translation;
  1422. mat4 parentMat;
  1423. if (model.parent != 0) {
  1424. parentMat = GetWorldMatrix(*model.parent);
  1425. }
  1426. return localMat * parentMat;
  1427. }
  1428. OBB GetOBB(const Model& model) {
  1429. mat4 world = GetWorldMatrix(model);
  1430. AABB aabb = model.GetBounds();
  1431. OBB obb;
  1432. obb.size = aabb.size;
  1433. obb.position = MultiplyPoint(aabb.position, world);
  1434. obb.orientation = Cut(world, 3, 3);
  1435. return obb;
  1436. }
  1437. float ModelRay(const Model& model, const Ray& ray) {
  1438. mat4 world = GetWorldMatrix(model);
  1439. mat4 inv = Inverse(world);
  1440. Ray local;
  1441. local.origin = MultiplyPoint(ray.origin, inv);
  1442. local.direction = MultiplyVector(ray.direction, inv);
  1443. local.NormalizeDirection();
  1444. if (model.GetMesh() != 0) {
  1445. return MeshRay(*(model.GetMesh()), local);
  1446. }
  1447. return -1;
  1448. }
  1449. bool Linetest(const Model& model, const Line& line) {
  1450. mat4 world = GetWorldMatrix(model);
  1451. mat4 inv = Inverse(world);
  1452. Line local;
  1453. local.start = MultiplyPoint(line.start, inv);
  1454. local.end = MultiplyPoint(line.end, inv);
  1455. if (model.GetMesh() != 0) {
  1456. return Linetest(*(model.GetMesh()), local);
  1457. }
  1458. return false;
  1459. }
  1460. bool ModelSphere(const Model& model, const Sphere& sphere) {
  1461. mat4 world = GetWorldMatrix(model);
  1462. mat4 inv = Inverse(world);
  1463. Sphere local;
  1464. local.position = MultiplyPoint(sphere.position, inv);
  1465. if (model.GetMesh() != 0) {
  1466. return MeshSphere(*(model.GetMesh()), local);
  1467. }
  1468. return false;
  1469. }
  1470. bool ModelAABB(const Model& model, const AABB& aabb) {
  1471. mat4 world = GetWorldMatrix(model);
  1472. mat4 inv = Inverse(world);
  1473. OBB local;
  1474. local.size = aabb.size;
  1475. local.position = MultiplyPoint(aabb.position, inv);
  1476. local.orientation = Cut(inv, 3, 3);
  1477. if (model.GetMesh() != 0) {
  1478. return MeshOBB(*(model.GetMesh()), local);
  1479. }
  1480. return false;
  1481. }
  1482. bool ModelOBB(const Model& model, const OBB& obb) {
  1483. mat4 world = GetWorldMatrix(model);
  1484. mat4 inv = Inverse(world);
  1485. OBB local;
  1486. local.size = obb.size;
  1487. local.position = MultiplyPoint(obb.position, inv);
  1488. local.orientation = obb.orientation * Cut(inv, 3, 3);
  1489. if (model.GetMesh() != 0) {
  1490. return MeshOBB(*(model.GetMesh()), local);
  1491. }
  1492. return false;
  1493. }
  1494. bool ModelPlane(const Model& model, const Plane& plane) {
  1495. mat4 world = GetWorldMatrix(model);
  1496. mat4 inv = Inverse(world);
  1497. Plane local;
  1498. local.normal = MultiplyVector(plane.normal, inv);
  1499. local.distance = plane.distance;
  1500. if (model.GetMesh() != 0) {
  1501. return MeshPlane(*(model.GetMesh()), local);
  1502. }
  1503. return false;
  1504. }
  1505. bool ModelTriangle(const Model& model, const Triangle& triangle) {
  1506. mat4 world = GetWorldMatrix(model);
  1507. mat4 inv = Inverse(world);
  1508. Triangle local;
  1509. local.a = MultiplyPoint(triangle.a, inv);
  1510. local.b = MultiplyPoint(triangle.b, inv);
  1511. local.c = MultiplyPoint(triangle.c, inv);
  1512. if (model.GetMesh() != 0) {
  1513. return MeshTriangle(*(model.GetMesh()), local);
  1514. }
  1515. return false;
  1516. }
  1517. Point Intersection(Plane p1, Plane p2, Plane p3) {
  1518. /*return ((Cross(p2.normal, p3.normal) * -p1.distance) +
  1519. (Cross(p3.normal, p1.normal) * -p2.distance) +
  1520. (Cross(p1.normal, p2.normal) * -p3.distance)) /
  1521. (Dot(p1.normal, Cross(p2.normal, p3.normal)));*/
  1522. #if 1
  1523. mat3 D(
  1524. p1.normal.x, p2.normal.x, p3.normal.x,
  1525. p1.normal.y, p2.normal.y, p3.normal.y,
  1526. p1.normal.z, p2.normal.z, p3.normal.z
  1527. );
  1528. vec3 A(-p1.distance, -p2.distance, -p3.distance);
  1529. mat3 Dx = D, Dy = D, Dz = D;
  1530. Dx._11 = A.x; Dx._12 = A.y; Dx._13 = A.z;
  1531. Dy._21 = A.x; Dy._22 = A.y; Dy._23 = A.z;
  1532. Dz._31 = A.x; Dz._32 = A.y; Dz._33 = A.z;
  1533. float detD = Determinant(D);
  1534. if (CMP(detD, 0)) {
  1535. return Point();
  1536. }
  1537. float detDx = Determinant(Dx);
  1538. float detDy = Determinant(Dy);
  1539. float detDz = Determinant(Dz);
  1540. return Point(detDx / detD, detDy / detD, detDz / detD);
  1541. #else
  1542. vec3 m1(p1.normal.x, p2.normal.x, p3.normal.x);
  1543. vec3 m2(p1.normal.y, p2.normal.y, p3.normal.y);
  1544. vec3 m3(p1.normal.z, p2.normal.z, p3.normal.z);
  1545. vec3 d(-p1.distance, -p2.distance, -p3.distance);
  1546. vec3 u = Cross(m2, m3);
  1547. vec3 v = Cross(m1, d);
  1548. float denom = Dot(m1, u);
  1549. if (CMP(denom, 0.0f)) {
  1550. return Point();
  1551. }
  1552. Point result;
  1553. result.x = Dot(d, u) / denom;
  1554. result.y = Dot(m3, v) / denom;
  1555. result.z = -Dot(m2, v) / denom;
  1556. return result;
  1557. #endif
  1558. }
  1559. void GetCorners(const Frustum& f, vec3* outCorners) {
  1560. outCorners[0] = Intersection(f._near, f.top, f.left);
  1561. outCorners[1] = Intersection(f._near, f.top, f.right);
  1562. outCorners[2] = Intersection(f._near, f.bottom, f.left);
  1563. outCorners[3] = Intersection(f._near, f.bottom, f.right);
  1564. outCorners[4] = Intersection(f._far, f.top, f.left);
  1565. outCorners[5] = Intersection(f._far, f.top, f.right);
  1566. outCorners[6] = Intersection(f._far, f.bottom, f.left);
  1567. outCorners[7] = Intersection(f._far, f.bottom, f.right);
  1568. }
  1569. bool Intersects(const Frustum& f, const Point& p) {
  1570. for (int i = 0; i < 6; ++i) {
  1571. vec3 normal = f.planes[i].normal;
  1572. float dist = f.planes[i].distance;
  1573. float side = Dot(p, normal) + dist;
  1574. if (side < 0.0f) {
  1575. return false;
  1576. }
  1577. }
  1578. return true;
  1579. }
  1580. bool Intersects(const Frustum& f, const Sphere& s) {
  1581. for (int i = 0; i < 6; ++i) {
  1582. vec3 normal = f.planes[i].normal;
  1583. float dist = f.planes[i].distance;
  1584. float side = Dot(s.position, normal) + dist;
  1585. if (side < -s.radius) {
  1586. return false;
  1587. }
  1588. }
  1589. return true;
  1590. }
  1591. float Classify(const AABB& aabb, const Plane& plane) {
  1592. // maximum extent in direction of plane normal
  1593. float r = fabsf(aabb.size.x * plane.normal.x)
  1594. + fabsf(aabb.size.y * plane.normal.y)
  1595. + fabsf(aabb.size.z * plane.normal.z);
  1596. // signed distance between box center and plane
  1597. //float d = plane.Test(mCenter);
  1598. float d = Dot(plane.normal, aabb.position) + plane.distance;
  1599. // return signed distance
  1600. if (fabsf(d) < r) {
  1601. return 0.0f;
  1602. }
  1603. else if (d < 0.0f) {
  1604. return d + r;
  1605. }
  1606. return d - r;
  1607. }
  1608. float Classify(const OBB& obb, const Plane& plane) {
  1609. vec3 normal = MultiplyVector(plane.normal, obb.orientation);
  1610. // maximum extent in direction of plane normal
  1611. float r = fabsf(obb.size.x * normal.x)
  1612. + fabsf(obb.size.y * normal.y)
  1613. + fabsf(obb.size.z * normal.z);
  1614. // signed distance between box center and plane
  1615. //float d = plane.Test(mCenter);
  1616. float d = Dot(plane.normal, obb.position) + plane.distance;
  1617. // return signed distance
  1618. if (fabsf(d) < r) {
  1619. return 0.0f;
  1620. }
  1621. else if (d < 0.0f) {
  1622. return d + r;
  1623. }
  1624. return d - r;
  1625. }
  1626. bool Intersects(const Frustum& f, const OBB& obb) {
  1627. for (int i = 0; i < 6; ++i) {
  1628. float side = Classify(obb, f.planes[i]);
  1629. if (side < 0) {
  1630. return false;
  1631. }
  1632. }
  1633. return true;
  1634. }
  1635. bool Intersects(const Frustum& f, const AABB& aabb) {
  1636. for (int i = 0; i < 6; ++i) {
  1637. float side = Classify(aabb, f.planes[i]);
  1638. if (side < 0) {
  1639. return false;
  1640. }
  1641. }
  1642. return true;
  1643. }
  1644. vec3 Unproject(const vec3& viewportPoint, const vec2& viewportOrigin, const vec2& viewportSize, const mat4& view, const mat4& projection) {
  1645. // Step 1, Normalize the input vector to the view port
  1646. float normalized[4] = {
  1647. (viewportPoint.x - viewportOrigin.x) / viewportSize.x,
  1648. (viewportPoint.y - viewportOrigin.y) / viewportSize.y,
  1649. viewportPoint.z,
  1650. 1.0f
  1651. };
  1652. // Step 2, Translate into NDC space
  1653. float ndcSpace[4] = {
  1654. normalized[0], normalized[1],
  1655. normalized[2], normalized[3]
  1656. };
  1657. // X Range: -1 to 1
  1658. ndcSpace[0] = ndcSpace[0] * 2.0f - 1.0f;
  1659. // Y Range: -1 to 1, our Y axis is flipped!
  1660. ndcSpace[1] = 1.0f - ndcSpace[1] * 2.0f;
  1661. // Z Range: 0 to 1
  1662. if (ndcSpace[2] < 0.0f) {
  1663. ndcSpace[2] = 0.0f;
  1664. }
  1665. if (ndcSpace[2] > 1.0f) {
  1666. ndcSpace[2] = 1.0f;
  1667. }
  1668. // Step 3, NDC to Eye Space
  1669. mat4 invProjection = Inverse(projection);
  1670. float eyeSpace[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
  1671. // eyeSpace = MultiplyPoint(ndcSpace, invProjection);
  1672. Multiply(eyeSpace, ndcSpace, 1, 4, invProjection.asArray, 4, 4);
  1673. // Step 4, Eye Space to World Space
  1674. mat4 invView = Inverse(view);
  1675. float worldSpace[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
  1676. // worldSpace = MultiplyPoint(eyeSpace, invView);
  1677. Multiply(worldSpace, eyeSpace, 1, 4, invView.asArray, 4, 4);
  1678. // Step 5, Undo perspective divide!
  1679. if (!CMP(worldSpace[3], 0.0f)) {
  1680. worldSpace[0] /= worldSpace[3];
  1681. worldSpace[1] /= worldSpace[3];
  1682. worldSpace[2] /= worldSpace[3];
  1683. }
  1684. // Return the resulting world space point
  1685. return vec3(worldSpace[0], worldSpace[1], worldSpace[2]);
  1686. }
  1687. Ray GetPickRay(const vec2& viewportPoint, const vec2& viewportOrigin, const vec2& viewportSize, const mat4& view, const mat4& projection) {
  1688. vec3 nearPoint(viewportPoint.x, viewportPoint.y, 0.0f);
  1689. vec3 farPoint(viewportPoint.x, viewportPoint.y, 1.0f);
  1690. vec3 pNear = Unproject(nearPoint, viewportOrigin, viewportSize, view, projection);
  1691. vec3 pFar = Unproject(farPoint, viewportOrigin, viewportSize, view, projection);
  1692. vec3 normal = Normalized(pFar - pNear);
  1693. vec3 origin = pNear;
  1694. return Ray(origin, normal);
  1695. }
  1696. // Chapter 15
  1697. void ResetCollisionManifold(CollisionManifold* result) {
  1698. if (result != 0) {
  1699. result->colliding = false;
  1700. result->normal = vec3(0, 0, 1);
  1701. result->depth = FLT_MAX;
  1702. if (result->contacts.size() > 0) {
  1703. result->contacts.clear();
  1704. }
  1705. }
  1706. }
  1707. std::vector<Point> GetVertices(const OBB& obb) {
  1708. std::vector<vec3> v;
  1709. v.resize(8);
  1710. vec3 C = obb.position; // OBB Center
  1711. vec3 E = obb.size; // OBB Extents
  1712. const float* o = obb.orientation.asArray;
  1713. vec3 A[] = { // OBB Axis
  1714. vec3(o[0], o[1], o[2]),
  1715. vec3(o[3], o[4], o[5]),
  1716. vec3(o[6], o[7], o[8]),
  1717. };
  1718. v[0] = C + A[0] * E[0] + A[1] * E[1] + A[2] * E[2];
  1719. v[1] = C - A[0] * E[0] + A[1] * E[1] + A[2] * E[2];
  1720. v[2] = C + A[0] * E[0] - A[1] * E[1] + A[2] * E[2];
  1721. v[3] = C + A[0] * E[0] + A[1] * E[1] - A[2] * E[2];
  1722. v[4] = C - A[0] * E[0] - A[1] * E[1] - A[2] * E[2];
  1723. v[5] = C + A[0] * E[0] - A[1] * E[1] - A[2] * E[2];
  1724. v[6] = C - A[0] * E[0] + A[1] * E[1] - A[2] * E[2];
  1725. v[7] = C - A[0] * E[0] - A[1] * E[1] + A[2] * E[2];
  1726. return v;
  1727. }
  1728. std::vector<Line> GetEdges(const OBB& obb) {
  1729. std::vector<Line> result;
  1730. result.reserve(12);
  1731. std::vector<Point> v = GetVertices(obb);
  1732. int index[][2] = { // Indices of edges
  1733. { 6, 1 },{ 6, 3 },{ 6, 4 },{ 2, 7 },{ 2, 5 },{ 2, 0 },
  1734. { 0, 1 },{ 0, 3 },{ 7, 1 },{ 7, 4 },{ 4, 5 },{ 5, 3 }
  1735. };
  1736. for (int j = 0; j < 12; ++j) {
  1737. result.push_back(Line(
  1738. v[index[j][0]], v[index[j][1]]
  1739. ));
  1740. }
  1741. return result;
  1742. }
  1743. std::vector<Plane> GetPlanes(const OBB& obb) {
  1744. vec3 c = obb.position; // OBB Center
  1745. vec3 e = obb.size; // OBB Extents
  1746. const float* o = obb.orientation.asArray;
  1747. vec3 a[] = { // OBB Axis
  1748. vec3(o[0], o[1], o[2]),
  1749. vec3(o[3], o[4], o[5]),
  1750. vec3(o[6], o[7], o[8]),
  1751. };
  1752. std::vector<Plane> result;
  1753. result.resize(6);
  1754. result[0] = Plane(a[0] , Dot(a[0], (c + a[0] * e.x)));
  1755. result[1] = Plane(a[0] * -1.0f, -Dot(a[0], (c - a[0] * e.x)));
  1756. result[2] = Plane(a[1] , Dot(a[1], (c + a[1] * e.y)));
  1757. result[3] = Plane(a[1] * -1.0f, -Dot(a[1], (c - a[1] * e.y)));
  1758. result[4] = Plane(a[2] , Dot(a[2], (c + a[2] * e.z)));
  1759. result[5] = Plane(a[2] * -1.0f, -Dot(a[2], (c - a[2] * e.z)));
  1760. return result;
  1761. }
  1762. bool ClipToPlane(const Plane& plane, const Line& line, Point* outPoint) {
  1763. vec3 ab = line.end - line.start;
  1764. float nA = Dot(plane.normal, line.start);
  1765. float nAB = Dot(plane.normal, ab);
  1766. if (CMP(nAB, 0)) {
  1767. return false;
  1768. }
  1769. float t = (plane.distance - nA) / nAB;
  1770. if (t >= 0.0f && t <= 1.0f) {
  1771. if (outPoint != 0) {
  1772. *outPoint = line.start + ab * t;
  1773. }
  1774. return true;
  1775. }
  1776. return false;
  1777. }
  1778. std::vector<Point> ClipEdgesToOBB(const std::vector<Line>& edges, const OBB& obb) {
  1779. std::vector<Point> result;
  1780. result.reserve(edges.size() * 3);
  1781. Point intersection;
  1782. std::vector<Plane>& planes = GetPlanes(obb);
  1783. for (int i = 0; i < planes.size(); ++i) {
  1784. for (int j = 0; j < edges.size(); ++j) {
  1785. if (ClipToPlane(planes[i], edges[j], &intersection)) {
  1786. if (PointInOBB(intersection, obb)) {
  1787. result.push_back(intersection);
  1788. }
  1789. }
  1790. }
  1791. }
  1792. return result;
  1793. }
  1794. float PenetrationDepth(const OBB& o1, const OBB& o2, const vec3& axis, bool* outShouldFlip) {
  1795. Interval i1 = GetInterval(o1, Normalized(axis));
  1796. Interval i2 = GetInterval(o2, Normalized(axis));
  1797. if (!((i2.min <= i1.max) && (i1.min <= i2.max))) {
  1798. return 0.0f; // No penerattion
  1799. }
  1800. float len1 = i1.max - i1.min;
  1801. float len2 = i2.max - i2.min;
  1802. float min = fminf(i1.min, i2.min);
  1803. float max = fmaxf(i1.max, i2.max);
  1804. float length = max - min;
  1805. if (outShouldFlip != 0) {
  1806. *outShouldFlip = (i2.min < i1.min);
  1807. }
  1808. return (len1 + len2) - length;
  1809. }
  1810. CollisionManifold FindCollisionFeatures(const OBB& A, const OBB& B) {
  1811. CollisionManifold result; // Will return result of intersection!
  1812. ResetCollisionManifold(&result);
  1813. Sphere s1(A.position, Magnitude(A.size));
  1814. Sphere s2(B.position, Magnitude(B.size));
  1815. if (!SphereSphere(s1, s2)) {
  1816. return result;
  1817. }
  1818. const float* o1 = A.orientation.asArray;
  1819. const float* o2 = B.orientation.asArray;
  1820. vec3 test[15] = {
  1821. vec3(o1[0], o1[1], o1[2]),
  1822. vec3(o1[3], o1[4], o1[5]),
  1823. vec3(o1[6], o1[7], o1[8]),
  1824. vec3(o2[0], o2[1], o2[2]),
  1825. vec3(o2[3], o2[4], o2[5]),
  1826. vec3(o2[6], o2[7], o2[8])
  1827. };
  1828. for (int i = 0; i < 3; ++i) { // Fill out rest of axis
  1829. test[6 + i * 3 + 0] = Cross(test[i], test[0]);
  1830. test[6 + i * 3 + 1] = Cross(test[i], test[1]);
  1831. test[6 + i * 3 + 2] = Cross(test[i], test[2]);
  1832. }
  1833. vec3* hitNormal = 0;
  1834. bool shouldFlip;
  1835. for (int i = 0; i < 15; ++i) {
  1836. if (test[i].x < 0.000001f) test[i].x = 0.0f;
  1837. if (test[i].y < 0.000001f) test[i].y = 0.0f;
  1838. if (test[i].z < 0.000001f) test[i].z = 0.0f;
  1839. if (MagnitudeSq(test[i])< 0.001f) {
  1840. continue;
  1841. }
  1842. float depth = PenetrationDepth(A, B, test[i], &shouldFlip);
  1843. if (depth <= 0.0f) {
  1844. return result;
  1845. }
  1846. else if (depth < result.depth) {
  1847. if (shouldFlip) {
  1848. test[i] = test[i] * -1.0f;
  1849. }
  1850. result.depth = depth;
  1851. hitNormal = &test[i];
  1852. }
  1853. }
  1854. if (hitNormal == 0) {
  1855. return result;
  1856. }
  1857. vec3 axis = Normalized(*hitNormal);
  1858. std::vector<Point> c1 = ClipEdgesToOBB(GetEdges(B), A);
  1859. std::vector<Point> c2 = ClipEdgesToOBB(GetEdges(A), B);
  1860. result.contacts.reserve(c1.size() + c2.size());
  1861. result.contacts.insert(result.contacts.end(), c1.begin(), c1.end());
  1862. result.contacts.insert(result.contacts.end(), c2.begin(), c2.end());
  1863. Interval i = GetInterval(A, axis);
  1864. float distance = (i.max - i.min)* 0.5f - result.depth * 0.5f;
  1865. vec3 pointOnPlane = A.position + axis * distance;
  1866. for (int i = result.contacts.size() - 1; i >= 0; --i) {
  1867. vec3 contact = result.contacts[i];
  1868. result.contacts[i] = contact + (axis * Dot(axis, pointOnPlane - contact));
  1869. // This bit is in the "There is more" section of the book
  1870. for (int j = result.contacts.size() - 1; j > i; --j) {
  1871. if (MagnitudeSq(result.contacts[j] - result.contacts[i]) < 0.0001f) {
  1872. result.contacts.erase(result.contacts.begin() + j);
  1873. break;
  1874. }
  1875. }
  1876. }
  1877. result.colliding = true;
  1878. result.normal = axis;
  1879. return result;
  1880. }
  1881. CollisionManifold FindCollisionFeatures(const Sphere& A, const Sphere& B) {
  1882. CollisionManifold result; // Will return result of intersection!
  1883. ResetCollisionManifold(&result);
  1884. float r = A.radius + B.radius;
  1885. vec3 d = B.position - A.position;
  1886. if (MagnitudeSq(d) - r * r > 0 || MagnitudeSq(d) == 0.0f) {
  1887. return result;
  1888. }
  1889. Normalize(d);
  1890. result.colliding = true;
  1891. result.normal = d;
  1892. result.depth = fabsf(Magnitude(d) - r) * 0.5f;
  1893. // dtp - Distance to intersection point
  1894. float dtp = A.radius - result.depth;
  1895. Point contact = A.position + d * dtp;
  1896. result.contacts.push_back(contact);
  1897. return result;
  1898. }
  1899. CollisionManifold FindCollisionFeatures(const OBB& A, const Sphere& B) {
  1900. CollisionManifold result; // Will return result of intersection!
  1901. ResetCollisionManifold(&result);
  1902. Point closestPoint = ClosestPoint(A, B.position);
  1903. float distanceSq = MagnitudeSq(closestPoint - B.position);
  1904. if (distanceSq > B.radius * B.radius) {
  1905. return result;
  1906. }
  1907. vec3 normal;
  1908. if (CMP(distanceSq, 0.0f)) {
  1909. if (CMP(MagnitudeSq(closestPoint - A.position), 0.0f)) {
  1910. return result;
  1911. }
  1912. // Closest point is at the center of the sphere
  1913. normal = Normalized(closestPoint - A.position);
  1914. }
  1915. else {
  1916. normal = Normalized(B.position - closestPoint);
  1917. }
  1918. Point outsidePoint = B.position - normal * B.radius;
  1919. float distance = Magnitude(closestPoint - outsidePoint);
  1920. result.colliding = true;
  1921. result.contacts.push_back(closestPoint + (outsidePoint - closestPoint) * 0.5f);
  1922. result.normal = normal;
  1923. result.depth = distance * 0.5f;
  1924. return result;
  1925. }

game-physics-cookbook----Vector.cpp

  1. #include "Compare.h"
  2. #include "vectors.h"
  3. #include <cmath>
  4. #include <cfloat>
  5. float CorrectDegrees(float degrees) {
  6. while (degrees > 360.0f) {
  7. degrees -= 360.0f;
  8. }
  9. while (degrees < -360.0f) {
  10. degrees += 360.0f;
  11. }
  12. return degrees;
  13. }
  14. #ifndef RAD2DEG
  15. float RAD2DEG(float radians) {
  16. float degrees = radians * 57.295754f;
  17. degrees = CorrectDegrees(degrees);
  18. return degrees;
  19. }
  20. #endif
  21. #ifndef DEG2RAD
  22. float DEG2RAD(float degrees) {
  23. degrees = CorrectDegrees(degrees);
  24. float radians = degrees * 0.0174533f;
  25. return radians;
  26. }
  27. #endif
  28. bool operator==(const vec2& l, const vec2& r) {
  29. return CMP(l.x, r.x) && CMP(l.y, r.y);
  30. }
  31. bool operator==(const vec3& l, const vec3& r) {
  32. return CMP(l.x, r.x) && CMP(l.y, r.y) && CMP(l.z, r.z);
  33. }
  34. bool operator!=(const vec2& l, const vec2& r) {
  35. return !(l == r);
  36. }
  37. bool operator!=(const vec3& l, const vec3& r) {
  38. return !(l == r);
  39. }
  40. vec2 operator+(const vec2& l, const vec2& r) {
  41. return { l.x + r.x, l.y + r.y };
  42. }
  43. vec3 operator+(const vec3& l, const vec3& r) {
  44. return { l.x + r.x, l.y + r.y, l.z + r.z };
  45. }
  46. vec2 operator-(const vec2& l, const vec2& r) {
  47. return { l.x - r.x, l.y - r.y };
  48. }
  49. vec3 operator-(const vec3& l, const vec3& r) {
  50. return { l.x - r.x, l.y - r.y, l.z - r.z };
  51. }
  52. vec2 operator*(const vec2& l, const vec2& r) {
  53. return { l.x * r.x, l.y * r.y };
  54. }
  55. vec3 operator*(const vec3& l, const vec3& r) {
  56. return { l.x * r.x, l.y * r.y, l.z * r.z };
  57. }
  58. vec2 operator*(const vec2& l, float r) {
  59. return { l.x * r, l.y * r };
  60. }
  61. vec3 operator*(const vec3& l, float r) {
  62. return { l.x * r, l.y * r, l.z * r };
  63. }
  64. vec2 operator/(const vec2& l, const vec2& r) {
  65. return{ l.x / r.x, l.y / r.y };
  66. }
  67. vec3 operator/(const vec3& l, const vec3& r) {
  68. return{ l.x / r.x, l.y / r.y, l.z / r.z };
  69. }
  70. vec2 operator/(const vec2& l, float r) {
  71. return{ l.x / r, l.y / r };
  72. }
  73. vec3 operator/(const vec3& l, float r) {
  74. return{ l.x / r, l.y / r, l.z / r };
  75. }
  76. std::ostream& operator<<(std::ostream& os, const vec2& m) {
  77. os << "(" << m.x << ", " << m.y << ")";
  78. return os;
  79. }
  80. std::ostream& operator<<(std::ostream& os, const vec3& m) {
  81. os << "(" << m.x << ", " << m.y << ", " << m.z << ")";
  82. return os;
  83. }
  84. float Dot(const vec2& l, const vec2& r) {
  85. return l.x * r.x + l.y * r.y;
  86. }
  87. float Dot(const vec3& l, const vec3& r) {
  88. return l.x * r.x + l.y * r.y + l.z * r.z;
  89. }
  90. vec2& operator+=(vec2& l, const vec2& r) {
  91. l.x += r.x;
  92. l.y += r.y;
  93. return l;
  94. }
  95. vec2& operator-=(vec2& l, const vec2& r) {
  96. l.x -= r.y;
  97. l.y -= r.y;
  98. return l;
  99. }
  100. vec2& operator*=(vec2& l, const vec2& r) {
  101. l.x *= r.x;
  102. l.y *= r.y;
  103. return l;
  104. }
  105. vec2& operator*=(vec2& l, const float r) {
  106. l.x *= r;
  107. l.y *= r;
  108. return l;
  109. }
  110. vec2& operator/=(vec2& l, const vec2& r) {
  111. l.x /= r.x;
  112. l.y /= r.y;
  113. return l;
  114. }
  115. vec2& operator/=(vec2& l, const float r) {
  116. l.x /= r;
  117. l.y /= r;
  118. return l;
  119. }
  120. vec3& operator+=(vec3& l, const vec3& r) {
  121. l.x += r.x;
  122. l.y += r.y;
  123. l.z += r.z;
  124. return l;
  125. }
  126. vec3& operator-=(vec3& l, const vec3& r) {
  127. l.x -= r.x;
  128. l.y -= r.y;
  129. l.z -= r.z;
  130. return l;
  131. }
  132. vec3& operator*=(vec3& l, const vec3& r) {
  133. l.x *= r.x;
  134. l.y *= r.y;
  135. l.z *= r.z;
  136. return l;
  137. }
  138. vec3& operator*=(vec3& l, const float r) {
  139. l.x *= r;
  140. l.y *= r;
  141. l.z *= r;
  142. return l;
  143. }
  144. vec3& operator/=(vec3& l, const vec3& r) {
  145. l.x /= r.x;
  146. l.y /= r.y;
  147. l.z /= r.z;
  148. return l;
  149. }
  150. vec3& operator/=(vec3& l, const float r) {
  151. l.x /= r;
  152. l.y /= r;
  153. l.z /= r;
  154. return l;
  155. }
  156. float Magnitude(const vec2& v) {
  157. return sqrtf(Dot(v, v));
  158. }
  159. float Magnitude(const vec3& v) {
  160. return sqrtf(Dot(v, v));
  161. }
  162. float MagnitudeSq(const vec2& v) {
  163. return Dot(v, v);
  164. }
  165. float MagnitudeSq(const vec3& v) {
  166. return Dot(v, v);
  167. }
  168. float Distance(const vec2& p1, const vec2& p2) {
  169. return Magnitude(p1 - p2);
  170. }
  171. float Distance(const vec3& p1, const vec3& p2) {
  172. return Magnitude(p1 - p2);
  173. }
  174. float DistanceSq(const vec2& p1, const vec2& p2) {
  175. return MagnitudeSq(p1 - p2);
  176. }
  177. float DistanceSq(const vec3& p1, const vec3& p2) {
  178. return MagnitudeSq(p1 - p2);
  179. }
  180. vec2 RotateVector(const vec2& vector, float degrees) {
  181. degrees = DEG2RAD(degrees);
  182. float s = sinf(degrees);
  183. float c = cosf(degrees);
  184. return vec2(
  185. vector.x * c - vector.y * s,
  186. vector.x * s + vector.y * c
  187. );
  188. }
  189. void Normalize(vec2& v) {
  190. v = v * (1.0f / Magnitude(v));
  191. }
  192. void Normalize(vec3& v) {
  193. v = v * (1.0f / Magnitude(v));
  194. }
  195. vec2 Normalized(const vec2& v) {
  196. return v * (1.0f / Magnitude(v));
  197. }
  198. vec3 Normalized(const vec3& v) {
  199. return v * (1.0f / Magnitude(v));
  200. }
  201. vec3 Cross(const vec3& l, const vec3& r) {
  202. vec3 result;
  203. result.x = l.y * r.z - l.z * r.y;
  204. result.y = l.z * r.x - l.x * r.z;
  205. result.z = l.x * r.y - l.y * r.x;
  206. return result;
  207. }
  208. float Angle(const vec2& l, const vec2& r) {
  209. return acosf(Dot(l, r) / sqrtf(MagnitudeSq(l) * MagnitudeSq(r)));
  210. }
  211. float Angle(const vec3& l, const vec3& r) {
  212. return acosf(Dot(l, r) / sqrtf(MagnitudeSq(l) * MagnitudeSq(r)));
  213. }
  214. vec2 Project(const vec2& length, const vec2& direction) {
  215. float dot = Dot(length, direction);
  216. float magSq = MagnitudeSq(direction);
  217. return direction * (dot / magSq);
  218. }
  219. vec3 Project(const vec3& length, const vec3& direction) {
  220. float dot = Dot(length, direction);
  221. float magSq = MagnitudeSq(direction);
  222. return direction * (dot / magSq);
  223. }
  224. vec2 Perpendicular(const vec2& length, const vec2& direction) {
  225. return length - Project(length, direction);
  226. }
  227. vec3 Perpendicular(const vec3& length, const vec3& direction) {
  228. return length - Project(length, direction);
  229. }
  230. vec2 Reflection(const vec2& sourceVector, const vec2& normal) {
  231. return sourceVector - normal * (Dot(sourceVector, normal) * 2.0f );
  232. }
  233. vec3 Reflection(const vec3& sourceVector, const vec3& normal) {
  234. return sourceVector - normal * (Dot(sourceVector, normal) * 2.0f);
  235. }

Blender----vectorbase.h

  1. /******************************************************************************
  2. *
  3. * MantaFlow fluid solver framework
  4. * Copyright 2011-2016 Tobias Pfaff, Nils Thuerey
  5. *
  6. * This program is free software, distributed under the terms of the
  7. * Apache License, Version 2.0
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Basic vector class
  11. *
  12. ******************************************************************************/
  13. #ifndef _VECTORBASE_H
  14. #define _VECTORBASE_H
  15. // get rid of windos min/max defines
  16. #if (defined(WIN32) || defined(_WIN32)) && !defined(NOMINMAX)
  17. # define NOMINMAX
  18. #endif
  19. #include <stdio.h>
  20. #include <string>
  21. #include <limits>
  22. #include <iostream>
  23. #include "general.h"
  24. // if min/max are still around...
  25. #if defined(WIN32) || defined(_WIN32)
  26. # undef min
  27. # undef max
  28. #endif
  29. // redefine usage of some windows functions
  30. #if defined(WIN32) || defined(_WIN32)
  31. # ifndef snprintf
  32. # define snprintf _snprintf
  33. # endif
  34. #endif
  35. // use which fp-precision? 1=float, 2=double
  36. #ifndef FLOATINGPOINT_PRECISION
  37. # define FLOATINGPOINT_PRECISION 1
  38. #endif
  39. // VECTOR_EPSILON is the minimal vector length
  40. // In order to be able to discriminate floating point values near zero, and
  41. // to be sure not to fail a comparison because of roundoff errors, use this
  42. // value as a threshold.
  43. #if FLOATINGPOINT_PRECISION == 1
  44. typedef float Real;
  45. # define VECTOR_EPSILON (1e-6f)
  46. #else
  47. typedef double Real;
  48. # define VECTOR_EPSILON (1e-10)
  49. #endif
  50. #ifndef M_PI
  51. # define M_PI 3.1415926536
  52. #endif
  53. #ifndef M_E
  54. # define M_E 2.7182818284
  55. #endif
  56. namespace Manta {
  57. //! Basic inlined vector class
  58. template<class S> class Vector3D {
  59. public:
  60. //! Constructor
  61. inline Vector3D() : x(0), y(0), z(0)
  62. {
  63. }
  64. //! Copy-Constructor
  65. inline Vector3D(const Vector3D<S> &v) : x(v.x), y(v.y), z(v.z)
  66. {
  67. }
  68. //! Copy-Constructor
  69. inline Vector3D(const int *v) : x((S)v[0]), y((S)v[1]), z((S)v[2])
  70. {
  71. }
  72. //! Copy-Constructor
  73. inline Vector3D(const float *v) : x((S)v[0]), y((S)v[1]), z((S)v[2])
  74. {
  75. }
  76. //! Copy-Constructor
  77. inline Vector3D(const double *v) : x((S)v[0]), y((S)v[1]), z((S)v[2])
  78. {
  79. }
  80. //! Construct a vector from one S
  81. inline Vector3D(S v) : x(v), y(v), z(v)
  82. {
  83. }
  84. //! Construct a vector from three Ss
  85. inline Vector3D(S vx, S vy, S vz) : x(vx), y(vy), z(vz)
  86. {
  87. }
  88. // Operators
  89. //! Assignment operator
  90. inline const Vector3D<S> &operator=(const Vector3D<S> &v)
  91. {
  92. x = v.x;
  93. y = v.y;
  94. z = v.z;
  95. return *this;
  96. }
  97. //! Assignment operator
  98. inline const Vector3D<S> &operator=(S s)
  99. {
  100. x = y = z = s;
  101. return *this;
  102. }
  103. //! Assign and add operator
  104. inline const Vector3D<S> &operator+=(const Vector3D<S> &v)
  105. {
  106. x += v.x;
  107. y += v.y;
  108. z += v.z;
  109. return *this;
  110. }
  111. //! Assign and add operator
  112. inline const Vector3D<S> &operator+=(S s)
  113. {
  114. x += s;
  115. y += s;
  116. z += s;
  117. return *this;
  118. }
  119. //! Assign and sub operator
  120. inline const Vector3D<S> &operator-=(const Vector3D<S> &v)
  121. {
  122. x -= v.x;
  123. y -= v.y;
  124. z -= v.z;
  125. return *this;
  126. }
  127. //! Assign and sub operator
  128. inline const Vector3D<S> &operator-=(S s)
  129. {
  130. x -= s;
  131. y -= s;
  132. z -= s;
  133. return *this;
  134. }
  135. //! Assign and mult operator
  136. inline const Vector3D<S> &operator*=(const Vector3D<S> &v)
  137. {
  138. x *= v.x;
  139. y *= v.y;
  140. z *= v.z;
  141. return *this;
  142. }
  143. //! Assign and mult operator
  144. inline const Vector3D<S> &operator*=(S s)
  145. {
  146. x *= s;
  147. y *= s;
  148. z *= s;
  149. return *this;
  150. }
  151. //! Assign and div operator
  152. inline const Vector3D<S> &operator/=(const Vector3D<S> &v)
  153. {
  154. x /= v.x;
  155. y /= v.y;
  156. z /= v.z;
  157. return *this;
  158. }
  159. //! Assign and div operator
  160. inline const Vector3D<S> &operator/=(S s)
  161. {
  162. x /= s;
  163. y /= s;
  164. z /= s;
  165. return *this;
  166. }
  167. //! Negation operator
  168. inline Vector3D<S> operator-() const
  169. {
  170. return Vector3D<S>(-x, -y, -z);
  171. }
  172. //! Get smallest component
  173. inline S min() const
  174. {
  175. return (x < y) ? ((x < z) ? x : z) : ((y < z) ? y : z);
  176. }
  177. //! Get biggest component
  178. inline S max() const
  179. {
  180. return (x > y) ? ((x > z) ? x : z) : ((y > z) ? y : z);
  181. }
  182. //! Test if all components are zero
  183. inline bool empty()
  184. {
  185. return x == 0 && y == 0 && z == 0;
  186. }
  187. //! access operator
  188. inline S &operator[](unsigned int i)
  189. {
  190. return value[i];
  191. }
  192. //! constant access operator
  193. inline const S &operator[](unsigned int i) const
  194. {
  195. return value[i];
  196. }
  197. //! debug output vector to a string
  198. std::string toString() const;
  199. //! test if nans are present
  200. bool isValid() const;
  201. //! actual values
  202. union {
  203. S value[3];
  204. struct {
  205. S x;
  206. S y;
  207. S z;
  208. };
  209. struct {
  210. S X;
  211. S Y;
  212. S Z;
  213. };
  214. };
  215. //! zero element
  216. static const Vector3D<S> Zero, Invalid;
  217. //! For compatibility with 4d vectors (discards 4th comp)
  218. inline Vector3D(S vx, S vy, S vz, S vDummy) : x(vx), y(vy), z(vz)
  219. {
  220. }
  221. protected:
  222. };
  223. //! helper to check whether value is non-zero
  224. template<class S> inline bool notZero(S v)
  225. {
  226. return (std::abs(v) > VECTOR_EPSILON);
  227. }
  228. template<class S> inline bool notZero(Vector3D<S> v)
  229. {
  230. return (std::abs(norm(v)) > VECTOR_EPSILON);
  231. }
  232. //************************************************************************
  233. // Additional operators
  234. //************************************************************************
  235. //! Addition operator
  236. template<class S> inline Vector3D<S> operator+(const Vector3D<S> &v1, const Vector3D<S> &v2)
  237. {
  238. return Vector3D<S>(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
  239. }
  240. //! Addition operator
  241. template<class S, class S2> inline Vector3D<S> operator+(const Vector3D<S> &v, S2 s)
  242. {
  243. return Vector3D<S>(v.x + s, v.y + s, v.z + s);
  244. }
  245. //! Addition operator
  246. template<class S, class S2> inline Vector3D<S> operator+(S2 s, const Vector3D<S> &v)
  247. {
  248. return Vector3D<S>(v.x + s, v.y + s, v.z + s);
  249. }
  250. //! Subtraction operator
  251. template<class S> inline Vector3D<S> operator-(const Vector3D<S> &v1, const Vector3D<S> &v2)
  252. {
  253. return Vector3D<S>(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
  254. }
  255. //! Subtraction operator
  256. template<class S, class S2> inline Vector3D<S> operator-(const Vector3D<S> &v, S2 s)
  257. {
  258. return Vector3D<S>(v.x - s, v.y - s, v.z - s);
  259. }
  260. //! Subtraction operator
  261. template<class S, class S2> inline Vector3D<S> operator-(S2 s, const Vector3D<S> &v)
  262. {
  263. return Vector3D<S>(s - v.x, s - v.y, s - v.z);
  264. }
  265. //! Multiplication operator
  266. template<class S> inline Vector3D<S> operator*(const Vector3D<S> &v1, const Vector3D<S> &v2)
  267. {
  268. return Vector3D<S>(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z);
  269. }
  270. //! Multiplication operator
  271. template<class S, class S2> inline Vector3D<S> operator*(const Vector3D<S> &v, S2 s)
  272. {
  273. return Vector3D<S>(v.x * s, v.y * s, v.z * s);
  274. }
  275. //! Multiplication operator
  276. template<class S, class S2> inline Vector3D<S> operator*(S2 s, const Vector3D<S> &v)
  277. {
  278. return Vector3D<S>(s * v.x, s * v.y, s * v.z);
  279. }
  280. //! Division operator
  281. template<class S> inline Vector3D<S> operator/(const Vector3D<S> &v1, const Vector3D<S> &v2)
  282. {
  283. return Vector3D<S>(v1.x / v2.x, v1.y / v2.y, v1.z / v2.z);
  284. }
  285. //! Division operator
  286. template<class S, class S2> inline Vector3D<S> operator/(const Vector3D<S> &v, S2 s)
  287. {
  288. return Vector3D<S>(v.x / s, v.y / s, v.z / s);
  289. }
  290. //! Division operator
  291. template<class S, class S2> inline Vector3D<S> operator/(S2 s, const Vector3D<S> &v)
  292. {
  293. return Vector3D<S>(s / v.x, s / v.y, s / v.z);
  294. }
  295. //! Comparison operator
  296. template<class S> inline bool operator==(const Vector3D<S> &s1, const Vector3D<S> &s2)
  297. {
  298. return s1.x == s2.x && s1.y == s2.y && s1.z == s2.z;
  299. }
  300. //! Comparison operator
  301. template<class S> inline bool operator!=(const Vector3D<S> &s1, const Vector3D<S> &s2)
  302. {
  303. return s1.x != s2.x || s1.y != s2.y || s1.z != s2.z;
  304. }
  305. //************************************************************************
  306. // External functions
  307. //************************************************************************
  308. //! Min operator
  309. template<class S> inline Vector3D<S> vmin(const Vector3D<S> &s1, const Vector3D<S> &s2)
  310. {
  311. return Vector3D<S>(std::min(s1.x, s2.x), std::min(s1.y, s2.y), std::min(s1.z, s2.z));
  312. }
  313. //! Min operator
  314. template<class S, class S2> inline Vector3D<S> vmin(const Vector3D<S> &s1, S2 s2)
  315. {
  316. return Vector3D<S>(std::min(s1.x, s2), std::min(s1.y, s2), std::min(s1.z, s2));
  317. }
  318. //! Min operator
  319. template<class S1, class S> inline Vector3D<S> vmin(S1 s1, const Vector3D<S> &s2)
  320. {
  321. return Vector3D<S>(std::min(s1, s2.x), std::min(s1, s2.y), std::min(s1, s2.z));
  322. }
  323. //! Max operator
  324. template<class S> inline Vector3D<S> vmax(const Vector3D<S> &s1, const Vector3D<S> &s2)
  325. {
  326. return Vector3D<S>(std::max(s1.x, s2.x), std::max(s1.y, s2.y), std::max(s1.z, s2.z));
  327. }
  328. //! Max operator
  329. template<class S, class S2> inline Vector3D<S> vmax(const Vector3D<S> &s1, S2 s2)
  330. {
  331. return Vector3D<S>(std::max(s1.x, s2), std::max(s1.y, s2), std::max(s1.z, s2));
  332. }
  333. //! Max operator
  334. template<class S1, class S> inline Vector3D<S> vmax(S1 s1, const Vector3D<S> &s2)
  335. {
  336. return Vector3D<S>(std::max(s1, s2.x), std::max(s1, s2.y), std::max(s1, s2.z));
  337. }
  338. //! Dot product
  339. template<class S> inline S dot(const Vector3D<S> &t, const Vector3D<S> &v)
  340. {
  341. return t.x * v.x + t.y * v.y + t.z * v.z;
  342. }
  343. //! Cross product
  344. template<class S> inline Vector3D<S> cross(const Vector3D<S> &t, const Vector3D<S> &v)
  345. {
  346. Vector3D<S> cp(
  347. ((t.y * v.z) - (t.z * v.y)), ((t.z * v.x) - (t.x * v.z)), ((t.x * v.y) - (t.y * v.x)));
  348. return cp;
  349. }
  350. //! Project a vector into a plane, defined by its normal
  351. /*! Projects a vector into a plane normal to the given vector, which must
  352. have unit length. Self is modified.
  353. \param v The vector to project
  354. \param n The plane normal
  355. \return The projected vector */
  356. template<class S>
  357. inline const Vector3D<S> &projectNormalTo(const Vector3D<S> &v, const Vector3D<S> &n)
  358. {
  359. S sprod = dot(v, n);
  360. return v - n * dot(v, n);
  361. }
  362. //! Compute the magnitude (length) of the vector
  363. //! (clamps to 0 and 1 with VECTOR_EPSILON)
  364. template<class S> inline S norm(const Vector3D<S> &v)
  365. {
  366. S l = v.x * v.x + v.y * v.y + v.z * v.z;
  367. if (l <= VECTOR_EPSILON * VECTOR_EPSILON)
  368. return (0.);
  369. return (fabs(l - 1.) < VECTOR_EPSILON * VECTOR_EPSILON) ? 1. : sqrt(l);
  370. }
  371. //! Compute squared magnitude
  372. template<class S> inline S normSquare(const Vector3D<S> &v)
  373. {
  374. return v.x * v.x + v.y * v.y + v.z * v.z;
  375. }
  376. //! compatibility, allow use of int, Real and Vec inputs with norm/normSquare
  377. inline Real norm(const Real v)
  378. {
  379. return fabs(v);
  380. }
  381. inline Real normSquare(const Real v)
  382. {
  383. return square(v);
  384. }
  385. inline Real norm(const int v)
  386. {
  387. return abs(v);
  388. }
  389. inline Real normSquare(const int v)
  390. {
  391. return square(v);
  392. }
  393. //! Compute sum of all components, allow use of int, Real too
  394. template<class S> inline S sum(const S v)
  395. {
  396. return v;
  397. }
  398. template<class S> inline S sum(const Vector3D<S> &v)
  399. {
  400. return v.x + v.y + v.z;
  401. }
  402. //! Get absolute representation of vector, allow use of int, Real too
  403. inline Real abs(const Real v)
  404. {
  405. return std::fabs(v);
  406. }
  407. inline int abs(const int v)
  408. {
  409. return std::abs(v);
  410. }
  411. template<class S> inline Vector3D<S> abs(const Vector3D<S> &v)
  412. {
  413. Vector3D<S> cp(v.x, v.y, v.z);
  414. for (int i = 0; i < 3; ++i) {
  415. if (cp[i] < 0)
  416. cp[i] *= (-1.0);
  417. }
  418. return cp;
  419. }
  420. //! Returns a normalized vector
  421. template<class S> inline Vector3D<S> getNormalized(const Vector3D<S> &v)
  422. {
  423. S l = v.x * v.x + v.y * v.y + v.z * v.z;
  424. if (fabs(l - 1.) < VECTOR_EPSILON * VECTOR_EPSILON)
  425. return v; /* normalized "enough"... */
  426. else if (l > VECTOR_EPSILON * VECTOR_EPSILON) {
  427. S fac = 1. / sqrt(l);
  428. return Vector3D<S>(v.x * fac, v.y * fac, v.z * fac);
  429. }
  430. else
  431. return Vector3D<S>((S)0);
  432. }
  433. //! Compute the norm of the vector and normalize it.
  434. /*! \return The value of the norm */
  435. template<class S> inline S normalize(Vector3D<S> &v)
  436. {
  437. S norm;
  438. S l = v.x * v.x + v.y * v.y + v.z * v.z;
  439. if (fabs(l - 1.) < VECTOR_EPSILON * VECTOR_EPSILON) {
  440. norm = 1.;
  441. }
  442. else if (l > VECTOR_EPSILON * VECTOR_EPSILON) {
  443. norm = sqrt(l);
  444. v *= 1. / norm;
  445. }
  446. else {
  447. v = Vector3D<S>::Zero;
  448. norm = 0.;
  449. }
  450. return (S)norm;
  451. }
  452. //! Obtain an orthogonal vector
  453. /*! Compute a vector that is orthonormal to the given vector.
  454. * Nothing else can be assumed for the direction of the new vector.
  455. * \return The orthonormal vector */
  456. template<class S> Vector3D<S> getOrthogonalVector(const Vector3D<S> &v)
  457. {
  458. // Determine the component with max. absolute value
  459. int maxIndex = (fabs(v.x) > fabs(v.y)) ? 0 : 1;
  460. maxIndex = (fabs(v[maxIndex]) > fabs(v.z)) ? maxIndex : 2;
  461. // Choose another axis than the one with max. component and project
  462. // orthogonal to self
  463. Vector3D<S> o(0.0);
  464. o[(maxIndex + 1) % 3] = 1;
  465. Vector3D<S> c = cross(v, o);
  466. normalize(c);
  467. return c;
  468. }
  469. //! Convert vector to polar coordinates
  470. /*! Stable vector to angle conversion
  471. *\param v vector to convert
  472. \param phi unique angle [0,2PI]
  473. \param theta unique angle [0,PI]
  474. */
  475. template<class S> inline void vecToAngle(const Vector3D<S> &v, S &phi, S &theta)
  476. {
  477. if (fabs(v.y) < VECTOR_EPSILON)
  478. theta = M_PI / 2;
  479. else if (fabs(v.x) < VECTOR_EPSILON && fabs(v.z) < VECTOR_EPSILON)
  480. theta = (v.y >= 0) ? 0 : M_PI;
  481. else
  482. theta = atan(sqrt(v.x * v.x + v.z * v.z) / v.y);
  483. if (theta < 0)
  484. theta += M_PI;
  485. if (fabs(v.x) < VECTOR_EPSILON)
  486. phi = M_PI / 2;
  487. else
  488. phi = atan(v.z / v.x);
  489. if (phi < 0)
  490. phi += M_PI;
  491. if (fabs(v.z) < VECTOR_EPSILON)
  492. phi = (v.x >= 0) ? 0 : M_PI;
  493. else if (v.z < 0)
  494. phi += M_PI;
  495. }
  496. //! Compute vector reflected at a surface
  497. /*! Compute a vector, that is self (as an incoming vector)
  498. * reflected at a surface with a distinct normal vector.
  499. * Note that the normal is reversed, if the scalar product with it is positive.
  500. \param t The incoming vector
  501. \param n The surface normal
  502. \return The new reflected vector
  503. */
  504. template<class S> inline Vector3D<S> reflectVector(const Vector3D<S> &t, const Vector3D<S> &n)
  505. {
  506. Vector3D<S> nn = (dot(t, n) > 0.0) ? (n * -1.0) : n;
  507. return (t - nn * (2.0 * dot(nn, t)));
  508. }
  509. //! Compute vector refracted at a surface
  510. /*! \param t The incoming vector
  511. * \param n The surface normal
  512. * \param nt The "inside" refraction index
  513. * \param nair The "outside" refraction index
  514. * \param refRefl Set to 1 on total reflection
  515. * \return The refracted vector
  516. */
  517. template<class S>
  518. inline Vector3D<S> refractVector(
  519. const Vector3D<S> &t, const Vector3D<S> &normal, S nt, S nair, int &refRefl)
  520. {
  521. // from Glassner's book, section 5.2 (Heckberts method)
  522. S eta = nair / nt;
  523. S n = -dot(t, normal);
  524. S tt = 1.0 + eta * eta * (n * n - 1.0);
  525. if (tt < 0.0) {
  526. // we have total reflection!
  527. refRefl = 1;
  528. }
  529. else {
  530. // normal reflection
  531. tt = eta * n - sqrt(tt);
  532. return (t * eta + normal * tt);
  533. }
  534. return t;
  535. }
  536. //! Outputs the object in human readable form as string
  537. template<class S> std::string Vector3D<S>::toString() const
  538. {
  539. char buf[256];
  540. snprintf(buf,
  541. 256,
  542. "[%+4.6f,%+4.6f,%+4.6f]",
  543. (double)(*this)[0],
  544. (double)(*this)[1],
  545. (double)(*this)[2]);
  546. // for debugging, optionally increase precision:
  547. // snprintf ( buf,256,"[%+4.16f,%+4.16f,%+4.16f]", ( double ) ( *this ) [0], ( double ) ( *this )
  548. // [1], ( double ) ( *this ) [2] );
  549. return std::string(buf);
  550. }
  551. template<> std::string Vector3D<int>::toString() const;
  552. //! Outputs the object in human readable form to stream
  553. /*! Output format [x,y,z] */
  554. template<class S> std::ostream &operator<<(std::ostream &os, const Vector3D<S> &i)
  555. {
  556. os << i.toString();
  557. return os;
  558. }
  559. //! Reads the contents of the object from a stream
  560. /*! Input format [x,y,z] */
  561. template<class S> std::istream &operator>>(std::istream &is, Vector3D<S> &i)
  562. {
  563. char c;
  564. char dummy[3];
  565. is >> c >> i[0] >> dummy >> i[1] >> dummy >> i[2] >> c;
  566. return is;
  567. }
  568. /**************************************************************************/
  569. // Define default vector alias
  570. /**************************************************************************/
  571. //! 3D vector class of type Real (typically float)
  572. typedef Vector3D<Real> Vec3;
  573. //! 3D vector class of type int
  574. typedef Vector3D<int> Vec3i;
  575. //! convert to Real Vector
  576. template<class T> inline Vec3 toVec3(T v)
  577. {
  578. return Vec3(v[0], v[1], v[2]);
  579. }
  580. //! convert to int Vector
  581. template<class T> inline Vec3i toVec3i(T v)
  582. {
  583. return Vec3i((int)v[0], (int)v[1], (int)v[2]);
  584. }
  585. //! convert to int Vector
  586. template<class T> inline Vec3i toVec3i(T v0, T v1, T v2)
  587. {
  588. return Vec3i((int)v0, (int)v1, (int)v2);
  589. }
  590. //! round, and convert to int Vector
  591. template<class T> inline Vec3i toVec3iRound(T v)
  592. {
  593. return Vec3i((int)round(v[0]), (int)round(v[1]), (int)round(v[2]));
  594. }
  595. template<class T> inline Vec3i toVec3iFloor(T v)
  596. {
  597. return Vec3i((int)floor(v[0]), (int)floor(v[1]), (int)floor(v[2]));
  598. }
  599. //! convert to int Vector if values are close enough to an int
  600. template<class T> inline Vec3i toVec3iChecked(T v)
  601. {
  602. Vec3i ret;
  603. for (size_t i = 0; i < 3; i++) {
  604. Real a = v[i];
  605. if (fabs(a - floor(a + 0.5)) > 1e-5)
  606. errMsg("argument is not an int, cannot convert");
  607. ret[i] = (int)(a + 0.5);
  608. }
  609. return ret;
  610. }
  611. //! convert to double Vector
  612. template<class T> inline Vector3D<double> toVec3d(T v)
  613. {
  614. return Vector3D<double>(v[0], v[1], v[2]);
  615. }
  616. //! convert to float Vector
  617. template<class T> inline Vector3D<float> toVec3f(T v)
  618. {
  619. return Vector3D<float>(v[0], v[1], v[2]);
  620. }
  621. /**************************************************************************/
  622. // Specializations for common math functions
  623. /**************************************************************************/
  624. template<> inline Vec3 clamp<Vec3>(const Vec3 &a, const Vec3 &b, const Vec3 &c)
  625. {
  626. return Vec3(clamp(a.x, b.x, c.x), clamp(a.y, b.y, c.y), clamp(a.z, b.z, c.z));
  627. }
  628. template<> inline Vec3 safeDivide<Vec3>(const Vec3 &a, const Vec3 &b)
  629. {
  630. return Vec3(safeDivide(a.x, b.x), safeDivide(a.y, b.y), safeDivide(a.z, b.z));
  631. }
  632. template<> inline Vec3 nmod<Vec3>(const Vec3 &a, const Vec3 &b)
  633. {
  634. return Vec3(nmod(a.x, b.x), nmod(a.y, b.y), nmod(a.z, b.z));
  635. }
  636. }; // namespace Manta
  637. #endif

Unreal Engine5----Vector.h

  1. // Copyright Epic Games, Inc. All Rights Reserved.
  2. #pragma once
  3. #include "CoreTypes.h"
  4. #include "Misc/AssertionMacros.h"
  5. #include "Math/NumericLimits.h"
  6. #include "Misc/Crc.h"
  7. #include "Math/UnrealMathUtility.h"
  8. #include "Containers/UnrealString.h"
  9. #include "Misc/Parse.h"
  10. #include "Misc/LargeWorldCoordinatesSerializer.h"
  11. #include "Misc/NetworkVersion.h"
  12. #include "Math/Color.h"
  13. #include "Math/IntPoint.h"
  14. #include "Logging/LogMacros.h"
  15. #include "Math/Vector2D.h"
  16. #include "Misc/ByteSwap.h"
  17. #include "Internationalization/Text.h"
  18. #include "Internationalization/Internationalization.h"
  19. #include "Math/IntVector.h"
  20. #include "Math/Axis.h"
  21. #include "Serialization/MemoryLayout.h"
  22. #include "UObject/ObjectVersion.h"
  23. #include <type_traits>
  24. #if PLATFORM_ENABLE_VECTORINTRINSICS
  25. #include "Math/VectorRegister.h"
  26. #endif
  27. #ifdef _MSC_VER
  28. #pragma warning (push)
  29. // Ensure template functions don't generate shadowing warnings against global variables at the point of instantiation.
  30. #pragma warning (disable : 4459)
  31. #endif
  32. // Move out of global namespace to avoid collisions with Chaos::TVector within the physics code.
  33. namespace UE
  34. {
  35. namespace Math
  36. {
  37. template<typename T> struct TPlane;
  38. /**
  39. * A vector in 3-D space composed of components (X, Y, Z) with floating point precision.
  40. */
  41. template<typename T>
  42. struct TVector
  43. {
  44. static_assert(std::is_floating_point_v<T>, "T must be floating point");
  45. public:
  46. using FReal = T;
  47. union
  48. {
  49. struct
  50. {
  51. /** Vector's X component. */
  52. T X;
  53. /** Vector's Y component. */
  54. T Y;
  55. /** Vector's Z component. */
  56. T Z;
  57. };
  58. UE_DEPRECATED(all, "For internal use only")
  59. T XYZ[3];
  60. };
  61. /** A zero vector (0,0,0) */
  62. CORE_API static const TVector<T> ZeroVector;
  63. /** One vector (1,1,1) */
  64. CORE_API static const TVector<T> OneVector;
  65. /** Unreal up vector (0,0,1) */
  66. CORE_API static const TVector<T> UpVector;
  67. /** Unreal down vector (0,0,-1) */
  68. CORE_API static const TVector<T> DownVector;
  69. /** Unreal forward vector (1,0,0) */
  70. CORE_API static const TVector<T> ForwardVector;
  71. /** Unreal backward vector (-1,0,0) */
  72. CORE_API static const TVector<T> BackwardVector;
  73. /** Unreal right vector (0,1,0) */
  74. CORE_API static const TVector<T> RightVector;
  75. /** Unreal left vector (0,-1,0) */
  76. CORE_API static const TVector<T> LeftVector;
  77. /** Unit X axis vector (1,0,0) */
  78. CORE_API static const TVector<T> XAxisVector;
  79. /** Unit Y axis vector (0,1,0) */
  80. CORE_API static const TVector<T> YAxisVector;
  81. /** Unit Z axis vector (0,0,1) */
  82. CORE_API static const TVector<T> ZAxisVector;
  83. /** @return Zero Vector (0,0,0) */
  84. static inline TVector<T> Zero() { return ZeroVector; }
  85. /** @return One Vector (1,1,1) */
  86. static inline TVector<T> One() { return OneVector; }
  87. /** @return Unit X Vector (1,0,0) */
  88. static inline TVector<T> UnitX() { return XAxisVector; }
  89. /** @return Unit Y Vector (0,1,0) */
  90. static inline TVector<T> UnitY() { return YAxisVector; }
  91. /** @return Unit Z Vector (0,0,1) */
  92. static inline TVector<T> UnitZ() { return ZAxisVector; }
  93. public:
  94. #if ENABLE_NAN_DIAGNOSTIC
  95. FORCEINLINE void DiagnosticCheckNaN() const
  96. {
  97. if (ContainsNaN())
  98. {
  99. logOrEnsureNanError(TEXT("FVector contains NaN: %s"), *ToString());
  100. *const_cast<TVector<T>*>(static_cast<const TVector<T>*>(this)) = ZeroVector;
  101. }
  102. }
  103. FORCEINLINE void DiagnosticCheckNaN(const TCHAR* Message) const
  104. {
  105. if (ContainsNaN())
  106. {
  107. logOrEnsureNanError(TEXT("%s: FVector contains NaN: %s"), Message, *ToString());
  108. *const_cast<TVector<T>*>(static_cast<const TVector<T>*>(this)) = ZeroVector;
  109. }
  110. }
  111. #else
  112. FORCEINLINE void DiagnosticCheckNaN() const {}
  113. FORCEINLINE void DiagnosticCheckNaN(const TCHAR* Message) const {}
  114. #endif
  115. /** Default constructor (no initialization). */
  116. FORCEINLINE TVector();
  117. /**
  118. * Constructor initializing all components to a single T value.
  119. *
  120. * @param InF Value to set all components to.
  121. */
  122. explicit FORCEINLINE TVector(T InF);
  123. /**
  124. * Constructor using initial values for each component.
  125. *
  126. * @param InX X Coordinate.
  127. * @param InY Y Coordinate.
  128. * @param InZ Z Coordinate.
  129. */
  130. FORCEINLINE TVector(T InX, T InY, T InZ);
  131. /**
  132. * Constructs a vector from an TVector2<T> and Z value.
  133. *
  134. * @param V Vector to copy from.
  135. * @param InZ Z Coordinate.
  136. */
  137. explicit FORCEINLINE TVector(const TVector2<T> V, T InZ);
  138. /**
  139. * Constructor using the XYZ components from a 4D vector.
  140. *
  141. * @param V 4D Vector to copy from.
  142. */
  143. FORCEINLINE TVector(const UE::Math::TVector4<T>& V);
  144. /**
  145. * Constructs a vector from an FLinearColor.
  146. *
  147. * @param InColor Color to copy from.
  148. */
  149. explicit TVector(const FLinearColor& InColor);
  150. /**
  151. * Constructs a vector from an FIntVector.
  152. *
  153. * @param InVector FIntVector to copy from.
  154. */
  155. explicit TVector(FIntVector InVector);
  156. /**
  157. * Constructs a vector from an FIntPoint.
  158. *
  159. * @param A Int Point used to set X and Y coordinates, Z is set to zero.
  160. */
  161. explicit TVector(FIntPoint A);
  162. /**
  163. * Constructor which initializes all components to zero.
  164. *
  165. * @param EForceInit Force init enum
  166. */
  167. explicit FORCEINLINE TVector(EForceInit);
  168. #ifdef IMPLEMENT_ASSIGNMENT_OPERATOR_MANUALLY
  169. /**
  170. * Copy another TVector<T> into this one
  171. *
  172. * @param Other The other vector.
  173. * @return Reference to vector after copy.
  174. */
  175. FORCEINLINE TVector<T>& operator=(const TVector<T>& Other);
  176. #endif
  177. /**
  178. * Calculate cross product between this and another vector.
  179. *
  180. * @param V The other vector.
  181. * @return The cross product.
  182. */
  183. FORCEINLINE TVector<T> operator^(const TVector<T>& V) const;
  184. /**
  185. * Calculate cross product between this and another vector.
  186. *
  187. * @param V The other vector.
  188. * @return The cross product.
  189. */
  190. FORCEINLINE TVector<T> Cross(const TVector<T>& V2) const;
  191. /**
  192. * Calculate the cross product of two vectors.
  193. *
  194. * @param A The first vector.
  195. * @param B The second vector.
  196. * @return The cross product.
  197. */
  198. FORCEINLINE static TVector<T> CrossProduct(const TVector<T>& A, const TVector<T>& B);
  199. /**
  200. * Calculate the dot product between this and another vector.
  201. *
  202. * @param V The other vector.
  203. * @return The dot product.
  204. */
  205. FORCEINLINE T operator|(const TVector<T>& V) const;
  206. /**
  207. * Calculate the dot product between this and another vector.
  208. *
  209. * @param V The other vector.
  210. * @return The dot product.
  211. */
  212. FORCEINLINE T Dot(const TVector<T>& V) const;
  213. /**
  214. * Calculate the dot product of two vectors.
  215. *
  216. * @param A The first vector.
  217. * @param B The second vector.
  218. * @return The dot product.
  219. */
  220. FORCEINLINE static T DotProduct(const TVector<T>& A, const TVector<T>& B);
  221. /**
  222. * Gets the result of component-wise addition of this and another vector.
  223. *
  224. * @param V The vector to add to this.
  225. * @return The result of vector addition.
  226. */
  227. FORCEINLINE TVector<T> operator+(const TVector<T>& V) const;
  228. /**
  229. * Gets the result of component-wise subtraction of this by another vector.
  230. *
  231. * @param V The vector to subtract from this.
  232. * @return The result of vector subtraction.
  233. */
  234. FORCEINLINE TVector<T> operator-(const TVector<T>& V) const;
  235. /**
  236. * Gets the result of subtracting from each component of the vector.
  237. *
  238. * @param Bias How much to subtract from each component.
  239. * @return The result of subtraction.
  240. */
  241. template<typename FArg, TEMPLATE_REQUIRES(std::is_arithmetic<FArg>::value)>
  242. FORCEINLINE TVector<T> operator-(FArg Bias) const
  243. {
  244. return TVector<T>(X - (T)Bias, Y - (T)Bias, Z - (T)Bias);
  245. }
  246. /**
  247. * Gets the result of adding to each component of the vector.
  248. *
  249. * @param Bias How much to add to each component.
  250. * @return The result of addition.
  251. */
  252. template<typename FArg, TEMPLATE_REQUIRES(std::is_arithmetic<FArg>::value)>
  253. FORCEINLINE TVector<T> operator+(FArg Bias) const
  254. {
  255. return TVector<T>(X + (T)Bias, Y + (T)Bias, Z + (T)Bias);
  256. }
  257. /**
  258. * Gets the result of scaling the vector (multiplying each component by a value).
  259. *
  260. * @param Scale What to multiply each component by.
  261. * @return The result of multiplication.
  262. */
  263. template<typename FArg, TEMPLATE_REQUIRES(std::is_arithmetic<FArg>::value)>
  264. FORCEINLINE TVector<T> operator*(FArg Scale) const
  265. {
  266. return TVector<T>(X * (T)Scale, Y * (T)Scale, Z * (T)Scale);
  267. }
  268. /**
  269. * Gets the result of dividing each component of the vector by a value.
  270. *
  271. * @param Scale What to divide each component by.
  272. * @return The result of division.
  273. */
  274. template<typename FArg, TEMPLATE_REQUIRES(std::is_arithmetic<FArg>::value)>
  275. TVector<T> operator/(FArg Scale) const
  276. {
  277. const T RScale = T(1) / Scale;
  278. return TVector<T>(X * RScale, Y * RScale, Z * RScale);
  279. }
  280. /**
  281. * Gets the result of component-wise multiplication of this vector by another.
  282. *
  283. * @param V The vector to multiply with.
  284. * @return The result of multiplication.
  285. */
  286. FORCEINLINE TVector<T> operator*(const TVector<T>& V) const;
  287. /**
  288. * Gets the result of component-wise division of this vector by another.
  289. *
  290. * @param V The vector to divide by.
  291. * @return The result of division.
  292. */
  293. FORCEINLINE TVector<T> operator/(const TVector<T>& V) const;
  294. // Binary comparison operators.
  295. /**
  296. * Check against another vector for equality.
  297. *
  298. * @param V The vector to check against.
  299. * @return true if the vectors are equal, false otherwise.
  300. */
  301. bool operator==(const TVector<T>& V) const;
  302. /**
  303. * Check against another vector for inequality.
  304. *
  305. * @param V The vector to check against.
  306. * @return true if the vectors are not equal, false otherwise.
  307. */
  308. bool operator!=(const TVector<T>& V) const;
  309. /**
  310. * Check against another vector for equality, within specified error limits.
  311. *
  312. * @param V The vector to check against.
  313. * @param Tolerance Error tolerance.
  314. * @return true if the vectors are equal within tolerance limits, false otherwise.
  315. */
  316. bool Equals(const TVector<T>& V, T Tolerance=KINDA_SMALL_NUMBER) const;
  317. /**
  318. * Checks whether all components of this vector are the same, within a tolerance.
  319. *
  320. * @param Tolerance Error tolerance.
  321. * @return true if the vectors are equal within tolerance limits, false otherwise.
  322. */
  323. bool AllComponentsEqual(T Tolerance=KINDA_SMALL_NUMBER) const;
  324. /**
  325. * Get a negated copy of the vector.
  326. *
  327. * @return A negated copy of the vector.
  328. */
  329. FORCEINLINE TVector<T> operator-() const;
  330. /**
  331. * Adds another vector to this.
  332. * Uses component-wise addition.
  333. *
  334. * @param V Vector to add to this.
  335. * @return Copy of the vector after addition.
  336. */
  337. FORCEINLINE TVector<T> operator+=(const TVector<T>& V);
  338. /**
  339. * Subtracts another vector from this.
  340. * Uses component-wise subtraction.
  341. *
  342. * @param V Vector to subtract from this.
  343. * @return Copy of the vector after subtraction.
  344. */
  345. FORCEINLINE TVector<T> operator-=(const TVector<T>& V);
  346. /**
  347. * Scales the vector.
  348. *
  349. * @param Scale Amount to scale this vector by.
  350. * @return Copy of the vector after scaling.
  351. */
  352. template<typename FArg, TEMPLATE_REQUIRES(std::is_arithmetic<FArg>::value)>
  353. FORCEINLINE TVector<T> operator*=(FArg Scale)
  354. {
  355. X *= Scale; Y *= Scale; Z *= Scale;
  356. DiagnosticCheckNaN();
  357. return *this;
  358. }
  359. /**
  360. * Divides the vector by a number.
  361. *
  362. * @param V What to divide this vector by.
  363. * @return Copy of the vector after division.
  364. */
  365. template<typename FArg, TEMPLATE_REQUIRES(std::is_arithmetic<FArg>::value)>
  366. TVector<T> operator/=(FArg Scale)
  367. {
  368. const T RV = (T)1 / Scale;
  369. X *= RV; Y *= RV; Z *= RV;
  370. DiagnosticCheckNaN();
  371. return *this;
  372. }
  373. /**
  374. * Multiplies the vector with another vector, using component-wise multiplication.
  375. *
  376. * @param V What to multiply this vector with.
  377. * @return Copy of the vector after multiplication.
  378. */
  379. TVector<T> operator*=(const TVector<T>& V);
  380. /**
  381. * Divides the vector by another vector, using component-wise division.
  382. *
  383. * @param V What to divide vector by.
  384. * @return Copy of the vector after division.
  385. */
  386. TVector<T> operator/=(const TVector<T>& V);
  387. /**
  388. * Gets specific component of the vector.
  389. *
  390. * @param Index the index of vector component
  391. * @return reference to component.
  392. */
  393. T& operator[](int32 Index);
  394. /**
  395. * Gets specific component of the vector.
  396. *
  397. * @param Index the index of vector component
  398. * @return Copy of the component.
  399. */
  400. T operator[](int32 Index)const;
  401. /**
  402. * Gets a specific component of the vector.
  403. *
  404. * @param Index The index of the component required.
  405. *
  406. * @return Reference to the specified component.
  407. */
  408. T& Component(int32 Index);
  409. /**
  410. * Gets a specific component of the vector.
  411. *
  412. * @param Index The index of the component required.
  413. * @return Copy of the specified component.
  414. */
  415. T Component(int32 Index) const;
  416. /** Get a specific component of the vector, given a specific axis by enum */
  417. T GetComponentForAxis(EAxis::Type Axis) const;
  418. /** Set a specified componet of the vector, given a specific axis by enum */
  419. void SetComponentForAxis(EAxis::Type Axis, T Component);
  420. public:
  421. // Simple functions.
  422. /**
  423. * Set the values of the vector directly.
  424. *
  425. * @param InX New X coordinate.
  426. * @param InY New Y coordinate.
  427. * @param InZ New Z coordinate.
  428. */
  429. void Set(T InX, T InY, T InZ);
  430. /**
  431. * Get the maximum value of the vector's components.
  432. *
  433. * @return The maximum value of the vector's components.
  434. */
  435. T GetMax() const;
  436. /**
  437. * Get the maximum absolute value of the vector's components.
  438. *
  439. * @return The maximum absolute value of the vector's components.
  440. */
  441. T GetAbsMax() const;
  442. /**
  443. * Get the minimum value of the vector's components.
  444. *
  445. * @return The minimum value of the vector's components.
  446. */
  447. T GetMin() const;
  448. /**
  449. * Get the minimum absolute value of the vector's components.
  450. *
  451. * @return The minimum absolute value of the vector's components.
  452. */
  453. T GetAbsMin() const;
  454. /** Gets the component-wise min of two vectors. */
  455. TVector<T> ComponentMin(const TVector<T>& Other) const;
  456. /** Gets the component-wise max of two vectors. */
  457. TVector<T> ComponentMax(const TVector<T>& Other) const;
  458. /**
  459. * Get a copy of this vector with absolute value of each component.
  460. *
  461. * @return A copy of this vector with absolute value of each component.
  462. */
  463. TVector<T> GetAbs() const;
  464. /**
  465. * Get the length (magnitude) of this vector.
  466. *
  467. * @return The length of this vector.
  468. */
  469. T Size() const;
  470. /**
  471. * Get the length (magnitude) of this vector.
  472. *
  473. * @return The length of this vector.
  474. */
  475. T Length() const;
  476. /**
  477. * Get the squared length of this vector.
  478. *
  479. * @return The squared length of this vector.
  480. */
  481. T SizeSquared() const;
  482. /**
  483. * Get the squared length of this vector.
  484. *
  485. * @return The squared length of this vector.
  486. */
  487. T SquaredLength() const;
  488. /**
  489. * Get the length of the 2D components of this vector.
  490. *
  491. * @return The 2D length of this vector.
  492. */
  493. T Size2D() const ;
  494. /**
  495. * Get the squared length of the 2D components of this vector.
  496. *
  497. * @return The squared 2D length of this vector.
  498. */
  499. T SizeSquared2D() const ;
  500. /**
  501. * Checks whether vector is near to zero within a specified tolerance.
  502. *
  503. * @param Tolerance Error tolerance.
  504. * @return true if the vector is near to zero, false otherwise.
  505. */
  506. bool IsNearlyZero(T Tolerance=KINDA_SMALL_NUMBER) const;
  507. /**
  508. * Checks whether all components of the vector are exactly zero.
  509. *
  510. * @return true if the vector is exactly zero, false otherwise.
  511. */
  512. bool IsZero() const;
  513. /**
  514. * Check if the vector is of unit length, with specified tolerance.
  515. *
  516. * @param LengthSquaredTolerance Tolerance against squared length.
  517. * @return true if the vector is a unit vector within the specified tolerance.
  518. */
  519. FORCEINLINE bool IsUnit(T LengthSquaredTolerance = KINDA_SMALL_NUMBER) const;
  520. /**
  521. * Checks whether vector is normalized.
  522. *
  523. * @return true if normalized, false otherwise.
  524. */
  525. bool IsNormalized() const;
  526. /**
  527. * Normalize this vector in-place if it is larger than a given tolerance. Leaves it unchanged if not.
  528. *
  529. * @param Tolerance Minimum squared length of vector for normalization.
  530. * @return true if the vector was normalized correctly, false otherwise.
  531. */
  532. bool Normalize(T Tolerance=SMALL_NUMBER);
  533. /**
  534. * Calculates normalized version of vector without checking for zero length.
  535. *
  536. * @return Normalized version of vector.
  537. * @see GetSafeNormal()
  538. */
  539. FORCEINLINE TVector<T> GetUnsafeNormal() const;
  540. /**
  541. * Gets a normalized copy of the vector, checking it is safe to do so based on the length.
  542. * Returns zero vector by default if vector length is too small to safely normalize.
  543. *
  544. * @param Tolerance Minimum squared vector length.
  545. * @return A normalized copy if safe, ResultIfZero otherwise.
  546. */
  547. TVector<T> GetSafeNormal(T Tolerance=SMALL_NUMBER, const TVector<T>& ResultIfZero = ZeroVector) const;
  548. /**
  549. * Gets a normalized copy of the 2D components of the vector, checking it is safe to do so. Z is set to zero.
  550. * Returns zero vector by default if vector length is too small to normalize.
  551. *
  552. * @param Tolerance Minimum squared vector length.
  553. * @return Normalized copy if safe, otherwise returns ResultIfZero.
  554. */
  555. TVector<T> GetSafeNormal2D(T Tolerance=SMALL_NUMBER, const TVector<T>& ResultIfZero = ZeroVector) const;
  556. /**
  557. * Util to convert this vector into a unit direction vector and its original length.
  558. *
  559. * @param OutDir Reference passed in to store unit direction vector.
  560. * @param OutLength Reference passed in to store length of the vector.
  561. */
  562. void ToDirectionAndLength(TVector<T>& OutDir, double& OutLength) const;
  563. void ToDirectionAndLength(TVector<T>& OutDir, float& OutLength) const;
  564. /**
  565. * Get a copy of the vector as sign only.
  566. * Each component is set to +1 or -1, with the sign of zero treated as +1.
  567. *
  568. * @param A copy of the vector with each component set to +1 or -1
  569. */
  570. FORCEINLINE TVector<T> GetSignVector() const;
  571. /**
  572. * Projects 2D components of vector based on Z.
  573. *
  574. * @return Projected version of vector based on Z.
  575. */
  576. TVector<T> Projection() const;
  577. /**
  578. * Calculates normalized 2D version of vector without checking for zero length.
  579. *
  580. * @return Normalized version of vector.
  581. * @see GetSafeNormal2D()
  582. */
  583. FORCEINLINE TVector<T> GetUnsafeNormal2D() const;
  584. /**
  585. * Gets a copy of this vector snapped to a grid.
  586. *
  587. * @param GridSz Grid dimension.
  588. * @return A copy of this vector snapped to a grid.
  589. * @see FMath::GridSnap()
  590. */
  591. TVector<T> GridSnap(const T& GridSz) const;
  592. /**
  593. * Get a copy of this vector, clamped inside of a cube.
  594. *
  595. * @param Radius Half size of the cube.
  596. * @return A copy of this vector, bound by cube.
  597. */
  598. TVector<T> BoundToCube(T Radius) const;
  599. /** Get a copy of this vector, clamped inside of a cube. */
  600. TVector<T> BoundToBox(const TVector<T>& Min, const TVector<T> Max) const;
  601. /** Create a copy of this vector, with its magnitude clamped between Min and Max. */
  602. TVector<T> GetClampedToSize(T Min, T Max) const;
  603. /** Create a copy of this vector, with the 2D magnitude clamped between Min and Max. Z is unchanged. */
  604. TVector<T> GetClampedToSize2D(T Min, T Max) const;
  605. /** Create a copy of this vector, with its maximum magnitude clamped to MaxSize. */
  606. TVector<T> GetClampedToMaxSize(T MaxSize) const;
  607. /** Create a copy of this vector, with the maximum 2D magnitude clamped to MaxSize. Z is unchanged. */
  608. TVector<T> GetClampedToMaxSize2D(T MaxSize) const;
  609. /**
  610. * Add a vector to this and clamp the result in a cube.
  611. *
  612. * @param V Vector to add.
  613. * @param Radius Half size of the cube.
  614. */
  615. void AddBounded(const TVector<T>& V, T Radius=MAX_int16);
  616. /**
  617. * Gets the reciprocal of this vector, avoiding division by zero.
  618. * Zero components are set to BIG_NUMBER.
  619. *
  620. * @return Reciprocal of this vector.
  621. */
  622. TVector<T> Reciprocal() const;
  623. /**
  624. * Check whether X, Y and Z are nearly equal.
  625. *
  626. * @param Tolerance Specified Tolerance.
  627. * @return true if X == Y == Z within the specified tolerance.
  628. */
  629. bool IsUniform(T Tolerance=KINDA_SMALL_NUMBER) const;
  630. /**
  631. * Mirror a vector about a normal vector.
  632. *
  633. * @param MirrorNormal Normal vector to mirror about.
  634. * @return Mirrored vector.
  635. */
  636. TVector<T> MirrorByVector(const TVector<T>& MirrorNormal) const;
  637. /**
  638. * Mirrors a vector about a plane.
  639. *
  640. * @param Plane Plane to mirror about.
  641. * @return Mirrored vector.
  642. */
  643. TVector<T> MirrorByPlane(const TPlane<T>& Plane) const;
  644. /**
  645. * Rotates around Axis (assumes Axis.Size() == 1).
  646. *
  647. * @param Angle Angle to rotate (in degrees).
  648. * @param Axis Axis to rotate around.
  649. * @return Rotated Vector.
  650. */
  651. TVector<T> RotateAngleAxis(const T AngleDeg, const TVector<T>& Axis) const;
  652. /**
  653. * Returns the cosine of the angle between this vector and another projected onto the XY plane (no Z).
  654. *
  655. * @param B the other vector to find the 2D cosine of the angle with.
  656. * @return The cosine.
  657. */
  658. FORCEINLINE T CosineAngle2D(TVector<T> B) const;
  659. /**
  660. * Gets a copy of this vector projected onto the input vector.
  661. *
  662. * @param A Vector to project onto, does not assume it is normalized.
  663. * @return Projected vector.
  664. */
  665. FORCEINLINE TVector<T> ProjectOnTo(const TVector<T>& A) const ;
  666. /**
  667. * Gets a copy of this vector projected onto the input vector, which is assumed to be unit length.
  668. *
  669. * @param Normal Vector to project onto (assumed to be unit length).
  670. * @return Projected vector.
  671. */
  672. FORCEINLINE TVector<T> ProjectOnToNormal(const TVector<T>& Normal) const;
  673. /**
  674. * Return the TRotator orientation corresponding to the direction in which the vector points.
  675. * Sets Yaw and Pitch to the proper numbers, and sets Roll to zero because the roll can'T be determined from a vector.
  676. *
  677. * @return TRotator from the Vector's direction, without any roll.
  678. * @see ToOrientationQuat()
  679. */
  680. CORE_API TRotator<T> ToOrientationRotator() const;
  681. /**
  682. * Return the Quaternion orientation corresponding to the direction in which the vector points.
  683. * Similar to the UE::Math::TRotator<T> version, returns a result without roll such that it preserves the up vector.
  684. *
  685. * @note If you don'T care about preserving the up vector and just want the most direct rotation, you can use the faster
  686. * 'FQuat::FindBetweenVectors(FVector::ForwardVector, YourVector)' or 'FQuat::FindBetweenNormals(...)' if you know the vector is of unit length.
  687. *
  688. * @return Quaternion from the Vector's direction, without any roll.
  689. * @see ToOrientationRotator(), FQuat::FindBetweenVectors()
  690. */
  691. CORE_API TQuat<T> ToOrientationQuat() const;
  692. /**
  693. * Return the UE::Math::TRotator<T> orientation corresponding to the direction in which the vector points.
  694. * Sets Yaw and Pitch to the proper numbers, and sets Roll to zero because the roll can't be determined from a vector.
  695. * @note Identical to 'ToOrientationRotator()' and preserved for legacy reasons.
  696. * @return UE::Math::TRotator<T> from the Vector's direction.
  697. * @see ToOrientationRotator(), ToOrientationQuat()
  698. */
  699. FORCEINLINE UE::Math::TRotator<T> Rotation() const
  700. {
  701. return ToOrientationRotator();
  702. }
  703. /**
  704. * Find good arbitrary axis vectors to represent U and V axes of a plane,
  705. * using this vector as the normal of the plane.
  706. *
  707. * @param Axis1 Reference to first axis.
  708. * @param Axis2 Reference to second axis.
  709. */
  710. void FindBestAxisVectors(TVector<T>& Axis1, TVector<T>& Axis2) const;
  711. /** When this vector contains Euler angles (degrees), ensure that angles are between +/-180 */
  712. void UnwindEuler();
  713. /**
  714. * Utility to check if there are any non-finite values (NaN or Inf) in this vector.
  715. *
  716. * @return true if there are any non-finite values in this vector, false otherwise.
  717. */
  718. bool ContainsNaN() const;
  719. /**
  720. * Get a textual representation of this vector.
  721. *
  722. * @return A string describing the vector.
  723. */
  724. FString ToString() const;
  725. /**
  726. * Get a locale aware textual representation of this vector.
  727. *
  728. * @return A string describing the vector.
  729. */
  730. FText ToText() const;
  731. /** Get a short textural representation of this vector, for compact readable logging. */
  732. FString ToCompactString() const;
  733. /** Get a short locale aware textural representation of this vector, for compact readable logging. */
  734. FText ToCompactText() const;
  735. /**
  736. * Initialize this Vector based on an FString. The String is expected to contain X=, Y=, Z=.
  737. * The TVector<T> will be bogus when InitFromString returns false.
  738. *
  739. * @param InSourceString FString containing the vector values.
  740. * @return true if the X,Y,Z values were read successfully; false otherwise.
  741. */
  742. bool InitFromString(const FString& InSourceString);
  743. /**
  744. * Initialize this Vector based on an FString. The String is expected to contain V(0)
  745. * or at least one value X=, Y=, Z=, previously produced by ToCompactString()
  746. * The TVector<T> will be bogus when InitFromString returns false.
  747. *
  748. * @param InSourceString FString containing the vector values.
  749. * @return true if any of the X,Y,Z values were read successfully; false otherwise.
  750. */
  751. bool InitFromCompactString(const FString& InSourceString);
  752. /**
  753. * Converts a Cartesian unit vector into spherical coordinates on the unit sphere.
  754. * @return Output Theta will be in the range [0, PI], and output Phi will be in the range [-PI, PI].
  755. */
  756. TVector2<T> UnitCartesianToSpherical() const;
  757. /**
  758. * Convert a direction vector into a 'heading' angle.
  759. *
  760. * @return 'Heading' angle between +/-PI. 0 is pointing down +X.
  761. */
  762. T HeadingAngle() const;
  763. /**
  764. * Create an orthonormal basis from a basis with at least two orthogonal vectors.
  765. * It may change the directions of the X and Y axes to make the basis orthogonal,
  766. * but it won'T change the direction of the Z axis.
  767. * All axes will be normalized.
  768. *
  769. * @param XAxis The input basis' XAxis, and upon return the orthonormal basis' XAxis.
  770. * @param YAxis The input basis' YAxis, and upon return the orthonormal basis' YAxis.
  771. * @param ZAxis The input basis' ZAxis, and upon return the orthonormal basis' ZAxis.
  772. */
  773. static void CreateOrthonormalBasis(TVector<T>& XAxis,TVector<T>& YAxis,TVector<T>& ZAxis);
  774. /**
  775. * Compare two points and see if they're the same, using a threshold.
  776. *
  777. * @param P First vector.
  778. * @param Q Second vector.
  779. * @return Whether points are the same within a threshold. Uses fast distance approximation (linear per-component distance).
  780. */
  781. static bool PointsAreSame(const TVector<T> &P, const TVector<T> &Q);
  782. /**
  783. * Compare two points and see if they're within specified distance.
  784. *
  785. * @param Point1 First vector.
  786. * @param Point2 Second vector.
  787. * @param Dist Specified distance.
  788. * @return Whether two points are within the specified distance. Uses fast distance approximation (linear per-component distance).
  789. */
  790. static bool PointsAreNear(const TVector<T> &Point1, const TVector<T> &Point2, T Dist);
  791. /**
  792. * Calculate the signed distance (in the direction of the normal) between a point and a plane.
  793. *
  794. * @param Point The Point we are checking.
  795. * @param PlaneBase The Base Point in the plane.
  796. * @param PlaneNormal The Normal of the plane (assumed to be unit length).
  797. * @return Signed distance between point and plane.
  798. */
  799. static T PointPlaneDist(const TVector<T> &Point, const TVector<T> &PlaneBase, const TVector<T> &PlaneNormal);
  800. /**
  801. * Calculate the projection of a point on the given plane.
  802. *
  803. * @param Point The point to project onto the plane
  804. * @param Plane The plane
  805. * @return Projection of Point onto Plane
  806. */
  807. static TVector<T> PointPlaneProject(const TVector<T>& Point, const TPlane<T>& Plane);
  808. /**
  809. * Calculate the projection of a point on the plane defined by counter-clockwise (CCW) points A,B,C.
  810. *
  811. * @param Point The point to project onto the plane
  812. * @param A 1st of three points in CCW order defining the plane
  813. * @param B 2nd of three points in CCW order defining the plane
  814. * @param C 3rd of three points in CCW order defining the plane
  815. * @return Projection of Point onto plane ABC
  816. */
  817. static TVector<T> PointPlaneProject(const TVector<T>& Point, const TVector<T>& A, const TVector<T>& B, const TVector<T>& C);
  818. /**
  819. * Calculate the projection of a point on the plane defined by PlaneBase and PlaneNormal.
  820. *
  821. * @param Point The point to project onto the plane
  822. * @param PlaneBase Point on the plane
  823. * @param PlaneNorm Normal of the plane (assumed to be unit length).
  824. * @return Projection of Point onto plane
  825. */
  826. static TVector<T> PointPlaneProject(const TVector<T>& Point, const TVector<T>& PlaneBase, const TVector<T>& PlaneNormal);
  827. /**
  828. * Calculate the projection of a vector on the plane defined by PlaneNormal.
  829. *
  830. * @param V The vector to project onto the plane.
  831. * @param PlaneNormal Normal of the plane (assumed to be unit length).
  832. * @return Projection of V onto plane.
  833. */
  834. static TVector<T> VectorPlaneProject(const TVector<T>& V, const TVector<T>& PlaneNormal);
  835. /**
  836. * Euclidean distance between two points.
  837. *
  838. * @param V1 The first point.
  839. * @param V2 The second point.
  840. * @return The distance between two points.
  841. */
  842. static FORCEINLINE T Dist(const TVector<T> &V1, const TVector<T> &V2);
  843. static FORCEINLINE T Distance(const TVector<T> &V1, const TVector<T> &V2) { return Dist(V1, V2); }
  844. /**
  845. * Euclidean distance between two points in the XY plane (ignoring Z).
  846. *
  847. * @param V1 The first point.
  848. * @param V2 The second point.
  849. * @return The distance between two points in the XY plane.
  850. */
  851. static FORCEINLINE T DistXY(const TVector<T> &V1, const TVector<T> &V2);
  852. static FORCEINLINE T Dist2D(const TVector<T> &V1, const TVector<T> &V2) { return DistXY(V1, V2); }
  853. /**
  854. * Squared distance between two points.
  855. *
  856. * @param V1 The first point.
  857. * @param V2 The second point.
  858. * @return The squared distance between two points.
  859. */
  860. static FORCEINLINE T DistSquared(const TVector<T> &V1, const TVector<T> &V2);
  861. /**
  862. * Squared distance between two points in the XY plane only.
  863. *
  864. * @param V1 The first point.
  865. * @param V2 The second point.
  866. * @return The squared distance between two points in the XY plane
  867. */
  868. static FORCEINLINE T DistSquaredXY(const TVector<T> &V1, const TVector<T> &V2);
  869. static FORCEINLINE T DistSquared2D(const TVector<T> &V1, const TVector<T> &V2) { return DistSquaredXY(V1, V2); }
  870. /**
  871. * Compute pushout of a box from a plane.
  872. *
  873. * @param Normal The plane normal.
  874. * @param Size The size of the box.
  875. * @return Pushout required.
  876. */
  877. static FORCEINLINE T BoxPushOut(const TVector<T>& Normal, const TVector<T>& Size);
  878. /**
  879. * Min, Max, Min3, Max3 like FMath
  880. */
  881. static FORCEINLINE TVector<T> Min( const TVector<T>& A, const TVector<T>& B );
  882. static FORCEINLINE TVector<T> Max( const TVector<T>& A, const TVector<T>& B );
  883. static FORCEINLINE TVector<T> Min3( const TVector<T>& A, const TVector<T>& B, const TVector<T>& C );
  884. static FORCEINLINE TVector<T> Max3( const TVector<T>& A, const TVector<T>& B, const TVector<T>& C );
  885. /**
  886. * See if two normal vectors are nearly parallel, meaning the angle between them is close to 0 degrees.
  887. *
  888. * @param Normal1 First normalized vector.
  889. * @param Normal1 Second normalized vector.
  890. * @param ParallelCosineThreshold Normals are parallel if absolute value of dot product (cosine of angle between them) is greater than or equal to this. For example: cos(1.0 degrees).
  891. * @return true if vectors are nearly parallel, false otherwise.
  892. */
  893. static bool Parallel(const TVector<T>& Normal1, const TVector<T>& Normal2, T ParallelCosineThreshold = THRESH_NORMALS_ARE_PARALLEL);
  894. /**
  895. * See if two normal vectors are coincident (nearly parallel and point in the same direction).
  896. *
  897. * @param Normal1 First normalized vector.
  898. * @param Normal2 Second normalized vector.
  899. * @param ParallelCosineThreshold Normals are coincident if dot product (cosine of angle between them) is greater than or equal to this. For example: cos(1.0 degrees).
  900. * @return true if vectors are coincident (nearly parallel and point in the same direction), false otherwise.
  901. */
  902. static bool Coincident(const TVector<T>& Normal1, const TVector<T>& Normal2, T ParallelCosineThreshold = THRESH_NORMALS_ARE_PARALLEL);
  903. /**
  904. * See if two normal vectors are nearly orthogonal (perpendicular), meaning the angle between them is close to 90 degrees.
  905. *
  906. * @param Normal1 First normalized vector.
  907. * @param Normal2 Second normalized vector.
  908. * @param OrthogonalCosineThreshold Normals are orthogonal if absolute value of dot product (cosine of angle between them) is less than or equal to this. For example: cos(89.0 degrees).
  909. * @return true if vectors are orthogonal (perpendicular), false otherwise.
  910. */
  911. static bool Orthogonal(const TVector<T>& Normal1, const TVector<T>& Normal2, T OrthogonalCosineThreshold = THRESH_NORMALS_ARE_ORTHOGONAL);
  912. /**
  913. * See if two planes are coplanar. They are coplanar if the normals are nearly parallel and the planes include the same set of points.
  914. *
  915. * @param Base1 The base point in the first plane.
  916. * @param Normal1 The normal of the first plane.
  917. * @param Base2 The base point in the second plane.
  918. * @param Normal2 The normal of the second plane.
  919. * @param ParallelCosineThreshold Normals are parallel if absolute value of dot product is greater than or equal to this.
  920. * @return true if the planes are coplanar, false otherwise.
  921. */
  922. static bool Coplanar(const TVector<T>& Base1, const TVector<T>& Normal1, const TVector<T>& Base2, const TVector<T>& Normal2, T ParallelCosineThreshold = THRESH_NORMALS_ARE_PARALLEL);
  923. /**
  924. * Triple product of three vectors: X dot (Y cross Z).
  925. *
  926. * @param X The first vector.
  927. * @param Y The second vector.
  928. * @param Z The third vector.
  929. * @return The triple product: X dot (Y cross Z).
  930. */
  931. static T Triple(const TVector<T>& X, const TVector<T>& Y, const TVector<T>& Z);
  932. /**
  933. * Generates a list of sample points on a Bezier curve defined by 2 points.
  934. *
  935. * @param ControlPoints Array of 4 FVectors (vert1, controlpoint1, controlpoint2, vert2).
  936. * @param NumPoints Number of samples.
  937. * @param OutPoints Receives the output samples.
  938. * @return The path length.
  939. */
  940. static T EvaluateBezier(const TVector<T>* ControlPoints, int32 NumPoints, TArray<TVector<T>>& OutPoints);
  941. /**
  942. * Converts a vector containing radian values to a vector containing degree values.
  943. *
  944. * @param RadVector Vector containing radian values
  945. * @return Vector containing degree values
  946. */
  947. static TVector<T> RadiansToDegrees(const TVector<T>& RadVector);
  948. /**
  949. * Converts a vector containing degree values to a vector containing radian values.
  950. *
  951. * @param DegVector Vector containing degree values
  952. * @return Vector containing radian values
  953. */
  954. static TVector<T> DegreesToRadians(const TVector<T>& DegVector);
  955. /**
  956. * Given a current set of cluster centers, a set of points, iterate N times to move clusters to be central.
  957. *
  958. * @param Clusters Reference to array of Clusters.
  959. * @param Points Set of points.
  960. * @param NumIterations Number of iterations.
  961. * @param NumConnectionsToBeValid Sometimes you will have long strings that come off the mass of points
  962. * which happen to have been chosen as Cluster starting points. You want to be able to disregard those.
  963. */
  964. static void GenerateClusterCenters(TArray<TVector<T>>& Clusters, const TArray<TVector<T>>& Points, int32 NumIterations, int32 NumConnectionsToBeValid);
  965. bool Serialize(FStructuredArchive::FSlot Slot)
  966. {
  967. Slot << (TVector<T>&)*this;
  968. return true;
  969. }
  970. bool SerializeFromMismatchedTag(FName StructTag, FStructuredArchive::FSlot Slot);
  971. /**
  972. * Network serialization function.
  973. * FVectors NetSerialize without quantization (ie exact values are serialized). se the FVectors_NetQuantize etc (NetSerialization.h) instead.
  974. *
  975. * @see FVector_NetQuantize, FVector_NetQuantize10, FVector_NetQuantize100, FVector_NetQuantizeNormal
  976. */
  977. bool NetSerialize(FArchive& Ar, class UPackageMap* Map, bool& bOutSuccess)
  978. {
  979. if (Ar.EngineNetVer() >= HISTORY_SERIALIZE_DOUBLE_VECTORS_AS_DOUBLES)
  980. {
  981. Ar << X << Y << Z;
  982. }
  983. else
  984. {
  985. checkf(Ar.IsLoading(), TEXT("float -> double conversion applied outside of load!"));
  986. // Always serialize as float
  987. float SX, SY, SZ;
  988. Ar << SX << SY << SZ;
  989. X = SX;
  990. Y = SY;
  991. Z = SZ;
  992. }
  993. return true;
  994. }
  995. // Conversion from other type.
  996. template<typename FArg, TEMPLATE_REQUIRES(!TIsSame<T, FArg>::Value)>
  997. explicit TVector(const TVector<FArg>& From) : TVector<T>((T)From.X, (T)From.Y, (T)From.Z) {}
  998. };
  999. /**
  1000. * Structured archive slot serializer for FVector3f.
  1001. *
  1002. * @param Slot Structured archive slot.
  1003. * @param V Vector to serialize.
  1004. */
  1005. inline void operator<<(FStructuredArchive::FSlot Slot, TVector<float>& V)
  1006. {
  1007. // @warning BulkSerialize: FVector3f is serialized as memory dump
  1008. // See TArray::BulkSerialize for detailed description of implied limitations.
  1009. FStructuredArchive::FRecord Record = Slot.EnterRecord();
  1010. Record << SA_VALUE(TEXT("X"), V.X);
  1011. Record << SA_VALUE(TEXT("Y"), V.Y);
  1012. Record << SA_VALUE(TEXT("Z"), V.Z);
  1013. V.DiagnosticCheckNaN();
  1014. }
  1015. /**
  1016. * Structured archive slot serializer for FVector3d.
  1017. *
  1018. * @param Slot Structured archive slot.
  1019. * @param V Vector to serialize.
  1020. */
  1021. inline void operator<<(FStructuredArchive::FSlot Slot, TVector<double>& V)
  1022. {
  1023. // @warning BulkSerialize: FVector3d is serialized as memory dump
  1024. // See TArray::BulkSerialize for detailed description of implied limitations.
  1025. FStructuredArchive::FRecord Record = Slot.EnterRecord();
  1026. if (Slot.GetUnderlyingArchive().UEVer() >= EUnrealEngineObjectUE5Version::LARGE_WORLD_COORDINATES)
  1027. {
  1028. Record << SA_VALUE(TEXT("X"), V.X);
  1029. Record << SA_VALUE(TEXT("Y"), V.Y);
  1030. Record << SA_VALUE(TEXT("Z"), V.Z);
  1031. }
  1032. else
  1033. {
  1034. checkf(Slot.GetUnderlyingArchive().IsLoading(), TEXT("float -> double conversion applied outside of load!"));
  1035. // Stored as floats, so serialize float and copy.
  1036. float X, Y, Z;
  1037. Record << SA_VALUE(TEXT("X"), X);
  1038. Record << SA_VALUE(TEXT("Y"), Y);
  1039. Record << SA_VALUE(TEXT("Z"), Z);
  1040. V = TVector<double>(X, Y, Z);
  1041. }
  1042. V.DiagnosticCheckNaN();
  1043. }
  1044. /* FVector inline functions
  1045. *****************************************************************************/
  1046. template<typename T>
  1047. FORCEINLINE TVector<T>::TVector(const TVector2<T> V, T InZ)
  1048. : X(V.X), Y(V.Y), Z(InZ)
  1049. {
  1050. DiagnosticCheckNaN();
  1051. }
  1052. template<typename T>
  1053. inline TVector<T> TVector<T>::RotateAngleAxis(const T AngleDeg, const TVector<T>& Axis) const
  1054. {
  1055. T S, C;
  1056. FMath::SinCos(&S, &C, FMath::DegreesToRadians(AngleDeg));
  1057. const T XX = Axis.X * Axis.X;
  1058. const T YY = Axis.Y * Axis.Y;
  1059. const T ZZ = Axis.Z * Axis.Z;
  1060. const T XY = Axis.X * Axis.Y;
  1061. const T YZ = Axis.Y * Axis.Z;
  1062. const T ZX = Axis.Z * Axis.X;
  1063. const T XS = Axis.X * S;
  1064. const T YS = Axis.Y * S;
  1065. const T ZS = Axis.Z * S;
  1066. const T OMC = 1.f - C;
  1067. return TVector<T>(
  1068. (OMC * XX + C) * X + (OMC * XY - ZS) * Y + (OMC * ZX + YS) * Z,
  1069. (OMC * XY + ZS) * X + (OMC * YY + C) * Y + (OMC * YZ - XS) * Z,
  1070. (OMC * ZX - YS) * X + (OMC * YZ + XS) * Y + (OMC * ZZ + C) * Z
  1071. );
  1072. }
  1073. template<typename T>
  1074. inline bool TVector<T>::PointsAreSame(const TVector<T>& P, const TVector<T>& Q)
  1075. {
  1076. T Temp;
  1077. Temp=P.X-Q.X;
  1078. if((Temp > -THRESH_POINTS_ARE_SAME) && (Temp < THRESH_POINTS_ARE_SAME))
  1079. {
  1080. Temp=P.Y-Q.Y;
  1081. if((Temp > -THRESH_POINTS_ARE_SAME) && (Temp < THRESH_POINTS_ARE_SAME))
  1082. {
  1083. Temp=P.Z-Q.Z;
  1084. if((Temp > -THRESH_POINTS_ARE_SAME) && (Temp < THRESH_POINTS_ARE_SAME))
  1085. {
  1086. return true;
  1087. }
  1088. }
  1089. }
  1090. return false;
  1091. }
  1092. template<typename T>
  1093. inline bool TVector<T>::PointsAreNear(const TVector<T>& Point1, const TVector<T>& Point2, T Dist)
  1094. {
  1095. T Temp;
  1096. Temp=(Point1.X - Point2.X); if (FMath::Abs(Temp)>=Dist) return false;
  1097. Temp=(Point1.Y - Point2.Y); if (FMath::Abs(Temp)>=Dist) return false;
  1098. Temp=(Point1.Z - Point2.Z); if (FMath::Abs(Temp)>=Dist) return false;
  1099. return true;
  1100. }
  1101. template<typename T>
  1102. inline T TVector<T>::PointPlaneDist
  1103. (
  1104. const TVector<T> &Point,
  1105. const TVector<T> &PlaneBase,
  1106. const TVector<T> &PlaneNormal
  1107. )
  1108. {
  1109. return (Point - PlaneBase) | PlaneNormal;
  1110. }
  1111. template<typename T>
  1112. inline TVector<T> TVector<T>::PointPlaneProject(const TVector<T>& Point, const TVector<T>& PlaneBase, const TVector<T>& PlaneNorm)
  1113. {
  1114. //Find the distance of X from the plane
  1115. //Add the distance back along the normal from the point
  1116. return Point - TVector<T>::PointPlaneDist(Point,PlaneBase,PlaneNorm) * PlaneNorm;
  1117. }
  1118. template<typename T>
  1119. inline TVector<T> TVector<T>::VectorPlaneProject(const TVector<T>& V, const TVector<T>& PlaneNormal)
  1120. {
  1121. return V - V.ProjectOnToNormal(PlaneNormal);
  1122. }
  1123. template<typename T>
  1124. inline bool TVector<T>::Parallel(const TVector<T>& Normal1, const TVector<T>& Normal2, T ParallelCosineThreshold)
  1125. {
  1126. const T NormalDot = Normal1 | Normal2;
  1127. return FMath::Abs(NormalDot) >= ParallelCosineThreshold;
  1128. }
  1129. template<typename T>
  1130. inline bool TVector<T>::Coincident(const TVector<T>& Normal1, const TVector<T>& Normal2, T ParallelCosineThreshold)
  1131. {
  1132. const T NormalDot = Normal1 | Normal2;
  1133. return NormalDot >= ParallelCosineThreshold;
  1134. }
  1135. template<typename T>
  1136. inline bool TVector<T>::Orthogonal(const TVector<T>& Normal1, const TVector<T>& Normal2, T OrthogonalCosineThreshold)
  1137. {
  1138. const T NormalDot = Normal1 | Normal2;
  1139. return FMath::Abs(NormalDot) <= OrthogonalCosineThreshold;
  1140. }
  1141. template<typename T>
  1142. inline bool TVector<T>::Coplanar(const TVector<T>& Base1, const TVector<T>& Normal1, const TVector<T>& Base2, const TVector<T>& Normal2, T ParallelCosineThreshold)
  1143. {
  1144. if (!TVector<T>::Parallel(Normal1,Normal2,ParallelCosineThreshold)) return false;
  1145. else if (FMath::Abs(TVector<T>::PointPlaneDist (Base2,Base1,Normal1)) > THRESH_POINT_ON_PLANE) return false;
  1146. else return true;
  1147. }
  1148. template<typename T>
  1149. inline T TVector<T>::Triple(const TVector<T>& X, const TVector<T>& Y, const TVector<T>& Z)
  1150. {
  1151. return
  1152. ( (X.X * (Y.Y * Z.Z - Y.Z * Z.Y))
  1153. + (X.Y * (Y.Z * Z.X - Y.X * Z.Z))
  1154. + (X.Z * (Y.X * Z.Y - Y.Y * Z.X)));
  1155. }
  1156. template<typename T>
  1157. inline TVector<T> TVector<T>::RadiansToDegrees(const TVector<T>& RadVector)
  1158. {
  1159. return RadVector * (180.f / PI);
  1160. }
  1161. template<typename T>
  1162. inline TVector<T> TVector<T>::DegreesToRadians(const TVector<T>& DegVector)
  1163. {
  1164. return DegVector * (PI / 180.f);
  1165. }
  1166. template<typename T>
  1167. FORCEINLINE TVector<T>::TVector()
  1168. {}
  1169. template<typename T>
  1170. FORCEINLINE TVector<T>::TVector(T InF)
  1171. : X(InF), Y(InF), Z(InF)
  1172. {
  1173. DiagnosticCheckNaN();
  1174. }
  1175. template<typename T>
  1176. FORCEINLINE TVector<T>::TVector(T InX, T InY, T InZ)
  1177. : X(InX), Y(InY), Z(InZ)
  1178. {
  1179. DiagnosticCheckNaN();
  1180. }
  1181. template<typename T>
  1182. FORCEINLINE TVector<T>::TVector(const FLinearColor& InColor)
  1183. : X(InColor.R), Y(InColor.G), Z(InColor.B)
  1184. {
  1185. DiagnosticCheckNaN();
  1186. }
  1187. template<typename T>
  1188. FORCEINLINE TVector<T>::TVector(FIntVector InVector)
  1189. : X((T)InVector.X), Y((T)InVector.Y), Z((T)InVector.Z)
  1190. {
  1191. DiagnosticCheckNaN();
  1192. }
  1193. template<typename T>
  1194. FORCEINLINE TVector<T>::TVector(FIntPoint A)
  1195. : X((T)A.X), Y((T)A.Y), Z(0.f)
  1196. {
  1197. DiagnosticCheckNaN();
  1198. }
  1199. template<typename T>
  1200. FORCEINLINE TVector<T>::TVector(EForceInit)
  1201. : X(0.0f), Y(0.0f), Z(0.0f)
  1202. {
  1203. DiagnosticCheckNaN();
  1204. }
  1205. #ifdef IMPLEMENT_ASSIGNMENT_OPERATOR_MANUALLY
  1206. template<typename T>
  1207. FORCEINLINE TVector<T>& TVector<T>::operator=(const TVector<T>& Other)
  1208. {
  1209. this->X = Other.X;
  1210. this->Y = Other.Y;
  1211. this->Z = Other.Z;
  1212. DiagnosticCheckNaN();
  1213. return *this;
  1214. }
  1215. #endif
  1216. template<typename T>
  1217. FORCEINLINE TVector<T> TVector<T>::operator^(const TVector<T>& V) const
  1218. {
  1219. return TVector<T>
  1220. (
  1221. Y * V.Z - Z * V.Y,
  1222. Z * V.X - X * V.Z,
  1223. X * V.Y - Y * V.X
  1224. );
  1225. }
  1226. template<typename T>
  1227. FORCEINLINE TVector<T> TVector<T>::Cross(const TVector<T>& V) const
  1228. {
  1229. return *this ^ V;
  1230. }
  1231. template<typename T>
  1232. FORCEINLINE TVector<T> TVector<T>::CrossProduct(const TVector<T>& A, const TVector<T>& B)
  1233. {
  1234. return A ^ B;
  1235. }
  1236. template<typename T>
  1237. FORCEINLINE T TVector<T>::operator|(const TVector<T>& V) const
  1238. {
  1239. return X*V.X + Y*V.Y + Z*V.Z;
  1240. }
  1241. template<typename T>
  1242. FORCEINLINE T TVector<T>::Dot(const TVector<T>& V) const
  1243. {
  1244. return *this | V;
  1245. }
  1246. template<typename T>
  1247. FORCEINLINE T TVector<T>::DotProduct(const TVector<T>& A, const TVector<T>& B)
  1248. {
  1249. return A | B;
  1250. }
  1251. template<typename T>
  1252. FORCEINLINE TVector<T> TVector<T>::operator+(const TVector<T>& V) const
  1253. {
  1254. return TVector<T>(X + V.X, Y + V.Y, Z + V.Z);
  1255. }
  1256. template<typename T>
  1257. FORCEINLINE TVector<T> TVector<T>::operator-(const TVector<T>& V) const
  1258. {
  1259. return TVector<T>(X - V.X, Y - V.Y, Z - V.Z);
  1260. }
  1261. template<typename T>
  1262. FORCEINLINE TVector<T> TVector<T>::operator*(const TVector<T>& V) const
  1263. {
  1264. return TVector<T>(X * V.X, Y * V.Y, Z * V.Z);
  1265. }
  1266. template<typename T>
  1267. FORCEINLINE TVector<T> TVector<T>::operator/(const TVector<T>& V) const
  1268. {
  1269. return TVector<T>(X / V.X, Y / V.Y, Z / V.Z);
  1270. }
  1271. template<typename T>
  1272. FORCEINLINE bool TVector<T>::operator==(const TVector<T>& V) const
  1273. {
  1274. return X==V.X && Y==V.Y && Z==V.Z;
  1275. }
  1276. template<typename T>
  1277. FORCEINLINE bool TVector<T>::operator!=(const TVector<T>& V) const
  1278. {
  1279. return X!=V.X || Y!=V.Y || Z!=V.Z;
  1280. }
  1281. template<typename T>
  1282. FORCEINLINE bool TVector<T>::Equals(const TVector<T>& V, T Tolerance) const
  1283. {
  1284. return FMath::Abs(X-V.X) <= Tolerance && FMath::Abs(Y-V.Y) <= Tolerance && FMath::Abs(Z-V.Z) <= Tolerance;
  1285. }
  1286. template<typename T>
  1287. FORCEINLINE bool TVector<T>::AllComponentsEqual(T Tolerance) const
  1288. {
  1289. return FMath::Abs(X - Y) <= Tolerance && FMath::Abs(X - Z) <= Tolerance && FMath::Abs(Y - Z) <= Tolerance;
  1290. }
  1291. template<typename T>
  1292. FORCEINLINE TVector<T> TVector<T>::operator-() const
  1293. {
  1294. return TVector<T>(-X, -Y, -Z);
  1295. }
  1296. template<typename T>
  1297. FORCEINLINE TVector<T> TVector<T>::operator+=(const TVector<T>& V)
  1298. {
  1299. X += V.X; Y += V.Y; Z += V.Z;
  1300. DiagnosticCheckNaN();
  1301. return *this;
  1302. }
  1303. template<typename T>
  1304. FORCEINLINE TVector<T> TVector<T>::operator-=(const TVector<T>& V)
  1305. {
  1306. X -= V.X; Y -= V.Y; Z -= V.Z;
  1307. DiagnosticCheckNaN();
  1308. return *this;
  1309. }
  1310. template<typename T>
  1311. FORCEINLINE TVector<T> TVector<T>::operator*=(const TVector<T>& V)
  1312. {
  1313. X *= V.X; Y *= V.Y; Z *= V.Z;
  1314. DiagnosticCheckNaN();
  1315. return *this;
  1316. }
  1317. template<typename T>
  1318. FORCEINLINE TVector<T> TVector<T>::operator/=(const TVector<T>& V)
  1319. {
  1320. X /= V.X; Y /= V.Y; Z /= V.Z;
  1321. DiagnosticCheckNaN();
  1322. return *this;
  1323. }
  1324. template<typename T>
  1325. FORCEINLINE T& TVector<T>::operator[](int32 Index)
  1326. {
  1327. checkSlow(Index >= 0 && Index < 3);
  1328. PRAGMA_DISABLE_DEPRECATION_WARNINGS
  1329. return XYZ[Index];
  1330. PRAGMA_ENABLE_DEPRECATION_WARNINGS
  1331. }
  1332. template<typename T>
  1333. FORCEINLINE T TVector<T>::operator[](int32 Index)const
  1334. {
  1335. checkSlow(Index >= 0 && Index < 3);
  1336. PRAGMA_DISABLE_DEPRECATION_WARNINGS
  1337. return XYZ[Index];
  1338. PRAGMA_ENABLE_DEPRECATION_WARNINGS
  1339. }
  1340. template<typename T>
  1341. FORCEINLINE void TVector<T>::Set(T InX, T InY, T InZ)
  1342. {
  1343. X = InX;
  1344. Y = InY;
  1345. Z = InZ;
  1346. DiagnosticCheckNaN();
  1347. }
  1348. template<typename T>
  1349. FORCEINLINE T TVector<T>::GetMax() const
  1350. {
  1351. return FMath::Max(FMath::Max(X,Y),Z);
  1352. }
  1353. template<typename T>
  1354. FORCEINLINE T TVector<T>::GetAbsMax() const
  1355. {
  1356. return FMath::Max(FMath::Max(FMath::Abs(X),FMath::Abs(Y)),FMath::Abs(Z));
  1357. }
  1358. template<typename T>
  1359. FORCEINLINE T TVector<T>::GetMin() const
  1360. {
  1361. return FMath::Min(FMath::Min(X,Y),Z);
  1362. }
  1363. template<typename T>
  1364. FORCEINLINE T TVector<T>::GetAbsMin() const
  1365. {
  1366. return FMath::Min(FMath::Min(FMath::Abs(X),FMath::Abs(Y)),FMath::Abs(Z));
  1367. }
  1368. template<typename T>
  1369. FORCEINLINE TVector<T> TVector<T>::ComponentMin(const TVector<T>& Other) const
  1370. {
  1371. return TVector<T>(FMath::Min(X, Other.X), FMath::Min(Y, Other.Y), FMath::Min(Z, Other.Z));
  1372. }
  1373. template<typename T>
  1374. FORCEINLINE TVector<T> TVector<T>::ComponentMax(const TVector<T>& Other) const
  1375. {
  1376. return TVector<T>(FMath::Max(X, Other.X), FMath::Max(Y, Other.Y), FMath::Max(Z, Other.Z));
  1377. }
  1378. template<typename T>
  1379. FORCEINLINE TVector<T> TVector<T>::GetAbs() const
  1380. {
  1381. return TVector<T>(FMath::Abs(X), FMath::Abs(Y), FMath::Abs(Z));
  1382. }
  1383. template<typename T>
  1384. FORCEINLINE T TVector<T>::Size() const
  1385. {
  1386. return FMath::Sqrt(X*X + Y*Y + Z*Z);
  1387. }
  1388. template<typename T>
  1389. FORCEINLINE T TVector<T>::Length() const
  1390. {
  1391. return Size();
  1392. }
  1393. template<typename T>
  1394. FORCEINLINE T TVector<T>::SizeSquared() const
  1395. {
  1396. return X*X + Y*Y + Z*Z;
  1397. }
  1398. template<typename T>
  1399. FORCEINLINE T TVector<T>::SquaredLength() const
  1400. {
  1401. return SizeSquared();
  1402. }
  1403. template<typename T>
  1404. FORCEINLINE T TVector<T>::Size2D() const
  1405. {
  1406. return FMath::Sqrt(X*X + Y*Y);
  1407. }
  1408. template<typename T>
  1409. FORCEINLINE T TVector<T>::SizeSquared2D() const
  1410. {
  1411. return X*X + Y*Y;
  1412. }
  1413. template<typename T>
  1414. FORCEINLINE bool TVector<T>::IsNearlyZero(T Tolerance) const
  1415. {
  1416. return
  1417. FMath::Abs(X)<=Tolerance
  1418. && FMath::Abs(Y)<=Tolerance
  1419. && FMath::Abs(Z)<=Tolerance;
  1420. }
  1421. template<typename T>
  1422. FORCEINLINE bool TVector<T>::IsZero() const
  1423. {
  1424. return X==0.f && Y==0.f && Z==0.f;
  1425. }
  1426. template<typename T>
  1427. FORCEINLINE bool TVector<T>::Normalize(T Tolerance)
  1428. {
  1429. const T SquareSum = X*X + Y*Y + Z*Z;
  1430. if(SquareSum > Tolerance)
  1431. {
  1432. const T Scale = FMath::InvSqrt(SquareSum);
  1433. X *= Scale; Y *= Scale; Z *= Scale;
  1434. return true;
  1435. }
  1436. return false;
  1437. }
  1438. template<typename T>
  1439. FORCEINLINE bool TVector<T>::IsUnit(T LengthSquaredTolerance) const
  1440. {
  1441. return FMath::Abs(1.0f - SizeSquared()) < LengthSquaredTolerance;
  1442. }
  1443. template<typename T>
  1444. FORCEINLINE bool TVector<T>::IsNormalized() const
  1445. {
  1446. return (FMath::Abs(1.f - SizeSquared()) < THRESH_VECTOR_NORMALIZED);
  1447. }
  1448. template<typename T>
  1449. FORCEINLINE void TVector<T>::ToDirectionAndLength(TVector<T>& OutDir, double& OutLength) const
  1450. {
  1451. OutLength = Size();
  1452. if (OutLength > SMALL_NUMBER)
  1453. {
  1454. T OneOverLength = T(1.0 / OutLength);
  1455. OutDir = TVector<T>(X * OneOverLength, Y * OneOverLength, Z * OneOverLength);
  1456. }
  1457. else
  1458. {
  1459. OutDir = ZeroVector;
  1460. }
  1461. }
  1462. template<typename T>
  1463. FORCEINLINE void TVector<T>::ToDirectionAndLength(TVector<T>& OutDir, float& OutLength) const
  1464. {
  1465. OutLength = (float)Size();
  1466. if (OutLength > SMALL_NUMBER)
  1467. {
  1468. float OneOverLength = 1.0f / OutLength;
  1469. OutDir = TVector<T>(X * OneOverLength, Y * OneOverLength, Z * OneOverLength);
  1470. }
  1471. else
  1472. {
  1473. OutDir = ZeroVector;
  1474. }
  1475. }
  1476. template<typename T>
  1477. FORCEINLINE TVector<T> TVector<T>::GetSignVector() const
  1478. {
  1479. return TVector<T>
  1480. (
  1481. FMath::FloatSelect(X, (T)1, (T)-1), // LWC_TODO: Templatize FMath functionality
  1482. FMath::FloatSelect(Y, (T)1, (T)-1),
  1483. FMath::FloatSelect(Z, (T)1, (T)-1)
  1484. );
  1485. }
  1486. template<typename T>
  1487. FORCEINLINE TVector<T> TVector<T>::Projection() const
  1488. {
  1489. const T RZ = 1.f/Z;
  1490. return TVector<T>(X*RZ, Y*RZ, 1);
  1491. }
  1492. template<typename T>
  1493. FORCEINLINE TVector<T> TVector<T>::GetUnsafeNormal() const
  1494. {
  1495. const T Scale = FMath::InvSqrt(X*X+Y*Y+Z*Z);
  1496. return TVector<T>(X*Scale, Y*Scale, Z*Scale);
  1497. }
  1498. template<typename T>
  1499. FORCEINLINE TVector<T> TVector<T>::GetUnsafeNormal2D() const
  1500. {
  1501. const T Scale = FMath::InvSqrt(X * X + Y * Y);
  1502. return TVector<T>(X*Scale, Y*Scale, 0);
  1503. }
  1504. template<typename T>
  1505. FORCEINLINE TVector<T> TVector<T>::GridSnap(const T& GridSz) const
  1506. {
  1507. return TVector<T>(FMath::GridSnap(X, GridSz),FMath::GridSnap(Y, GridSz),FMath::GridSnap(Z, GridSz));
  1508. }
  1509. template<typename T>
  1510. FORCEINLINE TVector<T> TVector<T>::BoundToCube(T Radius) const
  1511. {
  1512. return TVector<T>
  1513. (
  1514. FMath::Clamp(X,-Radius,Radius),
  1515. FMath::Clamp(Y,-Radius,Radius),
  1516. FMath::Clamp(Z,-Radius,Radius)
  1517. );
  1518. }
  1519. template<typename T>
  1520. FORCEINLINE TVector<T> TVector<T>::BoundToBox(const TVector<T>& Min, const TVector<T> Max) const
  1521. {
  1522. return TVector<T>
  1523. (
  1524. FMath::Clamp(X, Min.X, Max.X),
  1525. FMath::Clamp(Y, Min.Y, Max.Y),
  1526. FMath::Clamp(Z, Min.Z, Max.Z)
  1527. );
  1528. }
  1529. template<typename T>
  1530. FORCEINLINE TVector<T> TVector<T>::GetClampedToSize(T Min, T Max) const
  1531. {
  1532. T VecSize = Size();
  1533. const TVector<T> VecDir = (VecSize > SMALL_NUMBER) ? (*this/VecSize) : ZeroVector;
  1534. VecSize = FMath::Clamp(VecSize, Min, Max);
  1535. return VecSize * VecDir;
  1536. }
  1537. template<typename T>
  1538. FORCEINLINE TVector<T> TVector<T>::GetClampedToSize2D(T Min, T Max) const
  1539. {
  1540. T VecSize2D = Size2D();
  1541. const TVector<T> VecDir = (VecSize2D > SMALL_NUMBER) ? (*this/VecSize2D) : ZeroVector;
  1542. VecSize2D = FMath::Clamp(VecSize2D, Min, Max);
  1543. return TVector<T>(VecSize2D * VecDir.X, VecSize2D * VecDir.Y, Z);
  1544. }
  1545. template<typename T>
  1546. FORCEINLINE TVector<T> TVector<T>::GetClampedToMaxSize(T MaxSize) const
  1547. {
  1548. if (MaxSize < KINDA_SMALL_NUMBER)
  1549. {
  1550. return ZeroVector;
  1551. }
  1552. const T VSq = SizeSquared();
  1553. if (VSq > FMath::Square(MaxSize))
  1554. {
  1555. const T Scale = MaxSize * FMath::InvSqrt(VSq);
  1556. return TVector<T>(X*Scale, Y*Scale, Z*Scale);
  1557. }
  1558. else
  1559. {
  1560. return *this;
  1561. }
  1562. }
  1563. template<typename T>
  1564. FORCEINLINE TVector<T> TVector<T>::GetClampedToMaxSize2D(T MaxSize) const
  1565. {
  1566. if (MaxSize < KINDA_SMALL_NUMBER)
  1567. {
  1568. return TVector<T>(0.f, 0.f, Z);
  1569. }
  1570. const T VSq2D = SizeSquared2D();
  1571. if (VSq2D > FMath::Square(MaxSize))
  1572. {
  1573. const T Scale = MaxSize * FMath::InvSqrt(VSq2D);
  1574. return TVector<T>(X*Scale, Y*Scale, Z);
  1575. }
  1576. else
  1577. {
  1578. return *this;
  1579. }
  1580. }
  1581. template<typename T>
  1582. FORCEINLINE void TVector<T>::AddBounded(const TVector<T>& V, T Radius)
  1583. {
  1584. *this = (*this + V).BoundToCube(Radius);
  1585. }
  1586. template<typename T>
  1587. FORCEINLINE T& TVector<T>::Component(int32 Index)
  1588. {
  1589. PRAGMA_DISABLE_DEPRECATION_WARNINGS
  1590. return XYZ[Index];
  1591. PRAGMA_ENABLE_DEPRECATION_WARNINGS
  1592. }
  1593. template<typename T>
  1594. FORCEINLINE T TVector<T>::Component(int32 Index) const
  1595. {
  1596. PRAGMA_DISABLE_DEPRECATION_WARNINGS
  1597. return XYZ[Index];
  1598. PRAGMA_ENABLE_DEPRECATION_WARNINGS
  1599. }
  1600. template<typename T>
  1601. FORCEINLINE T TVector<T>::GetComponentForAxis(EAxis::Type Axis) const
  1602. {
  1603. switch (Axis)
  1604. {
  1605. case EAxis::X:
  1606. return X;
  1607. case EAxis::Y:
  1608. return Y;
  1609. case EAxis::Z:
  1610. return Z;
  1611. default:
  1612. return 0.f;
  1613. }
  1614. }
  1615. template<typename T>
  1616. FORCEINLINE void TVector<T>::SetComponentForAxis(EAxis::Type Axis, T Component)
  1617. {
  1618. switch (Axis)
  1619. {
  1620. case EAxis::X:
  1621. X = Component;
  1622. break;
  1623. case EAxis::Y:
  1624. Y = Component;
  1625. break;
  1626. case EAxis::Z:
  1627. Z = Component;
  1628. break;
  1629. }
  1630. }
  1631. template<typename T>
  1632. FORCEINLINE TVector<T> TVector<T>::Reciprocal() const
  1633. {
  1634. TVector<T> RecVector;
  1635. if (X!=0.f)
  1636. {
  1637. RecVector.X = 1.f/X;
  1638. }
  1639. else
  1640. {
  1641. RecVector.X = BIG_NUMBER;
  1642. }
  1643. if (Y!=0.f)
  1644. {
  1645. RecVector.Y = 1.f/Y;
  1646. }
  1647. else
  1648. {
  1649. RecVector.Y = BIG_NUMBER;
  1650. }
  1651. if (Z!=0.f)
  1652. {
  1653. RecVector.Z = 1.f/Z;
  1654. }
  1655. else
  1656. {
  1657. RecVector.Z = BIG_NUMBER;
  1658. }
  1659. return RecVector;
  1660. }
  1661. template<typename T>
  1662. FORCEINLINE bool TVector<T>::IsUniform(T Tolerance) const
  1663. {
  1664. return AllComponentsEqual(Tolerance);
  1665. }
  1666. template<typename T>
  1667. FORCEINLINE TVector<T> TVector<T>::MirrorByVector(const TVector<T>& MirrorNormal) const
  1668. {
  1669. return *this - MirrorNormal * (2.f * (*this | MirrorNormal));
  1670. }
  1671. template<typename T>
  1672. FORCEINLINE TVector<T> TVector<T>::GetSafeNormal(T Tolerance, const TVector<T>& ResultIfZero) const
  1673. {
  1674. const T SquareSum = X*X + Y*Y + Z*Z;
  1675. // Not sure if it's safe to add tolerance in there. Might introduce too many errors
  1676. if(SquareSum == 1.f)
  1677. {
  1678. return *this;
  1679. }
  1680. else if(SquareSum < Tolerance)
  1681. {
  1682. return ResultIfZero;
  1683. }
  1684. const T Scale = (T)FMath::InvSqrt(SquareSum);
  1685. return TVector<T>(X*Scale, Y*Scale, Z*Scale);
  1686. }
  1687. template<typename T>
  1688. FORCEINLINE TVector<T> TVector<T>::GetSafeNormal2D(T Tolerance, const TVector<T>& ResultIfZero) const
  1689. {
  1690. const T SquareSum = X*X + Y*Y;
  1691. // Not sure if it's safe to add tolerance in there. Might introduce too many errors
  1692. if(SquareSum == 1.f)
  1693. {
  1694. if(Z == 0.f)
  1695. {
  1696. return *this;
  1697. }
  1698. else
  1699. {
  1700. return TVector<T>(X, Y, 0.f);
  1701. }
  1702. }
  1703. else if(SquareSum < Tolerance)
  1704. {
  1705. return ResultIfZero;
  1706. }
  1707. const T Scale = FMath::InvSqrt(SquareSum);
  1708. return TVector<T>(X*Scale, Y*Scale, 0.f);
  1709. }
  1710. template<typename T>
  1711. FORCEINLINE T TVector<T>::CosineAngle2D(TVector<T> B) const
  1712. {
  1713. TVector<T> A(*this);
  1714. A.Z = 0.0f;
  1715. B.Z = 0.0f;
  1716. A.Normalize();
  1717. B.Normalize();
  1718. return A | B;
  1719. }
  1720. template<typename T>
  1721. FORCEINLINE TVector<T> TVector<T>::ProjectOnTo(const TVector<T>& A) const
  1722. {
  1723. return (A * ((*this | A) / (A | A)));
  1724. }
  1725. template<typename T>
  1726. FORCEINLINE TVector<T> TVector<T>::ProjectOnToNormal(const TVector<T>& Normal) const
  1727. {
  1728. return (Normal * (*this | Normal));
  1729. }
  1730. template<typename T>
  1731. void TVector<T>::GenerateClusterCenters(TArray<TVector<T>>& Clusters, const TArray<TVector<T>>& Points, int32 NumIterations, int32 NumConnectionsToBeValid)
  1732. {
  1733. struct FClusterMovedHereToMakeCompile
  1734. {
  1735. TVector<T> ClusterPosAccum;
  1736. int32 ClusterSize;
  1737. };
  1738. // Check we have >0 points and clusters
  1739. if (Points.Num() == 0 || Clusters.Num() == 0)
  1740. {
  1741. return;
  1742. }
  1743. // Temp storage for each cluster that mirrors the order of the passed in Clusters array
  1744. TArray<FClusterMovedHereToMakeCompile> ClusterData;
  1745. ClusterData.AddZeroed(Clusters.Num());
  1746. // Then iterate
  1747. for (int32 ItCount = 0; ItCount < NumIterations; ItCount++)
  1748. {
  1749. // Classify each point - find closest cluster center
  1750. for (int32 i = 0; i < Points.Num(); i++)
  1751. {
  1752. const TVector<T>& Pos = Points[i];
  1753. // Iterate over all clusters to find closes one
  1754. int32 NearestClusterIndex = INDEX_NONE;
  1755. T NearestClusterDistSqr = BIG_NUMBER;
  1756. for (int32 j = 0; j < Clusters.Num(); j++)
  1757. {
  1758. const T DistSqr = (Pos - Clusters[j]).SizeSquared();
  1759. if (DistSqr < NearestClusterDistSqr)
  1760. {
  1761. NearestClusterDistSqr = DistSqr;
  1762. NearestClusterIndex = j;
  1763. }
  1764. }
  1765. // Update its info with this point
  1766. if (NearestClusterIndex != INDEX_NONE)
  1767. {
  1768. ClusterData[NearestClusterIndex].ClusterPosAccum += Pos;
  1769. ClusterData[NearestClusterIndex].ClusterSize++;
  1770. }
  1771. }
  1772. // All points classified - update cluster center as average of membership
  1773. for (int32 i = 0; i < Clusters.Num(); i++)
  1774. {
  1775. if (ClusterData[i].ClusterSize > 0)
  1776. {
  1777. Clusters[i] = ClusterData[i].ClusterPosAccum / (T)ClusterData[i].ClusterSize;
  1778. }
  1779. }
  1780. }
  1781. // so now after we have possible cluster centers we want to remove the ones that are outliers and not part of the main cluster
  1782. for (int32 i = 0; i < ClusterData.Num(); i++)
  1783. {
  1784. if (ClusterData[i].ClusterSize < NumConnectionsToBeValid)
  1785. {
  1786. Clusters.RemoveAt(i);
  1787. }
  1788. }
  1789. }
  1790. template<typename T>
  1791. T TVector<T>::EvaluateBezier(const TVector<T>* ControlPoints, int32 NumPoints, TArray<TVector<T>>& OutPoints)
  1792. {
  1793. check(ControlPoints);
  1794. check(NumPoints >= 2);
  1795. // var q is the change in t between successive evaluations.
  1796. const T q = 1.f / (T)(NumPoints - 1); // q is dependent on the number of GAPS = POINTS-1
  1797. // recreate the names used in the derivation
  1798. const TVector<T>& P0 = ControlPoints[0];
  1799. const TVector<T>& P1 = ControlPoints[1];
  1800. const TVector<T>& P2 = ControlPoints[2];
  1801. const TVector<T>& P3 = ControlPoints[3];
  1802. // coefficients of the cubic polynomial that we're FDing -
  1803. const TVector<T> a = P0;
  1804. const TVector<T> b = 3 * (P1 - P0);
  1805. const TVector<T> c = 3 * (P2 - 2 * P1 + P0);
  1806. const TVector<T> d = P3 - 3 * P2 + 3 * P1 - P0;
  1807. // initial values of the poly and the 3 diffs -
  1808. TVector<T> S = a; // the poly value
  1809. TVector<T> U = b * q + c * q * q + d * q * q * q; // 1st order diff (quadratic)
  1810. TVector<T> V = 2 * c * q * q + 6 * d * q * q * q; // 2nd order diff (linear)
  1811. TVector<T> W = 6 * d * q * q * q; // 3rd order diff (constant)
  1812. // Path length.
  1813. T Length = 0;
  1814. TVector<T> OldPos = P0;
  1815. OutPoints.Add(P0); // first point on the curve is always P0.
  1816. for (int32 i = 1; i < NumPoints; ++i)
  1817. {
  1818. // calculate the next value and update the deltas
  1819. S += U; // update poly value
  1820. U += V; // update 1st order diff value
  1821. V += W; // update 2st order diff value
  1822. // 3rd order diff is constant => no update needed.
  1823. // Update Length.
  1824. Length += TVector<T>::Dist(S, OldPos);
  1825. OldPos = S;
  1826. OutPoints.Add(S);
  1827. }
  1828. // Return path length as experienced in sequence (linear interpolation between points).
  1829. return Length;
  1830. }
  1831. template<typename T>
  1832. void TVector<T>::CreateOrthonormalBasis(TVector<T>& XAxis, TVector<T>& YAxis, TVector<T>& ZAxis)
  1833. {
  1834. // Project the X and Y axes onto the plane perpendicular to the Z axis.
  1835. XAxis -= (XAxis | ZAxis) / (ZAxis | ZAxis) * ZAxis;
  1836. YAxis -= (YAxis | ZAxis) / (ZAxis | ZAxis) * ZAxis;
  1837. // If the X axis was parallel to the Z axis, choose a vector which is orthogonal to the Y and Z axes.
  1838. if (XAxis.SizeSquared() < DELTA * DELTA)
  1839. {
  1840. XAxis = YAxis ^ ZAxis;
  1841. }
  1842. // If the Y axis was parallel to the Z axis, choose a vector which is orthogonal to the X and Z axes.
  1843. if (YAxis.SizeSquared() < DELTA * DELTA)
  1844. {
  1845. YAxis = XAxis ^ ZAxis;
  1846. }
  1847. // Normalize the basis vectors.
  1848. XAxis.Normalize();
  1849. YAxis.Normalize();
  1850. ZAxis.Normalize();
  1851. }
  1852. template<typename T>
  1853. void TVector<T>::UnwindEuler()
  1854. {
  1855. X = FMath::UnwindDegrees(X);
  1856. Y = FMath::UnwindDegrees(Y);
  1857. Z = FMath::UnwindDegrees(Z);
  1858. }
  1859. template<typename T>
  1860. void TVector<T>::FindBestAxisVectors(TVector<T>& Axis1, TVector<T>& Axis2) const
  1861. {
  1862. const T NX = FMath::Abs(X);
  1863. const T NY = FMath::Abs(Y);
  1864. const T NZ = FMath::Abs(Z);
  1865. // Find best basis vectors.
  1866. if (NZ > NX && NZ > NY) Axis1 = TVector<T>(1, 0, 0);
  1867. else Axis1 = TVector<T>(0, 0, 1);
  1868. TVector<T> Tmp = Axis1 - *this * (Axis1 | *this);
  1869. Axis1 = Tmp.GetSafeNormal();
  1870. Axis2 = Axis1 ^ *this;
  1871. }
  1872. template<typename T>
  1873. FORCEINLINE bool TVector<T>::ContainsNaN() const
  1874. {
  1875. return (!FMath::IsFinite(X) ||
  1876. !FMath::IsFinite(Y) ||
  1877. !FMath::IsFinite(Z));
  1878. }
  1879. template<typename T>
  1880. FORCEINLINE FString TVector<T>::ToString() const
  1881. {
  1882. return FString::Printf(TEXT("X=%3.3f Y=%3.3f Z=%3.3f"), X, Y, Z);
  1883. }
  1884. template<typename T>
  1885. FORCEINLINE FText TVector<T>::ToText() const
  1886. {
  1887. FFormatNamedArguments Args;
  1888. Args.Add(TEXT("X"), X);
  1889. Args.Add(TEXT("Y"), Y);
  1890. Args.Add(TEXT("Z"), Z);
  1891. return FText::Format(NSLOCTEXT("Core", "Vector3", "X={X} Y={Y} Z={Z}"), Args);
  1892. }
  1893. template<typename T>
  1894. FORCEINLINE FText TVector<T>::ToCompactText() const
  1895. {
  1896. if (IsNearlyZero())
  1897. {
  1898. return NSLOCTEXT("Core", "Vector3_CompactZeroVector", "V(0)");
  1899. }
  1900. const bool XIsNotZero = !FMath::IsNearlyZero(X);
  1901. const bool YIsNotZero = !FMath::IsNearlyZero(Y);
  1902. const bool ZIsNotZero = !FMath::IsNearlyZero(Z);
  1903. FNumberFormattingOptions FormatRules;
  1904. FormatRules.MinimumFractionalDigits = 2;
  1905. FormatRules.MinimumIntegralDigits = 0;
  1906. FFormatNamedArguments Args;
  1907. Args.Add(TEXT("X"), FText::AsNumber(X, &FormatRules));
  1908. Args.Add(TEXT("Y"), FText::AsNumber(Y, &FormatRules));
  1909. Args.Add(TEXT("Z"), FText::AsNumber(Z, &FormatRules));
  1910. if (XIsNotZero && YIsNotZero && ZIsNotZero)
  1911. {
  1912. return FText::Format(NSLOCTEXT("Core", "Vector3_CompactXYZ", "V(X={X}, Y={Y}, Z={Z})"), Args);
  1913. }
  1914. else if (!XIsNotZero && YIsNotZero && ZIsNotZero)
  1915. {
  1916. return FText::Format(NSLOCTEXT("Core", "Vector3_CompactYZ", "V(Y={Y}, Z={Z})"), Args);
  1917. }
  1918. else if (XIsNotZero && !YIsNotZero && ZIsNotZero)
  1919. {
  1920. return FText::Format(NSLOCTEXT("Core", "Vector3_CompactXZ", "V(X={X}, Z={Z})"), Args);
  1921. }
  1922. else if (XIsNotZero && YIsNotZero && !ZIsNotZero)
  1923. {
  1924. return FText::Format(NSLOCTEXT("Core", "Vector3_CompactXY", "V(X={X}, Y={Y})"), Args);
  1925. }
  1926. else if (!XIsNotZero && !YIsNotZero && ZIsNotZero)
  1927. {
  1928. return FText::Format(NSLOCTEXT("Core", "Vector3_CompactZ", "V(Z={Z})"), Args);
  1929. }
  1930. else if (XIsNotZero && !YIsNotZero && !ZIsNotZero)
  1931. {
  1932. return FText::Format(NSLOCTEXT("Core", "Vector3_CompactX", "V(X={X})"), Args);
  1933. }
  1934. else if (!XIsNotZero && YIsNotZero && !ZIsNotZero)
  1935. {
  1936. return FText::Format(NSLOCTEXT("Core", "Vector3_CompactY", "V(Y={Y})"), Args);
  1937. }
  1938. return NSLOCTEXT("Core", "Vector3_CompactZeroVector", "V(0)");
  1939. }
  1940. template<typename T>
  1941. FORCEINLINE FString TVector<T>::ToCompactString() const
  1942. {
  1943. if(IsNearlyZero())
  1944. {
  1945. return FString::Printf(TEXT("V(0)"));
  1946. }
  1947. FString ReturnString(TEXT("V("));
  1948. bool bIsEmptyString = true;
  1949. if(!FMath::IsNearlyZero(X))
  1950. {
  1951. ReturnString += FString::Printf(TEXT("X=%.2f"), X);
  1952. bIsEmptyString = false;
  1953. }
  1954. if(!FMath::IsNearlyZero(Y))
  1955. {
  1956. if(!bIsEmptyString)
  1957. {
  1958. ReturnString += FString(TEXT(", "));
  1959. }
  1960. ReturnString += FString::Printf(TEXT("Y=%.2f"), Y);
  1961. bIsEmptyString = false;
  1962. }
  1963. if(!FMath::IsNearlyZero(Z))
  1964. {
  1965. if(!bIsEmptyString)
  1966. {
  1967. ReturnString += FString(TEXT(", "));
  1968. }
  1969. ReturnString += FString::Printf(TEXT("Z=%.2f"), Z);
  1970. bIsEmptyString = false;
  1971. }
  1972. ReturnString += FString(TEXT(")"));
  1973. return ReturnString;
  1974. }
  1975. template<typename T>
  1976. FORCEINLINE bool TVector<T>::InitFromCompactString(const FString& InSourceString)
  1977. {
  1978. bool bAxisFound = false;
  1979. X = Y = Z = 0;
  1980. if (FCString::Strifind(*InSourceString, TEXT("V(0)")) != nullptr)
  1981. {
  1982. return true;
  1983. }
  1984. const bool bSuccessful = FParse::Value(*InSourceString, TEXT("X="), X) | FParse::Value(*InSourceString, TEXT("Y="), Y) | FParse::Value(*InSourceString, TEXT("Z="), Z);
  1985. return bSuccessful;
  1986. }
  1987. template<typename T>
  1988. FORCEINLINE bool TVector<T>::InitFromString(const FString& InSourceString)
  1989. {
  1990. X = Y = Z = 0;
  1991. // The initialization is only successful if the X, Y, and Z values can all be parsed from the string
  1992. const bool bSuccessful = FParse::Value(*InSourceString, TEXT("X=") , X) && FParse::Value(*InSourceString, TEXT("Y="), Y) && FParse::Value(*InSourceString, TEXT("Z="), Z);
  1993. return bSuccessful;
  1994. }
  1995. template<typename T>
  1996. FORCEINLINE TVector2<T> TVector<T>::UnitCartesianToSpherical() const
  1997. {
  1998. checkSlow(IsUnit());
  1999. const T Theta = FMath::Acos(Z / Size());
  2000. const T Phi = FMath::Atan2(Y, X);
  2001. return TVector2<T>(Theta, Phi);
  2002. }
  2003. template<typename T>
  2004. FORCEINLINE T TVector<T>::HeadingAngle() const
  2005. {
  2006. // Project Dir into Z plane.
  2007. TVector<T> PlaneDir = *this;
  2008. PlaneDir.Z = 0.f;
  2009. PlaneDir = PlaneDir.GetSafeNormal();
  2010. T Angle = FMath::Acos(PlaneDir.X);
  2011. if(PlaneDir.Y < 0.0f)
  2012. {
  2013. Angle *= -1.0f;
  2014. }
  2015. return Angle;
  2016. }
  2017. template<typename T>
  2018. FORCEINLINE T TVector<T>::Dist(const TVector<T>& V1, const TVector<T>& V2)
  2019. {
  2020. return FMath::Sqrt(TVector<T>::DistSquared(V1, V2));
  2021. }
  2022. template<typename T>
  2023. FORCEINLINE T TVector<T>::DistXY(const TVector<T>& V1, const TVector<T>& V2)
  2024. {
  2025. return FMath::Sqrt(TVector<T>::DistSquaredXY(V1, V2));
  2026. }
  2027. template<typename T>
  2028. FORCEINLINE T TVector<T>::DistSquared(const TVector<T>& V1, const TVector<T>& V2)
  2029. {
  2030. return FMath::Square(V2.X-V1.X) + FMath::Square(V2.Y-V1.Y) + FMath::Square(V2.Z-V1.Z);
  2031. }
  2032. template<typename T>
  2033. FORCEINLINE T TVector<T>::DistSquaredXY(const TVector<T>& V1, const TVector<T>& V2)
  2034. {
  2035. return FMath::Square(V2.X-V1.X) + FMath::Square(V2.Y-V1.Y);
  2036. }
  2037. template<typename T>
  2038. FORCEINLINE T TVector<T>::BoxPushOut(const TVector<T>& Normal, const TVector<T>& Size)
  2039. {
  2040. return FMath::Abs(Normal.X*Size.X) + FMath::Abs(Normal.Y*Size.Y) + FMath::Abs(Normal.Z*Size.Z);
  2041. }
  2042. template<typename T>
  2043. FORCEINLINE TVector<T> TVector<T>::Min(const TVector<T>& A, const TVector<T>& B)
  2044. {
  2045. return TVector<T>(
  2046. FMath::Min( A.X, B.X ),
  2047. FMath::Min( A.Y, B.Y ),
  2048. FMath::Min( A.Z, B.Z )
  2049. );
  2050. }
  2051. template<typename T>
  2052. FORCEINLINE TVector<T> TVector<T>::Max(const TVector<T>& A, const TVector<T>& B)
  2053. {
  2054. return TVector<T>(
  2055. FMath::Max( A.X, B.X ),
  2056. FMath::Max( A.Y, B.Y ),
  2057. FMath::Max( A.Z, B.Z )
  2058. );
  2059. }
  2060. template<typename T>
  2061. FORCEINLINE TVector<T> TVector<T>::Min3( const TVector<T>& A, const TVector<T>& B, const TVector<T>& C )
  2062. {
  2063. return TVector<T>(
  2064. FMath::Min3( A.X, B.X, C.X ),
  2065. FMath::Min3( A.Y, B.Y, C.Y ),
  2066. FMath::Min3( A.Z, B.Z, C.Z )
  2067. );
  2068. }
  2069. template<typename T>
  2070. FORCEINLINE TVector<T> TVector<T>::Max3(const TVector<T>& A, const TVector<T>& B, const TVector<T>& C)
  2071. {
  2072. return TVector<T>(
  2073. FMath::Max3( A.X, B.X, C.X ),
  2074. FMath::Max3( A.Y, B.Y, C.Y ),
  2075. FMath::Max3( A.Z, B.Z, C.Z )
  2076. );
  2077. }
  2078. #if !defined(_MSC_VER) || defined(__clang__) // MSVC can't forward declare explicit specializations
  2079. template<> CORE_API const FVector3f FVector3f::ZeroVector;
  2080. template<> CORE_API const FVector3f FVector3f::OneVector;
  2081. template<> CORE_API const FVector3f FVector3f::UpVector;
  2082. template<> CORE_API const FVector3f FVector3f::DownVector;
  2083. template<> CORE_API const FVector3f FVector3f::ForwardVector;
  2084. template<> CORE_API const FVector3f FVector3f::BackwardVector;
  2085. template<> CORE_API const FVector3f FVector3f::RightVector;
  2086. template<> CORE_API const FVector3f FVector3f::LeftVector;
  2087. template<> CORE_API const FVector3f FVector3f::XAxisVector;
  2088. template<> CORE_API const FVector3f FVector3f::YAxisVector;
  2089. template<> CORE_API const FVector3f FVector3f::ZAxisVector;
  2090. template<> CORE_API const FVector3d FVector3d::ZeroVector;
  2091. template<> CORE_API const FVector3d FVector3d::OneVector;
  2092. template<> CORE_API const FVector3d FVector3d::UpVector;
  2093. template<> CORE_API const FVector3d FVector3d::DownVector;
  2094. template<> CORE_API const FVector3d FVector3d::ForwardVector;
  2095. template<> CORE_API const FVector3d FVector3d::BackwardVector;
  2096. template<> CORE_API const FVector3d FVector3d::RightVector;
  2097. template<> CORE_API const FVector3d FVector3d::LeftVector;
  2098. template<> CORE_API const FVector3d FVector3d::XAxisVector;
  2099. template<> CORE_API const FVector3d FVector3d::YAxisVector;
  2100. template<> CORE_API const FVector3d FVector3d::ZAxisVector;
  2101. #endif
  2102. /**
  2103. * Multiplies a vector by a scaling factor.
  2104. *
  2105. * @param Scale Scaling factor.
  2106. * @param V Vector to scale.
  2107. * @return Result of multiplication.
  2108. */
  2109. template<typename T, typename T2, TEMPLATE_REQUIRES(std::is_arithmetic<T2>::value)>
  2110. FORCEINLINE TVector<T> operator*(T2 Scale, const TVector<T>& V)
  2111. {
  2112. return V.operator*(Scale);
  2113. }
  2114. /**
  2115. * Creates a hash value from an FVector.
  2116. *
  2117. * @param Vector the vector to create a hash value for
  2118. * @return The hash value from the components
  2119. */
  2120. template<typename T>
  2121. FORCEINLINE uint32 GetTypeHash(const TVector<T>& Vector)
  2122. {
  2123. // Note: this assumes there's no padding in Vector that could contain uncompared data.
  2124. return FCrc::MemCrc_DEPRECATED(&Vector, sizeof(Vector));
  2125. }
  2126. } // namespace UE::Math
  2127. } // namespace UE
  2128. UE_DECLARE_LWC_TYPE(Vector, 3);
  2129. template<> struct TCanBulkSerialize<FVector3f> { enum { Value = true }; };
  2130. template<> struct TIsPODType<FVector3f> { enum { Value = true }; };
  2131. template<> struct TIsUECoreVariant<FVector3f> { enum { Value = true }; };
  2132. DECLARE_INTRINSIC_TYPE_LAYOUT(FVector3f);
  2133. template<> struct TCanBulkSerialize<FVector3d> { enum { Value = true }; };
  2134. template<> struct TIsPODType<FVector3d> { enum { Value = true }; };
  2135. template<> struct TIsUECoreVariant<FVector3d> { enum { Value = true }; };
  2136. DECLARE_INTRINSIC_TYPE_LAYOUT(FVector3d);
  2137. /** Component-wise clamp for TVector */
  2138. template<typename T>
  2139. FORCEINLINE UE::Math::TVector<T> ClampVector(const UE::Math::TVector<T>& V, const UE::Math::TVector<T>& Min, const UE::Math::TVector<T>& Max)
  2140. {
  2141. return UE::Math::TVector<T>(
  2142. FMath::Clamp(V.X, Min.X, Max.X),
  2143. FMath::Clamp(V.Y, Min.Y, Max.Y),
  2144. FMath::Clamp(V.Z, Min.Z, Max.Z)
  2145. );
  2146. }
  2147. #if PLATFORM_LITTLE_ENDIAN
  2148. #define INTEL_ORDER_VECTOR(x) (x)
  2149. #else
  2150. template<typename T>
  2151. static FORCEINLINE UE::Math::TVector<T> INTEL_ORDER_VECTOR(UE::Math::TVector<T> v)
  2152. {
  2153. return UE::Math::TVector<T>(INTEL_ORDERF(v.X), INTEL_ORDERF(v.Y), INTEL_ORDERF(v.Z));
  2154. }
  2155. #endif
  2156. /**
  2157. * Util to calculate distance from a point to a bounding box
  2158. *
  2159. * @param Mins 3D Point defining the lower values of the axis of the bound box
  2160. * @param Max 3D Point defining the lower values of the axis of the bound box
  2161. * @param Point 3D position of interest
  2162. * @return the distance from the Point to the bounding box.
  2163. */
  2164. template<typename T, typename U>
  2165. FORCEINLINE T ComputeSquaredDistanceFromBoxToPoint(const UE::Math::TVector<T>& Mins, const UE::Math::TVector<T>& Maxs, const UE::Math::TVector<U>& Point)
  2166. {
  2167. // Accumulates the distance as we iterate axis
  2168. T DistSquared = 0;
  2169. // Check each axis for min/max and add the distance accordingly
  2170. // NOTE: Loop manually unrolled for > 2x speed up
  2171. if (Point.X < Mins.X)
  2172. {
  2173. DistSquared += FMath::Square(Point.X - Mins.X);
  2174. }
  2175. else if (Point.X > Maxs.X)
  2176. {
  2177. DistSquared += FMath::Square(Point.X - Maxs.X);
  2178. }
  2179. if (Point.Y < Mins.Y)
  2180. {
  2181. DistSquared += FMath::Square(Point.Y - Mins.Y);
  2182. }
  2183. else if (Point.Y > Maxs.Y)
  2184. {
  2185. DistSquared += FMath::Square(Point.Y - Maxs.Y);
  2186. }
  2187. if (Point.Z < Mins.Z)
  2188. {
  2189. DistSquared += FMath::Square(Point.Z - Mins.Z);
  2190. }
  2191. else if (Point.Z > Maxs.Z)
  2192. {
  2193. DistSquared += FMath::Square(Point.Z - Maxs.Z);
  2194. }
  2195. return DistSquared;
  2196. }
  2197. /* FMath inline functions
  2198. *****************************************************************************/
  2199. template<typename T>
  2200. inline UE::Math::TVector<T> FMath::LinePlaneIntersection
  2201. (
  2202. const UE::Math::TVector<T>&Point1,
  2203. const UE::Math::TVector<T>&Point2,
  2204. const UE::Math::TVector<T>&PlaneOrigin,
  2205. const UE::Math::TVector<T>&PlaneNormal
  2206. )
  2207. {
  2208. return
  2209. Point1
  2210. + (Point2 - Point1)
  2211. * (((PlaneOrigin - Point1)|PlaneNormal) / ((Point2 - Point1)|PlaneNormal));
  2212. }
  2213. template<typename T>
  2214. inline bool FMath::LineSphereIntersection(const UE::Math::TVector<T>& Start, const UE::Math::TVector<T>& Dir, T Length, const UE::Math::TVector<T>& Origin, T Radius)
  2215. {
  2216. const UE::Math::TVector<T> EO = Start - Origin;
  2217. const T v = (Dir | (Origin - Start));
  2218. const T disc = Radius * Radius - ((EO | EO) - v * v);
  2219. if(disc >= 0)
  2220. {
  2221. const T Time = (v - Sqrt(disc)) / Length;
  2222. if(Time >= 0 && Time <= 1)
  2223. return 1;
  2224. else
  2225. return 0;
  2226. }
  2227. else
  2228. return 0;
  2229. }
  2230. inline FVector FMath::VRand()
  2231. {
  2232. FVector Result;
  2233. FVector::FReal L;
  2234. do
  2235. {
  2236. // Check random vectors in the unit sphere so result is statistically uniform.
  2237. Result.X = FRand() * 2.f - 1.f;
  2238. Result.Y = FRand() * 2.f - 1.f;
  2239. Result.Z = FRand() * 2.f - 1.f;
  2240. L = Result.SizeSquared();
  2241. }
  2242. while(L > 1.0f || L < KINDA_SMALL_NUMBER);
  2243. return Result * (1.0f / Sqrt(L));
  2244. }
  2245. FORCEINLINE FIntVector::FIntVector(FVector InVector)
  2246. : X(FMath::TruncToInt32(InVector.X))
  2247. , Y(FMath::TruncToInt32(InVector.Y))
  2248. , Z(FMath::TruncToInt32(InVector.Z))
  2249. {
  2250. }
  2251. template<>
  2252. inline bool FVector3f::SerializeFromMismatchedTag(FName StructTag, FStructuredArchive::FSlot Slot)
  2253. {
  2254. return UE_SERIALIZE_VARIANT_FROM_MISMATCHED_TAG(Slot, Vector, Vector3f, Vector3d);
  2255. }
  2256. template<>
  2257. inline bool FVector3d::SerializeFromMismatchedTag(FName StructTag, FStructuredArchive::FSlot Slot)
  2258. {
  2259. return UE_SERIALIZE_VARIANT_FROM_MISMATCHED_TAG(Slot, Vector, Vector3d, Vector3f);
  2260. }
  2261. /* TVector2<T> inline functions
  2262. *****************************************************************************/
  2263. namespace UE {
  2264. namespace Math {
  2265. template<typename T>
  2266. FORCEINLINE TVector2<T>::TVector2( const TVector<T>& V )
  2267. : X(V.X), Y(V.Y)
  2268. {
  2269. DiagnosticCheckNaN();
  2270. }
  2271. template<typename T>
  2272. inline TVector<T> TVector2<T>::SphericalToUnitCartesian() const
  2273. {
  2274. const T SinTheta = FMath::Sin(X);
  2275. return TVector<T>(FMath::Cos(Y) * SinTheta, FMath::Sin(Y) * SinTheta, FMath::Cos(X));
  2276. }
  2277. } // namespace UE::Math
  2278. } // namespace UE
  2279. #if PLATFORM_ENABLE_VECTORINTRINSICS
  2280. template<>
  2281. FORCEINLINE_DEBUGGABLE FVector FMath::CubicInterp(const FVector& P0, const FVector& T0, const FVector& P1, const FVector& T1, const float& A)
  2282. {
  2283. static_assert(PLATFORM_ENABLE_VECTORINTRINSICS == 1, "Requires vector intrinsics.");
  2284. FVector res;
  2285. const float A2 = A * A;
  2286. const float A3 = A2 * A;
  2287. const float s0 = (2 * A3) - (3 * A2) + 1;
  2288. const float s1 = A3 - (2 * A2) + A;
  2289. const float s2 = (A3 - A2);
  2290. const float s3 = (-2 * A3) + (3 * A2);
  2291. VectorRegister v0 = VectorMultiply(VectorLoadFloat1(&s0), VectorLoadFloat3(&P0));
  2292. v0 = VectorMultiplyAdd(VectorLoadFloat1(&s1), VectorLoadFloat3(&T0), v0);
  2293. VectorRegister v1 = VectorMultiply(VectorLoadFloat1(&s2), VectorLoadFloat3(&T1));
  2294. v1 = VectorMultiplyAdd(VectorLoadFloat1(&s3), VectorLoadFloat3(&P1), v1);
  2295. VectorStoreFloat3(VectorAdd(v0, v1), &res);
  2296. return res;
  2297. }
  2298. #endif
  2299. #ifdef _MSC_VER
  2300. #pragma warning (pop)
  2301. #endif

Godot----vector3.h

  1. /*************************************************************************/
  2. /* vector3.h */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /*************************************************************************/
  30. #ifndef VECTOR3_H
  31. #define VECTOR3_H
  32. #include "core/error/error_macros.h"
  33. #include "core/math/math_funcs.h"
  34. class String;
  35. struct Basis;
  36. struct Vector2;
  37. struct Vector3i;
  38. struct _NO_DISCARD_ Vector3 {
  39. static const int AXIS_COUNT = 3;
  40. enum Axis {
  41. AXIS_X,
  42. AXIS_Y,
  43. AXIS_Z,
  44. };
  45. union {
  46. struct {
  47. real_t x;
  48. real_t y;
  49. real_t z;
  50. };
  51. real_t coord[3] = { 0 };
  52. };
  53. _FORCE_INLINE_ const real_t &operator[](const int p_axis) const {
  54. DEV_ASSERT((unsigned int)p_axis < 3);
  55. return coord[p_axis];
  56. }
  57. _FORCE_INLINE_ real_t &operator[](const int p_axis) {
  58. DEV_ASSERT((unsigned int)p_axis < 3);
  59. return coord[p_axis];
  60. }
  61. void set_axis(const int p_axis, const real_t p_value);
  62. real_t get_axis(const int p_axis) const;
  63. _FORCE_INLINE_ void set_all(const real_t p_value) {
  64. x = y = z = p_value;
  65. }
  66. _FORCE_INLINE_ Vector3::Axis min_axis_index() const {
  67. return x < y ? (x < z ? Vector3::AXIS_X : Vector3::AXIS_Z) : (y < z ? Vector3::AXIS_Y : Vector3::AXIS_Z);
  68. }
  69. _FORCE_INLINE_ Vector3::Axis max_axis_index() const {
  70. return x < y ? (y < z ? Vector3::AXIS_Z : Vector3::AXIS_Y) : (x < z ? Vector3::AXIS_Z : Vector3::AXIS_X);
  71. }
  72. _FORCE_INLINE_ real_t length() const;
  73. _FORCE_INLINE_ real_t length_squared() const;
  74. _FORCE_INLINE_ void normalize();
  75. _FORCE_INLINE_ Vector3 normalized() const;
  76. _FORCE_INLINE_ bool is_normalized() const;
  77. _FORCE_INLINE_ Vector3 inverse() const;
  78. Vector3 limit_length(const real_t p_len = 1.0) const;
  79. _FORCE_INLINE_ void zero();
  80. void snap(const Vector3 p_val);
  81. Vector3 snapped(const Vector3 p_val) const;
  82. void rotate(const Vector3 &p_axis, const real_t p_angle);
  83. Vector3 rotated(const Vector3 &p_axis, const real_t p_angle) const;
  84. /* Static Methods between 2 vector3s */
  85. _FORCE_INLINE_ Vector3 lerp(const Vector3 &p_to, const real_t p_weight) const;
  86. _FORCE_INLINE_ Vector3 slerp(const Vector3 &p_to, const real_t p_weight) const;
  87. _FORCE_INLINE_ Vector3 cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, const real_t p_weight) const;
  88. _FORCE_INLINE_ Vector3 bezier_interpolate(const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, const real_t p_t) const;
  89. Vector3 move_toward(const Vector3 &p_to, const real_t p_delta) const;
  90. Vector2 octahedron_encode() const;
  91. static Vector3 octahedron_decode(const Vector2 &p_oct);
  92. _FORCE_INLINE_ Vector3 cross(const Vector3 &p_with) const;
  93. _FORCE_INLINE_ real_t dot(const Vector3 &p_with) const;
  94. Basis outer(const Vector3 &p_with) const;
  95. _FORCE_INLINE_ Vector3 abs() const;
  96. _FORCE_INLINE_ Vector3 floor() const;
  97. _FORCE_INLINE_ Vector3 sign() const;
  98. _FORCE_INLINE_ Vector3 ceil() const;
  99. _FORCE_INLINE_ Vector3 round() const;
  100. Vector3 clamp(const Vector3 &p_min, const Vector3 &p_max) const;
  101. _FORCE_INLINE_ real_t distance_to(const Vector3 &p_to) const;
  102. _FORCE_INLINE_ real_t distance_squared_to(const Vector3 &p_to) const;
  103. _FORCE_INLINE_ Vector3 posmod(const real_t p_mod) const;
  104. _FORCE_INLINE_ Vector3 posmodv(const Vector3 &p_modv) const;
  105. _FORCE_INLINE_ Vector3 project(const Vector3 &p_to) const;
  106. _FORCE_INLINE_ real_t angle_to(const Vector3 &p_to) const;
  107. _FORCE_INLINE_ real_t signed_angle_to(const Vector3 &p_to, const Vector3 &p_axis) const;
  108. _FORCE_INLINE_ Vector3 direction_to(const Vector3 &p_to) const;
  109. _FORCE_INLINE_ Vector3 slide(const Vector3 &p_normal) const;
  110. _FORCE_INLINE_ Vector3 bounce(const Vector3 &p_normal) const;
  111. _FORCE_INLINE_ Vector3 reflect(const Vector3 &p_normal) const;
  112. bool is_equal_approx(const Vector3 &p_v) const;
  113. /* Operators */
  114. _FORCE_INLINE_ Vector3 &operator+=(const Vector3 &p_v);
  115. _FORCE_INLINE_ Vector3 operator+(const Vector3 &p_v) const;
  116. _FORCE_INLINE_ Vector3 &operator-=(const Vector3 &p_v);
  117. _FORCE_INLINE_ Vector3 operator-(const Vector3 &p_v) const;
  118. _FORCE_INLINE_ Vector3 &operator*=(const Vector3 &p_v);
  119. _FORCE_INLINE_ Vector3 operator*(const Vector3 &p_v) const;
  120. _FORCE_INLINE_ Vector3 &operator/=(const Vector3 &p_v);
  121. _FORCE_INLINE_ Vector3 operator/(const Vector3 &p_v) const;
  122. _FORCE_INLINE_ Vector3 &operator*=(const real_t p_scalar);
  123. _FORCE_INLINE_ Vector3 operator*(const real_t p_scalar) const;
  124. _FORCE_INLINE_ Vector3 &operator/=(const real_t p_scalar);
  125. _FORCE_INLINE_ Vector3 operator/(const real_t p_scalar) const;
  126. _FORCE_INLINE_ Vector3 operator-() const;
  127. _FORCE_INLINE_ bool operator==(const Vector3 &p_v) const;
  128. _FORCE_INLINE_ bool operator!=(const Vector3 &p_v) const;
  129. _FORCE_INLINE_ bool operator<(const Vector3 &p_v) const;
  130. _FORCE_INLINE_ bool operator<=(const Vector3 &p_v) const;
  131. _FORCE_INLINE_ bool operator>(const Vector3 &p_v) const;
  132. _FORCE_INLINE_ bool operator>=(const Vector3 &p_v) const;
  133. operator String() const;
  134. operator Vector3i() const;
  135. _FORCE_INLINE_ Vector3() {}
  136. _FORCE_INLINE_ Vector3(const real_t p_x, const real_t p_y, const real_t p_z) {
  137. x = p_x;
  138. y = p_y;
  139. z = p_z;
  140. }
  141. };
  142. Vector3 Vector3::cross(const Vector3 &p_with) const {
  143. Vector3 ret(
  144. (y * p_with.z) - (z * p_with.y),
  145. (z * p_with.x) - (x * p_with.z),
  146. (x * p_with.y) - (y * p_with.x));
  147. return ret;
  148. }
  149. real_t Vector3::dot(const Vector3 &p_with) const {
  150. return x * p_with.x + y * p_with.y + z * p_with.z;
  151. }
  152. Vector3 Vector3::abs() const {
  153. return Vector3(Math::abs(x), Math::abs(y), Math::abs(z));
  154. }
  155. Vector3 Vector3::sign() const {
  156. return Vector3(SIGN(x), SIGN(y), SIGN(z));
  157. }
  158. Vector3 Vector3::floor() const {
  159. return Vector3(Math::floor(x), Math::floor(y), Math::floor(z));
  160. }
  161. Vector3 Vector3::ceil() const {
  162. return Vector3(Math::ceil(x), Math::ceil(y), Math::ceil(z));
  163. }
  164. Vector3 Vector3::round() const {
  165. return Vector3(Math::round(x), Math::round(y), Math::round(z));
  166. }
  167. Vector3 Vector3::lerp(const Vector3 &p_to, const real_t p_weight) const {
  168. return Vector3(
  169. x + (p_weight * (p_to.x - x)),
  170. y + (p_weight * (p_to.y - y)),
  171. z + (p_weight * (p_to.z - z)));
  172. }
  173. Vector3 Vector3::slerp(const Vector3 &p_to, const real_t p_weight) const {
  174. real_t start_length_sq = length_squared();
  175. real_t end_length_sq = p_to.length_squared();
  176. if (unlikely(start_length_sq == 0.0f || end_length_sq == 0.0f)) {
  177. // Zero length vectors have no angle, so the best we can do is either lerp or throw an error.
  178. return lerp(p_to, p_weight);
  179. }
  180. real_t start_length = Math::sqrt(start_length_sq);
  181. real_t result_length = Math::lerp(start_length, Math::sqrt(end_length_sq), p_weight);
  182. real_t angle = angle_to(p_to);
  183. return rotated(cross(p_to).normalized(), angle * p_weight) * (result_length / start_length);
  184. }
  185. Vector3 Vector3::cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, const real_t p_weight) const {
  186. Vector3 res = *this;
  187. res.x = Math::cubic_interpolate(res.x, p_b.x, p_pre_a.x, p_post_b.x, p_weight);
  188. res.y = Math::cubic_interpolate(res.y, p_b.y, p_pre_a.y, p_post_b.y, p_weight);
  189. res.z = Math::cubic_interpolate(res.z, p_b.z, p_pre_a.z, p_post_b.z, p_weight);
  190. return res;
  191. }
  192. Vector3 Vector3::bezier_interpolate(const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, const real_t p_t) const {
  193. Vector3 res = *this;
  194. /* Formula from Wikipedia article on Bezier curves. */
  195. real_t omt = (1.0 - p_t);
  196. real_t omt2 = omt * omt;
  197. real_t omt3 = omt2 * omt;
  198. real_t t2 = p_t * p_t;
  199. real_t t3 = t2 * p_t;
  200. return res * omt3 + p_control_1 * omt2 * p_t * 3.0 + p_control_2 * omt * t2 * 3.0 + p_end * t3;
  201. }
  202. real_t Vector3::distance_to(const Vector3 &p_to) const {
  203. return (p_to - *this).length();
  204. }
  205. real_t Vector3::distance_squared_to(const Vector3 &p_to) const {
  206. return (p_to - *this).length_squared();
  207. }
  208. Vector3 Vector3::posmod(const real_t p_mod) const {
  209. return Vector3(Math::fposmod(x, p_mod), Math::fposmod(y, p_mod), Math::fposmod(z, p_mod));
  210. }
  211. Vector3 Vector3::posmodv(const Vector3 &p_modv) const {
  212. return Vector3(Math::fposmod(x, p_modv.x), Math::fposmod(y, p_modv.y), Math::fposmod(z, p_modv.z));
  213. }
  214. Vector3 Vector3::project(const Vector3 &p_to) const {
  215. return p_to * (dot(p_to) / p_to.length_squared());
  216. }
  217. real_t Vector3::angle_to(const Vector3 &p_to) const {
  218. return Math::atan2(cross(p_to).length(), dot(p_to));
  219. }
  220. real_t Vector3::signed_angle_to(const Vector3 &p_to, const Vector3 &p_axis) const {
  221. Vector3 cross_to = cross(p_to);
  222. real_t unsigned_angle = Math::atan2(cross_to.length(), dot(p_to));
  223. real_t sign = cross_to.dot(p_axis);
  224. return (sign < 0) ? -unsigned_angle : unsigned_angle;
  225. }
  226. Vector3 Vector3::direction_to(const Vector3 &p_to) const {
  227. Vector3 ret(p_to.x - x, p_to.y - y, p_to.z - z);
  228. ret.normalize();
  229. return ret;
  230. }
  231. /* Operators */
  232. Vector3 &Vector3::operator+=(const Vector3 &p_v) {
  233. x += p_v.x;
  234. y += p_v.y;
  235. z += p_v.z;
  236. return *this;
  237. }
  238. Vector3 Vector3::operator+(const Vector3 &p_v) const {
  239. return Vector3(x + p_v.x, y + p_v.y, z + p_v.z);
  240. }
  241. Vector3 &Vector3::operator-=(const Vector3 &p_v) {
  242. x -= p_v.x;
  243. y -= p_v.y;
  244. z -= p_v.z;
  245. return *this;
  246. }
  247. Vector3 Vector3::operator-(const Vector3 &p_v) const {
  248. return Vector3(x - p_v.x, y - p_v.y, z - p_v.z);
  249. }
  250. Vector3 &Vector3::operator*=(const Vector3 &p_v) {
  251. x *= p_v.x;
  252. y *= p_v.y;
  253. z *= p_v.z;
  254. return *this;
  255. }
  256. Vector3 Vector3::operator*(const Vector3 &p_v) const {
  257. return Vector3(x * p_v.x, y * p_v.y, z * p_v.z);
  258. }
  259. Vector3 &Vector3::operator/=(const Vector3 &p_v) {
  260. x /= p_v.x;
  261. y /= p_v.y;
  262. z /= p_v.z;
  263. return *this;
  264. }
  265. Vector3 Vector3::operator/(const Vector3 &p_v) const {
  266. return Vector3(x / p_v.x, y / p_v.y, z / p_v.z);
  267. }
  268. Vector3 &Vector3::operator*=(const real_t p_scalar) {
  269. x *= p_scalar;
  270. y *= p_scalar;
  271. z *= p_scalar;
  272. return *this;
  273. }
  274. // Multiplication operators required to workaround issues with LLVM using implicit conversion
  275. // to Vector3i instead for integers where it should not.
  276. _FORCE_INLINE_ Vector3 operator*(const float p_scalar, const Vector3 &p_vec) {
  277. return p_vec * p_scalar;
  278. }
  279. _FORCE_INLINE_ Vector3 operator*(const double p_scalar, const Vector3 &p_vec) {
  280. return p_vec * p_scalar;
  281. }
  282. _FORCE_INLINE_ Vector3 operator*(const int32_t p_scalar, const Vector3 &p_vec) {
  283. return p_vec * p_scalar;
  284. }
  285. _FORCE_INLINE_ Vector3 operator*(const int64_t p_scalar, const Vector3 &p_vec) {
  286. return p_vec * p_scalar;
  287. }
  288. Vector3 Vector3::operator*(const real_t p_scalar) const {
  289. return Vector3(x * p_scalar, y * p_scalar, z * p_scalar);
  290. }
  291. Vector3 &Vector3::operator/=(const real_t p_scalar) {
  292. x /= p_scalar;
  293. y /= p_scalar;
  294. z /= p_scalar;
  295. return *this;
  296. }
  297. Vector3 Vector3::operator/(const real_t p_scalar) const {
  298. return Vector3(x / p_scalar, y / p_scalar, z / p_scalar);
  299. }
  300. Vector3 Vector3::operator-() const {
  301. return Vector3(-x, -y, -z);
  302. }
  303. bool Vector3::operator==(const Vector3 &p_v) const {
  304. return x == p_v.x && y == p_v.y && z == p_v.z;
  305. }
  306. bool Vector3::operator!=(const Vector3 &p_v) const {
  307. return x != p_v.x || y != p_v.y || z != p_v.z;
  308. }
  309. bool Vector3::operator<(const Vector3 &p_v) const {
  310. if (x == p_v.x) {
  311. if (y == p_v.y) {
  312. return z < p_v.z;
  313. }
  314. return y < p_v.y;
  315. }
  316. return x < p_v.x;
  317. }
  318. bool Vector3::operator>(const Vector3 &p_v) const {
  319. if (x == p_v.x) {
  320. if (y == p_v.y) {
  321. return z > p_v.z;
  322. }
  323. return y > p_v.y;
  324. }
  325. return x > p_v.x;
  326. }
  327. bool Vector3::operator<=(const Vector3 &p_v) const {
  328. if (x == p_v.x) {
  329. if (y == p_v.y) {
  330. return z <= p_v.z;
  331. }
  332. return y < p_v.y;
  333. }
  334. return x < p_v.x;
  335. }
  336. bool Vector3::operator>=(const Vector3 &p_v) const {
  337. if (x == p_v.x) {
  338. if (y == p_v.y) {
  339. return z >= p_v.z;
  340. }
  341. return y > p_v.y;
  342. }
  343. return x > p_v.x;
  344. }
  345. _FORCE_INLINE_ Vector3 vec3_cross(const Vector3 &p_a, const Vector3 &p_b) {
  346. return p_a.cross(p_b);
  347. }
  348. _FORCE_INLINE_ real_t vec3_dot(const Vector3 &p_a, const Vector3 &p_b) {
  349. return p_a.dot(p_b);
  350. }
  351. real_t Vector3::length() const {
  352. real_t x2 = x * x;
  353. real_t y2 = y * y;
  354. real_t z2 = z * z;
  355. return Math::sqrt(x2 + y2 + z2);
  356. }
  357. real_t Vector3::length_squared() const {
  358. real_t x2 = x * x;
  359. real_t y2 = y * y;
  360. real_t z2 = z * z;
  361. return x2 + y2 + z2;
  362. }
  363. void Vector3::normalize() {
  364. real_t lengthsq = length_squared();
  365. if (lengthsq == 0) {
  366. x = y = z = 0;
  367. } else {
  368. real_t length = Math::sqrt(lengthsq);
  369. x /= length;
  370. y /= length;
  371. z /= length;
  372. }
  373. }
  374. Vector3 Vector3::normalized() const {
  375. Vector3 v = *this;
  376. v.normalize();
  377. return v;
  378. }
  379. bool Vector3::is_normalized() const {
  380. // use length_squared() instead of length() to avoid sqrt(), makes it more stringent.
  381. return Math::is_equal_approx(length_squared(), 1, (real_t)UNIT_EPSILON);
  382. }
  383. Vector3 Vector3::inverse() const {
  384. return Vector3(1.0f / x, 1.0f / y, 1.0f / z);
  385. }
  386. void Vector3::zero() {
  387. x = y = z = 0;
  388. }
  389. // slide returns the component of the vector along the given plane, specified by its normal vector.
  390. Vector3 Vector3::slide(const Vector3 &p_normal) const {
  391. #ifdef MATH_CHECKS
  392. ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector3(), "The normal Vector3 must be normalized.");
  393. #endif
  394. return *this - p_normal * this->dot(p_normal);
  395. }
  396. Vector3 Vector3::bounce(const Vector3 &p_normal) const {
  397. return -reflect(p_normal);
  398. }
  399. Vector3 Vector3::reflect(const Vector3 &p_normal) const {
  400. #ifdef MATH_CHECKS
  401. ERR_FAIL_COND_V_MSG(!p_normal.is_normalized(), Vector3(), "The normal Vector3 must be normalized.");
  402. #endif
  403. return 2.0f * p_normal * this->dot(p_normal) - *this;
  404. }
  405. #endif // VECTOR3_H

三维空间中向量常见的数学运算

  1. #ifndef __VECTOR_H__
  2. #define __VECTOR_H__
  3. #include <math.h>
  4. template <class T>
  5. struct Vector3
  6. {
  7. // 创建一个三维向量向量
  8. Vector3 (T x_=0, T y_=0, T z_=0) : x(x_), y(y_), z(z_) {}
  9. // 设置三维向量三个方向上的坐标
  10. void set (T x_, T y_, T z_) { x=x_; y=y_; z=z_; }
  11. // 三维向量归一化
  12. Vector3 normalize() const { return((*this) / norm()); }
  13. double norm () const { return sqrt(normSquared()); }
  14. T normSquared () const { return x*x+y*y+z*z; }
  15. // BOOL型操作运算符
  16. bool operator == (const Vector3& v) const { return x==v.x && y==v.y && z==v.z; }
  17. bool operator != (const Vector3& v) const { return x!=v.x || y!=v.y || z!=v.z; }
  18. // 常见的运算符
  19. Vector3 operator + (const Vector3 &v) const { return Vector3(x+v.x, y+v.y, z+v.z); }
  20. Vector3& operator += (const Vector3 &v) { x+=v.x; y+=v.y; z+=v.z; return *this; }
  21. Vector3 operator - () const { return Vector3(-x, -y, -z); }
  22. Vector3 operator - (const Vector3 &v) const { return Vector3(x-v.x, y-v.y, z-v.z); }
  23. Vector3& operator -= (const Vector3 &v) { x-=v.x; y-=v.y; z-=v.z; return *this; }
  24. Vector3 operator * (T s) const { return Vector3(x*s, y*s, z*s); }
  25. Vector3& operator *= (float s) { x*=s; y*=s; z*=s; return *this; }
  26. Vector3 operator / (float s) const { ASSERT(s); return (*this)* (1/s); }
  27. Vector3& operator /= (float s) { ASSERT(s); return (*this)*=(1/s); }
  28. // 三维向量坐标
  29. T x, y, z;
  30. };
  31. template <class T> inline
  32. //三维向量点积
  33. T Dot (const Vector3<T>& l, const Vector3<T>& r)
  34. {
  35. return l.x*r.x + l.y*r.y + l.z*r.z;
  36. }
  37. // 三维向量叉积
  38. template <class T> inline
  39. Vector3<T> Cross (const Vector3<T>& l, const Vector3<T>& r)
  40. {
  41. return Vector3<T>(
  42. l.y*r.z - l.z*r.y,
  43. l.z*r.x - l.x*r.z,
  44. l.x*r.y - l.y*r.x );
  45. }
  46. // 三维向量混合积
  47. template <class T> inline
  48. T BlendProduct (const Vector3<T>& l, const Vector3<T>& m, const Vector3<T>& r)
  49. {
  50. return Dot(Cross(l, m), r);
  51. }
  52. //各种三维向量类型的定义
  53. typedef Vector3<char> Vector3c;
  54. typedef Vector3<int> Vector3i;
  55. typedef Vector3<float> Vector3f;
  56. typedef Vector3<double> Vector3d;
  57. #endif

 

 

 

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
  

闽ICP备14008679号