frillrun/include/cglm/struct/frustum.h
2024-08-24 00:47:58 -04:00

156 lines
4.2 KiB
C

/*
* Copyright (c), Recep Aslantas.
*
* MIT License (MIT), http://opensource.org/licenses/MIT
* Full license can be found in the LICENSE file
*/
#ifndef cglms_frustums_h
#define cglms_frustums_h
#include "../common.h"
#include "../types-struct.h"
#include "../frustum.h"
#include "plane.h"
#include "vec3.h"
#include "vec4.h"
#include "mat4.h"
/* 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 GLMS_CSCOORD_LBN {-1.0f, -1.0f, -1.0f, 1.0f}
#define GLMS_CSCOORD_LTN {-1.0f, 1.0f, -1.0f, 1.0f}
#define GLMS_CSCOORD_RTN { 1.0f, 1.0f, -1.0f, 1.0f}
#define GLMS_CSCOORD_RBN { 1.0f, -1.0f, -1.0f, 1.0f}
/* far */
#define GLMS_CSCOORD_LBF {-1.0f, -1.0f, 1.0f, 1.0f}
#define GLMS_CSCOORD_LTF {-1.0f, 1.0f, 1.0f, 1.0f}
#define GLMS_CSCOORD_RTF { 1.0f, 1.0f, 1.0f, 1.0f}
#define GLMS_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 extracted view frustum planes (see brief)
*/
CGLM_INLINE
void
glms_frustum_planes(mat4s m, vec4s dest[6]) {
vec4 rawDest[6];
glm_frustum_planes(m.raw, rawDest);
glms_vec4_pack(dest, rawDest, 6);
}
/*!
* @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_vec3_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
glms_frustum_corners(mat4s invMat, vec4s dest[8]) {
vec4 rawDest[8];
glm_frustum_corners(invMat.raw, rawDest);
glms_vec4_pack(dest, rawDest, 8);
}
/*!
* @brief finds center of view frustum
*
* @param[in] corners view frustum corners
* @returns view frustum center
*/
CGLM_INLINE
vec4s
glms_frustum_center(vec4s corners[8]) {
vec4 rawCorners[8];
vec4s r;
glms_vec4_unpack(rawCorners, corners, 8);
glm_frustum_center(rawCorners, r.raw);
return r;
}
/*!
* @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
glms_frustum_box(vec4s corners[8], mat4s m, vec3s box[2]) {
vec4 rawCorners[8];
vec3 rawBox[2];
glms_vec4_unpack(rawCorners, corners, 8);
glm_frustum_box(rawCorners, m.raw, rawBox);
glms_vec3_pack(box, rawBox, 2);
}
/*!
* @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
glms_frustum_corners_at(vec4s corners[8],
float splitDist,
float farDist,
vec4s planeCorners[4]) {
vec4 rawCorners[8];
vec4 rawPlaneCorners[4];
glms_vec4_unpack(rawCorners, corners, 8);
glm_frustum_corners_at(rawCorners, splitDist, farDist, rawPlaneCorners);
glms_vec4_pack(planeCorners, rawPlaneCorners, 8);
}
#endif /* cglms_frustums_h */