1
0

project.h 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  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. #ifndef cglm_project_h
  8. #define cglm_project_h
  9. #include "common.h"
  10. #include "vec3.h"
  11. #include "vec4.h"
  12. #include "mat4.h"
  13. #ifndef CGLM_CLIPSPACE_INCLUDE_ALL
  14. # if CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_ZO_BIT
  15. # include "clipspace/project_zo.h"
  16. # elif CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_NO_BIT
  17. # include "clipspace/project_no.h"
  18. # endif
  19. #else
  20. # include "clipspace/project_zo.h"
  21. # include "clipspace/project_no.h"
  22. #endif
  23. /*!
  24. * @brief maps the specified viewport coordinates into specified space [1]
  25. * the matrix should contain projection matrix.
  26. *
  27. * if you don't have ( and don't want to have ) an inverse matrix then use
  28. * glm_unproject version. You may use existing inverse of matrix in somewhere
  29. * else, this is why glm_unprojecti exists to save save inversion cost
  30. *
  31. * [1] space:
  32. * 1- if m = invProj: View Space
  33. * 2- if m = invViewProj: World Space
  34. * 3- if m = invMVP: Object Space
  35. *
  36. * You probably want to map the coordinates into object space
  37. * so use invMVP as m
  38. *
  39. * Computing viewProj:
  40. * glm_mat4_mul(proj, view, viewProj);
  41. * glm_mat4_mul(viewProj, model, MVP);
  42. * glm_mat4_inv(viewProj, invMVP);
  43. *
  44. * @param[in] pos point/position in viewport coordinates
  45. * @param[in] invMat matrix (see brief)
  46. * @param[in] vp viewport as [x, y, width, height]
  47. * @param[out] dest unprojected coordinates
  48. */
  49. CGLM_INLINE
  50. void
  51. glm_unprojecti(vec3 pos, mat4 invMat, vec4 vp, vec3 dest) {
  52. #if CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_ZO_BIT
  53. glm_unprojecti_zo(pos, invMat, vp, dest);
  54. #elif CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_NO_BIT
  55. glm_unprojecti_no(pos, invMat, vp, dest);
  56. #endif
  57. }
  58. /*!
  59. * @brief maps the specified viewport coordinates into specified space [1]
  60. * the matrix should contain projection matrix.
  61. *
  62. * this is same as glm_unprojecti except this function get inverse matrix for
  63. * you.
  64. *
  65. * [1] space:
  66. * 1- if m = proj: View Space
  67. * 2- if m = viewProj: World Space
  68. * 3- if m = MVP: Object Space
  69. *
  70. * You probably want to map the coordinates into object space
  71. * so use MVP as m
  72. *
  73. * Computing viewProj and MVP:
  74. * glm_mat4_mul(proj, view, viewProj);
  75. * glm_mat4_mul(viewProj, model, MVP);
  76. *
  77. * @param[in] pos point/position in viewport coordinates
  78. * @param[in] m matrix (see brief)
  79. * @param[in] vp viewport as [x, y, width, height]
  80. * @param[out] dest unprojected coordinates
  81. */
  82. CGLM_INLINE
  83. void
  84. glm_unproject(vec3 pos, mat4 m, vec4 vp, vec3 dest) {
  85. mat4 inv;
  86. glm_mat4_inv(m, inv);
  87. glm_unprojecti(pos, inv, vp, dest);
  88. }
  89. /*!
  90. * @brief map object coordinates to window coordinates
  91. *
  92. * Computing MVP:
  93. * glm_mat4_mul(proj, view, viewProj);
  94. * glm_mat4_mul(viewProj, model, MVP);
  95. *
  96. * @param[in] pos object coordinates
  97. * @param[in] m MVP matrix
  98. * @param[in] vp viewport as [x, y, width, height]
  99. * @param[out] dest projected coordinates
  100. */
  101. CGLM_INLINE
  102. void
  103. glm_project(vec3 pos, mat4 m, vec4 vp, vec3 dest) {
  104. #if CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_ZO_BIT
  105. glm_project_zo(pos, m, vp, dest);
  106. #elif CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_NO_BIT
  107. glm_project_no(pos, m, vp, dest);
  108. #endif
  109. }
  110. /*!
  111. * @brief map object's z coordinate to window coordinates
  112. *
  113. * Computing MVP:
  114. * glm_mat4_mul(proj, view, viewProj);
  115. * glm_mat4_mul(viewProj, model, MVP);
  116. *
  117. * @param[in] v object coordinates
  118. * @param[in] m MVP matrix
  119. *
  120. * @returns projected z coordinate
  121. */
  122. CGLM_INLINE
  123. float
  124. glm_project_z(vec3 v, mat4 m) {
  125. #if CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_ZO_BIT
  126. return glm_project_z_zo(v, m);
  127. #elif CGLM_CONFIG_CLIP_CONTROL & CGLM_CLIP_CONTROL_NO_BIT
  128. return glm_project_z_no(v, m);
  129. #endif
  130. }
  131. /*!
  132. * @brief define a picking region
  133. *
  134. * @param[in] center center [x, y] of a picking region in window coordinates
  135. * @param[in] size size [width, height] of the picking region in window coordinates
  136. * @param[in] vp viewport as [x, y, width, height]
  137. * @param[out] dest projected coordinates
  138. */
  139. CGLM_INLINE
  140. void
  141. glm_pickmatrix(vec2 center, vec2 size, vec4 vp, mat4 dest) {
  142. mat4 res;
  143. vec3 v;
  144. if (size[0] <= 0.0f || size[1] <= 0.0f)
  145. return;
  146. /* Translate and scale the picked region to the entire window */
  147. v[0] = (vp[2] - 2.0f * (center[0] - vp[0])) / size[0];
  148. v[1] = (vp[3] - 2.0f * (center[1] - vp[1])) / size[1];
  149. v[2] = 0.0f;
  150. glm_translate_make(res, v);
  151. v[0] = vp[2] / size[0];
  152. v[1] = vp[3] / size[1];
  153. v[2] = 1.0f;
  154. glm_scale(res, v);
  155. glm_mat4_copy(res, dest);
  156. }
  157. #endif /* cglm_project_h */