Initial commit
This commit is contained in:
166
Torque/SDK/engine/util/frustrumCuller.cpp
Normal file
166
Torque/SDK/engine/util/frustrumCuller.cpp
Normal file
@@ -0,0 +1,166 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Shader Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "util/frustrumCuller.h"
|
||||
#include "sceneGraph/sceneGraph.h"
|
||||
#include "sceneGraph/sgUtil.h"
|
||||
#include "terrain/sky.h"
|
||||
#include "dgl/dgl.h"
|
||||
|
||||
SceneState *FrustrumCuller::smSceneState;
|
||||
Point3F FrustrumCuller::smCamPos;
|
||||
U32 FrustrumCuller::smNumClipPlanes;
|
||||
F32 FrustrumCuller::smFarDistance;
|
||||
PlaneF FrustrumCuller::smClipPlane[MaxClipPlanes];
|
||||
|
||||
void FrustrumCuller::init(SceneState *state)
|
||||
{
|
||||
if(Con::getBoolVariable("$lockFrustrum", false))
|
||||
return;
|
||||
|
||||
// Set up some general info.
|
||||
smSceneState = state;
|
||||
smFarDistance = gClientSceneGraph->getCurrentSky()->getVisibleDistance();
|
||||
|
||||
// Now determine the frustrum.
|
||||
F64 realfrustumParam[6];
|
||||
|
||||
dglGetFrustum(&realfrustumParam[0], &realfrustumParam[1],
|
||||
&realfrustumParam[2], &realfrustumParam[3],
|
||||
&realfrustumParam[4], &realfrustumParam[5]);
|
||||
|
||||
MatrixF camToObj;
|
||||
dglGetModelview(&camToObj); // BUG? Test this.
|
||||
camToObj.inverse();
|
||||
camToObj.getColumn(3, &smCamPos);
|
||||
|
||||
Point3F osCamPoint(0,0,0);
|
||||
camToObj.mulP(osCamPoint);
|
||||
sgComputeOSFrustumPlanes(
|
||||
realfrustumParam,
|
||||
camToObj,
|
||||
osCamPoint,
|
||||
smClipPlane[4],
|
||||
smClipPlane[0],
|
||||
smClipPlane[1],
|
||||
smClipPlane[2],
|
||||
smClipPlane[3]);
|
||||
|
||||
smNumClipPlanes = 4;
|
||||
|
||||
if (state->mFlipCull)
|
||||
{
|
||||
smClipPlane[0].neg();
|
||||
smClipPlane[1].neg();
|
||||
smClipPlane[2].neg();
|
||||
smClipPlane[3].neg();
|
||||
smClipPlane[4].neg();
|
||||
}
|
||||
|
||||
AssertFatal(smNumClipPlanes <= MaxClipPlanes, "FrustrumCuller::init - got too many clip planes!");
|
||||
}
|
||||
|
||||
|
||||
F32 FrustrumCuller::getBoxDistance(const Box3F &box)
|
||||
{
|
||||
Point3F vec;
|
||||
|
||||
const Point3F &minPoint = box.min;
|
||||
const Point3F &maxPoint = box.max;
|
||||
|
||||
if(smCamPos.z < minPoint.z)
|
||||
vec.z = minPoint.z - smCamPos.z;
|
||||
else if(smCamPos.z > maxPoint.z)
|
||||
vec.z = maxPoint.z - smCamPos.z;
|
||||
else
|
||||
vec.z = 0;
|
||||
|
||||
if(smCamPos.x < minPoint.x)
|
||||
vec.x = minPoint.x - smCamPos.x;
|
||||
else if(smCamPos.x > maxPoint.x)
|
||||
vec.x = smCamPos.x - maxPoint.x;
|
||||
else
|
||||
vec.x = 0;
|
||||
|
||||
if(smCamPos.y < minPoint.y)
|
||||
vec.y = minPoint.y - smCamPos.y;
|
||||
else if(smCamPos.y > maxPoint.y)
|
||||
vec.y = smCamPos.y - maxPoint.y;
|
||||
else
|
||||
vec.y = 0;
|
||||
|
||||
return vec.len();
|
||||
}
|
||||
|
||||
S32 FrustrumCuller::testBoxVisibility(const Box3F &bounds, const S32 mask, const F32 expand)
|
||||
{
|
||||
S32 retMask = 0;
|
||||
|
||||
Point3F minPoint, maxPoint;
|
||||
for(S32 i = 0; i < smNumClipPlanes; i++)
|
||||
{
|
||||
if(mask & (1 << i))
|
||||
{
|
||||
if(smClipPlane[i].x > 0)
|
||||
{
|
||||
maxPoint.x = bounds.max.x;
|
||||
minPoint.x = bounds.min.x;
|
||||
}
|
||||
else
|
||||
{
|
||||
maxPoint.x = bounds.min.x;
|
||||
minPoint.x = bounds.max.x;
|
||||
}
|
||||
if(smClipPlane[i].y > 0)
|
||||
{
|
||||
maxPoint.y = bounds.max.y;
|
||||
minPoint.y = bounds.min.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
maxPoint.y = bounds.min.y;
|
||||
minPoint.y = bounds.max.y;
|
||||
}
|
||||
|
||||
if(smClipPlane[i].z > 0)
|
||||
{
|
||||
maxPoint.z = bounds.max.z;
|
||||
minPoint.z = bounds.min.z;
|
||||
}
|
||||
else
|
||||
{
|
||||
maxPoint.z = bounds.min.z;
|
||||
minPoint.z = bounds.max.z;
|
||||
}
|
||||
|
||||
|
||||
F32 maxDot = mDot(maxPoint, smClipPlane[i]);
|
||||
F32 minDot = mDot(minPoint, smClipPlane[i]);
|
||||
F32 planeD = smClipPlane[i].d;
|
||||
|
||||
if(maxDot <= -(planeD + expand))
|
||||
return -1;
|
||||
|
||||
if(minDot <= -planeD)
|
||||
retMask |= (1 << i);
|
||||
}
|
||||
}
|
||||
|
||||
// Check the far distance as well.
|
||||
if(mask & FarSphereMask)
|
||||
{
|
||||
F32 squareDistance = getBoxDistance(bounds);
|
||||
|
||||
// Reject stuff outside our visible range...
|
||||
if(squareDistance >= smFarDistance)
|
||||
return -1;
|
||||
|
||||
// See if the box potentially hits the far sphere. (Sort of assumes a square box!)
|
||||
if(squareDistance + bounds.len_x() + bounds.len_z() > smFarDistance)
|
||||
retMask |= FarSphereMask;
|
||||
}
|
||||
|
||||
return retMask;
|
||||
}
|
||||
Reference in New Issue
Block a user