diff --git a/include/cglm/call.h b/include/cglm/call.h
index c306ab9..00eb13c 100644
--- a/include/cglm/call.h
+++ b/include/cglm/call.h
@@ -21,6 +21,7 @@ extern "C" {
#include "call/quat.h"
#include "call/euler.h"
#include "call/plane.h"
+#include "call/frustum.h"
#include "call/io.h"
#ifdef __cplusplus
diff --git a/include/cglm/call/cam.h b/include/cglm/call/cam.h
index dc01f6f..35fb18d 100644
--- a/include/cglm/call/cam.h
+++ b/include/cglm/call/cam.h
@@ -53,18 +53,6 @@ CGLM_EXPORT
void
glmc_look_anyup(vec3 eye, vec3 dir, 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/frustum.h b/include/cglm/call/frustum.h
new file mode 100644
index 0000000..6b4facb
--- /dev/null
+++ b/include/cglm/call/frustum.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglmc_frustum_h
+#define cglmc_frustum_h
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../cglm.h"
+
+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);
+
+CGLM_EXPORT
+void
+glmc_frustum_box(vec4 corners[8], mat4 m, vec3 box[2]);
+
+CGLM_EXPORT
+void
+glmc_frustum_corners_at(vec4 corners[8],
+ float splitDist,
+ float farDist,
+ vec4 planeCorners[4]);
+#ifdef __cplusplus
+}
+#endif
+#endif /* cglmc_frustum_h */
diff --git a/include/cglm/cam.h b/include/cglm/cam.h
index 23504cc..0d13a3d 100644
--- a/include/cglm/cam.h
+++ b/include/cglm/cam.h
@@ -541,116 +541,4 @@ glm_persp_sizes(mat4 proj, float fovy, vec4 dest) {
dest[2] = a * dest[3];
}
-/*!
- * @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 csCoords[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, csCoords[0], c[0]);
- glm_mat4_mulv(invMat, csCoords[1], c[1]);
- glm_mat4_mulv(invMat, csCoords[2], c[2]);
- glm_mat4_mulv(invMat, csCoords[3], c[3]);
- glm_mat4_mulv(invMat, csCoords[4], c[4]);
- glm_mat4_mulv(invMat, csCoords[5], c[5]);
- glm_mat4_mulv(invMat, csCoords[6], c[6]);
- glm_mat4_mulv(invMat, csCoords[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 24544d1..e9fa774 100644
--- a/include/cglm/cglm.h
+++ b/include/cglm/cglm.h
@@ -15,6 +15,7 @@
#include "mat3.h"
#include "affine.h"
#include "cam.h"
+#include "frustum.h"
#include "quat.h"
#include "euler.h"
#include "plane.h"
diff --git a/include/cglm/frustum.h b/include/cglm/frustum.h
new file mode 100644
index 0000000..b526c34
--- /dev/null
+++ b/include/cglm/frustum.h
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c), Recep Aslantas.
+ *
+ * MIT License (MIT), http://opensource.org/licenses/MIT
+ * Full license can be found in the LICENSE file
+ */
+
+#ifndef cglm_frustum_h
+#define cglm_frustum_h
+
+#include "common.h"
+#include "plane.h"
+
+#define GLM_LBN 0 /* left bottom near */
+#define GLM_LTN 1 /* left top near */
+#define GLM_RTN 2 /* right top near */
+#define GLM_RBN 3 /* right bottom near */
+
+#define GLM_LBF 4 /* left bottom far */
+#define GLM_LTF 5 /* left top far */
+#define GLM_RTF 6 /* right top far */
+#define GLM_RBF 7 /* right bottom far */
+
+#define GLM_LEFT 0
+#define GLM_RIGHT 1
+#define GLM_BOTTOM 2
+#define GLM_TOP 3
+#define GLM_NEAR 4
+#define GLM_FAR 5
+
+/* you can override clip space coords
+ but you have to provide all with same name
+ e.g.: define GLM_CSCOORD_LBN {0.0f, 0.0f, 1.0f, 1.0f} */
+#ifndef GLM_CUSTOM_CLIPSPACE
+
+/* near */
+#define GLM_CSCOORD_LBN {-1.0f, -1.0f, -1.0f, 1.0f}
+#define GLM_CSCOORD_LTN {-1.0f, 1.0f, -1.0f, 1.0f}
+#define GLM_CSCOORD_RTN { 1.0f, 1.0f, -1.0f, 1.0f}
+#define GLM_CSCOORD_RBN { 1.0f, -1.0f, -1.0f, 1.0f}
+
+/* far */
+#define GLM_CSCOORD_LBF {-1.0f, -1.0f, 1.0f, 1.0f}
+#define GLM_CSCOORD_LTF {-1.0f, 1.0f, 1.0f, 1.0f}
+#define GLM_CSCOORD_RTF { 1.0f, 1.0f, 1.0f, 1.0f}
+#define GLM_CSCOORD_RBF { 1.0f, -1.0f, 1.0f, 1.0f}
+
+#endif
+
+/*!
+ * @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);
+ *
+ * if you have a near coord at i index, you can get it's far coord by i + 4
+ *
+ * Find center coordinates:
+ * for (j = 0; j < 4; j++) {
+ * glm_vec_center(corners[i], corners[i + 4], centerCorners[i]);
+ * }
+ *
+ * @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];
+
+ /* indexOf(nearCoord) = indexOf(farCoord) + 4 */
+ vec4 csCoords[8] = {
+ GLM_CSCOORD_LBN,
+ GLM_CSCOORD_LTN,
+ GLM_CSCOORD_RTN,
+ GLM_CSCOORD_RBN,
+
+ GLM_CSCOORD_LBF,
+ GLM_CSCOORD_LTF,
+ GLM_CSCOORD_RTF,
+ GLM_CSCOORD_RBF
+ };
+
+ glm_mat4_mulv(invMat, csCoords[0], c[0]);
+ glm_mat4_mulv(invMat, csCoords[1], c[1]);
+ glm_mat4_mulv(invMat, csCoords[2], c[2]);
+ glm_mat4_mulv(invMat, csCoords[3], c[3]);
+ glm_mat4_mulv(invMat, csCoords[4], c[4]);
+ glm_mat4_mulv(invMat, csCoords[5], c[5]);
+ glm_mat4_mulv(invMat, csCoords[6], c[6]);
+ glm_mat4_mulv(invMat, csCoords[7], c[7]);
+
+ glm_vec4_scale(c[0], 1.0f / c[0][3], dest[0]);
+ 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);
+}
+
+/*!
+ * @brief finds bounding box of frustum relative to given matrix e.g. view mat
+ *
+ * @param[in] corners view frustum corners
+ * @param[in] m matrix to convert existing conners
+ * @param[out] box bounding box as array [min, max]
+ */
+CGLM_INLINE
+void
+glm_frustum_box(vec4 corners[8], mat4 m, vec3 box[2]) {
+ vec4 v;
+ vec3 min, max;
+ int i;
+
+ glm_vec_broadcast(0.0f, min);
+ glm_vec_broadcast(0.0f, max);
+
+ for (i = 0; i < 8; i++) {
+ glm_mat4_mulv(m, corners[i], v);
+
+ min[0] = glm_min(min[0], v[0]);
+ min[1] = glm_min(min[1], v[1]);
+ min[2] = glm_min(min[2], v[2]);
+
+ max[0] = glm_max(max[0], v[0]);
+ max[1] = glm_max(max[1], v[1]);
+ max[2] = glm_max(max[2], v[2]);
+ }
+
+ glm_vec_copy(min, box[0]);
+ glm_vec_copy(max, box[1]);
+}
+
+/*!
+ * @brief finds planes corners which is between near and far planes (parallel)
+ *
+ * this will be helpful if you want to split a frustum e.g. CSM/PSSM. This will
+ * find planes' corners but you will need to one more plane.
+ * Actually you have it, it is near, far or created previously with this func ;)
+ *
+ * @param[in] corners view frustum corners
+ * @param[in] splitDist split distance
+ * @param[in] farDist far distance (zFar)
+ * @param[out] planeCorners plane corners [LB, LT, RT, RB]
+ */
+CGLM_INLINE
+void
+glm_frustum_corners_at(vec4 corners[8],
+ float splitDist,
+ float farDist,
+ vec4 planeCorners[4]) {
+ vec4 corner;
+ float dist, sc;
+
+ /* because distance and scale is same for all */
+ dist = glm_vec_distance(corners[GLM_RTF], corners[GLM_RTN]);
+ sc = dist * (splitDist / farDist);
+
+ /* left bottom */
+ glm_vec4_sub(corners[GLM_LBF], corners[GLM_LBN], corner);
+ glm_vec4_scale_as(corner, sc, corner);
+ glm_vec4_add(corners[GLM_LBN], corner, planeCorners[0]);
+
+ /* left top */
+ glm_vec4_sub(corners[GLM_LTF], corners[GLM_LTN], corner);
+ glm_vec4_scale_as(corner, sc, corner);
+ glm_vec4_add(corners[GLM_LTN], corner, planeCorners[1]);
+
+ /* right top */
+ glm_vec4_sub(corners[GLM_RTF], corners[GLM_RTN], corner);
+ glm_vec4_scale_as(corner, sc, corner);
+ glm_vec4_add(corners[GLM_RTN], corner, planeCorners[2]);
+
+ /* right bottom */
+ glm_vec4_sub(corners[GLM_RBF], corners[GLM_RBN], corner);
+ glm_vec4_scale_as(corner, sc, corner);
+ glm_vec4_add(corners[GLM_RBN], corner, planeCorners[3]);
+}
+
+#endif /* cglm_frustum_h */
diff --git a/makefile.am b/makefile.am
index 5830700..2350b9c 100644
--- a/makefile.am
+++ b/makefile.am
@@ -88,7 +88,9 @@ libcglm_la_SOURCES=\
src/vec3.c \
src/vec4.c \
src/mat3.c \
- src/mat4.c
+ src/mat4.c \
+ src/plane.c \
+ src/frustum.c
test_tests_SOURCES=\
test/src/test_common.c \
diff --git a/src/cam.c b/src/cam.c
index 3def839..aeac3c7 100644
--- a/src/cam.c
+++ b/src/cam.c
@@ -78,21 +78,3 @@ void
glmc_look_anyup(vec3 eye, vec3 dir, mat4 dest) {
glm_look_anyup(eye, dir, 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/frustum.c b/src/frustum.c
new file mode 100644
index 0000000..312c3d3
--- /dev/null
+++ b/src/frustum.c
@@ -0,0 +1,42 @@
+/*
+ * 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_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);
+}
+
+CGLM_EXPORT
+void
+glmc_frustum_box(vec4 corners[8], mat4 m, vec3 box[2]) {
+ glm_frustum_box(corners, m, box);
+}
+
+CGLM_EXPORT
+void
+glmc_frustum_corners_at(vec4 corners[8],
+ float splitDist,
+ float farDist,
+ vec4 planeCorners[4]) {
+ glm_frustum_corners_at(corners, splitDist, farDist, planeCorners);
+}
diff --git a/win/cglm.vcxproj b/win/cglm.vcxproj
index 91e8fa5..93d9e9b 100644
--- a/win/cglm.vcxproj
+++ b/win/cglm.vcxproj
@@ -23,9 +23,11 @@
+
+
@@ -37,9 +39,11 @@
+
+
@@ -47,9 +51,11 @@
+
+
@@ -73,7 +79,7 @@
{CA8BCAF9-CD25-4133-8F62-3D1449B5D2FC}
Win32Proj
cglm
- 10.0.14393.0
+ 10.0.16299.0
diff --git a/win/cglm.vcxproj.filters b/win/cglm.vcxproj.filters
index bed473d..5ea5810 100644
--- a/win/cglm.vcxproj.filters
+++ b/win/cglm.vcxproj.filters
@@ -66,6 +66,12 @@
src
+
+ src
+
+
+ src
+
@@ -176,5 +182,17 @@
include\cglm
+
+ include\cglm\call
+
+
+ include\cglm\call
+
+
+ include\cglm
+
+
+ include\cglm
+
\ No newline at end of file