diff --git a/LICENSE b/LICENSE
index f22658b..2367e77 100644
--- a/LICENSE
+++ b/LICENSE
@@ -52,3 +52,9 @@ LICENSE:
Computing Euler angles from a rotation matrix (euler.pdf)
Gregory G. Slabaugh
+
+4. Extracting Planes
+Fast Extraction of Viewing Frustum Planes from the World-View-Projection Matrix
+Authors:
+ Gil Gribb (ggribb@ravensoft.com)
+ Klaus Hartmann (k_hartmann@osnabrueck.netsurf.de)
diff --git a/README.md b/README.md
index c90f6ea..3e6964a 100644
--- a/README.md
+++ b/README.md
@@ -50,6 +50,7 @@ https://github.com/g-truc/glm
- euler angles / yaw-pitch-roll to matrix
- extract euler angles
- inline or pre-compiled function call
+- extract view frustum planes
diff --git a/include/cglm/call.h b/include/cglm/call.h
index 2b8025a..c306ab9 100644
--- a/include/cglm/call.h
+++ b/include/cglm/call.h
@@ -20,6 +20,7 @@ extern "C" {
#include "call/cam.h"
#include "call/quat.h"
#include "call/euler.h"
+#include "call/plane.h"
#include "call/io.h"
#ifdef __cplusplus
diff --git a/include/cglm/call/cam.h b/include/cglm/call/cam.h
index 03e066a..7b2c409 100644
--- a/include/cglm/call/cam.h
+++ b/include/cglm/call/cam.h
@@ -48,6 +48,18 @@ glmc_lookat(vec3 eye,
vec3 up,
mat4 dest);
+CGLM_EXPORT
+void
+glmc_frustum_planes(mat4 m, vec4 dest[6]);
+
+CGLM_EXPORT
+void
+glmc_frustum_corners(mat4 invMat, vec4 dest[8]);
+
+CGLM_EXPORT
+void
+glmc_frustum_center(vec4 corners[8], vec4 dest);
+
#ifdef __cplusplus
}
#endif
diff --git a/include/cglm/call/plane.h b/include/cglm/call/plane.h
new file mode 100644
index 0000000..f991121
--- /dev/null
+++ b/include/cglm/call/plane.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_plane_h
+#define cglmc_plane_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../cglm.h"
+
+CGLM_EXPORT
+void
+glmc_plane_normalize(vec4 plane);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_plane_h */
diff --git a/include/cglm/cam.h b/include/cglm/cam.h
index a78ba4b..5d39ef2 100644
--- a/include/cglm/cam.h
+++ b/include/cglm/cam.h
@@ -50,12 +50,15 @@
float * __restrict farVal);
CGLM_INLINE void glm_persp_decomp_far(mat4 proj, float * __restrict farVal);
CGLM_INLINE void glm_persp_decomp_near(mat4 proj, float *__restrict nearVal);
+ CGLM_INLINE void glm_frustum_planes(mat4 m, vec4 dest[6]);
+ CGLM_INLINE void glm_frustum_corners(mat4 invMat, vec4 dest[8]);
*/
#ifndef cglm_vcam_h
#define cglm_vcam_h
#include "common.h"
+#include "plane.h"
/*!
* @brief set up perspective peprojection matrix
@@ -422,4 +425,117 @@ void
glm_persp_decomp_near(mat4 proj, float * __restrict nearVal) {
*nearVal = proj[3][2] / (proj[2][2] - 1);
}
+
+/*!
+ * @brief extracts view frustum planes
+ *
+ * planes' space:
+ * 1- if m = proj: View Space
+ * 2- if m = viewProj: World Space
+ * 3- if m = MVP: Object Space
+ *
+ * You probably want to extract planes in world space so use viewProj as m
+ * Computing viewProj:
+ * glm_mat4_mul(proj, view, viewProj);
+ *
+ * Exracted planes order: [left, right, bottom, top, near, far]
+ *
+ * @param[in] m matrix (see brief)
+ * @param[out] dest exracted view frustum planes (see brief)
+ */
+CGLM_INLINE
+void
+glm_frustum_planes(mat4 m, vec4 dest[6]) {
+ mat4 t;
+
+ glm_mat4_transpose_to(m, t);
+
+ glm_vec4_add(t[3], t[0], dest[0]); /* left */
+ glm_vec4_sub(t[3], t[0], dest[1]); /* right */
+ glm_vec4_add(t[3], t[1], dest[2]); /* bottom */
+ glm_vec4_sub(t[3], t[1], dest[3]); /* top */
+ glm_vec4_add(t[3], t[2], dest[4]); /* near */
+ glm_vec4_sub(t[3], t[2], dest[5]); /* far */
+
+ glm_plane_normalize(dest[0]);
+ glm_plane_normalize(dest[1]);
+ glm_plane_normalize(dest[2]);
+ glm_plane_normalize(dest[3]);
+ glm_plane_normalize(dest[4]);
+ glm_plane_normalize(dest[5]);
+}
+
+/*!
+ * @brief extracts view frustum corners using clip-space coordinates
+ *
+ * corners' space:
+ * 1- if m = invViewProj: World Space
+ * 2- if m = invMVP: Object Space
+ *
+ * You probably want to extract corners in world space so use invViewProj
+ * Computing invViewProj:
+ * glm_mat4_mul(proj, view, viewProj);
+ * ...
+ * glm_mat4_inv(viewProj, invViewProj);
+ *
+ * @param[in] invMat matrix (see brief)
+ * @param[out] dest exracted view frustum corners (see brief)
+ */
+CGLM_INLINE
+void
+glm_frustum_corners(mat4 invMat, vec4 dest[8]) {
+ vec4 c[8];
+ vec4 ndcCorners[8] = {
+ {-1.0f, -1.0f, -1.0f, 1.0f},
+ {-1.0f, 1.0f, -1.0f, 1.0f},
+ { 1.0f, -1.0f, -1.0f, 1.0f},
+ { 1.0f, 1.0f, -1.0f, 1.0f},
+ {-1.0f, -1.0f, 1.0f, 1.0f},
+ {-1.0f, 1.0f, 1.0f, 1.0f},
+ { 1.0f, -1.0f, 1.0f, 1.0f},
+ { 1.0f, 1.0f, 1.0f, 1.0f}
+ };
+
+ glm_mat4_mulv(invMat, ndcCorners[0], c[0]);
+ glm_mat4_mulv(invMat, ndcCorners[1], c[1]);
+ glm_mat4_mulv(invMat, ndcCorners[2], c[2]);
+ glm_mat4_mulv(invMat, ndcCorners[3], c[3]);
+ glm_mat4_mulv(invMat, ndcCorners[4], c[4]);
+ glm_mat4_mulv(invMat, ndcCorners[5], c[5]);
+ glm_mat4_mulv(invMat, ndcCorners[6], c[6]);
+ glm_mat4_mulv(invMat, ndcCorners[7], c[7]);
+
+ glm_vec4_scale(c[1], 1.0f / c[1][3], dest[1]);
+ glm_vec4_scale(c[2], 1.0f / c[2][3], dest[2]);
+ glm_vec4_scale(c[3], 1.0f / c[3][3], dest[3]);
+ glm_vec4_scale(c[4], 1.0f / c[4][3], dest[4]);
+ glm_vec4_scale(c[5], 1.0f / c[5][3], dest[5]);
+ glm_vec4_scale(c[6], 1.0f / c[6][3], dest[6]);
+ glm_vec4_scale(c[7], 1.0f / c[7][3], dest[7]);
+}
+
+/*!
+ * @brief finds center of view frustum
+ *
+ * @param[in] corners view frustum corners
+ * @param[out] dest view frustum center
+ */
+CGLM_INLINE
+void
+glm_frustum_center(vec4 corners[8], vec4 dest) {
+ vec4 center;
+
+ glm_vec4_copy(corners[0], center);
+
+ glm_vec4_add(corners[1], center, center);
+ glm_vec4_add(corners[2], center, center);
+ glm_vec4_add(corners[3], center, center);
+ glm_vec4_add(corners[4], center, center);
+ glm_vec4_add(corners[5], center, center);
+ glm_vec4_add(corners[6], center, center);
+ glm_vec4_add(corners[7], center, center);
+
+ glm_vec4_scale(center, 0.125f, dest);
+}
+
#endif /* cglm_vcam_h */
diff --git a/include/cglm/cglm.h b/include/cglm/cglm.h
index 1dabb70..24544d1 100644
--- a/include/cglm/cglm.h
+++ b/include/cglm/cglm.h
@@ -17,6 +17,7 @@
#include "cam.h"
#include "quat.h"
#include "euler.h"
+#include "plane.h"
#include "util.h"
#include "io.h"
diff --git a/include/cglm/plane.h b/include/cglm/plane.h
new file mode 100644
index 0000000..9faac9c
--- /dev/null
+++ b/include/cglm/plane.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglm_plane_h
+#define cglm_plane_h
+
+#include "common.h"
+#include "mat4.h"
+#include "vec4.h"
+#include "vec3.h"
+
+/*
+ Plane equation: Ax + By + Cz + D = 0;
+
+ It stored in vec4 as [A, B, C, D]. (A, B, C) is normal and D is distance
+*/
+
+/*
+ Functions:
+ CGLM_INLINE void glm_plane_normalize(vec4 plane);
+ */
+
+/*!
+ * @brief normalizes a plane
+ *
+ * @param[in, out] plane pnale to normalize
+ */
+CGLM_INLINE
+void
+glm_plane_normalize(vec4 plane) {
+ glm_vec4_scale(plane, 1.0f / glm_vec_norm(plane), plane);
+}
+
+#endif /* cglm_plane_h */
diff --git a/include/cglm/util.h b/include/cglm/util.h
index d1b62a2..6b97648 100644
--- a/include/cglm/util.h
+++ b/include/cglm/util.h
@@ -61,4 +61,20 @@ glm_pow2(float x) {
return x * x;
}
+CGLM_INLINE
+float
+glm_min(float a, float b) {
+ if (a < b)
+ return a;
+ return b;
+}
+
+CGLM_INLINE
+float
+glm_max(float a, float b) {
+ if (a > b)
+ return a;
+ return b;
+}
+
#endif /* cglm_util_h */
diff --git a/include/cglm/vec4-ext.h b/include/cglm/vec4-ext.h
index 6410e41..ca697af 100644
--- a/include/cglm/vec4-ext.h
+++ b/include/cglm/vec4-ext.h
@@ -17,7 +17,7 @@
CGLM_INLINE bool glm_vec4_eq_eps(vec4 v, float val);
CGLM_INLINE bool glm_vec4_eq_all(vec4 v);
CGLM_INLINE bool glm_vec4_eqv(vec4 v1, vec4 v2);
- CGLM_INLINE bool glm_vec4_eqv_eps(vec3 v1, vec3 v2);
+ CGLM_INLINE bool glm_vec4_eqv_eps(vec4 v1, vec4 v2);
CGLM_INLINE float glm_vec4_max(vec4 v);
CGLM_INLINE float glm_vec4_min(vec4 v);
*/
@@ -133,7 +133,7 @@ glm_vec4_eqv(vec4 v1, vec4 v2) {
*/
CGLM_INLINE
bool
-glm_vec4_eqv_eps(vec3 v1, vec3 v2) {
+glm_vec4_eqv_eps(vec4 v1, vec4 v2) {
return fabsf(v1[0] - v2[0]) <= FLT_EPSILON
&& fabsf(v1[1] - v2[1]) <= FLT_EPSILON
&& fabsf(v1[2] - v2[2]) <= FLT_EPSILON
diff --git a/src/cam.c b/src/cam.c
index 0dcdc4b..602b1fc 100644
--- a/src/cam.c
+++ b/src/cam.c
@@ -66,3 +66,21 @@ glmc_lookat(vec3 eye,
mat4 dest) {
glm_lookat(eye, center, up, dest);
}
+
+CGLM_EXPORT
+void
+glmc_frustum_planes(mat4 m, vec4 dest[6]) {
+ glm_frustum_planes(m, dest);
+}
+
+CGLM_EXPORT
+void
+glmc_frustum_corners(mat4 invMat, vec4 dest[8]) {
+ glm_frustum_corners(invMat, dest);
+}
+
+CGLM_EXPORT
+void
+glmc_frustum_center(vec4 corners[8], vec4 dest) {
+ glm_frustum_center(corners, dest);
+}
diff --git a/src/plane.c b/src/plane.c
new file mode 100644
index 0000000..7ee0c0f
--- /dev/null
+++ b/src/plane.c
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#include "../include/cglm/cglm.h"
+#include "../include/cglm/call.h"
+
+CGLM_EXPORT
+void
+glmc_plane_normalize(vec4 plane) {
+ glm_plane_normalize(plane);
+}