💿🐜 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.

645 lines
18 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. constexpr 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. constexpr 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. constexpr 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. constexpr 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. constexpr 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. constexpr 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. T 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. constexpr T 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. constexpr 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. constexpr 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. constexpr 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. constexpr 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. constexpr 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. constexpr 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. constexpr 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. constexpr 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. constexpr 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. constexpr 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. constexpr 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. constexpr 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. constexpr 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. constexpr 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. constexpr 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. constexpr 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. constexpr 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. constexpr 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. constexpr 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. constexpr 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. constexpr 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. constexpr 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. constexpr 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. constexpr 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. constexpr 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. constexpr 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. constexpr 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. constexpr 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 T 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. constexpr inline T 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. constexpr 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. constexpr 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. constexpr 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. constexpr 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. constexpr 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. constexpr 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. constexpr 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. constexpr 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. constexpr 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. constexpr 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. constexpr 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. constexpr 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. constexpr inline T length_squared(const vector<T, N>& x)
  436. {
  437. return dot(x, x);
  438. }
  439. /// @private
  440. template <class T, std::size_t N, std::size_t... I>
  441. constexpr inline vector<bool, N> less_than(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>)
  442. {
  443. return {(x[I] < y[I])...};
  444. }
  445. template <class T, std::size_t N>
  446. constexpr inline vector<bool, N> less_than(const vector<T, N>& x, const vector<T, N>& y)
  447. {
  448. return less_than(x, y, std::make_index_sequence<N>{});
  449. }
  450. /// @private
  451. template <class T, std::size_t N, std::size_t... I>
  452. constexpr inline vector<bool, N> less_than_equal(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>)
  453. {
  454. return {(x[I] <= y[I])...};
  455. }
  456. template <class T, std::size_t N>
  457. constexpr inline vector<bool, N> less_than_equal(const vector<T, N>& x, const vector<T, N>& y)
  458. {
  459. return less_than_equal(x, y, std::make_index_sequence<N>{});
  460. }
  461. /// @private
  462. template <class T, std::size_t N, std::size_t... I>
  463. constexpr inline vector<T, N> mul(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>)
  464. {
  465. return {(x[I] * y[I])...};
  466. }
  467. template <class T, std::size_t N>
  468. constexpr inline vector<T, N> mul(const vector<T, N>& x, const vector<T, N>& y)
  469. {
  470. return mul(x, y, std::make_index_sequence<N>{});
  471. }
  472. /// @private
  473. template <class T, std::size_t N, std::size_t... I>
  474. constexpr inline vector<T, N> mul(const vector<T, N>& v, T s, std::index_sequence<I...>)
  475. {
  476. return {(v[I] * s)...};
  477. }
  478. template <class T, std::size_t N>
  479. constexpr inline vector<T, N> mul(const vector<T, N>& v, T s)
  480. {
  481. return mul(v, s, std::make_index_sequence<N>{});
  482. }
  483. /// @private
  484. template <class T, std::size_t N, std::size_t... I>
  485. constexpr inline vector<T, N> negate(const vector<T, N>& x, std::index_sequence<I...>)
  486. {
  487. return {(-x[I])...};
  488. }
  489. template <class T, std::size_t N>
  490. constexpr inline vector<T, N> negate(const vector<T, N>& x)
  491. {
  492. return negate(x, std::make_index_sequence<N>{});
  493. }
  494. template <class T, std::size_t N>
  495. inline vector<T, N> normalize(const vector<T, N>& x)
  496. {
  497. static_assert(std::is_floating_point<T>::value);
  498. return mul(x, T(1) / length(x));
  499. }
  500. /// @private
  501. template <class T, std::size_t N, std::size_t... I>
  502. constexpr inline vector<bool, N> not(const vector<T, N>& x, std::index_sequence<I...>)
  503. {
  504. return {!x[I]...};
  505. }
  506. template <class T, std::size_t N>
  507. constexpr inline vector<bool, N> not(const vector<T, N>& x)
  508. {
  509. return not(x, std::make_index_sequence<N>{});
  510. }
  511. /// @private
  512. template <class T, std::size_t N, std::size_t... I>
  513. constexpr inline vector<bool, N> not_equal(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>)
  514. {
  515. return {(x[I] != y[I])...};
  516. }
  517. template <class T, std::size_t N>
  518. constexpr inline vector<bool, N> not_equal(const vector<T, N>& x, const vector<T, N>& y)
  519. {
  520. return not_equal(x, y, std::make_index_sequence<N>{});
  521. }
  522. template <std::size_t N1, class T, std::size_t N0>
  523. constexpr vector<T, N1> resize(const vector<T, N0>& v)
  524. {
  525. vector<T, N1> resized;
  526. for (std::size_t i = 0; i < N1; ++i)
  527. {
  528. resized[i] = (i < N0) ? v[i] : T(0);
  529. }
  530. return resized;
  531. }
  532. /// @private
  533. template <class T, std::size_t N, std::size_t... I>
  534. constexpr inline vector<T, N> sub(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>)
  535. {
  536. return {(x[I] - y[I])...};
  537. }
  538. template <class T, std::size_t N>
  539. constexpr inline vector<T, N> sub(const vector<T, N>& x, const vector<T, N>& y)
  540. {
  541. return sub(x, y, std::make_index_sequence<N>{});
  542. }
  543. template <std::size_t... Indices, class T, std::size_t N>
  544. constexpr inline vector<T, sizeof...(Indices)> swizzle(const vector<T, N>& v)
  545. {
  546. return { v[Indices]... };
  547. }
  548. /// @private
  549. template <class T2, class T1, std::size_t N, std::size_t... I>
  550. constexpr inline vector<T2, N> type_cast(const vector<T1, N>& v, std::index_sequence<I...>)
  551. {
  552. return {static_cast<T2>(v[I])...};
  553. }
  554. template <class T2, class T1, std::size_t N>
  555. constexpr inline vector<T2, N> type_cast(const vector<T1, N>& v)
  556. {
  557. return type_cast<T2>(v, std::make_index_sequence<N>{});
  558. }
  559. } // namespace math
  560. #endif // ANTKEEPER_MATH_VECTOR_FUNCTIONS_HPP