vec3.h 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264
  1. /*
  2. * Copyright (c), Recep Aslantas.
  3. *
  4. * MIT License (MIT), http://opensource.org/licenses/MIT
  5. * Full license can be found in the LICENSE file
  6. */
  7. /*
  8. Macros:
  9. GLM_VEC3_ONE_INIT
  10. GLM_VEC3_ZERO_INIT
  11. GLM_VEC3_ONE
  12. GLM_VEC3_ZERO
  13. GLM_YUP
  14. GLM_ZUP
  15. GLM_XUP
  16. Functions:
  17. CGLM_INLINE void glm_vec3(vec4 v4, vec3 dest);
  18. CGLM_INLINE void glm_vec3_copy(vec3 a, vec3 dest);
  19. CGLM_INLINE void glm_vec3_zero(vec3 v);
  20. CGLM_INLINE void glm_vec3_one(vec3 v);
  21. CGLM_INLINE float glm_vec3_dot(vec3 a, vec3 b);
  22. CGLM_INLINE float glm_vec3_norm2(vec3 v);
  23. CGLM_INLINE float glm_vec3_norm(vec3 v);
  24. CGLM_INLINE float glm_vec3_norm_one(vec3 v);
  25. CGLM_INLINE float glm_vec3_norm_inf(vec3 v);
  26. CGLM_INLINE void glm_vec3_add(vec3 a, vec3 b, vec3 dest);
  27. CGLM_INLINE void glm_vec3_adds(vec3 a, float s, vec3 dest);
  28. CGLM_INLINE void glm_vec3_sub(vec3 a, vec3 b, vec3 dest);
  29. CGLM_INLINE void glm_vec3_subs(vec3 a, float s, vec3 dest);
  30. CGLM_INLINE void glm_vec3_mul(vec3 a, vec3 b, vec3 dest);
  31. CGLM_INLINE void glm_vec3_scale(vec3 v, float s, vec3 dest);
  32. CGLM_INLINE void glm_vec3_scale_as(vec3 v, float s, vec3 dest);
  33. CGLM_INLINE void glm_vec3_div(vec3 a, vec3 b, vec3 dest);
  34. CGLM_INLINE void glm_vec3_divs(vec3 a, float s, vec3 dest);
  35. CGLM_INLINE void glm_vec3_addadd(vec3 a, vec3 b, vec3 dest);
  36. CGLM_INLINE void glm_vec3_subadd(vec3 a, vec3 b, vec3 dest);
  37. CGLM_INLINE void glm_vec3_muladd(vec3 a, vec3 b, vec3 dest);
  38. CGLM_INLINE void glm_vec3_muladds(vec3 a, float s, vec3 dest);
  39. CGLM_INLINE void glm_vec3_maxadd(vec3 a, vec3 b, vec3 dest);
  40. CGLM_INLINE void glm_vec3_minadd(vec3 a, vec3 b, vec3 dest);
  41. CGLM_INLINE void glm_vec3_subsub(vec3 a, vec3 b, vec3 dest);
  42. CGLM_INLINE void glm_vec3_addsub(vec3 a, vec3 b, vec3 dest);
  43. CGLM_INLINE void glm_vec3_mulsub(vec3 a, vec3 b, vec3 dest);
  44. CGLM_INLINE void glm_vec3_mulsubs(vec3 a, float s, vec3 dest);
  45. CGLM_INLINE void glm_vec3_maxsub(vec3 a, vec3 b, vec3 dest);
  46. CGLM_INLINE void glm_vec3_minsub(vec3 a, vec3 b, vec3 dest);
  47. CGLM_INLINE void glm_vec3_flipsign(vec3 v);
  48. CGLM_INLINE void glm_vec3_flipsign_to(vec3 v, vec3 dest);
  49. CGLM_INLINE void glm_vec3_negate_to(vec3 v, vec3 dest);
  50. CGLM_INLINE void glm_vec3_negate(vec3 v);
  51. CGLM_INLINE void glm_vec3_inv(vec3 v);
  52. CGLM_INLINE void glm_vec3_inv_to(vec3 v, vec3 dest);
  53. CGLM_INLINE void glm_vec3_normalize(vec3 v);
  54. CGLM_INLINE void glm_vec3_normalize_to(vec3 v, vec3 dest);
  55. CGLM_INLINE void glm_vec3_cross(vec3 a, vec3 b, vec3 d);
  56. CGLM_INLINE void glm_vec3_crossn(vec3 a, vec3 b, vec3 dest);
  57. CGLM_INLINE float glm_vec3_angle(vec3 a, vec3 b);
  58. CGLM_INLINE void glm_vec3_rotate(vec3 v, float angle, vec3 axis);
  59. CGLM_INLINE void glm_vec3_rotate_m4(mat4 m, vec3 v, vec3 dest);
  60. CGLM_INLINE void glm_vec3_rotate_m3(mat3 m, vec3 v, vec3 dest);
  61. CGLM_INLINE void glm_vec3_proj(vec3 a, vec3 b, vec3 dest);
  62. CGLM_INLINE void glm_vec3_center(vec3 a, vec3 b, vec3 dest);
  63. CGLM_INLINE float glm_vec3_distance(vec3 a, vec3 b);
  64. CGLM_INLINE float glm_vec3_distance2(vec3 a, vec3 b);
  65. CGLM_INLINE void glm_vec3_maxv(vec3 a, vec3 b, vec3 dest);
  66. CGLM_INLINE void glm_vec3_minv(vec3 a, vec3 b, vec3 dest);
  67. CGLM_INLINE void glm_vec3_ortho(vec3 v, vec3 dest);
  68. CGLM_INLINE void glm_vec3_clamp(vec3 v, float minVal, float maxVal);
  69. CGLM_INLINE void glm_vec3_lerp(vec3 from, vec3 to, float t, vec3 dest);
  70. CGLM_INLINE void glm_vec3_lerpc(vec3 from, vec3 to, float t, vec3 dest);
  71. CGLM_INLINE void glm_vec3_mix(vec3 from, vec3 to, float t, vec3 dest);
  72. CGLM_INLINE void glm_vec3_mixc(vec3 from, vec3 to, float t, vec3 dest);
  73. CGLM_INLINE void glm_vec3_step(vec3 edge, vec3 x, vec3 dest);
  74. CGLM_INLINE void glm_vec3_smoothstep_uni(float edge0, float edge1, vec3 x, vec3 dest);
  75. CGLM_INLINE void glm_vec3_smoothstep(vec3 edge0, vec3 edge1, vec3 x, vec3 dest);
  76. CGLM_INLINE void glm_vec3_smoothinterp(vec3 from, vec3 to, float t, vec3 dest);
  77. CGLM_INLINE void glm_vec3_smoothinterpc(vec3 from, vec3 to, float t, vec3 dest);
  78. CGLM_INLINE void glm_vec3_swizzle(vec3 v, int mask, vec3 dest);
  79. CGLM_INLINE void glm_vec3_make(float * restrict src, vec3 dest);
  80. CGLM_INLINE void glm_vec3_faceforward(vec3 n, vec3 v, vec3 nref, vec3 dest);
  81. CGLM_INLINE void glm_vec3_reflect(vec3 v, vec3 n, vec3 dest);
  82. CGLM_INLINE void glm_vec3_refract(vec3 v, vec3 n, float eta, vec3 dest);
  83. Convenient:
  84. CGLM_INLINE void glm_cross(vec3 a, vec3 b, vec3 d);
  85. CGLM_INLINE float glm_dot(vec3 a, vec3 b);
  86. CGLM_INLINE void glm_normalize(vec3 v);
  87. CGLM_INLINE void glm_normalize_to(vec3 v, vec3 dest);
  88. DEPRECATED:
  89. glm_vec3_dup
  90. glm_vec3_flipsign
  91. glm_vec3_flipsign_to
  92. glm_vec3_inv
  93. glm_vec3_inv_to
  94. glm_vec3_mulv
  95. glm_vec3_step_uni --> use glm_vec3_steps
  96. */
  97. #ifndef cglm_vec3_h
  98. #define cglm_vec3_h
  99. #include "common.h"
  100. #include "vec4.h"
  101. #include "vec3-ext.h"
  102. #include "util.h"
  103. /* DEPRECATED! use _copy, _ucopy versions */
  104. #define glm_vec3_dup(v, dest) glm_vec3_copy(v, dest)
  105. #define glm_vec3_flipsign(v) glm_vec3_negate(v)
  106. #define glm_vec3_flipsign_to(v, dest) glm_vec3_negate_to(v, dest)
  107. #define glm_vec3_inv(v) glm_vec3_negate(v)
  108. #define glm_vec3_inv_to(v, dest) glm_vec3_negate_to(v, dest)
  109. #define glm_vec3_mulv(a, b, d) glm_vec3_mul(a, b, d)
  110. #define glm_vec3_step_uni(edge, x, dest) glm_vec3_steps(edge, x, dest)
  111. #define GLM_VEC3_ONE_INIT {1.0f, 1.0f, 1.0f}
  112. #define GLM_VEC3_ZERO_INIT {0.0f, 0.0f, 0.0f}
  113. #define GLM_VEC3_ONE ((vec3)GLM_VEC3_ONE_INIT)
  114. #define GLM_VEC3_ZERO ((vec3)GLM_VEC3_ZERO_INIT)
  115. #define GLM_YUP ((vec3){0.0f, 1.0f, 0.0f})
  116. #define GLM_ZUP ((vec3){0.0f, 0.0f, 1.0f})
  117. #define GLM_XUP ((vec3){1.0f, 0.0f, 0.0f})
  118. #define GLM_FORWARD ((vec3){0.0f, 0.0f, -1.0f})
  119. #define GLM_XXX GLM_SHUFFLE3(0, 0, 0)
  120. #define GLM_YYY GLM_SHUFFLE3(1, 1, 1)
  121. #define GLM_ZZZ GLM_SHUFFLE3(2, 2, 2)
  122. #define GLM_ZYX GLM_SHUFFLE3(0, 1, 2)
  123. /*!
  124. * @brief init vec3 using vec4
  125. *
  126. * @param[in] v4 vector4
  127. * @param[out] dest destination
  128. */
  129. CGLM_INLINE
  130. void
  131. glm_vec3(vec4 v4, vec3 dest) {
  132. dest[0] = v4[0];
  133. dest[1] = v4[1];
  134. dest[2] = v4[2];
  135. }
  136. /*!
  137. * @brief copy all members of [a] to [dest]
  138. *
  139. * @param[in] a source
  140. * @param[out] dest destination
  141. */
  142. CGLM_INLINE
  143. void
  144. glm_vec3_copy(vec3 a, vec3 dest) {
  145. dest[0] = a[0];
  146. dest[1] = a[1];
  147. dest[2] = a[2];
  148. }
  149. /*!
  150. * @brief make vector zero
  151. *
  152. * @param[in, out] v vector
  153. */
  154. CGLM_INLINE
  155. void
  156. glm_vec3_zero(vec3 v) {
  157. v[0] = v[1] = v[2] = 0.0f;
  158. }
  159. /*!
  160. * @brief make vector one
  161. *
  162. * @param[in, out] v vector
  163. */
  164. CGLM_INLINE
  165. void
  166. glm_vec3_one(vec3 v) {
  167. v[0] = v[1] = v[2] = 1.0f;
  168. }
  169. /*!
  170. * @brief vec3 dot product
  171. *
  172. * @param[in] a vector1
  173. * @param[in] b vector2
  174. *
  175. * @return dot product
  176. */
  177. CGLM_INLINE
  178. float
  179. glm_vec3_dot(vec3 a, vec3 b) {
  180. return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
  181. }
  182. /*!
  183. * @brief norm * norm (magnitude) of vec
  184. *
  185. * we can use this func instead of calling norm * norm, because it would call
  186. * sqrtf function twice but with this func we can avoid func call, maybe this is
  187. * not good name for this func
  188. *
  189. * @param[in] v vector
  190. *
  191. * @return norm * norm
  192. */
  193. CGLM_INLINE
  194. float
  195. glm_vec3_norm2(vec3 v) {
  196. return glm_vec3_dot(v, v);
  197. }
  198. /*!
  199. * @brief euclidean norm (magnitude), also called L2 norm
  200. * this will give magnitude of vector in euclidean space
  201. *
  202. * @param[in] v vector
  203. *
  204. * @return norm
  205. */
  206. CGLM_INLINE
  207. float
  208. glm_vec3_norm(vec3 v) {
  209. return sqrtf(glm_vec3_norm2(v));
  210. }
  211. /*!
  212. * @brief L1 norm of vec3
  213. * Also known as Manhattan Distance or Taxicab norm.
  214. * L1 Norm is the sum of the magnitudes of the vectors in a space.
  215. * It is calculated as the sum of the absolute values of the vector components.
  216. * In this norm, all the components of the vector are weighted equally.
  217. *
  218. * This computes:
  219. * R = |v[0]| + |v[1]| + |v[2]|
  220. *
  221. * @param[in] v vector
  222. *
  223. * @return L1 norm
  224. */
  225. CGLM_INLINE
  226. float
  227. glm_vec3_norm_one(vec3 v) {
  228. vec3 t;
  229. glm_vec3_abs(v, t);
  230. return glm_vec3_hadd(t);
  231. }
  232. /*!
  233. * @brief infinity norm of vec3
  234. * Also known as Maximum norm.
  235. * Infinity Norm is the largest magnitude among each element of a vector.
  236. * It is calculated as the maximum of the absolute values of the vector components.
  237. *
  238. * This computes:
  239. * inf norm = max(|v[0]|, |v[1]|, |v[2]|)
  240. *
  241. * @param[in] v vector
  242. *
  243. * @return infinity norm
  244. */
  245. CGLM_INLINE
  246. float
  247. glm_vec3_norm_inf(vec3 v) {
  248. vec3 t;
  249. glm_vec3_abs(v, t);
  250. return glm_vec3_max(t);
  251. }
  252. /*!
  253. * @brief add a vector to b vector store result in dest
  254. *
  255. * @param[in] a vector1
  256. * @param[in] b vector2
  257. * @param[out] dest destination vector
  258. */
  259. CGLM_INLINE
  260. void
  261. glm_vec3_add(vec3 a, vec3 b, vec3 dest) {
  262. dest[0] = a[0] + b[0];
  263. dest[1] = a[1] + b[1];
  264. dest[2] = a[2] + b[2];
  265. }
  266. /*!
  267. * @brief add scalar to v vector store result in dest (d = v + s)
  268. *
  269. * @param[in] v vector
  270. * @param[in] s scalar
  271. * @param[out] dest destination vector
  272. */
  273. CGLM_INLINE
  274. void
  275. glm_vec3_adds(vec3 v, float s, vec3 dest) {
  276. dest[0] = v[0] + s;
  277. dest[1] = v[1] + s;
  278. dest[2] = v[2] + s;
  279. }
  280. /*!
  281. * @brief subtract b vector from a vector store result in dest
  282. *
  283. * @param[in] a vector1
  284. * @param[in] b vector2
  285. * @param[out] dest destination vector
  286. */
  287. CGLM_INLINE
  288. void
  289. glm_vec3_sub(vec3 a, vec3 b, vec3 dest) {
  290. dest[0] = a[0] - b[0];
  291. dest[1] = a[1] - b[1];
  292. dest[2] = a[2] - b[2];
  293. }
  294. /*!
  295. * @brief subtract scalar from v vector store result in dest (d = v - s)
  296. *
  297. * @param[in] v vector
  298. * @param[in] s scalar
  299. * @param[out] dest destination vector
  300. */
  301. CGLM_INLINE
  302. void
  303. glm_vec3_subs(vec3 v, float s, vec3 dest) {
  304. dest[0] = v[0] - s;
  305. dest[1] = v[1] - s;
  306. dest[2] = v[2] - s;
  307. }
  308. /*!
  309. * @brief multiply two vectors (component-wise multiplication)
  310. *
  311. * @param a vector1
  312. * @param b vector2
  313. * @param dest v3 = (a[0] * b[0], a[1] * b[1], a[2] * b[2])
  314. */
  315. CGLM_INLINE
  316. void
  317. glm_vec3_mul(vec3 a, vec3 b, vec3 dest) {
  318. dest[0] = a[0] * b[0];
  319. dest[1] = a[1] * b[1];
  320. dest[2] = a[2] * b[2];
  321. }
  322. /*!
  323. * @brief multiply/scale vec3 vector with scalar: result = v * s
  324. *
  325. * @param[in] v vector
  326. * @param[in] s scalar
  327. * @param[out] dest destination vector
  328. */
  329. CGLM_INLINE
  330. void
  331. glm_vec3_scale(vec3 v, float s, vec3 dest) {
  332. dest[0] = v[0] * s;
  333. dest[1] = v[1] * s;
  334. dest[2] = v[2] * s;
  335. }
  336. /*!
  337. * @brief make vec3 vector scale as specified: result = unit(v) * s
  338. *
  339. * @param[in] v vector
  340. * @param[in] s scalar
  341. * @param[out] dest destination vector
  342. */
  343. CGLM_INLINE
  344. void
  345. glm_vec3_scale_as(vec3 v, float s, vec3 dest) {
  346. float norm;
  347. norm = glm_vec3_norm(v);
  348. if (CGLM_UNLIKELY(norm < FLT_EPSILON)) {
  349. glm_vec3_zero(dest);
  350. return;
  351. }
  352. glm_vec3_scale(v, s / norm, dest);
  353. }
  354. /*!
  355. * @brief div vector with another component-wise division: d = a / b
  356. *
  357. * @param[in] a vector 1
  358. * @param[in] b vector 2
  359. * @param[out] dest result = (a[0]/b[0], a[1]/b[1], a[2]/b[2])
  360. */
  361. CGLM_INLINE
  362. void
  363. glm_vec3_div(vec3 a, vec3 b, vec3 dest) {
  364. dest[0] = a[0] / b[0];
  365. dest[1] = a[1] / b[1];
  366. dest[2] = a[2] / b[2];
  367. }
  368. /*!
  369. * @brief div vector with scalar: d = v / s
  370. *
  371. * @param[in] v vector
  372. * @param[in] s scalar
  373. * @param[out] dest result = (a[0]/s, a[1]/s, a[2]/s)
  374. */
  375. CGLM_INLINE
  376. void
  377. glm_vec3_divs(vec3 v, float s, vec3 dest) {
  378. dest[0] = v[0] / s;
  379. dest[1] = v[1] / s;
  380. dest[2] = v[2] / s;
  381. }
  382. /*!
  383. * @brief add two vectors and add result to sum
  384. *
  385. * it applies += operator so dest must be initialized
  386. *
  387. * @param[in] a vector 1
  388. * @param[in] b vector 2
  389. * @param[out] dest dest += (a + b)
  390. */
  391. CGLM_INLINE
  392. void
  393. glm_vec3_addadd(vec3 a, vec3 b, vec3 dest) {
  394. dest[0] += a[0] + b[0];
  395. dest[1] += a[1] + b[1];
  396. dest[2] += a[2] + b[2];
  397. }
  398. /*!
  399. * @brief sub two vectors and add result to dest
  400. *
  401. * it applies += operator so dest must be initialized
  402. *
  403. * @param[in] a vector 1
  404. * @param[in] b vector 2
  405. * @param[out] dest dest += (a + b)
  406. */
  407. CGLM_INLINE
  408. void
  409. glm_vec3_subadd(vec3 a, vec3 b, vec3 dest) {
  410. dest[0] += a[0] - b[0];
  411. dest[1] += a[1] - b[1];
  412. dest[2] += a[2] - b[2];
  413. }
  414. /*!
  415. * @brief mul two vectors and add result to dest
  416. *
  417. * it applies += operator so dest must be initialized
  418. *
  419. * @param[in] a vector 1
  420. * @param[in] b vector 2
  421. * @param[out] dest dest += (a * b)
  422. */
  423. CGLM_INLINE
  424. void
  425. glm_vec3_muladd(vec3 a, vec3 b, vec3 dest) {
  426. dest[0] += a[0] * b[0];
  427. dest[1] += a[1] * b[1];
  428. dest[2] += a[2] * b[2];
  429. }
  430. /*!
  431. * @brief mul vector with scalar and add result to sum
  432. *
  433. * it applies += operator so dest must be initialized
  434. *
  435. * @param[in] a vector
  436. * @param[in] s scalar
  437. * @param[out] dest dest += (a * b)
  438. */
  439. CGLM_INLINE
  440. void
  441. glm_vec3_muladds(vec3 a, float s, vec3 dest) {
  442. dest[0] += a[0] * s;
  443. dest[1] += a[1] * s;
  444. dest[2] += a[2] * s;
  445. }
  446. /*!
  447. * @brief add max of two vectors to result/dest
  448. *
  449. * it applies += operator so dest must be initialized
  450. *
  451. * @param[in] a vector 1
  452. * @param[in] b vector 2
  453. * @param[out] dest dest += max(a, b)
  454. */
  455. CGLM_INLINE
  456. void
  457. glm_vec3_maxadd(vec3 a, vec3 b, vec3 dest) {
  458. dest[0] += glm_max(a[0], b[0]);
  459. dest[1] += glm_max(a[1], b[1]);
  460. dest[2] += glm_max(a[2], b[2]);
  461. }
  462. /*!
  463. * @brief add min of two vectors to result/dest
  464. *
  465. * it applies += operator so dest must be initialized
  466. *
  467. * @param[in] a vector 1
  468. * @param[in] b vector 2
  469. * @param[out] dest dest += min(a, b)
  470. */
  471. CGLM_INLINE
  472. void
  473. glm_vec3_minadd(vec3 a, vec3 b, vec3 dest) {
  474. dest[0] += glm_min(a[0], b[0]);
  475. dest[1] += glm_min(a[1], b[1]);
  476. dest[2] += glm_min(a[2], b[2]);
  477. }
  478. /*!
  479. * @brief sub two vectors and sub result to dest
  480. *
  481. * it applies += operator so dest must be initialized
  482. *
  483. * @param[in] a vector 1
  484. * @param[in] b vector 2
  485. * @param[out] dest dest -= (a - b)
  486. */
  487. CGLM_INLINE
  488. void
  489. glm_vec3_subsub(vec3 a, vec3 b, vec3 dest) {
  490. dest[0] -= a[0] - b[0];
  491. dest[1] -= a[1] - b[1];
  492. dest[2] -= a[2] - b[2];
  493. }
  494. /*!
  495. * @brief add two vectors and sub result to dest
  496. *
  497. * it applies += operator so dest must be initialized
  498. *
  499. * @param[in] a vector 1
  500. * @param[in] b vector 2
  501. * @param[out] dest dest -= (a + b)
  502. */
  503. CGLM_INLINE
  504. void
  505. glm_vec3_addsub(vec3 a, vec3 b, vec3 dest) {
  506. dest[0] -= a[0] + b[0];
  507. dest[1] -= a[1] + b[1];
  508. dest[2] -= a[2] + b[2];
  509. }
  510. /*!
  511. * @brief mul two vectors and sub result to dest
  512. *
  513. * it applies -= operator so dest must be initialized
  514. *
  515. * @param[in] a vector 1
  516. * @param[in] b vector 2
  517. * @param[out] dest dest -= (a * b)
  518. */
  519. CGLM_INLINE
  520. void
  521. glm_vec3_mulsub(vec3 a, vec3 b, vec3 dest) {
  522. dest[0] -= a[0] * b[0];
  523. dest[1] -= a[1] * b[1];
  524. dest[2] -= a[2] * b[2];
  525. }
  526. /*!
  527. * @brief mul vector with scalar and sub result to dest
  528. *
  529. * it applies -= operator so dest must be initialized
  530. *
  531. * @param[in] a vector
  532. * @param[in] s scalar
  533. * @param[out] dest dest -= (a * b)
  534. */
  535. CGLM_INLINE
  536. void
  537. glm_vec3_mulsubs(vec3 a, float s, vec3 dest) {
  538. dest[0] -= a[0] * s;
  539. dest[1] -= a[1] * s;
  540. dest[2] -= a[2] * s;
  541. }
  542. /*!
  543. * @brief sub max of two vectors to result/dest
  544. *
  545. * it applies -= operator so dest must be initialized
  546. *
  547. * @param[in] a vector 1
  548. * @param[in] b vector 2
  549. * @param[out] dest dest -= max(a, b)
  550. */
  551. CGLM_INLINE
  552. void
  553. glm_vec3_maxsub(vec3 a, vec3 b, vec3 dest) {
  554. dest[0] -= glm_max(a[0], b[0]);
  555. dest[1] -= glm_max(a[1], b[1]);
  556. dest[2] -= glm_max(a[2], b[2]);
  557. }
  558. /*!
  559. * @brief sub min of two vectors to result/dest
  560. *
  561. * it applies -= operator so dest must be initialized
  562. *
  563. * @param[in] a vector 1
  564. * @param[in] b vector 2
  565. * @param[out] dest dest -= min(a, b)
  566. */
  567. CGLM_INLINE
  568. void
  569. glm_vec3_minsub(vec3 a, vec3 b, vec3 dest) {
  570. dest[0] -= glm_min(a[0], b[0]);
  571. dest[1] -= glm_min(a[1], b[1]);
  572. dest[2] -= glm_min(a[2], b[2]);
  573. }
  574. /*!
  575. * @brief negate vector components and store result in dest
  576. *
  577. * @param[in] v vector
  578. * @param[out] dest result vector
  579. */
  580. CGLM_INLINE
  581. void
  582. glm_vec3_negate_to(vec3 v, vec3 dest) {
  583. dest[0] = -v[0];
  584. dest[1] = -v[1];
  585. dest[2] = -v[2];
  586. }
  587. /*!
  588. * @brief negate vector components
  589. *
  590. * @param[in, out] v vector
  591. */
  592. CGLM_INLINE
  593. void
  594. glm_vec3_negate(vec3 v) {
  595. glm_vec3_negate_to(v, v);
  596. }
  597. /*!
  598. * @brief normalize vec3 and store result in same vec
  599. *
  600. * @param[in, out] v vector
  601. */
  602. CGLM_INLINE
  603. void
  604. glm_vec3_normalize(vec3 v) {
  605. float norm;
  606. norm = glm_vec3_norm(v);
  607. if (CGLM_UNLIKELY(norm < FLT_EPSILON)) {
  608. v[0] = v[1] = v[2] = 0.0f;
  609. return;
  610. }
  611. glm_vec3_scale(v, 1.0f / norm, v);
  612. }
  613. /*!
  614. * @brief normalize vec3 to dest
  615. *
  616. * @param[in] v source
  617. * @param[out] dest destination
  618. */
  619. CGLM_INLINE
  620. void
  621. glm_vec3_normalize_to(vec3 v, vec3 dest) {
  622. float norm;
  623. norm = glm_vec3_norm(v);
  624. if (CGLM_UNLIKELY(norm < FLT_EPSILON)) {
  625. glm_vec3_zero(dest);
  626. return;
  627. }
  628. glm_vec3_scale(v, 1.0f / norm, dest);
  629. }
  630. /*!
  631. * @brief cross product of two vector (RH)
  632. *
  633. * @param[in] a vector 1
  634. * @param[in] b vector 2
  635. * @param[out] dest destination
  636. */
  637. CGLM_INLINE
  638. void
  639. glm_vec3_cross(vec3 a, vec3 b, vec3 dest) {
  640. vec3 c;
  641. /* (u2.v3 - u3.v2, u3.v1 - u1.v3, u1.v2 - u2.v1) */
  642. c[0] = a[1] * b[2] - a[2] * b[1];
  643. c[1] = a[2] * b[0] - a[0] * b[2];
  644. c[2] = a[0] * b[1] - a[1] * b[0];
  645. glm_vec3_copy(c, dest);
  646. }
  647. /*!
  648. * @brief cross product of two vector (RH) and normalize the result
  649. *
  650. * @param[in] a vector 1
  651. * @param[in] b vector 2
  652. * @param[out] dest destination
  653. */
  654. CGLM_INLINE
  655. void
  656. glm_vec3_crossn(vec3 a, vec3 b, vec3 dest) {
  657. glm_vec3_cross(a, b, dest);
  658. glm_vec3_normalize(dest);
  659. }
  660. /*!
  661. * @brief angle between two vector
  662. *
  663. * @param[in] a vector1
  664. * @param[in] b vector2
  665. *
  666. * @return angle as radians
  667. */
  668. CGLM_INLINE
  669. float
  670. glm_vec3_angle(vec3 a, vec3 b) {
  671. float norm, dot;
  672. /* maybe compiler generate approximation instruction (rcp) */
  673. norm = 1.0f / (glm_vec3_norm(a) * glm_vec3_norm(b));
  674. dot = glm_vec3_dot(a, b) * norm;
  675. if (dot > 1.0f)
  676. return 0.0f;
  677. else if (dot < -1.0f)
  678. return CGLM_PI;
  679. return acosf(dot);
  680. }
  681. /*!
  682. * @brief rotate vec3 around axis by angle using Rodrigues' rotation formula
  683. *
  684. * @param[in, out] v vector
  685. * @param[in] axis axis vector (must be unit vector)
  686. * @param[in] angle angle by radians
  687. */
  688. CGLM_INLINE
  689. void
  690. glm_vec3_rotate(vec3 v, float angle, vec3 axis) {
  691. vec3 v1, v2, k;
  692. float c, s;
  693. c = cosf(angle);
  694. s = sinf(angle);
  695. glm_vec3_normalize_to(axis, k);
  696. /* Right Hand, Rodrigues' rotation formula:
  697. v = v*cos(t) + (kxv)sin(t) + k*(k.v)(1 - cos(t))
  698. */
  699. glm_vec3_scale(v, c, v1);
  700. glm_vec3_cross(k, v, v2);
  701. glm_vec3_scale(v2, s, v2);
  702. glm_vec3_add(v1, v2, v1);
  703. glm_vec3_scale(k, glm_vec3_dot(k, v) * (1.0f - c), v2);
  704. glm_vec3_add(v1, v2, v);
  705. }
  706. /*!
  707. * @brief apply rotation matrix to vector
  708. *
  709. * matrix format should be (no perspective):
  710. * a b c x
  711. * e f g y
  712. * i j k z
  713. * 0 0 0 w
  714. *
  715. * @param[in] m affine matrix or rot matrix
  716. * @param[in] v vector
  717. * @param[out] dest rotated vector
  718. */
  719. CGLM_INLINE
  720. void
  721. glm_vec3_rotate_m4(mat4 m, vec3 v, vec3 dest) {
  722. vec4 x, y, z, res;
  723. glm_vec4_normalize_to(m[0], x);
  724. glm_vec4_normalize_to(m[1], y);
  725. glm_vec4_normalize_to(m[2], z);
  726. glm_vec4_scale(x, v[0], res);
  727. glm_vec4_muladds(y, v[1], res);
  728. glm_vec4_muladds(z, v[2], res);
  729. glm_vec3(res, dest);
  730. }
  731. /*!
  732. * @brief apply rotation matrix to vector
  733. *
  734. * @param[in] m affine matrix or rot matrix
  735. * @param[in] v vector
  736. * @param[out] dest rotated vector
  737. */
  738. CGLM_INLINE
  739. void
  740. glm_vec3_rotate_m3(mat3 m, vec3 v, vec3 dest) {
  741. vec4 res, x, y, z;
  742. glm_vec4(m[0], 0.0f, x);
  743. glm_vec4(m[1], 0.0f, y);
  744. glm_vec4(m[2], 0.0f, z);
  745. glm_vec4_normalize(x);
  746. glm_vec4_normalize(y);
  747. glm_vec4_normalize(z);
  748. glm_vec4_scale(x, v[0], res);
  749. glm_vec4_muladds(y, v[1], res);
  750. glm_vec4_muladds(z, v[2], res);
  751. glm_vec3(res, dest);
  752. }
  753. /*!
  754. * @brief project a vector onto b vector
  755. *
  756. * @param[in] a vector1
  757. * @param[in] b vector2
  758. * @param[out] dest projected vector
  759. */
  760. CGLM_INLINE
  761. void
  762. glm_vec3_proj(vec3 a, vec3 b, vec3 dest) {
  763. glm_vec3_scale(b,
  764. glm_vec3_dot(a, b) / glm_vec3_norm2(b),
  765. dest);
  766. }
  767. /**
  768. * @brief find center point of two vector
  769. *
  770. * @param[in] a vector1
  771. * @param[in] b vector2
  772. * @param[out] dest center point
  773. */
  774. CGLM_INLINE
  775. void
  776. glm_vec3_center(vec3 a, vec3 b, vec3 dest) {
  777. glm_vec3_add(a, b, dest);
  778. glm_vec3_scale(dest, 0.5f, dest);
  779. }
  780. /**
  781. * @brief squared distance between two vectors
  782. *
  783. * @param[in] a vector1
  784. * @param[in] b vector2
  785. * @return returns squared distance (distance * distance)
  786. */
  787. CGLM_INLINE
  788. float
  789. glm_vec3_distance2(vec3 a, vec3 b) {
  790. return glm_pow2(a[0] - b[0])
  791. + glm_pow2(a[1] - b[1])
  792. + glm_pow2(a[2] - b[2]);
  793. }
  794. /**
  795. * @brief distance between two vectors
  796. *
  797. * @param[in] a vector1
  798. * @param[in] b vector2
  799. * @return returns distance
  800. */
  801. CGLM_INLINE
  802. float
  803. glm_vec3_distance(vec3 a, vec3 b) {
  804. return sqrtf(glm_vec3_distance2(a, b));
  805. }
  806. /*!
  807. * @brief max values of vectors
  808. *
  809. * @param[in] a vector1
  810. * @param[in] b vector2
  811. * @param[out] dest destination
  812. */
  813. CGLM_INLINE
  814. void
  815. glm_vec3_maxv(vec3 a, vec3 b, vec3 dest) {
  816. dest[0] = glm_max(a[0], b[0]);
  817. dest[1] = glm_max(a[1], b[1]);
  818. dest[2] = glm_max(a[2], b[2]);
  819. }
  820. /*!
  821. * @brief min values of vectors
  822. *
  823. * @param[in] a vector1
  824. * @param[in] b vector2
  825. * @param[out] dest destination
  826. */
  827. CGLM_INLINE
  828. void
  829. glm_vec3_minv(vec3 a, vec3 b, vec3 dest) {
  830. dest[0] = glm_min(a[0], b[0]);
  831. dest[1] = glm_min(a[1], b[1]);
  832. dest[2] = glm_min(a[2], b[2]);
  833. }
  834. /*!
  835. * @brief possible orthogonal/perpendicular vector
  836. *
  837. * @param[in] v vector
  838. * @param[out] dest orthogonal/perpendicular vector
  839. */
  840. CGLM_INLINE
  841. void
  842. glm_vec3_ortho(vec3 v, vec3 dest) {
  843. float ignore;
  844. float f = modff(fabsf(v[0]) + 0.5f, &ignore);
  845. vec3 result = {-v[1], v[0] - f * v[2], f * v[1]};
  846. glm_vec3_copy(result, dest);
  847. }
  848. /*!
  849. * @brief clamp vector's individual members between min and max values
  850. *
  851. * @param[in, out] v vector
  852. * @param[in] minVal minimum value
  853. * @param[in] maxVal maximum value
  854. */
  855. CGLM_INLINE
  856. void
  857. glm_vec3_clamp(vec3 v, float minVal, float maxVal) {
  858. v[0] = glm_clamp(v[0], minVal, maxVal);
  859. v[1] = glm_clamp(v[1], minVal, maxVal);
  860. v[2] = glm_clamp(v[2], minVal, maxVal);
  861. }
  862. /*!
  863. * @brief linear interpolation between two vectors
  864. *
  865. * formula: from + s * (to - from)
  866. *
  867. * @param[in] from from value
  868. * @param[in] to to value
  869. * @param[in] t interpolant (amount)
  870. * @param[out] dest destination
  871. */
  872. CGLM_INLINE
  873. void
  874. glm_vec3_lerp(vec3 from, vec3 to, float t, vec3 dest) {
  875. vec3 s, v;
  876. /* from + s * (to - from) */
  877. glm_vec3_broadcast(t, s);
  878. glm_vec3_sub(to, from, v);
  879. glm_vec3_mul(s, v, v);
  880. glm_vec3_add(from, v, dest);
  881. }
  882. /*!
  883. * @brief linear interpolation between two vectors (clamped)
  884. *
  885. * formula: from + s * (to - from)
  886. *
  887. * @param[in] from from value
  888. * @param[in] to to value
  889. * @param[in] t interpolant (amount) clamped between 0 and 1
  890. * @param[out] dest destination
  891. */
  892. CGLM_INLINE
  893. void
  894. glm_vec3_lerpc(vec3 from, vec3 to, float t, vec3 dest) {
  895. glm_vec3_lerp(from, to, glm_clamp_zo(t), dest);
  896. }
  897. /*!
  898. * @brief linear interpolation between two vectors
  899. *
  900. * formula: from + s * (to - from)
  901. *
  902. * @param[in] from from value
  903. * @param[in] to to value
  904. * @param[in] t interpolant (amount)
  905. * @param[out] dest destination
  906. */
  907. CGLM_INLINE
  908. void
  909. glm_vec3_mix(vec3 from, vec3 to, float t, vec3 dest) {
  910. glm_vec3_lerp(from, to, t, dest);
  911. }
  912. /*!
  913. * @brief linear interpolation between two vectors (clamped)
  914. *
  915. * formula: from + s * (to - from)
  916. *
  917. * @param[in] from from value
  918. * @param[in] to to value
  919. * @param[in] t interpolant (amount) clamped between 0 and 1
  920. * @param[out] dest destination
  921. */
  922. CGLM_INLINE
  923. void
  924. glm_vec3_mixc(vec3 from, vec3 to, float t, vec3 dest) {
  925. glm_vec3_lerpc(from, to, t, dest);
  926. }
  927. /*!
  928. * @brief threshold function
  929. *
  930. * @param[in] edge threshold
  931. * @param[in] x value to test against threshold
  932. * @param[out] dest destination
  933. */
  934. CGLM_INLINE
  935. void
  936. glm_vec3_step(vec3 edge, vec3 x, vec3 dest) {
  937. dest[0] = glm_step(edge[0], x[0]);
  938. dest[1] = glm_step(edge[1], x[1]);
  939. dest[2] = glm_step(edge[2], x[2]);
  940. }
  941. /*!
  942. * @brief threshold function with a smooth transition (unidimensional)
  943. *
  944. * @param[in] edge0 low threshold
  945. * @param[in] edge1 high threshold
  946. * @param[in] x value to test against threshold
  947. * @param[out] dest destination
  948. */
  949. CGLM_INLINE
  950. void
  951. glm_vec3_smoothstep_uni(float edge0, float edge1, vec3 x, vec3 dest) {
  952. dest[0] = glm_smoothstep(edge0, edge1, x[0]);
  953. dest[1] = glm_smoothstep(edge0, edge1, x[1]);
  954. dest[2] = glm_smoothstep(edge0, edge1, x[2]);
  955. }
  956. /*!
  957. * @brief threshold function with a smooth transition
  958. *
  959. * @param[in] edge0 low threshold
  960. * @param[in] edge1 high threshold
  961. * @param[in] x value to test against threshold
  962. * @param[out] dest destination
  963. */
  964. CGLM_INLINE
  965. void
  966. glm_vec3_smoothstep(vec3 edge0, vec3 edge1, vec3 x, vec3 dest) {
  967. dest[0] = glm_smoothstep(edge0[0], edge1[0], x[0]);
  968. dest[1] = glm_smoothstep(edge0[1], edge1[1], x[1]);
  969. dest[2] = glm_smoothstep(edge0[2], edge1[2], x[2]);
  970. }
  971. /*!
  972. * @brief smooth Hermite interpolation between two vectors
  973. *
  974. * formula: from + s * (to - from)
  975. *
  976. * @param[in] from from value
  977. * @param[in] to to value
  978. * @param[in] t interpolant (amount)
  979. * @param[out] dest destination
  980. */
  981. CGLM_INLINE
  982. void
  983. glm_vec3_smoothinterp(vec3 from, vec3 to, float t, vec3 dest) {
  984. vec3 s, v;
  985. /* from + s * (to - from) */
  986. glm_vec3_broadcast(glm_smooth(t), s);
  987. glm_vec3_sub(to, from, v);
  988. glm_vec3_mul(s, v, v);
  989. glm_vec3_add(from, v, dest);
  990. }
  991. /*!
  992. * @brief smooth Hermite interpolation between two vectors (clamped)
  993. *
  994. * formula: from + s * (to - from)
  995. *
  996. * @param[in] from from value
  997. * @param[in] to to value
  998. * @param[in] t interpolant (amount) clamped between 0 and 1
  999. * @param[out] dest destination
  1000. */
  1001. CGLM_INLINE
  1002. void
  1003. glm_vec3_smoothinterpc(vec3 from, vec3 to, float t, vec3 dest) {
  1004. glm_vec3_smoothinterp(from, to, glm_clamp_zo(t), dest);
  1005. }
  1006. /*!
  1007. * @brief swizzle vector components
  1008. *
  1009. * you can use existing masks e.g. GLM_XXX, GLM_ZYX
  1010. *
  1011. * @param[in] v source
  1012. * @param[in] mask mask
  1013. * @param[out] dest destination
  1014. */
  1015. CGLM_INLINE
  1016. void
  1017. glm_vec3_swizzle(vec3 v, int mask, vec3 dest) {
  1018. vec3 t;
  1019. t[0] = v[(mask & (3 << 0))];
  1020. t[1] = v[(mask & (3 << 2)) >> 2];
  1021. t[2] = v[(mask & (3 << 4)) >> 4];
  1022. glm_vec3_copy(t, dest);
  1023. }
  1024. /*!
  1025. * @brief vec3 cross product
  1026. *
  1027. * this is just convenient wrapper
  1028. *
  1029. * @param[in] a source 1
  1030. * @param[in] b source 2
  1031. * @param[out] d destination
  1032. */
  1033. CGLM_INLINE
  1034. void
  1035. glm_cross(vec3 a, vec3 b, vec3 d) {
  1036. glm_vec3_cross(a, b, d);
  1037. }
  1038. /*!
  1039. * @brief vec3 dot product
  1040. *
  1041. * this is just convenient wrapper
  1042. *
  1043. * @param[in] a vector1
  1044. * @param[in] b vector2
  1045. *
  1046. * @return dot product
  1047. */
  1048. CGLM_INLINE
  1049. float
  1050. glm_dot(vec3 a, vec3 b) {
  1051. return glm_vec3_dot(a, b);
  1052. }
  1053. /*!
  1054. * @brief normalize vec3 and store result in same vec
  1055. *
  1056. * this is just convenient wrapper
  1057. *
  1058. * @param[in, out] v vector
  1059. */
  1060. CGLM_INLINE
  1061. void
  1062. glm_normalize(vec3 v) {
  1063. glm_vec3_normalize(v);
  1064. }
  1065. /*!
  1066. * @brief normalize vec3 to dest
  1067. *
  1068. * this is just convenient wrapper
  1069. *
  1070. * @param[in] v source
  1071. * @param[out] dest destination
  1072. */
  1073. CGLM_INLINE
  1074. void
  1075. glm_normalize_to(vec3 v, vec3 dest) {
  1076. glm_vec3_normalize_to(v, dest);
  1077. }
  1078. /*!
  1079. * @brief Create three dimensional vector from pointer
  1080. *
  1081. * @param[in] src pointer to an array of floats
  1082. * @param[out] dest destination vector
  1083. */
  1084. CGLM_INLINE
  1085. void
  1086. glm_vec3_make(const float * __restrict src, vec3 dest) {
  1087. dest[0] = src[0];
  1088. dest[1] = src[1];
  1089. dest[2] = src[2];
  1090. }
  1091. /*!
  1092. * @brief a vector pointing in the same direction as another
  1093. *
  1094. * orients a vector to point away from a surface as defined by its normal
  1095. *
  1096. * @param[in] n vector to orient
  1097. * @param[in] v incident vector
  1098. * @param[in] nref reference vector
  1099. * @param[out] dest oriented vector, pointing away from the surface
  1100. */
  1101. CGLM_INLINE
  1102. void
  1103. glm_vec3_faceforward(vec3 n, vec3 v, vec3 nref, vec3 dest) {
  1104. if (glm_vec3_dot(v, nref) < 0.0f) {
  1105. /* N is facing away from I */
  1106. glm_vec3_copy(n, dest);
  1107. } else {
  1108. /* N is facing towards I, negate it */
  1109. glm_vec3_negate_to(n, dest);
  1110. }
  1111. }
  1112. /*!
  1113. * @brief reflection vector using an incident ray and a surface normal
  1114. *
  1115. * @param[in] v incident vector
  1116. * @param[in] n normalized normal vector
  1117. * @param[out] dest reflection result
  1118. */
  1119. CGLM_INLINE
  1120. void
  1121. glm_vec3_reflect(vec3 v, vec3 n, vec3 dest) {
  1122. vec3 temp;
  1123. glm_vec3_scale(n, 2.0f * glm_vec3_dot(v, n), temp);
  1124. glm_vec3_sub(v, temp, dest);
  1125. }
  1126. /*!
  1127. * @brief computes refraction vector for an incident vector and a surface normal.
  1128. *
  1129. * calculates the refraction vector based on Snell's law. If total internal reflection
  1130. * occurs (angle too great given eta), dest is set to zero and returns false.
  1131. * Otherwise, computes refraction vector, stores it in dest, and returns true.
  1132. *
  1133. * @param[in] v normalized incident vector
  1134. * @param[in] n normalized normal vector
  1135. * @param[in] eta ratio of indices of refraction (incident/transmitted)
  1136. * @param[out] dest refraction vector if refraction occurs; zero vector otherwise
  1137. *
  1138. * @returns true if refraction occurs; false if total internal reflection occurs.
  1139. */
  1140. CGLM_INLINE
  1141. bool
  1142. glm_vec3_refract(vec3 v, vec3 n, float eta, vec3 dest) {
  1143. float ndi, eni, k;
  1144. ndi = glm_vec3_dot(n, v);
  1145. eni = eta * ndi;
  1146. k = 1.0f - eta * eta + eni * eni;
  1147. if (k < 0.0f) {
  1148. glm_vec3_zero(dest);
  1149. return false;
  1150. }
  1151. glm_vec3_scale(v, eta, dest);
  1152. glm_vec3_mulsubs(n, eni + sqrtf(k), dest);
  1153. return true;
  1154. }
  1155. #endif /* cglm_vec3_h */