From 0887bc12691e5622b6bf2173e6b6ab71be5f0579 Mon Sep 17 00:00:00 2001 From: cutealien Date: Thu, 18 Sep 2014 21:57:30 +0000 Subject: [PATCH] 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 --- include/SViewFrustum.h | 87 ++++++++++++++++++++++++++-- source/Irrlicht/CCameraSceneNode.cpp | 3 + source/Irrlicht/CSceneManager.cpp | 13 ++++- 3 files changed, 97 insertions(+), 6 deletions(-) diff --git a/include/SViewFrustum.h b/include/SViewFrustum.h index 88d7e2e1..97e1a3d5 100644 --- a/include/SViewFrustum.h +++ b/include/SViewFrustum.h @@ -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 &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,11 +153,15 @@ namespace scene for (i=0; i longest) + longest = diam[i]; + } + + BoundingRadius = sqrtf(longest); + } } // end namespace scene } // end namespace irr diff --git a/source/Irrlicht/CCameraSceneNode.cpp b/source/Irrlicht/CCameraSceneNode.cpp index 760dda65..3f9bc891 100644 --- a/source/Irrlicht/CCameraSceneNode.cpp +++ b/source/Irrlicht/CCameraSceneNode.cpp @@ -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); } diff --git a/source/Irrlicht/CSceneManager.cpp b/source/Irrlicht/CSceneManager.cpp index 1f326427..f1588a2a 100644 --- a/source/Irrlicht/CSceneManager.cpp +++ b/source/Irrlicht/CSceneManager.cpp @@ -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 ?