1
0

vec4.h 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348
  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_VEC4_ONE_INIT
  10. GLM_VEC4_BLACK_INIT
  11. GLM_VEC4_ZERO_INIT
  12. GLM_VEC4_ONE
  13. GLM_VEC4_BLACK
  14. GLM_VEC4_ZERO
  15. Functions:
  16. CGLM_INLINE void glm_vec4(vec3 v3, float last, vec4 dest);
  17. CGLM_INLINE void glm_vec4_copy3(vec4 a, vec3 dest);
  18. CGLM_INLINE void glm_vec4_copy(vec4 v, vec4 dest);
  19. CGLM_INLINE void glm_vec4_ucopy(vec4 v, vec4 dest);
  20. CGLM_INLINE float glm_vec4_dot(vec4 a, vec4 b);
  21. CGLM_INLINE float glm_vec4_norm2(vec4 v);
  22. CGLM_INLINE float glm_vec4_norm(vec4 v);
  23. CGLM_INLINE float glm_vec4_norm_one(vec4 v);
  24. CGLM_INLINE float glm_vec4_norm_inf(vec4 v);
  25. CGLM_INLINE void glm_vec4_add(vec4 a, vec4 b, vec4 dest);
  26. CGLM_INLINE void glm_vec4_adds(vec4 v, float s, vec4 dest);
  27. CGLM_INLINE void glm_vec4_sub(vec4 a, vec4 b, vec4 dest);
  28. CGLM_INLINE void glm_vec4_subs(vec4 v, float s, vec4 dest);
  29. CGLM_INLINE void glm_vec4_mul(vec4 a, vec4 b, vec4 dest);
  30. CGLM_INLINE void glm_vec4_scale(vec4 v, float s, vec4 dest);
  31. CGLM_INLINE void glm_vec4_scale_as(vec4 v, float s, vec4 dest);
  32. CGLM_INLINE void glm_vec4_div(vec4 a, vec4 b, vec4 dest);
  33. CGLM_INLINE void glm_vec4_divs(vec4 v, float s, vec4 dest);
  34. CGLM_INLINE void glm_vec4_addadd(vec4 a, vec4 b, vec4 dest);
  35. CGLM_INLINE void glm_vec4_subadd(vec4 a, vec4 b, vec4 dest);
  36. CGLM_INLINE void glm_vec4_muladd(vec4 a, vec4 b, vec4 dest);
  37. CGLM_INLINE void glm_vec4_muladds(vec4 a, float s, vec4 dest);
  38. CGLM_INLINE void glm_vec4_maxadd(vec4 a, vec4 b, vec4 dest);
  39. CGLM_INLINE void glm_vec4_minadd(vec4 a, vec4 b, vec4 dest);
  40. CGLM_INLINE void glm_vec4_subsub(vec4 a, vec4 b, vec4 dest);
  41. CGLM_INLINE void glm_vec4_addsub(vec4 a, vec4 b, vec4 dest);
  42. CGLM_INLINE void glm_vec4_mulsub(vec4 a, vec4 b, vec4 dest);
  43. CGLM_INLINE void glm_vec4_mulsubs(vec4 a, float s, vec4 dest);
  44. CGLM_INLINE void glm_vec4_maxsub(vec4 a, vec4 b, vec4 dest);
  45. CGLM_INLINE void glm_vec4_minsub(vec4 a, vec4 b, vec4 dest);
  46. CGLM_INLINE void glm_vec4_negate(vec4 v);
  47. CGLM_INLINE void glm_vec4_inv(vec4 v);
  48. CGLM_INLINE void glm_vec4_inv_to(vec4 v, vec4 dest);
  49. CGLM_INLINE void glm_vec4_normalize(vec4 v);
  50. CGLM_INLINE void glm_vec4_normalize_to(vec4 vec, vec4 dest);
  51. CGLM_INLINE float glm_vec4_distance(vec4 a, vec4 b);
  52. CGLM_INLINE float glm_vec4_distance2(vec4 a, vec4 b);
  53. CGLM_INLINE void glm_vec4_maxv(vec4 a, vec4 b, vec4 dest);
  54. CGLM_INLINE void glm_vec4_minv(vec4 a, vec4 b, vec4 dest);
  55. CGLM_INLINE void glm_vec4_clamp(vec4 v, float minVal, float maxVal);
  56. CGLM_INLINE void glm_vec4_lerp(vec4 from, vec4 to, float t, vec4 dest);
  57. CGLM_INLINE void glm_vec4_lerpc(vec4 from, vec4 to, float t, vec4 dest);
  58. CGLM_INLINE void glm_vec4_step(vec4 edge, vec4 x, vec4 dest);
  59. CGLM_INLINE void glm_vec4_smoothstep_uni(float edge0, float edge1, vec4 x, vec4 dest);
  60. CGLM_INLINE void glm_vec4_smoothstep(vec4 edge0, vec4 edge1, vec4 x, vec4 dest);
  61. CGLM_INLINE void glm_vec4_smoothinterp(vec4 from, vec4 to, float t, vec4 dest);
  62. CGLM_INLINE void glm_vec4_smoothinterpc(vec4 from, vec4 to, float t, vec4 dest);
  63. CGLM_INLINE void glm_vec4_swizzle(vec4 v, int mask, vec4 dest);
  64. CGLM_INLINE void glm_vec4_make(float * restrict src, vec4 dest);
  65. CGLM_INLINE void glm_vec4_reflect(vec4 v, vec4 n, vec4 dest);
  66. CGLM_INLINE void glm_vec4_refract(vec4 v, vec4 n, float eta, vec4 dest);
  67. DEPRECATED:
  68. glm_vec4_dup
  69. glm_vec4_flipsign
  70. glm_vec4_flipsign_to
  71. glm_vec4_inv
  72. glm_vec4_inv_to
  73. glm_vec4_mulv
  74. glm_vec4_step_uni --> use glm_vec4_steps
  75. */
  76. #ifndef cglm_vec4_h
  77. #define cglm_vec4_h
  78. #include "common.h"
  79. #include "vec4-ext.h"
  80. #include "util.h"
  81. /* DEPRECATED! functions */
  82. #define glm_vec4_dup3(v, dest) glm_vec4_copy3(v, dest)
  83. #define glm_vec4_dup(v, dest) glm_vec4_copy(v, dest)
  84. #define glm_vec4_flipsign(v) glm_vec4_negate(v)
  85. #define glm_vec4_flipsign_to(v, dest) glm_vec4_negate_to(v, dest)
  86. #define glm_vec4_inv(v) glm_vec4_negate(v)
  87. #define glm_vec4_inv_to(v, dest) glm_vec4_negate_to(v, dest)
  88. #define glm_vec4_mulv(a, b, d) glm_vec4_mul(a, b, d)
  89. #define glm_vec4_step_uni(edge, x, dest) glm_vec4_steps(edge, x, dest)
  90. #define GLM_VEC4_ONE_INIT {1.0f, 1.0f, 1.0f, 1.0f}
  91. #define GLM_VEC4_BLACK_INIT {0.0f, 0.0f, 0.0f, 1.0f}
  92. #define GLM_VEC4_ZERO_INIT {0.0f, 0.0f, 0.0f, 0.0f}
  93. #define GLM_VEC4_ONE ((vec4)GLM_VEC4_ONE_INIT)
  94. #define GLM_VEC4_BLACK ((vec4)GLM_VEC4_BLACK_INIT)
  95. #define GLM_VEC4_ZERO ((vec4)GLM_VEC4_ZERO_INIT)
  96. #define GLM_XXXX GLM_SHUFFLE4(0, 0, 0, 0)
  97. #define GLM_YYYY GLM_SHUFFLE4(1, 1, 1, 1)
  98. #define GLM_ZZZZ GLM_SHUFFLE4(2, 2, 2, 2)
  99. #define GLM_WWWW GLM_SHUFFLE4(3, 3, 3, 3)
  100. #define GLM_WZYX GLM_SHUFFLE4(0, 1, 2, 3)
  101. /*!
  102. * @brief init vec4 using vec3
  103. *
  104. * @param[in] v3 vector3
  105. * @param[in] last last item
  106. * @param[out] dest destination
  107. */
  108. CGLM_INLINE
  109. void
  110. glm_vec4(vec3 v3, float last, vec4 dest) {
  111. dest[0] = v3[0];
  112. dest[1] = v3[1];
  113. dest[2] = v3[2];
  114. dest[3] = last;
  115. }
  116. /*!
  117. * @brief copy first 3 members of [a] to [dest]
  118. *
  119. * @param[in] a source
  120. * @param[out] dest destination
  121. */
  122. CGLM_INLINE
  123. void
  124. glm_vec4_copy3(vec4 a, vec3 dest) {
  125. dest[0] = a[0];
  126. dest[1] = a[1];
  127. dest[2] = a[2];
  128. }
  129. /*!
  130. * @brief copy all members of [a] to [dest]
  131. *
  132. * @param[in] v source
  133. * @param[out] dest destination
  134. */
  135. CGLM_INLINE
  136. void
  137. glm_vec4_copy(vec4 v, vec4 dest) {
  138. #if defined(__wasm__) && defined(__wasm_simd128__)
  139. glmm_store(dest, glmm_load(v));
  140. #elif defined( __SSE__ ) || defined( __SSE2__ )
  141. glmm_store(dest, glmm_load(v));
  142. #elif defined(CGLM_NEON_FP)
  143. vst1q_f32(dest, vld1q_f32(v));
  144. #else
  145. dest[0] = v[0];
  146. dest[1] = v[1];
  147. dest[2] = v[2];
  148. dest[3] = v[3];
  149. #endif
  150. }
  151. /*!
  152. * @brief copy all members of [a] to [dest]
  153. *
  154. * alignment is not required
  155. *
  156. * @param[in] v source
  157. * @param[out] dest destination
  158. */
  159. CGLM_INLINE
  160. void
  161. glm_vec4_ucopy(vec4 v, vec4 dest) {
  162. #if defined(__wasm__) && defined(__wasm_simd128__)
  163. /* note here wasm v128.load/v128.store support unaligned loads and stores */
  164. wasm_v128_store(dest, wasm_v128_load(v));
  165. #else
  166. dest[0] = v[0];
  167. dest[1] = v[1];
  168. dest[2] = v[2];
  169. dest[3] = v[3];
  170. #endif
  171. }
  172. /*!
  173. * @brief make vector zero
  174. *
  175. * @param[in, out] v vector
  176. */
  177. CGLM_INLINE
  178. void
  179. glm_vec4_zero(vec4 v) {
  180. #if defined(__wasm__) && defined(__wasm_simd128__)
  181. glmm_store(v, wasm_f32x4_const_splat(0.f));
  182. #elif defined( __SSE__ ) || defined( __SSE2__ )
  183. glmm_store(v, _mm_setzero_ps());
  184. #elif defined(CGLM_NEON_FP)
  185. vst1q_f32(v, vdupq_n_f32(0.0f));
  186. #else
  187. v[0] = 0.0f;
  188. v[1] = 0.0f;
  189. v[2] = 0.0f;
  190. v[3] = 0.0f;
  191. #endif
  192. }
  193. /*!
  194. * @brief make vector one
  195. *
  196. * @param[in, out] v vector
  197. */
  198. CGLM_INLINE
  199. void
  200. glm_vec4_one(vec4 v) {
  201. #if defined(__wasm__) && defined(__wasm_simd128__)
  202. glmm_store(v, wasm_f32x4_const_splat(1.0f));
  203. #elif defined( __SSE__ ) || defined( __SSE2__ )
  204. glmm_store(v, glmm_set1_rval(1.0f));
  205. #elif defined(CGLM_NEON_FP)
  206. vst1q_f32(v, vdupq_n_f32(1.0f));
  207. #else
  208. v[0] = 1.0f;
  209. v[1] = 1.0f;
  210. v[2] = 1.0f;
  211. v[3] = 1.0f;
  212. #endif
  213. }
  214. /*!
  215. * @brief vec4 dot product
  216. *
  217. * @param[in] a vector1
  218. * @param[in] b vector2
  219. *
  220. * @return dot product
  221. */
  222. CGLM_INLINE
  223. float
  224. glm_vec4_dot(vec4 a, vec4 b) {
  225. #if defined(CGLM_SIMD)
  226. return glmm_dot(glmm_load(a), glmm_load(b));
  227. #else
  228. return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
  229. #endif
  230. }
  231. /*!
  232. * @brief norm * norm (magnitude) of vec
  233. *
  234. * we can use this func instead of calling norm * norm, because it would call
  235. * sqrtf function twice but with this func we can avoid func call, maybe this is
  236. * not good name for this func
  237. *
  238. * @param[in] v vec4
  239. *
  240. * @return norm * norm
  241. */
  242. CGLM_INLINE
  243. float
  244. glm_vec4_norm2(vec4 v) {
  245. return glm_vec4_dot(v, v);
  246. }
  247. /*!
  248. * @brief euclidean norm (magnitude), also called L2 norm
  249. * this will give magnitude of vector in euclidean space
  250. *
  251. * @param[in] v vector
  252. *
  253. * @return norm
  254. */
  255. CGLM_INLINE
  256. float
  257. glm_vec4_norm(vec4 v) {
  258. #if defined(CGLM_SIMD)
  259. return glmm_norm(glmm_load(v));
  260. #else
  261. return sqrtf(glm_vec4_dot(v, v));
  262. #endif
  263. }
  264. /*!
  265. * @brief L1 norm of vec4
  266. * Also known as Manhattan Distance or Taxicab norm.
  267. * L1 Norm is the sum of the magnitudes of the vectors in a space.
  268. * It is calculated as the sum of the absolute values of the vector components.
  269. * In this norm, all the components of the vector are weighted equally.
  270. *
  271. * This computes:
  272. * L1 norm = |v[0]| + |v[1]| + |v[2]| + |v[3]|
  273. *
  274. * @param[in] v vector
  275. *
  276. * @return L1 norm
  277. */
  278. CGLM_INLINE
  279. float
  280. glm_vec4_norm_one(vec4 v) {
  281. #if defined(CGLM_SIMD)
  282. return glmm_norm_one(glmm_load(v));
  283. #else
  284. vec4 t;
  285. glm_vec4_abs(v, t);
  286. return glm_vec4_hadd(t);
  287. #endif
  288. }
  289. /*!
  290. * @brief infinity norm of vec4
  291. * Also known as Maximum norm.
  292. * Infinity Norm is the largest magnitude among each element of a vector.
  293. * It is calculated as the maximum of the absolute values of the vector components.
  294. *
  295. * This computes:
  296. * inf norm = max(|v[0]|, |v[1]|, |v[2]|, |v[3]|)
  297. *
  298. * @param[in] v vector
  299. *
  300. * @return infinity norm
  301. */
  302. CGLM_INLINE
  303. float
  304. glm_vec4_norm_inf(vec4 v) {
  305. #if defined(CGLM_SIMD)
  306. return glmm_norm_inf(glmm_load(v));
  307. #else
  308. vec4 t;
  309. glm_vec4_abs(v, t);
  310. return glm_vec4_max(t);
  311. #endif
  312. }
  313. /*!
  314. * @brief add b vector to a vector store result in dest
  315. *
  316. * @param[in] a vector1
  317. * @param[in] b vector2
  318. * @param[out] dest destination vector
  319. */
  320. CGLM_INLINE
  321. void
  322. glm_vec4_add(vec4 a, vec4 b, vec4 dest) {
  323. #if defined(__wasm__) && defined(__wasm_simd128__)
  324. glmm_store(dest, wasm_f32x4_add(glmm_load(a), glmm_load(b)));
  325. #elif defined( __SSE__ ) || defined( __SSE2__ )
  326. glmm_store(dest, _mm_add_ps(glmm_load(a), glmm_load(b)));
  327. #elif defined(CGLM_NEON_FP)
  328. vst1q_f32(dest, vaddq_f32(vld1q_f32(a), vld1q_f32(b)));
  329. #else
  330. dest[0] = a[0] + b[0];
  331. dest[1] = a[1] + b[1];
  332. dest[2] = a[2] + b[2];
  333. dest[3] = a[3] + b[3];
  334. #endif
  335. }
  336. /*!
  337. * @brief add scalar to v vector store result in dest (d = v + vec(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_vec4_adds(vec4 v, float s, vec4 dest) {
  346. #if defined(__wasm__) && defined(__wasm_simd128__)
  347. glmm_store(dest, wasm_f32x4_add(glmm_load(v), wasm_f32x4_splat(s)));
  348. #elif defined( __SSE__ ) || defined( __SSE2__ )
  349. glmm_store(dest, _mm_add_ps(glmm_load(v), glmm_set1(s)));
  350. #elif defined(CGLM_NEON_FP)
  351. vst1q_f32(dest, vaddq_f32(vld1q_f32(v), vdupq_n_f32(s)));
  352. #else
  353. dest[0] = v[0] + s;
  354. dest[1] = v[1] + s;
  355. dest[2] = v[2] + s;
  356. dest[3] = v[3] + s;
  357. #endif
  358. }
  359. /*!
  360. * @brief subtract b vector from a vector store result in dest (d = a - b)
  361. *
  362. * @param[in] a vector1
  363. * @param[in] b vector2
  364. * @param[out] dest destination vector
  365. */
  366. CGLM_INLINE
  367. void
  368. glm_vec4_sub(vec4 a, vec4 b, vec4 dest) {
  369. #if defined(__wasm__) && defined(__wasm_simd128__)
  370. glmm_store(dest, wasm_f32x4_sub(glmm_load(a), glmm_load(b)));
  371. #elif defined( __SSE__ ) || defined( __SSE2__ )
  372. glmm_store(dest, _mm_sub_ps(glmm_load(a), glmm_load(b)));
  373. #elif defined(CGLM_NEON_FP)
  374. vst1q_f32(dest, vsubq_f32(vld1q_f32(a), vld1q_f32(b)));
  375. #else
  376. dest[0] = a[0] - b[0];
  377. dest[1] = a[1] - b[1];
  378. dest[2] = a[2] - b[2];
  379. dest[3] = a[3] - b[3];
  380. #endif
  381. }
  382. /*!
  383. * @brief subtract scalar from v vector store result in dest (d = v - vec(s))
  384. *
  385. * @param[in] v vector
  386. * @param[in] s scalar
  387. * @param[out] dest destination vector
  388. */
  389. CGLM_INLINE
  390. void
  391. glm_vec4_subs(vec4 v, float s, vec4 dest) {
  392. #if defined(__wasm__) && defined(__wasm_simd128__)
  393. glmm_store(dest, wasm_f32x4_sub(glmm_load(v), wasm_f32x4_splat(s)));
  394. #elif defined( __SSE__ ) || defined( __SSE2__ )
  395. glmm_store(dest, _mm_sub_ps(glmm_load(v), glmm_set1(s)));
  396. #elif defined(CGLM_NEON_FP)
  397. vst1q_f32(dest, vsubq_f32(vld1q_f32(v), vdupq_n_f32(s)));
  398. #else
  399. dest[0] = v[0] - s;
  400. dest[1] = v[1] - s;
  401. dest[2] = v[2] - s;
  402. dest[3] = v[3] - s;
  403. #endif
  404. }
  405. /*!
  406. * @brief multiply two vectors (component-wise multiplication)
  407. *
  408. * @param a vector1
  409. * @param b vector2
  410. * @param dest dest = (a[0] * b[0], a[1] * b[1], a[2] * b[2], a[3] * b[3])
  411. */
  412. CGLM_INLINE
  413. void
  414. glm_vec4_mul(vec4 a, vec4 b, vec4 dest) {
  415. #if defined(__wasm__) && defined(__wasm_simd128__)
  416. glmm_store(dest, wasm_f32x4_mul(glmm_load(a), glmm_load(b)));
  417. #elif defined( __SSE__ ) || defined( __SSE2__ )
  418. glmm_store(dest, _mm_mul_ps(glmm_load(a), glmm_load(b)));
  419. #elif defined(CGLM_NEON_FP)
  420. vst1q_f32(dest, vmulq_f32(vld1q_f32(a), vld1q_f32(b)));
  421. #else
  422. dest[0] = a[0] * b[0];
  423. dest[1] = a[1] * b[1];
  424. dest[2] = a[2] * b[2];
  425. dest[3] = a[3] * b[3];
  426. #endif
  427. }
  428. /*!
  429. * @brief multiply/scale vec4 vector with scalar: result = v * s
  430. *
  431. * @param[in] v vector
  432. * @param[in] s scalar
  433. * @param[out] dest destination vector
  434. */
  435. CGLM_INLINE
  436. void
  437. glm_vec4_scale(vec4 v, float s, vec4 dest) {
  438. #if defined(__wasm__) && defined(__wasm_simd128__)
  439. glmm_store(dest, wasm_f32x4_mul(glmm_load(v), wasm_f32x4_splat(s)));
  440. #elif defined( __SSE__ ) || defined( __SSE2__ )
  441. glmm_store(dest, _mm_mul_ps(glmm_load(v), glmm_set1(s)));
  442. #elif defined(CGLM_NEON_FP)
  443. vst1q_f32(dest, vmulq_f32(vld1q_f32(v), vdupq_n_f32(s)));
  444. #else
  445. dest[0] = v[0] * s;
  446. dest[1] = v[1] * s;
  447. dest[2] = v[2] * s;
  448. dest[3] = v[3] * s;
  449. #endif
  450. }
  451. /*!
  452. * @brief make vec4 vector scale as specified: result = unit(v) * s
  453. *
  454. * @param[in] v vector
  455. * @param[in] s scalar
  456. * @param[out] dest destination vector
  457. */
  458. CGLM_INLINE
  459. void
  460. glm_vec4_scale_as(vec4 v, float s, vec4 dest) {
  461. float norm;
  462. norm = glm_vec4_norm(v);
  463. if (CGLM_UNLIKELY(norm < FLT_EPSILON)) {
  464. glm_vec4_zero(dest);
  465. return;
  466. }
  467. glm_vec4_scale(v, s / norm, dest);
  468. }
  469. /*!
  470. * @brief div vector with another component-wise division: d = a / b
  471. *
  472. * @param[in] a vector 1
  473. * @param[in] b vector 2
  474. * @param[out] dest result = (a[0]/b[0], a[1]/b[1], a[2]/b[2], a[3]/b[3])
  475. */
  476. CGLM_INLINE
  477. void
  478. glm_vec4_div(vec4 a, vec4 b, vec4 dest) {
  479. #if defined(CGLM_SIMD)
  480. glmm_store(dest, glmm_div(glmm_load(a), glmm_load(b)));
  481. #else
  482. dest[0] = a[0] / b[0];
  483. dest[1] = a[1] / b[1];
  484. dest[2] = a[2] / b[2];
  485. dest[3] = a[3] / b[3];
  486. #endif
  487. }
  488. /*!
  489. * @brief div vec4 vector with scalar: d = v / s
  490. *
  491. * @param[in] v vector
  492. * @param[in] s scalar
  493. * @param[out] dest destination vector
  494. */
  495. CGLM_INLINE
  496. void
  497. glm_vec4_divs(vec4 v, float s, vec4 dest) {
  498. #if defined(CGLM_SIMD)
  499. glmm_store(dest, glmm_div(glmm_load(v), glmm_set1(s)));
  500. #else
  501. glm_vec4_scale(v, 1.0f / s, dest);
  502. #endif
  503. }
  504. /*!
  505. * @brief add two vectors and add result to sum
  506. *
  507. * it applies += operator so dest must be initialized
  508. *
  509. * @param[in] a vector 1
  510. * @param[in] b vector 2
  511. * @param[out] dest dest += (a + b)
  512. */
  513. CGLM_INLINE
  514. void
  515. glm_vec4_addadd(vec4 a, vec4 b, vec4 dest) {
  516. #if defined(__wasm__) && defined(__wasm_simd128__)
  517. glmm_store(dest, wasm_f32x4_add(
  518. glmm_load(dest),
  519. wasm_f32x4_add(glmm_load(a), glmm_load(b))));
  520. #elif defined( __SSE__ ) || defined( __SSE2__ )
  521. glmm_store(dest, _mm_add_ps(glmm_load(dest),
  522. _mm_add_ps(glmm_load(a),
  523. glmm_load(b))));
  524. #elif defined(CGLM_NEON_FP)
  525. vst1q_f32(dest, vaddq_f32(vld1q_f32(dest),
  526. vaddq_f32(vld1q_f32(a),
  527. vld1q_f32(b))));
  528. #else
  529. dest[0] += a[0] + b[0];
  530. dest[1] += a[1] + b[1];
  531. dest[2] += a[2] + b[2];
  532. dest[3] += a[3] + b[3];
  533. #endif
  534. }
  535. /*!
  536. * @brief sub two vectors and add result to dest
  537. *
  538. * it applies += operator so dest must be initialized
  539. *
  540. * @param[in] a vector 1
  541. * @param[in] b vector 2
  542. * @param[out] dest dest += (a - b)
  543. */
  544. CGLM_INLINE
  545. void
  546. glm_vec4_subadd(vec4 a, vec4 b, vec4 dest) {
  547. #if defined(__wasm__) && defined(__wasm_simd128__)
  548. glmm_store(dest, wasm_f32x4_add(
  549. glmm_load(dest),
  550. wasm_f32x4_sub(glmm_load(a), glmm_load(b))));
  551. #elif defined( __SSE__ ) || defined( __SSE2__ )
  552. glmm_store(dest, _mm_add_ps(glmm_load(dest),
  553. _mm_sub_ps(glmm_load(a),
  554. glmm_load(b))));
  555. #elif defined(CGLM_NEON_FP)
  556. vst1q_f32(dest, vaddq_f32(vld1q_f32(dest),
  557. vsubq_f32(vld1q_f32(a),
  558. vld1q_f32(b))));
  559. #else
  560. dest[0] += a[0] - b[0];
  561. dest[1] += a[1] - b[1];
  562. dest[2] += a[2] - b[2];
  563. dest[3] += a[3] - b[3];
  564. #endif
  565. }
  566. /*!
  567. * @brief mul two vectors and add result to dest
  568. *
  569. * it applies += operator so dest must be initialized
  570. *
  571. * @param[in] a vector 1
  572. * @param[in] b vector 2
  573. * @param[out] dest dest += (a * b)
  574. */
  575. CGLM_INLINE
  576. void
  577. glm_vec4_muladd(vec4 a, vec4 b, vec4 dest) {
  578. #if defined(CGLM_SIMD)
  579. glmm_store(dest, glmm_fmadd(glmm_load(a), glmm_load(b), glmm_load(dest)));
  580. #else
  581. dest[0] += a[0] * b[0];
  582. dest[1] += a[1] * b[1];
  583. dest[2] += a[2] * b[2];
  584. dest[3] += a[3] * b[3];
  585. #endif
  586. }
  587. /*!
  588. * @brief mul vector with scalar and add result to sum
  589. *
  590. * it applies += operator so dest must be initialized
  591. *
  592. * @param[in] a vector
  593. * @param[in] s scalar
  594. * @param[out] dest dest += (a * b)
  595. */
  596. CGLM_INLINE
  597. void
  598. glm_vec4_muladds(vec4 a, float s, vec4 dest) {
  599. #if defined(CGLM_SIMD)
  600. glmm_store(dest, glmm_fmadd(glmm_load(a), glmm_set1(s), glmm_load(dest)));
  601. #else
  602. dest[0] += a[0] * s;
  603. dest[1] += a[1] * s;
  604. dest[2] += a[2] * s;
  605. dest[3] += a[3] * s;
  606. #endif
  607. }
  608. /*!
  609. * @brief add max of two vectors to result/dest
  610. *
  611. * it applies += operator so dest must be initialized
  612. *
  613. * @param[in] a vector 1
  614. * @param[in] b vector 2
  615. * @param[out] dest dest += max(a, b)
  616. */
  617. CGLM_INLINE
  618. void
  619. glm_vec4_maxadd(vec4 a, vec4 b, vec4 dest) {
  620. #if defined(__wasm__) && defined(__wasm_simd128__)
  621. glmm_store(dest, wasm_f32x4_add(glmm_load(dest),
  622. glmm_max(glmm_load(a), glmm_load(b))));
  623. #elif defined( __SSE__ ) || defined( __SSE2__ )
  624. glmm_store(dest, _mm_add_ps(glmm_load(dest),
  625. glmm_max(glmm_load(a), glmm_load(b))));
  626. #elif defined(CGLM_NEON_FP)
  627. glmm_store(dest, vaddq_f32(glmm_load(dest),
  628. glmm_max(glmm_load(a), glmm_load(b))));
  629. #else
  630. dest[0] += glm_max(a[0], b[0]);
  631. dest[1] += glm_max(a[1], b[1]);
  632. dest[2] += glm_max(a[2], b[2]);
  633. dest[3] += glm_max(a[3], b[3]);
  634. #endif
  635. }
  636. /*!
  637. * @brief add min of two vectors to result/dest
  638. *
  639. * it applies += operator so dest must be initialized
  640. *
  641. * @param[in] a vector 1
  642. * @param[in] b vector 2
  643. * @param[out] dest dest += min(a, b)
  644. */
  645. CGLM_INLINE
  646. void
  647. glm_vec4_minadd(vec4 a, vec4 b, vec4 dest) {
  648. #if defined(__wasm__) && defined(__wasm_simd128__)
  649. glmm_store(dest, wasm_f32x4_add(glmm_load(dest),
  650. glmm_min(glmm_load(a), glmm_load(b))));
  651. #elif defined( __SSE__ ) || defined( __SSE2__ )
  652. glmm_store(dest, _mm_add_ps(glmm_load(dest),
  653. glmm_min(glmm_load(a), glmm_load(b))));
  654. #elif defined(CGLM_NEON_FP)
  655. glmm_store(dest, vaddq_f32(glmm_load(dest),
  656. glmm_min(glmm_load(a), glmm_load(b))));
  657. #else
  658. dest[0] += glm_min(a[0], b[0]);
  659. dest[1] += glm_min(a[1], b[1]);
  660. dest[2] += glm_min(a[2], b[2]);
  661. dest[3] += glm_min(a[3], b[3]);
  662. #endif
  663. }
  664. /*!
  665. * @brief sub two vectors and sub result to dest
  666. *
  667. * it applies -= operator so dest must be initialized
  668. *
  669. * @param[in] a vector 1
  670. * @param[in] b vector 2
  671. * @param[out] dest dest -= (a - b)
  672. */
  673. CGLM_INLINE
  674. void
  675. glm_vec4_subsub(vec4 a, vec4 b, vec4 dest) {
  676. #if defined(__wasm__) && defined(__wasm_simd128__)
  677. glmm_store(dest, wasm_f32x4_sub(
  678. glmm_load(dest),
  679. wasm_f32x4_sub(glmm_load(a), glmm_load(b))));
  680. #elif defined( __SSE__ ) || defined( __SSE2__ )
  681. glmm_store(dest, _mm_sub_ps(glmm_load(dest),
  682. _mm_sub_ps(glmm_load(a),
  683. glmm_load(b))));
  684. #elif defined(CGLM_NEON_FP)
  685. vst1q_f32(dest, vsubq_f32(vld1q_f32(dest),
  686. vsubq_f32(vld1q_f32(a),
  687. vld1q_f32(b))));
  688. #else
  689. dest[0] -= a[0] - b[0];
  690. dest[1] -= a[1] - b[1];
  691. dest[2] -= a[2] - b[2];
  692. dest[3] -= a[3] - b[3];
  693. #endif
  694. }
  695. /*!
  696. * @brief add two vectors and sub result to dest
  697. *
  698. * it applies -= operator so dest must be initialized
  699. *
  700. * @param[in] a vector 1
  701. * @param[in] b vector 2
  702. * @param[out] dest dest -= (a + b)
  703. */
  704. CGLM_INLINE
  705. void
  706. glm_vec4_addsub(vec4 a, vec4 b, vec4 dest) {
  707. #if defined(__wasm__) && defined(__wasm_simd128__)
  708. glmm_store(dest, wasm_f32x4_sub(
  709. glmm_load(dest),
  710. wasm_f32x4_add(glmm_load(a), glmm_load(b))));
  711. #elif defined( __SSE__ ) || defined( __SSE2__ )
  712. glmm_store(dest, _mm_sub_ps(glmm_load(dest),
  713. _mm_add_ps(glmm_load(a),
  714. glmm_load(b))));
  715. #elif defined(CGLM_NEON_FP)
  716. vst1q_f32(dest, vsubq_f32(vld1q_f32(dest),
  717. vaddq_f32(vld1q_f32(a),
  718. vld1q_f32(b))));
  719. #else
  720. dest[0] -= a[0] + b[0];
  721. dest[1] -= a[1] + b[1];
  722. dest[2] -= a[2] + b[2];
  723. dest[3] -= a[3] + b[3];
  724. #endif
  725. }
  726. /*!
  727. * @brief mul two vectors and sub result to dest
  728. *
  729. * it applies -= operator so dest must be initialized
  730. *
  731. * @param[in] a vector 1
  732. * @param[in] b vector 2
  733. * @param[out] dest dest -= (a * b)
  734. */
  735. CGLM_INLINE
  736. void
  737. glm_vec4_mulsub(vec4 a, vec4 b, vec4 dest) {
  738. #if defined(CGLM_SIMD)
  739. glmm_store(dest, glmm_fnmadd(glmm_load(a), glmm_load(b), glmm_load(dest)));
  740. #else
  741. dest[0] -= a[0] * b[0];
  742. dest[1] -= a[1] * b[1];
  743. dest[2] -= a[2] * b[2];
  744. dest[3] -= a[3] * b[3];
  745. #endif
  746. }
  747. /*!
  748. * @brief mul vector with scalar and sub result to dest
  749. *
  750. * it applies -= operator so dest must be initialized
  751. *
  752. * @param[in] a vector
  753. * @param[in] s scalar
  754. * @param[out] dest dest -= (a * b)
  755. */
  756. CGLM_INLINE
  757. void
  758. glm_vec4_mulsubs(vec4 a, float s, vec4 dest) {
  759. #if defined(CGLM_SIMD)
  760. glmm_store(dest, glmm_fnmadd(glmm_load(a), glmm_set1(s), glmm_load(dest)));
  761. #else
  762. dest[0] -= a[0] * s;
  763. dest[1] -= a[1] * s;
  764. dest[2] -= a[2] * s;
  765. dest[3] -= a[3] * s;
  766. #endif
  767. }
  768. /*!
  769. * @brief sub max of two vectors to dest
  770. *
  771. * it applies -= operator so dest must be initialized
  772. *
  773. * @param[in] a vector 1
  774. * @param[in] b vector 2
  775. * @param[out] dest dest -= max(a, b)
  776. */
  777. CGLM_INLINE
  778. void
  779. glm_vec4_maxsub(vec4 a, vec4 b, vec4 dest) {
  780. #if defined(__wasm__) && defined(__wasm_simd128__)
  781. glmm_store(dest, wasm_f32x4_sub(glmm_load(dest),
  782. glmm_max(glmm_load(a), glmm_load(b))));
  783. #elif defined( __SSE__ ) || defined( __SSE2__ )
  784. glmm_store(dest, _mm_sub_ps(glmm_load(dest),
  785. glmm_max(glmm_load(a), glmm_load(b))));
  786. #elif defined(CGLM_NEON_FP)
  787. glmm_store(dest, vsubq_f32(glmm_load(dest),
  788. glmm_max(glmm_load(a), glmm_load(b))));
  789. #else
  790. dest[0] -= glm_max(a[0], b[0]);
  791. dest[1] -= glm_max(a[1], b[1]);
  792. dest[2] -= glm_max(a[2], b[2]);
  793. dest[3] -= glm_max(a[3], b[3]);
  794. #endif
  795. }
  796. /*!
  797. * @brief sub min of two vectors to dest
  798. *
  799. * it applies -= operator so dest must be initialized
  800. *
  801. * @param[in] a vector 1
  802. * @param[in] b vector 2
  803. * @param[out] dest dest -= min(a, b)
  804. */
  805. CGLM_INLINE
  806. void
  807. glm_vec4_minsub(vec4 a, vec4 b, vec4 dest) {
  808. #if defined(__wasm__) && defined(__wasm_simd128__)
  809. glmm_store(dest, wasm_f32x4_sub(glmm_load(dest),
  810. glmm_min(glmm_load(a), glmm_load(b))));
  811. #elif defined( __SSE__ ) || defined( __SSE2__ )
  812. glmm_store(dest, _mm_sub_ps(glmm_load(dest),
  813. glmm_min(glmm_load(a), glmm_load(b))));
  814. #elif defined(CGLM_NEON_FP)
  815. glmm_store(dest, vsubq_f32(vld1q_f32(dest),
  816. glmm_min(glmm_load(a), glmm_load(b))));
  817. #else
  818. dest[0] -= glm_min(a[0], b[0]);
  819. dest[1] -= glm_min(a[1], b[1]);
  820. dest[2] -= glm_min(a[2], b[2]);
  821. dest[3] -= glm_min(a[3], b[3]);
  822. #endif
  823. }
  824. /*!
  825. * @brief negate vector components and store result in dest
  826. *
  827. * @param[in] v vector
  828. * @param[out] dest result vector
  829. */
  830. CGLM_INLINE
  831. void
  832. glm_vec4_negate_to(vec4 v, vec4 dest) {
  833. #if defined(__wasm__) && defined(__wasm_simd128__)
  834. glmm_store(dest, wasm_f32x4_neg(glmm_load(v)));
  835. #elif defined( __SSE__ ) || defined( __SSE2__ )
  836. glmm_store(dest, _mm_xor_ps(glmm_load(v), glmm_float32x4_SIGNMASK_NEG));
  837. #elif defined(CGLM_NEON_FP)
  838. vst1q_f32(dest, vnegq_f32(vld1q_f32(v)));
  839. #else
  840. dest[0] = -v[0];
  841. dest[1] = -v[1];
  842. dest[2] = -v[2];
  843. dest[3] = -v[3];
  844. #endif
  845. }
  846. /*!
  847. * @brief flip sign of all vec4 members
  848. *
  849. * @param[in, out] v vector
  850. */
  851. CGLM_INLINE
  852. void
  853. glm_vec4_negate(vec4 v) {
  854. glm_vec4_negate_to(v, v);
  855. }
  856. /*!
  857. * @brief normalize vec4 to dest
  858. *
  859. * @param[in] v source
  860. * @param[out] dest destination
  861. */
  862. CGLM_INLINE
  863. void
  864. glm_vec4_normalize_to(vec4 v, vec4 dest) {
  865. #if defined(__wasm__) && defined(__wasm_simd128__)
  866. glmm_128 xdot, x0;
  867. float dot;
  868. x0 = glmm_load(v);
  869. xdot = glmm_vdot(x0, x0);
  870. /* dot = _mm_cvtss_f32(xdot); */
  871. dot = wasm_f32x4_extract_lane(xdot, 0);
  872. if (CGLM_UNLIKELY(dot < FLT_EPSILON)) {
  873. glmm_store(dest, wasm_f32x4_const_splat(0.f));
  874. return;
  875. }
  876. glmm_store(dest, glmm_div(x0, wasm_f32x4_sqrt(xdot)));
  877. #elif defined( __SSE__ ) || defined( __SSE2__ )
  878. __m128 xdot, x0;
  879. float dot;
  880. x0 = glmm_load(v);
  881. xdot = glmm_vdot(x0, x0);
  882. dot = _mm_cvtss_f32(xdot);
  883. if (CGLM_UNLIKELY(dot < FLT_EPSILON)) {
  884. glmm_store(dest, _mm_setzero_ps());
  885. return;
  886. }
  887. glmm_store(dest, glmm_div(x0, _mm_sqrt_ps(xdot)));
  888. #else
  889. float norm;
  890. norm = glm_vec4_norm(v);
  891. if (CGLM_UNLIKELY(norm < FLT_EPSILON)) {
  892. glm_vec4_zero(dest);
  893. return;
  894. }
  895. glm_vec4_scale(v, 1.0f / norm, dest);
  896. #endif
  897. }
  898. /*!
  899. * @brief normalize vec4 and store result in same vec
  900. *
  901. * @param[in, out] v vector
  902. */
  903. CGLM_INLINE
  904. void
  905. glm_vec4_normalize(vec4 v) {
  906. glm_vec4_normalize_to(v, v);
  907. }
  908. /**
  909. * @brief distance between two vectors
  910. *
  911. * @param[in] a vector1
  912. * @param[in] b vector2
  913. * @return returns distance
  914. */
  915. CGLM_INLINE
  916. float
  917. glm_vec4_distance(vec4 a, vec4 b) {
  918. #if defined(__wasm__) && defined(__wasm_simd128__)
  919. return glmm_norm(wasm_f32x4_sub(glmm_load(a), glmm_load(b)));
  920. #elif defined( __SSE__ ) || defined( __SSE2__ )
  921. return glmm_norm(_mm_sub_ps(glmm_load(a), glmm_load(b)));
  922. #elif defined(CGLM_NEON_FP)
  923. return glmm_norm(vsubq_f32(glmm_load(a), glmm_load(b)));
  924. #else
  925. return sqrtf(glm_pow2(a[0] - b[0])
  926. + glm_pow2(a[1] - b[1])
  927. + glm_pow2(a[2] - b[2])
  928. + glm_pow2(a[3] - b[3]));
  929. #endif
  930. }
  931. /**
  932. * @brief squared distance between two vectors
  933. *
  934. * @param[in] a vector1
  935. * @param[in] b vector2
  936. * @return returns squared distance
  937. */
  938. CGLM_INLINE
  939. float
  940. glm_vec4_distance2(vec4 a, vec4 b) {
  941. #if defined(__wasm__) && defined(__wasm_simd128__)
  942. return glmm_norm2(wasm_f32x4_sub(glmm_load(a), glmm_load(b)));
  943. #elif defined( __SSE__ ) || defined( __SSE2__ )
  944. return glmm_norm2(_mm_sub_ps(glmm_load(a), glmm_load(b)));
  945. #elif defined(CGLM_NEON_FP)
  946. return glmm_norm2(vsubq_f32(glmm_load(a), glmm_load(b)));
  947. #else
  948. return glm_pow2(a[0] - b[0])
  949. + glm_pow2(a[1] - b[1])
  950. + glm_pow2(a[2] - b[2])
  951. + glm_pow2(a[3] - b[3]);
  952. #endif
  953. }
  954. /*!
  955. * @brief max values of vectors
  956. *
  957. * @param[in] a vector1
  958. * @param[in] b vector2
  959. * @param[out] dest destination
  960. */
  961. CGLM_INLINE
  962. void
  963. glm_vec4_maxv(vec4 a, vec4 b, vec4 dest) {
  964. #if defined(CGLM_SIMD)
  965. glmm_store(dest, glmm_max(glmm_load(a), glmm_load(b)));
  966. #else
  967. dest[0] = glm_max(a[0], b[0]);
  968. dest[1] = glm_max(a[1], b[1]);
  969. dest[2] = glm_max(a[2], b[2]);
  970. dest[3] = glm_max(a[3], b[3]);
  971. #endif
  972. }
  973. /*!
  974. * @brief min values of vectors
  975. *
  976. * @param[in] a vector1
  977. * @param[in] b vector2
  978. * @param[out] dest destination
  979. */
  980. CGLM_INLINE
  981. void
  982. glm_vec4_minv(vec4 a, vec4 b, vec4 dest) {
  983. #if defined(CGLM_SIMD)
  984. glmm_store(dest, glmm_min(glmm_load(a), glmm_load(b)));
  985. #else
  986. dest[0] = glm_min(a[0], b[0]);
  987. dest[1] = glm_min(a[1], b[1]);
  988. dest[2] = glm_min(a[2], b[2]);
  989. dest[3] = glm_min(a[3], b[3]);
  990. #endif
  991. }
  992. /*!
  993. * @brief clamp vector's individual members between min and max values
  994. *
  995. * @param[in, out] v vector
  996. * @param[in] minVal minimum value
  997. * @param[in] maxVal maximum value
  998. */
  999. CGLM_INLINE
  1000. void
  1001. glm_vec4_clamp(vec4 v, float minVal, float maxVal) {
  1002. #if defined(__wasm__) && defined(__wasm_simd128__)
  1003. glmm_store(v, glmm_min(glmm_max(glmm_load(v), wasm_f32x4_splat(minVal)),
  1004. wasm_f32x4_splat(maxVal)));
  1005. #elif defined( __SSE__ ) || defined( __SSE2__ )
  1006. glmm_store(v, glmm_min(glmm_max(glmm_load(v), glmm_set1(minVal)),
  1007. glmm_set1(maxVal)));
  1008. #elif defined(CGLM_NEON_FP)
  1009. glmm_store(v, glmm_min(glmm_max(vld1q_f32(v), vdupq_n_f32(minVal)),
  1010. vdupq_n_f32(maxVal)));
  1011. #else
  1012. v[0] = glm_clamp(v[0], minVal, maxVal);
  1013. v[1] = glm_clamp(v[1], minVal, maxVal);
  1014. v[2] = glm_clamp(v[2], minVal, maxVal);
  1015. v[3] = glm_clamp(v[3], minVal, maxVal);
  1016. #endif
  1017. }
  1018. /*!
  1019. * @brief linear interpolation between two vectors
  1020. *
  1021. * formula: from + t * (to - from)
  1022. *
  1023. * @param[in] from from value
  1024. * @param[in] to to value
  1025. * @param[in] t interpolant (amount)
  1026. * @param[out] dest destination
  1027. */
  1028. CGLM_INLINE
  1029. void
  1030. glm_vec4_lerp(vec4 from, vec4 to, float t, vec4 dest) {
  1031. vec4 s, v;
  1032. /* from + s * (to - from) */
  1033. glm_vec4_broadcast(t, s);
  1034. glm_vec4_sub(to, from, v);
  1035. glm_vec4_mul(s, v, v);
  1036. glm_vec4_add(from, v, dest);
  1037. }
  1038. /*!
  1039. * @brief linear interpolation between two vectors (clamped)
  1040. *
  1041. * formula: from + t * (to - from)
  1042. *
  1043. * @param[in] from from value
  1044. * @param[in] to to value
  1045. * @param[in] t interpolant (amount) clamped between 0 and 1
  1046. * @param[out] dest destination
  1047. */
  1048. CGLM_INLINE
  1049. void
  1050. glm_vec4_lerpc(vec4 from, vec4 to, float t, vec4 dest) {
  1051. glm_vec4_lerp(from, to, glm_clamp_zo(t), dest);
  1052. }
  1053. /*!
  1054. * @brief linear interpolation between two vectors
  1055. *
  1056. * formula: from + t * (to - from)
  1057. *
  1058. * @param[in] from from value
  1059. * @param[in] to to value
  1060. * @param[in] t interpolant (amount)
  1061. * @param[out] dest destination
  1062. */
  1063. CGLM_INLINE
  1064. void
  1065. glm_vec4_mix(vec4 from, vec4 to, float t, vec4 dest) {
  1066. glm_vec4_lerp(from, to, t, dest);
  1067. }
  1068. /*!
  1069. * @brief linear interpolation between two vectors (clamped)
  1070. *
  1071. * formula: from + t * (to - from)
  1072. *
  1073. * @param[in] from from value
  1074. * @param[in] to to value
  1075. * @param[in] t interpolant (amount) clamped between 0 and 1
  1076. * @param[out] dest destination
  1077. */
  1078. CGLM_INLINE
  1079. void
  1080. glm_vec4_mixc(vec4 from, vec4 to, float t, vec4 dest) {
  1081. glm_vec4_lerpc(from, to, t, dest);
  1082. }
  1083. /*!
  1084. * @brief threshold function
  1085. *
  1086. * @param[in] edge threshold
  1087. * @param[in] x value to test against threshold
  1088. * @param[out] dest destination
  1089. */
  1090. CGLM_INLINE
  1091. void
  1092. glm_vec4_step(vec4 edge, vec4 x, vec4 dest) {
  1093. dest[0] = glm_step(edge[0], x[0]);
  1094. dest[1] = glm_step(edge[1], x[1]);
  1095. dest[2] = glm_step(edge[2], x[2]);
  1096. dest[3] = glm_step(edge[3], x[3]);
  1097. }
  1098. /*!
  1099. * @brief threshold function with a smooth transition (unidimensional)
  1100. *
  1101. * @param[in] edge0 low threshold
  1102. * @param[in] edge1 high threshold
  1103. * @param[in] x value to test against threshold
  1104. * @param[out] dest destination
  1105. */
  1106. CGLM_INLINE
  1107. void
  1108. glm_vec4_smoothstep_uni(float edge0, float edge1, vec4 x, vec4 dest) {
  1109. dest[0] = glm_smoothstep(edge0, edge1, x[0]);
  1110. dest[1] = glm_smoothstep(edge0, edge1, x[1]);
  1111. dest[2] = glm_smoothstep(edge0, edge1, x[2]);
  1112. dest[3] = glm_smoothstep(edge0, edge1, x[3]);
  1113. }
  1114. /*!
  1115. * @brief threshold function with a smooth transition
  1116. *
  1117. * @param[in] edge0 low threshold
  1118. * @param[in] edge1 high threshold
  1119. * @param[in] x value to test against threshold
  1120. * @param[out] dest destination
  1121. */
  1122. CGLM_INLINE
  1123. void
  1124. glm_vec4_smoothstep(vec4 edge0, vec4 edge1, vec4 x, vec4 dest) {
  1125. dest[0] = glm_smoothstep(edge0[0], edge1[0], x[0]);
  1126. dest[1] = glm_smoothstep(edge0[1], edge1[1], x[1]);
  1127. dest[2] = glm_smoothstep(edge0[2], edge1[2], x[2]);
  1128. dest[3] = glm_smoothstep(edge0[3], edge1[3], x[3]);
  1129. }
  1130. /*!
  1131. * @brief smooth Hermite interpolation between two vectors
  1132. *
  1133. * formula: t^2 * (3 - 2*t)
  1134. *
  1135. * @param[in] from from value
  1136. * @param[in] to to value
  1137. * @param[in] t interpolant (amount)
  1138. * @param[out] dest destination
  1139. */
  1140. CGLM_INLINE
  1141. void
  1142. glm_vec4_smoothinterp(vec4 from, vec4 to, float t, vec4 dest) {
  1143. vec4 s, v;
  1144. /* from + smoothstep * (to - from) */
  1145. glm_vec4_broadcast(glm_smooth(t), s);
  1146. glm_vec4_sub(to, from, v);
  1147. glm_vec4_mul(s, v, v);
  1148. glm_vec4_add(from, v, dest);
  1149. }
  1150. /*!
  1151. * @brief smooth Hermite interpolation between two vectors (clamped)
  1152. *
  1153. * formula: t^2 * (3 - 2*t)
  1154. *
  1155. * @param[in] from from value
  1156. * @param[in] to to value
  1157. * @param[in] t interpolant (amount) clamped between 0 and 1
  1158. * @param[out] dest destination
  1159. */
  1160. CGLM_INLINE
  1161. void
  1162. glm_vec4_smoothinterpc(vec4 from, vec4 to, float t, vec4 dest) {
  1163. glm_vec4_smoothinterp(from, to, glm_clamp_zo(t), dest);
  1164. }
  1165. /*!
  1166. * @brief helper to fill vec4 as [S^3, S^2, S, 1]
  1167. *
  1168. * @param[in] s parameter
  1169. * @param[out] dest destination
  1170. */
  1171. CGLM_INLINE
  1172. void
  1173. glm_vec4_cubic(float s, vec4 dest) {
  1174. float ss;
  1175. ss = s * s;
  1176. dest[0] = ss * s;
  1177. dest[1] = ss;
  1178. dest[2] = s;
  1179. dest[3] = 1.0f;
  1180. }
  1181. /*!
  1182. * @brief swizzle vector components
  1183. *
  1184. * you can use existing masks e.g. GLM_XXXX, GLM_WZYX
  1185. *
  1186. * @param[in] v source
  1187. * @param[in] mask mask
  1188. * @param[out] dest destination
  1189. */
  1190. CGLM_INLINE
  1191. void
  1192. glm_vec4_swizzle(vec4 v, int mask, vec4 dest) {
  1193. vec4 t;
  1194. t[0] = v[(mask & (3 << 0))];
  1195. t[1] = v[(mask & (3 << 2)) >> 2];
  1196. t[2] = v[(mask & (3 << 4)) >> 4];
  1197. t[3] = v[(mask & (3 << 6)) >> 6];
  1198. glm_vec4_copy(t, dest);
  1199. }
  1200. /*!
  1201. * @brief Create four dimensional vector from pointer
  1202. *
  1203. * @param[in] src pointer to an array of floats
  1204. * @param[out] dest destination vector
  1205. */
  1206. CGLM_INLINE
  1207. void
  1208. glm_vec4_make(const float * __restrict src, vec4 dest) {
  1209. dest[0] = src[0]; dest[1] = src[1];
  1210. dest[2] = src[2]; dest[3] = src[3];
  1211. }
  1212. /*!
  1213. * @brief reflection vector using an incident ray and a surface normal
  1214. *
  1215. * @param[in] v incident vector
  1216. * @param[in] n normalized normal vector
  1217. * @param[out] dest destination vector for the reflection result
  1218. */
  1219. CGLM_INLINE
  1220. void
  1221. glm_vec4_reflect(vec4 v, vec4 n, vec4 dest) {
  1222. vec4 temp;
  1223. /* TODO: direct simd touch */
  1224. glm_vec4_scale(n, 2.0f * glm_vec4_dot(v, n), temp);
  1225. glm_vec4_sub(v, temp, dest);
  1226. dest[3] = v[3];
  1227. }
  1228. /*!
  1229. * @brief computes refraction vector for an incident vector and a surface normal.
  1230. *
  1231. * calculates the refraction vector based on Snell's law. If total internal reflection
  1232. * occurs (angle too great given eta), dest is set to zero and returns false.
  1233. * Otherwise, computes refraction vector, stores it in dest, and returns true.
  1234. *
  1235. * this implementation does not explicitly preserve the 'w' component of the
  1236. * incident vector 'I' in the output 'dest', users requiring the preservation of
  1237. * the 'w' component should manually adjust 'dest' after calling this function.
  1238. *
  1239. * @param[in] v normalized incident vector
  1240. * @param[in] n normalized normal vector
  1241. * @param[in] eta ratio of indices of refraction (incident/transmitted)
  1242. * @param[out] dest refraction vector if refraction occurs; zero vector otherwise
  1243. *
  1244. * @returns true if refraction occurs; false if total internal reflection occurs.
  1245. */
  1246. CGLM_INLINE
  1247. bool
  1248. glm_vec4_refract(vec4 v, vec4 n, float eta, vec4 dest) {
  1249. float ndi, eni, k;
  1250. ndi = glm_vec4_dot(n, v);
  1251. eni = eta * ndi;
  1252. k = 1.0f - eta * eta + eni * eni;
  1253. if (k < 0.0f) {
  1254. glm_vec4_zero(dest);
  1255. return false;
  1256. }
  1257. glm_vec4_scale(v, eta, dest);
  1258. glm_vec4_mulsubs(n, eni + sqrtf(k), dest);
  1259. return true;
  1260. }
  1261. #endif /* cglm_vec4_h */