Merge revision 4920:4921 from trunk to ogl-es:

- Added sphere frustum culling support.


git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/branches/ogl-es@4935 dfc29bdd-3216-0410-991c-e03cc46cb475
master
cutealien 2014-09-18 21:57:30 +00:00
parent 6a85f02978
commit 0887bc1269
3 changed files with 97 additions and 6 deletions

View File

@ -45,7 +45,7 @@ namespace scene
//! Default Constructor
SViewFrustum() {}
SViewFrustum() : BoundingRadius(0.f), FarNearDistance(0.f) {}
//! Copy Constructor
SViewFrustum(const SViewFrustum& other);
@ -87,9 +87,18 @@ namespace scene
//! returns a bounding box enclosing the whole view frustum
const core::aabbox3d<f32> &getBoundingBox() const;
//! recalculates the bounding box member based on the planes
//! recalculates the bounding box and sphere based on the planes
inline void recalculateBoundingBox();
//! get the bounding sphere's radius (of an optimized sphere, not the AABB's)
float getBoundingRadius() const;
//! get the bounding sphere's radius (of an optimized sphere, not the AABB's)
core::vector3df getBoundingCenter() const;
//! the cam should tell the frustum the distance between far and near
void setFarNearDistance(float distance);
//! get the given state's matrix based on frustum E_TRANSFORMATION_STATE
core::matrix4& getTransform( video::E_TRANSFORMATION_STATE state);
@ -118,8 +127,15 @@ namespace scene
ETS_COUNT_FRUSTUM
};
//! recalculates the bounding sphere based on the planes
inline void recalculateBoundingSphere();
//! Hold a copy of important transform matrices
core::matrix4 Matrices[ETS_COUNT_FRUSTUM];
float BoundingRadius;
float FarNearDistance;
core::vector3df BoundingCenter;
};
@ -137,6 +153,10 @@ namespace scene
for (i=0; i<ETS_COUNT_FRUSTUM; ++i)
Matrices[i]=other.Matrices[i];
BoundingRadius = other.BoundingRadius;
FarNearDistance = other.FarNearDistance;
BoundingCenter = other.BoundingCenter;
}
inline SViewFrustum::SViewFrustum(const core::matrix4& mat)
@ -248,6 +268,24 @@ namespace scene
boundingBox.addInternalPoint(getFarRightUp());
boundingBox.addInternalPoint(getFarLeftDown());
boundingBox.addInternalPoint(getFarRightDown());
// Also recalculate the bounding sphere when the bbox changes
recalculateBoundingSphere();
}
inline float SViewFrustum::getBoundingRadius() const
{
return BoundingRadius;
}
inline core::vector3df SViewFrustum::getBoundingCenter() const
{
return BoundingCenter;
}
inline void SViewFrustum::setFarNearDistance(float distance)
{
FarNearDistance = distance;
}
//! This constructor creates a view frustum based on a projection
@ -362,6 +400,45 @@ namespace scene
return wasClipped;
}
inline void SViewFrustum::recalculateBoundingSphere()
{
// Find the center
const float shortlen = (getNearLeftUp() - getNearRightUp()).getLength();
const float longlen = (getFarLeftUp() - getFarRightUp()).getLength();
const float farlen = FarNearDistance;
const float fartocenter = (farlen + (shortlen - longlen) * (shortlen + longlen)/(4*farlen)) / 2;
const float neartocenter = farlen - fartocenter;
BoundingCenter = cameraPosition + -planes[VF_NEAR_PLANE].Normal * neartocenter;
// Find the radius
core::vector3df dir[8];
dir[0] = getFarLeftUp() - BoundingCenter;
dir[1] = getFarRightUp() - BoundingCenter;
dir[2] = getFarLeftDown() - BoundingCenter;
dir[3] = getFarRightDown() - BoundingCenter;
dir[4] = getNearRightDown() - BoundingCenter;
dir[5] = getNearLeftDown() - BoundingCenter;
dir[6] = getNearRightUp() - BoundingCenter;
dir[7] = getNearLeftUp() - BoundingCenter;
u32 i = 0;
float diam[8] = { 0.f };
for (i = 0; i < 8; ++i)
diam[i] = dir[i].getLengthSQ();
float longest = 0;
for (i = 0; i < 8; ++i)
{
if (diam[i] > longest)
longest = diam[i];
}
BoundingRadius = sqrtf(longest);
}
} // end namespace scene
} // end namespace irr

View File

@ -36,6 +36,7 @@ CCameraSceneNode::CCameraSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 i
recalculateProjectionMatrix();
recalculateViewArea();
ViewArea.setFarNearDistance(ZFar - ZNear);
}
@ -201,6 +202,7 @@ void CCameraSceneNode::setNearValue(f32 f)
{
ZNear = f;
recalculateProjectionMatrix();
ViewArea.setFarNearDistance(ZFar - ZNear);
}
@ -208,6 +210,7 @@ void CCameraSceneNode::setFarValue(f32 f)
{
ZFar = f;
recalculateProjectionMatrix();
ViewArea.setFarNearDistance(ZFar - ZNear);
}

View File

@ -1204,7 +1204,18 @@ bool CSceneManager::isCulled(const ISceneNode* node) const
// can be seen by a bounding sphere
if (!result && (node->getAutomaticCulling() & scene::EAC_FRUSTUM_SPHERE))
{ // requires bbox diameter
{
const core::aabbox3df nbox = node->getTransformedBoundingBox();
const float rad = nbox.getRadius();
const core::vector3df center = nbox.getCenter();
const float camrad = cam->getViewFrustum()->getBoundingRadius();
const core::vector3df camcenter = cam->getViewFrustum()->getBoundingCenter();
const float dist = (center - camcenter).getLengthSQ();
const float maxdist = (rad + camrad) * (rad + camrad);
result = dist > maxdist;
}
// can be seen by cam pyramid planes ?