1
0

cam.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  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. Functions:
  9. CGLM_INLINE mat4s glms_frustum(float left, float right,
  10. float bottom, float top,
  11. float nearZ, float farZ)
  12. CGLM_INLINE mat4s glms_ortho(float left, float right,
  13. float bottom, float top,
  14. float nearZ, float farZ)
  15. CGLM_INLINE mat4s glms_ortho_aabb(vec3s box[2]);
  16. CGLM_INLINE mat4s glms_ortho_aabb_p(vec3s box[2], float padding);
  17. CGLM_INLINE mat4s glms_ortho_aabb_pz(vec3s box[2], float padding);
  18. CGLM_INLINE mat4s glms_ortho_default(float aspect)
  19. CGLM_INLINE mat4s glms_ortho_default_s(float aspect, float size)
  20. CGLM_INLINE mat4s glms_perspective(float fovy,
  21. float aspect,
  22. float nearZ,
  23. float farZ)
  24. CGLM_INLINE void glms_persp_move_far(mat4s proj, float deltaFar)
  25. CGLM_INLINE mat4s glms_perspective_default(float aspect)
  26. CGLM_INLINE void glms_perspective_resize(mat4s proj, float aspect)
  27. CGLM_INLINE mat4s glms_lookat(vec3s eye, vec3s center, vec3s up)
  28. CGLM_INLINE mat4s glms_look(vec3s eye, vec3s dir, vec3s up)
  29. CGLM_INLINE mat4s glms_look_anyup(vec3s eye, vec3s dir)
  30. CGLM_INLINE void glms_persp_decomp(mat4s proj,
  31. float *nearv, float *farv,
  32. float *top, float *bottom,
  33. float *left, float *right)
  34. CGLM_INLINE void glms_persp_decompv(mat4s proj, float dest[6])
  35. CGLM_INLINE void glms_persp_decomp_x(mat4s proj, float *left, float *right)
  36. CGLM_INLINE void glms_persp_decomp_y(mat4s proj, float *top, float *bottom)
  37. CGLM_INLINE void glms_persp_decomp_z(mat4s proj, float *nearv, float *farv)
  38. CGLM_INLINE void glms_persp_decomp_far(mat4s proj, float *farZ)
  39. CGLM_INLINE void glms_persp_decomp_near(mat4s proj, float *nearZ)
  40. CGLM_INLINE float glms_persp_fovy(mat4s proj)
  41. CGLM_INLINE float glms_persp_aspect(mat4s proj)
  42. CGLM_INLINE vec4s glms_persp_sizes(mat4s proj, float fovy)
  43. */
  44. #ifndef cglms_cam_h
  45. #define cglms_cam_h
  46. #include "../common.h"
  47. #include "../types-struct.h"
  48. #include "../plane.h"
  49. #include "../cam.h"
  50. #ifndef CGLM_CLIPSPACE_INCLUDE_ALL
  51. # if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
  52. # include "clipspace/ortho_lh_zo.h"
  53. # include "clipspace/persp_lh_zo.h"
  54. # include "clipspace/view_lh_zo.h"
  55. # elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
  56. # include "clipspace/ortho_lh_no.h"
  57. # include "clipspace/persp_lh_no.h"
  58. # include "clipspace/view_lh_no.h"
  59. # elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
  60. # include "clipspace/ortho_rh_zo.h"
  61. # include "clipspace/persp_rh_zo.h"
  62. # include "clipspace/view_rh_zo.h"
  63. # elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
  64. # include "clipspace/ortho_rh_no.h"
  65. # include "clipspace/persp_rh_no.h"
  66. # include "clipspace/view_rh_no.h"
  67. # endif
  68. #else
  69. # include "clipspace/ortho_lh_zo.h"
  70. # include "clipspace/persp_lh_zo.h"
  71. # include "clipspace/ortho_lh_no.h"
  72. # include "clipspace/persp_lh_no.h"
  73. # include "clipspace/ortho_rh_zo.h"
  74. # include "clipspace/persp_rh_zo.h"
  75. # include "clipspace/ortho_rh_no.h"
  76. # include "clipspace/persp_rh_no.h"
  77. # include "clipspace/view_lh_zo.h"
  78. # include "clipspace/view_lh_no.h"
  79. # include "clipspace/view_rh_zo.h"
  80. # include "clipspace/view_rh_no.h"
  81. #endif
  82. /*!
  83. * @brief set up perspective peprojection matrix
  84. *
  85. * @param[in] left viewport.left
  86. * @param[in] right viewport.right
  87. * @param[in] bottom viewport.bottom
  88. * @param[in] top viewport.top
  89. * @param[in] nearZ near clipping plane
  90. * @param[in] farZ far clipping plane
  91. * @returns result matrix
  92. */
  93. CGLM_INLINE
  94. mat4s
  95. glms_frustum(float left, float right,
  96. float bottom, float top,
  97. float nearZ, float farZ) {
  98. #if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
  99. return glms_frustum_lh_zo(left, right, bottom, top, nearZ, farZ);
  100. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
  101. return glms_frustum_lh_no(left, right, bottom, top, nearZ, farZ);
  102. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
  103. return glms_frustum_rh_zo(left, right, bottom, top, nearZ, farZ);
  104. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
  105. return glms_frustum_rh_no(left, right, bottom, top, nearZ, farZ);
  106. #endif
  107. }
  108. /*!
  109. * @brief set up orthographic projection matrix
  110. *
  111. * @param[in] left viewport.left
  112. * @param[in] right viewport.right
  113. * @param[in] bottom viewport.bottom
  114. * @param[in] top viewport.top
  115. * @param[in] nearZ near clipping plane
  116. * @param[in] farZ far clipping plane
  117. * @returns result matrix
  118. */
  119. CGLM_INLINE
  120. mat4s
  121. glms_ortho(float left, float right,
  122. float bottom, float top,
  123. float nearZ, float farZ) {
  124. #if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
  125. return glms_ortho_lh_zo(left, right, bottom, top, nearZ, farZ);
  126. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
  127. return glms_ortho_lh_no(left, right, bottom, top, nearZ, farZ);
  128. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
  129. return glms_ortho_rh_zo(left, right, bottom, top, nearZ, farZ);
  130. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
  131. return glms_ortho_rh_no(left, right, bottom, top, nearZ, farZ);
  132. #endif
  133. }
  134. /*!
  135. * @brief set up orthographic projection matrix using bounding box
  136. *
  137. * bounding box (AABB) must be in view space
  138. *
  139. * @param[in] box AABB
  140. * @returns result matrix
  141. */
  142. CGLM_INLINE
  143. mat4s
  144. glms_ortho_aabb(vec3s box[2]) {
  145. #if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
  146. return glms_ortho_aabb_lh_zo(box);
  147. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
  148. return glms_ortho_aabb_lh_no(box);
  149. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
  150. return glms_ortho_aabb_rh_zo(box);
  151. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
  152. return glms_ortho_aabb_rh_no(box);
  153. #endif
  154. }
  155. /*!
  156. * @brief set up orthographic projection matrix using bounding box
  157. *
  158. * bounding box (AABB) must be in view space
  159. *
  160. * @param[in] box AABB
  161. * @param[in] padding padding
  162. * @returns result matrix
  163. */
  164. CGLM_INLINE
  165. mat4s
  166. glms_ortho_aabb_p(vec3s box[2], float padding) {
  167. #if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
  168. return glms_ortho_aabb_p_lh_zo(box, padding);
  169. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
  170. return glms_ortho_aabb_p_lh_no(box, padding);
  171. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
  172. return glms_ortho_aabb_p_rh_zo(box, padding);
  173. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
  174. return glms_ortho_aabb_p_rh_no(box, padding);
  175. #endif
  176. }
  177. /*!
  178. * @brief set up orthographic projection matrix using bounding box
  179. *
  180. * bounding box (AABB) must be in view space
  181. *
  182. * @param[in] box AABB
  183. * @param[in] padding padding for near and far
  184. * @returns result matrix
  185. */
  186. CGLM_INLINE
  187. mat4s
  188. glms_ortho_aabb_pz(vec3s box[2], float padding) {
  189. #if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
  190. return glms_ortho_aabb_pz_lh_zo(box, padding);
  191. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
  192. return glms_ortho_aabb_pz_lh_no(box, padding);
  193. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
  194. return glms_ortho_aabb_pz_rh_zo(box, padding);
  195. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
  196. return glms_ortho_aabb_pz_rh_no(box, padding);
  197. #endif
  198. }
  199. /*!
  200. * @brief set up unit orthographic projection matrix
  201. *
  202. * @param[in] aspect aspect ration ( width / height )
  203. * @returns result matrix
  204. */
  205. CGLM_INLINE
  206. mat4s
  207. glms_ortho_default(float aspect) {
  208. #if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
  209. return glms_ortho_default_lh_zo(aspect);
  210. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
  211. return glms_ortho_default_lh_no(aspect);
  212. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
  213. return glms_ortho_default_rh_zo(aspect);
  214. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
  215. return glms_ortho_default_rh_no(aspect);
  216. #endif
  217. }
  218. /*!
  219. * @brief set up orthographic projection matrix with given CUBE size
  220. *
  221. * @param[in] aspect aspect ratio ( width / height )
  222. * @param[in] size cube size
  223. * @returns result matrix
  224. */
  225. CGLM_INLINE
  226. mat4s
  227. glms_ortho_default_s(float aspect, float size) {
  228. #if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
  229. return glms_ortho_default_s_lh_zo(aspect, size);
  230. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
  231. return glms_ortho_default_s_lh_no(aspect, size);
  232. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
  233. return glms_ortho_default_s_rh_zo(aspect, size);
  234. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
  235. return glms_ortho_default_s_rh_no(aspect, size);
  236. #endif
  237. }
  238. /*!
  239. * @brief set up perspective projection matrix
  240. *
  241. * @param[in] fovy field of view angle
  242. * @param[in] aspect aspect ratio ( width / height )
  243. * @param[in] nearZ near clipping plane
  244. * @param[in] farZ far clipping planes
  245. * @returns result matrix
  246. */
  247. CGLM_INLINE
  248. mat4s
  249. glms_perspective(float fovy, float aspect, float nearZ, float farZ) {
  250. #if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
  251. return glms_perspective_lh_zo(fovy, aspect, nearZ, farZ);
  252. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
  253. return glms_perspective_lh_no(fovy, aspect, nearZ, farZ);
  254. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
  255. return glms_perspective_rh_zo(fovy, aspect, nearZ, farZ);
  256. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
  257. return glms_perspective_rh_no(fovy, aspect, nearZ, farZ);
  258. #endif
  259. }
  260. /*!
  261. * @brief extend perspective projection matrix's far distance
  262. *
  263. * NOTE: if you dodn't want to create new matrix then use array api on struct.raw
  264. * like glm_persp_move_far(prooj.raw, deltaFar) to avoid create new mat4
  265. * each time
  266. *
  267. * this function does not guarantee far >= near, be aware of that!
  268. *
  269. * @param[in, out] proj projection matrix to extend
  270. * @param[in] deltaFar distance from existing far (negative to shink)
  271. */
  272. CGLM_INLINE
  273. mat4s
  274. glms_persp_move_far(mat4s proj, float deltaFar) {
  275. #if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
  276. return glms_persp_move_far_lh_zo(proj, deltaFar);
  277. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
  278. return glms_persp_move_far_lh_no(proj, deltaFar);
  279. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
  280. return glms_persp_move_far_rh_zo(proj, deltaFar);
  281. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
  282. return glms_persp_move_far_rh_no(proj, deltaFar);
  283. #endif
  284. }
  285. /*!
  286. * @brief set up perspective projection matrix with default near/far
  287. * and angle values
  288. *
  289. * @param[in] aspect aspect ratio ( width / height )
  290. * @returns result matrix
  291. */
  292. CGLM_INLINE
  293. mat4s
  294. glms_perspective_default(float aspect) {
  295. #if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
  296. return glms_perspective_default_lh_zo(aspect);
  297. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
  298. return glms_perspective_default_lh_no(aspect);
  299. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
  300. return glms_perspective_default_rh_zo(aspect);
  301. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
  302. return glms_perspective_default_rh_no(aspect);
  303. #endif
  304. }
  305. /*!
  306. * @brief resize perspective matrix by aspect ratio ( width / height )
  307. * this makes very easy to resize proj matrix when window /viewport
  308. * reized
  309. *
  310. * NOTE: if you dodn't want to create new matrix then use array api on struct.raw
  311. * like glms_perspective_resize(proj.raw, aspect) to avoid create new mat4
  312. * each time
  313. *
  314. * @param[in, out] proj perspective projection matrix
  315. * @param[in] aspect aspect ratio ( width / height )
  316. */
  317. CGLM_INLINE
  318. mat4s
  319. glms_perspective_resize(mat4s proj, float aspect) {
  320. #if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
  321. return glms_perspective_resize_lh_zo(proj, aspect);
  322. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
  323. return glms_perspective_resize_lh_no(proj, aspect);
  324. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
  325. return glms_perspective_resize_rh_zo(proj, aspect);
  326. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
  327. return glms_perspective_resize_rh_no(proj, aspect);
  328. #endif
  329. }
  330. /*!
  331. * @brief set up view matrix
  332. *
  333. * NOTE: The UP vector must not be parallel to the line of sight from
  334. * the eye point to the reference point
  335. *
  336. * @param[in] eye eye vector
  337. * @param[in] center center vector
  338. * @param[in] up up vector
  339. * @returns result matrix
  340. */
  341. CGLM_INLINE
  342. mat4s
  343. glms_lookat(vec3s eye, vec3s center, vec3s up) {
  344. #if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
  345. return glms_lookat_lh_zo(eye, center, up);
  346. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
  347. return glms_lookat_lh_no(eye, center, up);
  348. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
  349. return glms_lookat_rh_zo(eye, center, up);
  350. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
  351. return glms_lookat_rh_no(eye, center, up);
  352. #endif
  353. }
  354. /*!
  355. * @brief set up view matrix
  356. *
  357. * convenient wrapper for lookat: if you only have direction not target self
  358. * then this might be useful. Because you need to get target from direction.
  359. *
  360. * NOTE: The UP vector must not be parallel to the line of sight from
  361. * the eye point to the reference point
  362. *
  363. * @param[in] eye eye vector
  364. * @param[in] dir direction vector
  365. * @param[in] up up vector
  366. * @returns result matrix
  367. */
  368. CGLM_INLINE
  369. mat4s
  370. glms_look(vec3s eye, vec3s dir, vec3s up) {
  371. #if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
  372. return glms_look_lh_zo(eye, dir, up);
  373. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
  374. return glms_look_lh_no(eye, dir, up);
  375. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
  376. return glms_look_rh_zo(eye, dir, up);
  377. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
  378. return glms_look_rh_no(eye, dir, up);
  379. #endif
  380. }
  381. /*!
  382. * @brief set up view matrix
  383. *
  384. * convenient wrapper for look: if you only have direction and if you don't
  385. * care what UP vector is then this might be useful to create view matrix
  386. *
  387. * @param[in] eye eye vector
  388. * @param[in] dir direction vector
  389. * @returns result matrix
  390. */
  391. CGLM_INLINE
  392. mat4s
  393. glms_look_anyup(vec3s eye, vec3s dir) {
  394. #if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
  395. return glms_look_anyup_lh_zo(eye, dir);
  396. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
  397. return glms_look_anyup_lh_no(eye, dir);
  398. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
  399. return glms_look_anyup_rh_zo(eye, dir);
  400. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
  401. return glms_look_anyup_rh_no(eye, dir);
  402. #endif
  403. }
  404. /*!
  405. * @brief decomposes frustum values of perspective projection.
  406. *
  407. * @param[in] proj perspective projection matrix
  408. * @param[out] nearZ near
  409. * @param[out] farZ far
  410. * @param[out] top top
  411. * @param[out] bottom bottom
  412. * @param[out] left left
  413. * @param[out] right right
  414. */
  415. CGLM_INLINE
  416. void
  417. glms_persp_decomp(mat4s proj,
  418. float * __restrict nearZ, float * __restrict farZ,
  419. float * __restrict top, float * __restrict bottom,
  420. float * __restrict left, float * __restrict right) {
  421. #if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
  422. glms_persp_decomp_lh_zo(proj, nearZ, farZ, top, bottom, left, right);
  423. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
  424. glms_persp_decomp_lh_no(proj, nearZ, farZ, top, bottom, left, right);
  425. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
  426. glms_persp_decomp_rh_zo(proj, nearZ, farZ, top, bottom, left, right);
  427. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
  428. glms_persp_decomp_rh_no(proj, nearZ, farZ, top, bottom, left, right);
  429. #endif
  430. }
  431. /*!
  432. * @brief decomposes frustum values of perspective projection.
  433. * this makes easy to get all values at once
  434. *
  435. * @param[in] proj perspective projection matrix
  436. * @param[out] dest array
  437. */
  438. CGLM_INLINE
  439. void
  440. glms_persp_decompv(mat4s proj, float dest[6]) {
  441. #if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
  442. glms_persp_decompv_lh_zo(proj, dest);
  443. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
  444. glms_persp_decompv_lh_no(proj, dest);
  445. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
  446. glms_persp_decompv_rh_zo(proj, dest);
  447. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
  448. glms_persp_decompv_rh_no(proj, dest);
  449. #endif
  450. }
  451. /*!
  452. * @brief decomposes left and right values of perspective projection.
  453. * x stands for x axis (left / right axis)
  454. *
  455. * @param[in] proj perspective projection matrix
  456. * @param[out] left left
  457. * @param[out] right right
  458. */
  459. CGLM_INLINE
  460. void
  461. glms_persp_decomp_x(mat4s proj,
  462. float * __restrict left,
  463. float * __restrict right) {
  464. #if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
  465. glms_persp_decomp_x_lh_zo(proj, left, right);
  466. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
  467. glms_persp_decomp_x_lh_no(proj, left, right);
  468. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
  469. glms_persp_decomp_x_rh_zo(proj, left, right);
  470. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
  471. glms_persp_decomp_x_rh_no(proj, left, right);
  472. #endif
  473. }
  474. /*!
  475. * @brief decomposes top and bottom values of perspective projection.
  476. * y stands for y axis (top / bottom axis)
  477. *
  478. * @param[in] proj perspective projection matrix
  479. * @param[out] top top
  480. * @param[out] bottom bottom
  481. */
  482. CGLM_INLINE
  483. void
  484. glms_persp_decomp_y(mat4s proj,
  485. float * __restrict top,
  486. float * __restrict bottom) {
  487. #if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
  488. glms_persp_decomp_y_lh_zo(proj, top, bottom);
  489. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
  490. glms_persp_decomp_y_lh_no(proj, top, bottom);
  491. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
  492. glms_persp_decomp_y_rh_zo(proj, top, bottom);
  493. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
  494. glms_persp_decomp_y_rh_no(proj, top, bottom);
  495. #endif
  496. }
  497. /*!
  498. * @brief decomposes near and far values of perspective projection.
  499. * z stands for z axis (near / far axis)
  500. *
  501. * @param[in] proj perspective projection matrix
  502. * @param[out] nearZ near
  503. * @param[out] farZ far
  504. */
  505. CGLM_INLINE
  506. void
  507. glms_persp_decomp_z(mat4s proj,
  508. float * __restrict nearZ,
  509. float * __restrict farZ) {
  510. #if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
  511. glms_persp_decomp_z_lh_zo(proj, nearZ, farZ);
  512. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
  513. glms_persp_decomp_z_lh_no(proj, nearZ, farZ);
  514. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
  515. glms_persp_decomp_z_rh_zo(proj, nearZ, farZ);
  516. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
  517. glms_persp_decomp_z_rh_no(proj, nearZ, farZ);
  518. #endif
  519. }
  520. /*!
  521. * @brief decomposes far value of perspective projection.
  522. *
  523. * @param[in] proj perspective projection matrix
  524. * @param[out] farZ far
  525. */
  526. CGLM_INLINE
  527. void
  528. glms_persp_decomp_far(mat4s proj, float * __restrict farZ) {
  529. #if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
  530. glms_persp_decomp_far_lh_zo(proj, farZ);
  531. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
  532. glms_persp_decomp_far_lh_no(proj, farZ);
  533. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
  534. glms_persp_decomp_far_rh_zo(proj, farZ);
  535. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
  536. glms_persp_decomp_far_rh_no(proj, farZ);
  537. #endif
  538. }
  539. /*!
  540. * @brief decomposes near value of perspective projection.
  541. *
  542. * @param[in] proj perspective projection matrix
  543. * @param[out] nearZ near
  544. */
  545. CGLM_INLINE
  546. void
  547. glms_persp_decomp_near(mat4s proj, float * __restrict nearZ) {
  548. #if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
  549. glms_persp_decomp_near_lh_zo(proj, nearZ);
  550. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
  551. glms_persp_decomp_near_lh_no(proj, nearZ);
  552. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
  553. glms_persp_decomp_near_rh_zo(proj, nearZ);
  554. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
  555. glms_persp_decomp_near_rh_no(proj, nearZ);
  556. #endif
  557. }
  558. /*!
  559. * @brief returns field of view angle along the Y-axis (in radians)
  560. *
  561. * if you need to degrees, use glm_deg to convert it or use this:
  562. * fovy_deg = glm_deg(glm_persp_fovy(projMatrix))
  563. *
  564. * @param[in] proj perspective projection matrix
  565. */
  566. CGLM_INLINE
  567. float
  568. glms_persp_fovy(mat4s proj) {
  569. #if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
  570. return glms_persp_fovy_lh_zo(proj);
  571. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
  572. return glms_persp_fovy_lh_no(proj);
  573. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
  574. return glms_persp_fovy_rh_zo(proj);
  575. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
  576. return glms_persp_fovy_rh_no(proj);
  577. #endif
  578. }
  579. /*!
  580. * @brief returns aspect ratio of perspective projection
  581. *
  582. * @param[in] proj perspective projection matrix
  583. */
  584. CGLM_INLINE
  585. float
  586. glms_persp_aspect(mat4s proj) {
  587. #if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
  588. return glms_persp_aspect_lh_zo(proj);
  589. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
  590. return glms_persp_aspect_lh_no(proj);
  591. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
  592. return glms_persp_aspect_rh_zo(proj);
  593. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
  594. return glms_persp_aspect_rh_no(proj);
  595. #endif
  596. }
  597. /*!
  598. * @brief returns sizes of near and far planes of perspective projection
  599. *
  600. * @param[in] proj perspective projection matrix
  601. * @param[in] fovy fovy (see brief)
  602. * @returns sizes as vector, sizes order: [Wnear, Hnear, Wfar, Hfar]
  603. */
  604. CGLM_INLINE
  605. vec4s
  606. glms_persp_sizes(mat4s proj, float fovy) {
  607. #if CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_ZO
  608. return glms_persp_sizes_lh_zo(proj, fovy);
  609. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_LH_NO
  610. return glms_persp_sizes_lh_no(proj, fovy);
  611. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_ZO
  612. return glms_persp_sizes_rh_zo(proj, fovy);
  613. #elif CGLM_CONFIG_CLIP_CONTROL == CGLM_CLIP_CONTROL_RH_NO
  614. return glms_persp_sizes_rh_no(proj, fovy);
  615. #endif
  616. }
  617. #endif /* cglms_cam_h */