💿🐜 Antkeeper source code https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

647 lines
17 KiB

  1. /*
  2. * Copyright (C) 2021 Christopher J. Howard
  3. *
  4. * This file is part of Antkeeper source code.
  5. *
  6. * Antkeeper source code is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Antkeeper source code is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #ifndef ANTKEEPER_MATH_VECTOR_FUNCTIONS_HPP
  20. #define ANTKEEPER_MATH_VECTOR_FUNCTIONS_HPP
  21. #include "math/vector-type.hpp"
  22. #include <algorithm>
  23. #include <cmath>
  24. #include <type_traits>
  25. #include <utility>
  26. namespace math {
  27. /**
  28. * Adds two vectors.
  29. *
  30. * @param x First vector.
  31. * @param y Second vector.
  32. * @return Sum of the two vectors.
  33. */
  34. template <class T, std::size_t N>
  35. vector<T, N> add(const vector<T, N>& x, const vector<T, N>& y);
  36. /**
  37. * Checks if all elements of a boolean vector are `true`.
  38. *
  39. * @param x Vector to be tested for truth.
  40. * @return `true` if all elements are `true`, `false` otherwise.
  41. */
  42. template <std::size_t N>
  43. bool all(const vector<bool, N>& x);
  44. /**
  45. * Checks if any elements of a boolean vector are `true`.
  46. *
  47. * @param x Vector to be tested for truth.
  48. * @return `true` if any elements are `true`, `false` otherwise.
  49. */
  50. template <std::size_t N>
  51. bool any(const vector<bool, N>& x);
  52. /**
  53. * Reinterprets data as an `N`-dimensional vector of type `T`.
  54. *
  55. * @tparam N Number of vector dimensions.
  56. * @tparam T Scalar type.
  57. * @param data Data to reinterpret.
  58. */
  59. template <std::size_t N, typename T>
  60. vector<T, N>& as_vector(T& data);
  61. /**
  62. * Clamps the values of a vector's elements.
  63. *
  64. * @param x Vector to clamp.
  65. * @param min_value Minimum element value.
  66. * @param max_value Maximum element value.
  67. * @return Clamped vector.
  68. */
  69. template <class T, std::size_t N>
  70. vector<T, N> clamp(const vector<T, N>& x, T min_value, T max_value);
  71. /**
  72. * Clamps the length of a vector.
  73. *
  74. * @param x Vector to clamp.
  75. * @param max_length Maximum length.
  76. * @return Length-clamped vector.
  77. */
  78. template <class T, std::size_t N>
  79. vector<T, N> clamp_length(const vector<T, N>& x, T max_length);
  80. /**
  81. * Calculate the cross product of two vectors.
  82. *
  83. * @param x First vector.
  84. * @param y Second vector.
  85. * @return Cross product of the two vectors.
  86. */
  87. template <class T>
  88. vector<T, 3> cross(const vector<T, 3>& x, const vector<T, 3>& y);
  89. /**
  90. * Calculates the distance between two points.
  91. *
  92. * @param p0 First of two points.
  93. * @param p1 Second of two points.
  94. * @return Distance between the two points.
  95. */
  96. template <class T, std::size_t N>
  97. vector<T, N> distance(const vector<T, N>& p0, const vector<T, N>& p1);
  98. /**
  99. * Calculates the squared distance between two points. The squared distance can be calculated faster than the distance because a call to `std::sqrt` is saved.
  100. *
  101. * @param p0 First of two points.
  102. * @param p1 Second of two points.
  103. * @return Squared distance between the two points.
  104. */
  105. template <class T, std::size_t N>
  106. vector<T, N> distance_squared(const vector<T, N>& p0, const vector<T, N>& p1);
  107. /**
  108. * Divides a vector by another vector.
  109. *
  110. * @param x First vector.
  111. * @param y Second vector.
  112. * @return Result of the division.
  113. */
  114. template <class T, std::size_t N>
  115. vector<T, N> div(const vector<T, N>& x, const vector<T, N>& y);
  116. /**
  117. * Divides a vector by a scalar.
  118. *
  119. * @param v Vector.
  120. * @param s Scalar.
  121. * @return Result of the division.
  122. */
  123. template <class T, std::size_t N>
  124. vector<T, N> div(const vector<T, N>& v, T s);
  125. /**
  126. * Calculates the dot product of two vectors.
  127. *
  128. * @param x First vector.
  129. * @param y Second vector.
  130. * @return Dot product of the two vectors.
  131. */
  132. template <class T, std::size_t N>
  133. T dot(const vector<T, N>& x, const vector<T, N>& y);
  134. /**
  135. * Compares two vectors for equality
  136. *
  137. * @param x First vector.
  138. * @param y Second vector.
  139. * @return Boolean vector containing the result of the element comparisons.
  140. */
  141. template <class T, std::size_t N>
  142. vector<bool, N> equal(const vector<T, N>& x, const vector<T, N>& y);
  143. /**
  144. * Performs a component-wise greater-than comparison of two vectors.
  145. *
  146. * @param x First vector.
  147. * @param y Second vector.
  148. * @return Boolean vector containing the result of the element comparisons.
  149. */
  150. template <class T, std::size_t N>
  151. vector<bool, N> greater_than(const vector<T, N>& x, const vector<T, N>& y);
  152. /**
  153. * Performs a component-wise greater-than or equal-to comparison of two vectors.
  154. *
  155. * @param x First vector.
  156. * @param y Second vector.
  157. * @return Boolean vector containing the result of the element comparisons.
  158. */
  159. template <class T, std::size_t N>
  160. vector<bool, N> greater_than_equal(const vector<T, N>& x, const vector<T, N>& y);
  161. /**
  162. * Calculates the length of a vector.
  163. *
  164. * @param x Vector of which to calculate the length.
  165. * @return Length of the vector.
  166. */
  167. template <class T, std::size_t N>
  168. T length(const vector<T, N>& x);
  169. /**
  170. * Calculates the squared length of a vector. The squared length can be calculated faster than the length because a call to `std::sqrt` is saved.
  171. *
  172. * @param x Vector of which to calculate the squared length.
  173. * @return Squared length of the vector.
  174. */
  175. template <class T, std::size_t N>
  176. T length_squared(const vector<T, N>& x);
  177. /**
  178. * Performs a component-wise less-than comparison of two vectors.
  179. *
  180. * @param x First vector.
  181. * @param y Second vector.
  182. * @return Boolean vector containing the result of the element comparisons.
  183. */
  184. template <class T, std::size_t N>
  185. vector<bool, N> less_than(const vector<T, N>& x, const vector<T, N>& y);
  186. /**
  187. * Performs a component-wise less-than or equal-to comparison of two vectors.
  188. *
  189. * @param x First vector.
  190. * @param y Second vector.
  191. * @return Boolean vector containing the result of the element comparisons.
  192. */
  193. template <class T, std::size_t N>
  194. vector<bool, N> less_than_equal(const vector<T, N>& x, const vector<T, N>& y);
  195. /**
  196. * Multiplies two vectors.
  197. *
  198. * @param x First vector.
  199. * @param y Second vector.
  200. * @return Product of the two vectors.
  201. */
  202. template <class T, std::size_t N>
  203. vector<T, N> mul(const vector<T, N>& x, const vector<T, N>& y);
  204. /**
  205. * Multiplies a vector by a scalar.
  206. *
  207. * @param v Vector.
  208. * @param s Scalar.
  209. * @return Product of the vector and scalar.
  210. */
  211. template <class T, std::size_t N>
  212. vector<T, N> mul(const vector<T, N>& v, T s);
  213. /**
  214. * Negates a vector.
  215. *
  216. * @param x Vector to negate.
  217. * @return Negated vector.
  218. */
  219. template <class T, std::size_t N>
  220. vector<T, N> negate(const vector<T, N>& x);
  221. /**
  222. * Calculates the unit vector in the same direction as the original vector.
  223. *
  224. * @param x Vector to normalize.
  225. * @return Normalized vector.
  226. */
  227. template <class T, std::size_t N>
  228. vector<T, N> normalize(const vector<T, N>& x);
  229. /**
  230. * Logically inverts a boolean vector.
  231. *
  232. * @param x Vector to be inverted.
  233. * @return Logically inverted vector.
  234. */
  235. template <class T, std::size_t N>
  236. vector<bool, N> not(const vector<T, N>& x);
  237. /**
  238. * Compares two vectors for inequality
  239. *
  240. * @param x First vector.
  241. * @param y Second vector.
  242. * @return Boolean vector containing the result of the element comparisons.
  243. */
  244. template <class T, std::size_t N>
  245. vector<bool, N> not_equal(const vector<T, N>& x, const vector<T, N>& y);
  246. /**
  247. * Resizes a vector. Any new elements will be set to `0`.
  248. *
  249. * @param v Vector to resize.
  250. * @return Resized vector.
  251. */
  252. template <std::size_t N1, class T, std::size_t N0>
  253. vector<T, N1> resize(const vector<T, N0>& v);
  254. /**
  255. * Subtracts a vector from another vector.
  256. *
  257. * @param x First vector.
  258. * @param y Second vector.
  259. * @return Difference between the two vectors.
  260. */
  261. template <class T, std::size_t N>
  262. vector<T, N> sub(const vector<T, N>& x, const vector<T, N>& y);
  263. /**
  264. * Makes an m-dimensional vector by rearranging and/or duplicating elements of an n-dimensional vector.
  265. *
  266. * @tparam Indices List of indices of elements in the vector `v`.
  267. * @tparam T Vector component type.
  268. * @tparam N Number of dimensions in vector `v`.
  269. * @return Vector containing elements from vector `v` in the order specified by `Indices`. The size of the returned vector is equivalent to the number of indices in `Indices`.
  270. */
  271. template <std::size_t... Indices, class T, std::size_t N>
  272. vector<T, sizeof...(Indices)> swizzle(const vector<T, N>& v);
  273. /**
  274. * Types casts each vector component and returns a vector of the casted type.
  275. *
  276. * @tparam T2 Target vector component type.
  277. * @tparam T1 Source vector component type.
  278. * @tparam N Number of dimensions.
  279. * @param v Vector to type cast.
  280. * @return Type-casted vector.
  281. */
  282. template <class T2, class T1, std::size_t N>
  283. vector<T2, N> type_cast(const vector<T1, N>& v);
  284. /// @private
  285. template <class T, std::size_t N, std::size_t... I>
  286. inline vector<T, N> add(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>)
  287. {
  288. return {(x[I] + y[I])...};
  289. }
  290. template <class T, std::size_t N>
  291. inline vector<T, N> add(const vector<T, N>& x, const vector<T, N>& y)
  292. {
  293. return add(x, y, std::make_index_sequence<N>{});
  294. }
  295. /// @private
  296. template <std::size_t N, std::size_t... I>
  297. inline bool all(const vector<bool, N>& x, std::index_sequence<I...>)
  298. {
  299. return (x[I] && ...);
  300. }
  301. template <std::size_t N>
  302. inline bool all(const vector<bool, N>& x)
  303. {
  304. return all(x, std::make_index_sequence<N>{});
  305. }
  306. /// @private
  307. template <std::size_t N, std::size_t... I>
  308. inline bool any(const vector<bool, N>& x, std::index_sequence<I...>)
  309. {
  310. return (x[I] || ...);
  311. }
  312. template <std::size_t N>
  313. inline bool any(const vector<bool, N>& x)
  314. {
  315. return any(x, std::make_index_sequence<N>{});
  316. }
  317. template <std::size_t N, typename T>
  318. inline vector<T, N>& as_vector(T& data)
  319. {
  320. static_assert(std::is_pod<vector<T, N>>::value);
  321. return reinterpret_cast<vector<T, N>&>(data);
  322. }
  323. /// @private
  324. template <class T, std::size_t N, std::size_t... I>
  325. inline vector<T, N> clamp(const vector<T, N>& x, T min_value, T max_value, std::index_sequence<I...>)
  326. {
  327. return {std::min<T>(max_value, std::max<T>(min_value, x[I]))...};
  328. }
  329. template <class T, std::size_t N>
  330. inline vector<T, N> clamp(const vector<T, N>& x, T min_value, T max_value)
  331. {
  332. return clamp(x, min_value, max_value, std::make_index_sequence<N>{});
  333. }
  334. template <class T, std::size_t N>
  335. vector<T, N> clamp_length(const vector<T, N>& x, T max_length)
  336. {
  337. T length2 = length_squared(x);
  338. return (length2 > max_length * max_length) ? (x * max_length / std::sqrt(length2)) : x;
  339. }
  340. template <class T>
  341. inline vector<T, 3> cross(const vector<T, 3>& x, const vector<T, 3>& y)
  342. {
  343. return
  344. {
  345. x[1] * y[2] - y[1] * x[2],
  346. x[2] * y[0] - y[2] * x[0],
  347. x[0] * y[1] - y[0] * x[1]
  348. };
  349. }
  350. template <class T, std::size_t N>
  351. inline vector<T, N> distance(const vector<T, N>& p0, const vector<T, N>& p1)
  352. {
  353. static_assert(std::is_floating_point<T>::value);
  354. return length(sub(p0, p1));
  355. }
  356. template <class T, std::size_t N>
  357. inline vector<T, N> distance_squared(const vector<T, N>& p0, const vector<T, N>& p1)
  358. {
  359. static_assert(std::is_floating_point<T>::value);
  360. return length_squared(sub(p0, p1));
  361. }
  362. /// @private
  363. template <class T, std::size_t N, std::size_t... I>
  364. inline vector<T, N> div(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>)
  365. {
  366. return {(x[I] / y[I])...};
  367. }
  368. template <class T, std::size_t N>
  369. inline vector<T, N> div(const vector<T, N>& x, const vector<T, N>& y)
  370. {
  371. return div(x, y, std::make_index_sequence<N>{});
  372. }
  373. /// @private
  374. template <class T, std::size_t N, std::size_t... I>
  375. inline vector<T, N> div(const vector<T, N>& v, T s, std::index_sequence<I...>)
  376. {
  377. return {(v[I] / s)...};
  378. }
  379. template <class T, std::size_t N>
  380. inline vector<T, N> div(const vector<T, N>& v, T s)
  381. {
  382. return div(v, s, std::make_index_sequence<N>{});
  383. }
  384. /// @private
  385. template <class T, std::size_t N, std::size_t... I>
  386. inline T dot(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>)
  387. {
  388. return ((x[I] * y[I]) + ...);
  389. }
  390. template <class T, std::size_t N>
  391. inline T dot(const vector<T, N>& x, const vector<T, N>& y)
  392. {
  393. return dot(x, y, std::make_index_sequence<N>{});
  394. }
  395. /// @private
  396. template <class T, std::size_t N, std::size_t... I>
  397. inline vector<bool, N> equal(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>)
  398. {
  399. return {(x[I] == y[I])...};
  400. }
  401. template <class T, std::size_t N>
  402. inline vector<bool, N> equal(const vector<T, N>& x, const vector<T, N>& y)
  403. {
  404. return equal(x, y, std::make_index_sequence<N>{});
  405. }
  406. /// @private
  407. template <class T, std::size_t N, std::size_t... I>
  408. inline vector<bool, N> greater_than(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>)
  409. {
  410. return {(x[I] > y[I])...};
  411. }
  412. template <class T, std::size_t N>
  413. inline vector<bool, N> greater_than(const vector<T, N>& x, const vector<T, N>& y)
  414. {
  415. return greater_than(x, y, std::make_index_sequence<N>{});
  416. }
  417. /// @private
  418. template <class T, std::size_t N, std::size_t... I>
  419. inline vector<bool, N> greater_than_equal(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>)
  420. {
  421. return {(x[I] >= y[I])...};
  422. }
  423. template <class T, std::size_t N>
  424. inline vector<bool, N> greater_than_equal(const vector<T, N>& x, const vector<T, N>& y)
  425. {
  426. return greater_than_equal(x, y, std::make_index_sequence<N>{});
  427. }
  428. template <class T, std::size_t N>
  429. inline T length(const vector<T, N>& x)
  430. {
  431. static_assert(std::is_floating_point<T>::value);
  432. return std::sqrt(dot(x, x));
  433. }
  434. template <class T, std::size_t N>
  435. inline T length_squared(const vector<T, N>& x)
  436. {
  437. static_assert(std::is_floating_point<T>::value);
  438. return dot(x, x);
  439. }
  440. /// @private
  441. template <class T, std::size_t N, std::size_t... I>
  442. inline vector<bool, N> less_than(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>)
  443. {
  444. return {(x[I] < y[I])...};
  445. }
  446. template <class T, std::size_t N>
  447. inline vector<bool, N> less_than(const vector<T, N>& x, const vector<T, N>& y)
  448. {
  449. return less_than(x, y, std::make_index_sequence<N>{});
  450. }
  451. /// @private
  452. template <class T, std::size_t N, std::size_t... I>
  453. inline vector<bool, N> less_than_equal(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>)
  454. {
  455. return {(x[I] <= y[I])...};
  456. }
  457. template <class T, std::size_t N>
  458. inline vector<bool, N> less_than_equal(const vector<T, N>& x, const vector<T, N>& y)
  459. {
  460. return less_than_equal(x, y, std::make_index_sequence<N>{});
  461. }
  462. /// @private
  463. template <class T, std::size_t N, std::size_t... I>
  464. inline vector<T, N> mul(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>)
  465. {
  466. return {(x[I] * y[I])...};
  467. }
  468. template <class T, std::size_t N>
  469. inline vector<T, N> mul(const vector<T, N>& x, const vector<T, N>& y)
  470. {
  471. return mul(x, y, std::make_index_sequence<N>{});
  472. }
  473. /// @private
  474. template <class T, std::size_t N, std::size_t... I>
  475. inline vector<T, N> mul(const vector<T, N>& v, T s, std::index_sequence<I...>)
  476. {
  477. return {(v[I] * s)...};
  478. }
  479. template <class T, std::size_t N>
  480. inline vector<T, N> mul(const vector<T, N>& v, T s)
  481. {
  482. return mul(v, s, std::make_index_sequence<N>{});
  483. }
  484. /// @private
  485. template <class T, std::size_t N, std::size_t... I>
  486. inline vector<T, N> negate(const vector<T, N>& x, std::index_sequence<I...>)
  487. {
  488. return {(-x[I])...};
  489. }
  490. template <class T, std::size_t N>
  491. inline vector<T, N> negate(const vector<T, N>& x)
  492. {
  493. return negate(x, std::make_index_sequence<N>{});
  494. }
  495. template <class T, std::size_t N>
  496. inline vector<T, N> normalize(const vector<T, N>& x)
  497. {
  498. static_assert(std::is_floating_point<T>::value);
  499. return mul(x, T(1) / length(x));
  500. }
  501. /// @private
  502. template <class T, std::size_t N, std::size_t... I>
  503. inline vector<bool, N> not(const vector<T, N>& x, std::index_sequence<I...>)
  504. {
  505. return {!x[I]...};
  506. }
  507. template <class T, std::size_t N>
  508. inline vector<bool, N> not(const vector<T, N>& x)
  509. {
  510. return not(x, std::make_index_sequence<N>{});
  511. }
  512. /// @private
  513. template <class T, std::size_t N, std::size_t... I>
  514. inline vector<bool, N> not_equal(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>)
  515. {
  516. return {(x[I] != y[I])...};
  517. }
  518. template <class T, std::size_t N>
  519. inline vector<bool, N> not_equal(const vector<T, N>& x, const vector<T, N>& y)
  520. {
  521. return not_equal(x, y, std::make_index_sequence<N>{});
  522. }
  523. template <std::size_t N1, class T, std::size_t N0>
  524. vector<T, N1> resize(const vector<T, N0>& v)
  525. {
  526. vector<T, N1> resized;
  527. for (std::size_t i = 0; i < N1; ++i)
  528. {
  529. resized[i] = (i < N0) ? v[i] : T(0);
  530. }
  531. return resized;
  532. }
  533. /// @private
  534. template <class T, std::size_t N, std::size_t... I>
  535. inline vector<T, N> sub(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>)
  536. {
  537. return {(x[I] - y[I])...};
  538. }
  539. template <class T, std::size_t N>
  540. inline vector<T, N> sub(const vector<T, N>& x, const vector<T, N>& y)
  541. {
  542. return sub(x, y, std::make_index_sequence<N>{});
  543. }
  544. template <std::size_t... Indices, class T, std::size_t N>
  545. inline vector<T, sizeof...(Indices)> swizzle(const vector<T, N>& v)
  546. {
  547. return { v[Indices]... };
  548. }
  549. /// @private
  550. template <class T2, class T1, std::size_t N, std::size_t... I>
  551. inline vector<T2, N> type_cast(const vector<T1, N>& v, std::index_sequence<I...>)
  552. {
  553. return {static_cast<T2>(v[I])...};
  554. }
  555. template <class T2, class T1, std::size_t N>
  556. inline vector<T2, N> type_cast(const vector<T1, N>& v)
  557. {
  558. return type_cast<T2>(v, std::make_index_sequence<N>{});
  559. }
  560. } // namespace math
  561. #endif // ANTKEEPER_MATH_VECTOR_FUNCTIONS_HPP