Frustum is useful in the game collision or render
vec3f = vector (x , y ,z)
This is the frustum, there will be 6 planes and 8 points combine
struct Frustum
{
Plane planes[6];
vec3f corners[8];
};
This is the plane, there will be one vector three and one offset value combine
struct Plane
{
vec3f normal;
float offset;
};
for coding clear meaning, using enum to stand for individual corner
enum FrustumCorners{ FTL , FBL, FBR, FTR, NTL, NTR, NBR, NBL };
enum FrustumPlanes{ NEAR_PLANE = 0, FAR_PLANE, LEFT_PLANE, RIGHT_PLANE, TOP_PLANE, BOTTOM_PLANE };
- This is the declaration of build frustum, we need to build based on camera position, because camera will move, so I use camera matrix to get the information.
- Z is forward, X is right, Y is up
void BuildFrustum( Frustum& frustum, float fov, float nearDist, float farDist, float ratio, const matrix4f& camXform )
{
//get near plane middle point and far plan middle based on the near distance and far distance
vec3f nc = camXform.axis_pos - camXform.axis_z*nearDist;
vec3f fc = camXform.axis_pos - camXform.axis_z*farDist;
//fov is the angle on x and z, so it can get the y axis difference
float Hnear = 2 * tan(fov / 2)*nearDist;
float Hfar = 2 * tan(fov / 2)*farDist;
// x axis difference can be got by ratio, because ratio definition is x / y , like our TV is 16:9
float Wnear = Hnear* ratio;
float Wfar = Hfar* ratio;
//so I can get the 8 corners vector value
frustum.corners[FTL] = fc + camXform.axis_y*Hfar*0.5 - camXform.axis_x * Wfar*0.5;
frustum.corners[FBL] = fc - camXform.axis_y*Hfar*0.5 - camXform.axis_x * Wfar*0.5;
frustum.corners[FBR] = fc - camXform.axis_y*Hfar*0.5 + camXform.axis_x * Wfar*0.5;
frustum.corners[FTR] = fc + camXform.axis_y*Hfar*0.5 + camXform.axis_x * Wfar*0.5;
frustum.corners[NTL] = nc + camXform.axis_y*Hnear*0.5 - camXform.axis_x * Wnear*0.5;
frustum.corners[NTR] = nc + camXform.axis_y*Hnear*0.5 + camXform.axis_x * Wnear*0.5;
frustum.corners[NBR] = nc - camXform.axis_y*Hnear*0.5 + camXform.axis_x * Wnear*0.5;
frustum.corners[NBL] = nc - camXform.axis_y*Hnear*0.5 - camXform.axis_x * Wnear*0.5;
//Right now I can get the plane normal based on the two vector cross product, I use right hand system
//The offset can be got by dot product of the point and normalized normal of plane. In geometry, because it is the same as (point - origin ) dot (normalized normal), so I can do that.
//NEAR_PLANE
cross_product(frustum.planes[NEAR_PLANE].normal, frustum.corners[NBL] - frustum.corners[NBR], frustum.corners[NTL] - frustum.corners[NBL]);
frustum.planes[NEAR_PLANE].normal.normalize();
frustum.planes[NEAR_PLANE].offset = dot_product(frustum.planes[NEAR_PLANE].normal, frustum.corners[NBL]);
//FAR_PLANE
cross_product(frustum.planes[FAR_PLANE].normal, frustum.corners[FBR] - frustum.corners[FBL], frustum.corners[FTR] - frustum.corners[FBR]);
frustum.planes[FAR_PLANE].normal.normalize();
frustum.planes[FAR_PLANE].offset = dot_product(frustum.planes[FAR_PLANE].normal, frustum.corners[FBR]);
//left_plane
cross_product(frustum.planes[LEFT_PLANE].normal, frustum.corners[FBL] - frustum.corners[NBL], frustum.corners[FTL] - frustum.corners[FBL]);
frustum.planes[LEFT_PLANE].normal.normalize();
frustum.planes[LEFT_PLANE].offset = dot_product(frustum.planes[LEFT_PLANE].normal, frustum.corners[FBL]);
//RIGHT_PLANE
cross_product(frustum.planes[RIGHT_PLANE].normal, frustum.corners[NBR] - frustum.corners[FBR], frustum.corners[NTR] - frustum.corners[NBR]);
frustum.planes[RIGHT_PLANE].normal.normalize();
frustum.planes[RIGHT_PLANE].offset = dot_product(frustum.planes[RIGHT_PLANE].normal, frustum.corners[NBR]);
//TOP_PLANE
cross_product(frustum.planes[TOP_PLANE].normal, frustum.corners[NTR] - frustum.corners[FTR], frustum.corners[NTL] - frustum.corners[NTR]);
frustum.planes[TOP_PLANE].normal.normalize();
frustum.planes[TOP_PLANE].offset = dot_product(frustum.planes[TOP_PLANE].normal, frustum.corners[NTR]);
//BOTTOM_PLANE
cross_product(frustum.planes[BOTTOM_PLANE].normal, frustum.corners[FBR] - frustum.corners[NBR], frustum.corners[FBL] - frustum.corners[FBR]);
frustum.planes[BOTTOM_PLANE].normal.normalize();
frustum.planes[BOTTOM_PLANE].offset = dot_product(frustum.planes[BOTTOM_PLANE].normal, frustum.corners[FBR]);
return ;
}
That’s it, it can be used against other objects
bool FrustumToSphere(const Frustum& frustum, const Sphere& sphere); bool FrustumToAABB(const Frustum& frustum, const AABB& aabb); bool FrustumToCapsule(const Frustum& frustum, const Capsule& capsule);
To be continues..
