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

652 lines
17 KiB

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