Search this site
Embedded Files
Skip to main content
Skip to navigation
Max Klassen
Home
Coding
C/C++
Tutorials
Permutations & Combinations
C++ Code Example
DigiPen Projects
Boxland
Unity
First Person Controller
Character Follow
Culling
Platformer Basics
Read Binary
Useful Snippets
Setup/tools
Git tutorial
Cmake
Misc
Javascript
GSheets
E-DiveSheet
Interests
Games
My gaming history
Esports Medley
TED Talks
Max Klassen
Culling
There is a great tutorial here on lighthouse3d:
http://www.lighthouse3d.com/tutorials/view-frustum-culling/geometric-approach-testing-boxes-ii/
And if you want to really understand this and do it the hardcore way read here:
http://www.lighthouse3d.com/tutorials/view-frustum-culling/clip-space-approach-extracting-the-planes/
Here is how to do it in Unity:
void Update()
{
UpdateFrustum(maincam.projectionMatrix * maincam.worldToCameraMatrix); // PM - for some reason this works better
//UpdateFrustum(maincam.worldToCameraMatrix * maincam.projectionMatrix); // MP - like lighthouse3d, but can't extract bottom plane normal
float near = maincam.nearClipPlane;
float far = maincam.farClipPlane;
float Hnear = 2 * Mathf.Tan(maincam.fieldOfView / 2 * Mathf.Deg2Rad) * near;
float Wnear = Hnear * maincam.aspect;
float Hfar = 2 * Mathf.Tan(maincam.fieldOfView / 2 * Mathf.Deg2Rad) * far;
float Wfar = Hfar * maincam.aspect;
Vector3 fc = maincam.transform.position + maincam.transform.forward * maincam.farClipPlane;
Vector3 ftl = fc + (maincam.transform.up * Hfar / 2) - (maincam.transform.right * Wfar / 2);
Vector3 ftr = fc + (maincam.transform.up * Hfar / 2) + (maincam.transform.right * Wfar / 2);
Vector3 fbl = fc - (maincam.transform.up * Hfar / 2) - (maincam.transform.right * Wfar / 2);
Vector3 fbr = fc - (maincam.transform.up * Hfar / 2) + (maincam.transform.right * Wfar / 2);
Vector3 nc = maincam.transform.position + maincam.transform.forward * maincam.nearClipPlane;
Vector3 ntl = nc + (maincam.transform.up * Hnear / 2) - (maincam.transform.right * Wnear / 2);
Vector3 ntr = nc + (maincam.transform.up * Hnear / 2) + (maincam.transform.right * Wnear / 2);
Vector3 nbl = nc - (maincam.transform.up * Hnear / 2) - (maincam.transform.right * Wnear / 2);
Vector3 nbr = nc - (maincam.transform.up * Hnear / 2) + (maincam.transform.right * Wnear / 2);
planesPoints[(int)Planes.NEAR] = ntl;
planesPoints[(int)Planes.FAR] = ftl;
planesPoints[(int)Planes.BOTTOM] = nbl;
planesPoints[(int)Planes.TOP] = ntl;
planesPoints[(int)Planes.LEFT] = ntl;
planesPoints[(int)Planes.RIGHT] = ntr;
}
void UpdateFrustum(Matrix4x4 vm)
{
planesCes[(int)Planes.NEAR] = new Vector4(
vm.m20 + vm.m30,
vm.m21 + vm.m31,
vm.m22 + vm.m32,
vm.m23 + vm.m33);
planesCes[(int)Planes.FAR] = new Vector4(
-vm.m20 + vm.m30,
-vm.m21 + vm.m31,
-vm.m22 + vm.m32,
-vm.m23 + vm.m33);
planesCes[(int)Planes.BOTTOM] = new Vector4(
vm.m10 + vm.m30,
vm.m11 + vm.m31,
vm.m12 + vm.m32,
vm.m13 + vm.m33);
planesCes[(int)Planes.TOP] = new Vector4(
-vm.m10 + vm.m30,
-vm.m11 + vm.m31,
-vm.m12 + vm.m32,
-vm.m13 + vm.m33);
planesCes[(int)Planes.LEFT] = new Vector4(
vm.m00 + vm.m30,
vm.m01 + vm.m31,
vm.m02 + vm.m32,
vm.m03 + vm.m33);
planesCes[(int)Planes.RIGHT] = new Vector4(
-vm.m00 + vm.m30,
-vm.m01 + vm.m31,
-vm.m02 + vm.m32,
-vm.m03 + vm.m33);
var nearp = planesCes[(int)Planes.NEAR];
var farp = planesCes[(int)Planes.FAR];
var botp = planesCes[(int)Planes.BOTTOM];
var topp = planesCes[(int)Planes.TOP];
var leftp = planesCes[(int)Planes.LEFT];
var rightp = planesCes[(int)Planes.RIGHT];
planesNorms[(int)Planes.NEAR] = new Vector3(nearp.x, nearp.y, nearp.z).normalized;
planesNorms[(int)Planes.FAR] = new Vector3(farp.x, farp.y, farp.z).normalized;
planesNorms[(int)Planes.BOTTOM] = new Vector3(botp.x, botp.y, botp.z).normalized;
planesNorms[(int)Planes.TOP] = new Vector3(topp.x, topp.y, topp.z).normalized;
planesNorms[(int)Planes.LEFT] = new Vector3(leftp.x, leftp.y, leftp.z).normalized;
planesNorms[(int)Planes.RIGHT] = new Vector3(rightp.x, rightp.y, rightp.z).normalized;
}
for (int j = 0; j < 6; j++) // each plane
{
Vector3 negativeCorner = GetMaxCorner(objs[i].GetComponent<Renderer>().bounds, planesCes[j]);
var toNvert = negativeCorner - planesPoints[j];
if (Vector3.Dot(planesNorms[j], toNvert) < 0)
{
objs[i].GetComponent<Renderer>().enabled = false;
break;
}
else
{
objs[i].GetComponent<Renderer>().enabled = true;
}
}
Vector3 GetMaxCorner(Bounds b, Vector3 dir)
{
Vector3 center = (b.max + b.min) * 0.5f;
var tomax = b.max - center;
var tomin = b.min - center;
Vector3 ret = tomin;
if (dir.x >= 0)
ret.x = tomax.x;
if (dir.y >= 0)
ret.y = tomax.y;
if (dir.z >= 0)
ret.z = tomax.z;
return center + ret;
}
Google Sites
Report abuse
Google Sites
Report abuse