From d8ac185656c8dd802a634e9ec3bafdb532248e8e Mon Sep 17 00:00:00 2001 From: parax0 Date: Sun, 27 Sep 2015 16:02:53 -0600 Subject: [PATCH] Implemented frustum culling --- Core/CCamera.cpp | 25 ++++++++++ Core/CCamera.h | 5 ++ Core/CFrustumPlanes.cpp | 98 +++++++++++++++++++++++++++++++++++++ Core/CFrustumPlanes.h | 30 ++++++++++++ Core/CSceneManager.cpp | 12 ++--- Core/CSceneManager.h | 2 +- Core/IRenderable.h | 3 +- PrimeWorldEditor.pro | 6 ++- Resource/CMaterial.cpp | 1 - Scene/CCollisionNode.cpp | 3 +- Scene/CCollisionNode.h | 2 +- Scene/CLightNode.cpp | 4 +- Scene/CLightNode.h | 2 +- Scene/CModelNode.cpp | 14 ++++-- Scene/CModelNode.h | 2 +- Scene/CRootNode.h | 2 +- Scene/CScriptNode.cpp | 46 ++++++++++------- Scene/CScriptNode.h | 2 +- Scene/CStaticNode.cpp | 6 ++- Scene/CStaticNode.h | 2 +- UI/CGizmo.cpp | 2 +- UI/CGizmo.h | 2 +- UI/CModelEditorViewport.cpp | 2 +- UI/CSceneViewport.cpp | 4 +- UI/CWorldEditorWindow.cpp | 2 +- 25 files changed, 229 insertions(+), 50 deletions(-) create mode 100644 Core/CFrustumPlanes.cpp create mode 100644 Core/CFrustumPlanes.h diff --git a/Core/CCamera.cpp b/Core/CCamera.cpp index 32f5a292..9723242d 100644 --- a/Core/CCamera.cpp +++ b/Core/CCamera.cpp @@ -18,6 +18,7 @@ CCamera::CCamera() mLookSpeed = 1.f; // Old: 0.003f mViewOutdated = true; mProjectionOutdated = true; + mFrustumPlanesOutdated = true; } CCamera::CCamera(CVector3f Position, CVector3f) @@ -50,6 +51,7 @@ void CCamera::Pan(float XAmount, float YAmount) mPosition += Right * (XAmount * mMoveSpeed); mPosition += Up * (YAmount * mMoveSpeed); mViewOutdated = true; + mFrustumPlanesOutdated = true; break; } @@ -77,6 +79,7 @@ void CCamera::Rotate(float XAmount, float YAmount) mYaw -= (XAmount * mLookSpeed * 0.3f); mPitch -= (YAmount * mLookSpeed * 0.3f); mViewOutdated = true; + mFrustumPlanesOutdated = true; break; } } @@ -85,6 +88,7 @@ void CCamera::Zoom(float Amount) { mPosition += (mDirection * Amount) * (mMoveSpeed * 25.f); mViewOutdated = true; + mFrustumPlanesOutdated = true; } void CCamera::Snap(CVector3f Position) @@ -93,6 +97,8 @@ void CCamera::Snap(CVector3f Position) mYaw = -Math::skHalfPi; mPitch = 0.0f; mViewOutdated = true; + mFrustumPlanesOutdated = true; + CalculateDirection(); } void CCamera::ProcessKeyInput(EKeyInputs KeyFlags, double DeltaTime) @@ -132,6 +138,8 @@ void CCamera::ProcessMouseInput(EKeyInputs KeyFlags, EMouseInputs MouseFlags, fl else if ((MouseFlags & eMiddleButton) || (MouseFlags & eRightButton)) Pan(XMovement, YMovement); } + + CalculateDirection(); } CRay CCamera::CastRay(CVector2f DeviceCoords) @@ -215,17 +223,27 @@ const CMatrix4f& CCamera::ProjectionMatrix() return mCachedProjectionMatrix; } +const CFrustumPlanes& CCamera::FrustumPlanes() +{ + if (mFrustumPlanesOutdated) + CalculateFrustumPlanes(); + + return mCachedFrustumPlanes; +} + // ************ SETTERS ************ void CCamera::SetPosition(CVector3f Position) { mPosition = Position; mViewOutdated = true; + mFrustumPlanesOutdated = true; } void CCamera::SetDirection(CVector3f Direction) { mDirection = Direction; mViewOutdated = true; + mFrustumPlanesOutdated = true; } void CCamera::SetYaw(float Yaw) @@ -263,6 +281,7 @@ void CCamera::SetAspectRatio(float AspectRatio) { mAspectRatio = AspectRatio; mProjectionOutdated = true; + mFrustumPlanesOutdated = true; } // ************ PRIVATE ************ @@ -303,3 +322,9 @@ void CCamera::CalculateProjection() mCachedProjectionMatrix = Math::PerspectiveMatrix(55.f, mAspectRatio, 0.1f, 4096.f); mProjectionOutdated = false; } + +void CCamera::CalculateFrustumPlanes() +{ + mCachedFrustumPlanes.SetPlanes(mPosition, mDirection, 55.f, mAspectRatio, 0.1f, 4096.f); + mFrustumPlanesOutdated = false; +} diff --git a/Core/CCamera.h b/Core/CCamera.h index 003bff37..f1505b93 100644 --- a/Core/CCamera.h +++ b/Core/CCamera.h @@ -1,6 +1,7 @@ #ifndef CCAMERA_H #define CCAMERA_H +#include "CFrustumPlanes.h" #include #include #include @@ -30,8 +31,10 @@ class CCamera CMatrix4f mCachedViewMatrix; CMatrix4f mCachedProjectionMatrix; + CFrustumPlanes mCachedFrustumPlanes; bool mViewOutdated; bool mProjectionOutdated; + bool mFrustumPlanesOutdated; public: CCamera(); @@ -56,6 +59,7 @@ public: const CMatrix4f& ViewMatrix(); CMatrix4f RotationOnlyViewMatrix(); const CMatrix4f& ProjectionMatrix(); + const CFrustumPlanes& FrustumPlanes(); // Setters void SetPosition(CVector3f Position); @@ -74,6 +78,7 @@ private: void CalculateDirection(); void CalculateView(); void CalculateProjection(); + void CalculateFrustumPlanes(); }; #endif // CCAMERA_H diff --git a/Core/CFrustumPlanes.cpp b/Core/CFrustumPlanes.cpp new file mode 100644 index 00000000..37f23bd3 --- /dev/null +++ b/Core/CFrustumPlanes.cpp @@ -0,0 +1,98 @@ +#include "CFrustumPlanes.h" +#include +#include + +CFrustumPlanes::CFrustumPlanes() +{ + +} + +CFrustumPlanes::~CFrustumPlanes() +{ + +} + +const CPlane& CFrustumPlanes::GetPlane(EFrustumSide side) const +{ + return mPlanes[side]; +} + +void CFrustumPlanes::SetPlanes(const CVector3f& position, const CVector3f& direction, float fieldOfView, float aspectRatio, float near, float far) +{ + // Calculate up/right vectors + CVector3f right = direction.Cross(CVector3f::skUp).Normalized(); + CVector3f up = right.Cross(direction).Normalized(); + + // Calculate dimensions of near plane + float nearHeight = 2 * tanf(Math::DegreesToRadians(fieldOfView) / 2.f) * near; + float nearWidth = nearHeight * aspectRatio; + + // Define the planes + CVector3f nearCenter = position + (direction * near); + mPlanes[eNearPlane].Redefine(direction, nearCenter); + + CVector3f farCenter = position + (direction * far); + mPlanes[eFarPlane].Redefine(-direction, farCenter); + + CVector3f midRight = nearCenter + (right * (nearWidth / 2.f)); + CVector3f rightNormal = up.Cross((midRight - position).Normalized()); + mPlanes[eRightPlane].Redefine(rightNormal, position); + + CVector3f midLeft = nearCenter - (right * (nearWidth / 2.f)); + CVector3f leftNormal = (midLeft - position).Normalized().Cross(up); + mPlanes[eLeftPlane].Redefine(leftNormal, position); + + CVector3f midTop = nearCenter + (up * (nearHeight / 2.f)); + CVector3f topNormal = (midTop - position).Normalized().Cross(right); + mPlanes[eTopPlane].Redefine(topNormal, position); + + CVector3f midBottom = nearCenter - (up * (nearHeight / 2.f)); + CVector3f bottomNormal = right.Cross((midBottom - position).Normalized()); + mPlanes[eBottomPlane].Redefine(bottomNormal, position); +} + +bool CFrustumPlanes::PointInFrustum(const CVector3f& point) const +{ + for (u32 iPlane = 0; iPlane < 6; iPlane++) + { + const CPlane& plane = mPlanes[iPlane]; + + if (plane.Normal().Dot(point) + plane.Dist() < 0.f) + return false; + } + + return true; +} + +bool CFrustumPlanes::BoxInFrustum(const CAABox& box) const +{ + CVector3f min = box.Min(); + CVector3f max = box.Max(); + + CVector3f points[8]; + points[0] = min; + points[1] = max; + points[2] = CVector3f(min.x, min.y, max.z); + points[3] = CVector3f(min.x, max.y, min.z); + points[4] = CVector3f(min.x, max.y, max.z); + points[5] = CVector3f(max.x, min.y, max.z); + points[6] = CVector3f(max.x, max.y, min.z); + points[7] = CVector3f(max.x, min.y, min.z); + + for (u32 iPlane = 0; iPlane < 6; iPlane++) + { + const CPlane& plane = mPlanes[iPlane]; + int numPoints = 0; + + for (u32 iPoint = 0; iPoint < 8; iPoint++) + { + if (plane.Normal().Dot(points[iPoint]) + plane.Dist() < 0.f) + numPoints++; + else + break; + } + + if (numPoints == 8) return false; + } + return true; +} diff --git a/Core/CFrustumPlanes.h b/Core/CFrustumPlanes.h new file mode 100644 index 00000000..c9c1c616 --- /dev/null +++ b/Core/CFrustumPlanes.h @@ -0,0 +1,30 @@ +#ifndef CFRUSTUMPLANES_H +#define CFRUSTUMPLANES_H + +#include +#include +#include + +class CFrustumPlanes +{ +public: + enum EFrustumSide + { + eNearPlane = 0, eFarPlane = 1, + eTopPlane = 2, eBottomPlane = 3, + eLeftPlane = 4, eRightPlane = 5 + }; + +private: + CPlane mPlanes[6]; + +public: + CFrustumPlanes(); + ~CFrustumPlanes(); + const CPlane& GetPlane(EFrustumSide side) const; + void SetPlanes(const CVector3f& position, const CVector3f& direction, float fieldOfView, float aspectRatio, float near, float far); + bool PointInFrustum(const CVector3f& point) const; + bool BoxInFrustum(const CAABox& box) const; +}; + +#endif // CFRUSTUMPLANES_H diff --git a/Core/CSceneManager.cpp b/Core/CSceneManager.cpp index f1f18db0..83d34ffe 100644 --- a/Core/CSceneManager.cpp +++ b/Core/CSceneManager.cpp @@ -215,7 +215,7 @@ void CSceneManager::ClearScene() mNodeCount = 0; } -void CSceneManager::AddSceneToRenderer(CRenderer *pRenderer) +void CSceneManager::AddSceneToRenderer(CRenderer *pRenderer, CCamera& camera) { ERenderOptions options = pRenderer->RenderOptions(); @@ -223,32 +223,32 @@ void CSceneManager::AddSceneToRenderer(CRenderer *pRenderer) { for (u32 n = 0; n < mModelNodes.size(); n++) if (mModelNodes[n]->IsVisible()) - mModelNodes[n]->AddToRenderer(pRenderer); + mModelNodes[n]->AddToRenderer(pRenderer, camera.FrustumPlanes()); for (u32 n = 0; n < mStaticNodes.size(); n++) if (mStaticNodes[n]->IsVisible()) - mStaticNodes[n]->AddToRenderer(pRenderer); + mStaticNodes[n]->AddToRenderer(pRenderer, camera.FrustumPlanes()); } if (options & eDrawWorldCollision) { for (u32 n = 0; n < mCollisionNodes.size(); n++) if (mCollisionNodes[n]->IsVisible()) - mCollisionNodes[n]->AddToRenderer(pRenderer); + mCollisionNodes[n]->AddToRenderer(pRenderer, camera.FrustumPlanes()); } if (options & eDrawLights) { for (u32 n = 0; n < mLightNodes.size(); n++) if (mLightNodes[n]->IsVisible()) - mLightNodes[n]->AddToRenderer(pRenderer); + mLightNodes[n]->AddToRenderer(pRenderer, camera.FrustumPlanes()); } if ((options & eDrawObjects) || (options & eDrawObjectCollision)) { for (u32 n = 0; n < mScriptNodes.size(); n++) if (mScriptNodes[n]->IsVisible()) - mScriptNodes[n]->AddToRenderer(pRenderer); + mScriptNodes[n]->AddToRenderer(pRenderer, camera.FrustumPlanes()); } } diff --git a/Core/CSceneManager.h b/Core/CSceneManager.h index 5b018a2b..f4dc45a1 100644 --- a/Core/CSceneManager.h +++ b/Core/CSceneManager.h @@ -57,7 +57,7 @@ public: void SetActiveArea(CGameArea *_area); void SetActiveWorld(CWorld *_world); void ClearScene(); - void AddSceneToRenderer(CRenderer *pRenderer); + void AddSceneToRenderer(CRenderer *pRenderer, CCamera& camera); SRayIntersection SceneRayCast(const CRay& Ray, ERenderOptions renderOptions); void PickEnvironmentObjects(); CScriptNode* ScriptNodeByID(u32 InstanceID); diff --git a/Core/IRenderable.h b/Core/IRenderable.h index 814efe25..9b26ffa7 100644 --- a/Core/IRenderable.h +++ b/Core/IRenderable.h @@ -4,6 +4,7 @@ #include "ERenderOptions.h" #include #include +#include class CRenderer; @@ -12,7 +13,7 @@ class IRenderable public: IRenderable() {} virtual ~IRenderable() {} - virtual void AddToRenderer(CRenderer *pRenderer) = 0; + virtual void AddToRenderer(CRenderer *pRenderer, const CFrustumPlanes& frustum) = 0; virtual void Draw(ERenderOptions options) {} virtual void DrawAsset(ERenderOptions options, u32 asset) {} virtual void DrawSelection() {} diff --git a/PrimeWorldEditor.pro b/PrimeWorldEditor.pro index 924c8a4d..58da7d79 100644 --- a/PrimeWorldEditor.pro +++ b/PrimeWorldEditor.pro @@ -151,7 +151,8 @@ SOURCES += \ Resource/script/CProperty.cpp \ Resource/CAnimationParameters.cpp \ UI/WAnimParamsEditor.cpp \ - Resource/CCollisionMeshGroup.cpp + Resource/CCollisionMeshGroup.cpp \ + Core/CFrustumPlanes.cpp HEADERS += \ Common/AnimUtil.h \ @@ -318,7 +319,8 @@ HEADERS += \ Resource/script/EVolumeShape.h \ Resource/CAnimationParameters.h \ UI/WAnimParamsEditor.h \ - Resource/CCollisionMeshGroup.h + Resource/CCollisionMeshGroup.h \ + Core/CFrustumPlanes.h FORMS += \ UI/CWorldEditorWindow.ui \ diff --git a/Resource/CMaterial.cpp b/Resource/CMaterial.cpp index cfcb8dfc..c6a09103 100644 --- a/Resource/CMaterial.cpp +++ b/Resource/CMaterial.cpp @@ -328,5 +328,4 @@ void CMaterial::SetLightingEnabled(bool Enabled) void CMaterial::KillCachedMaterial() { sCurrentMaterial = 0; - CShader::KillCachedShader(); } diff --git a/Scene/CCollisionNode.cpp b/Scene/CCollisionNode.cpp index 9bb8fe3a..e903c043 100644 --- a/Scene/CCollisionNode.cpp +++ b/Scene/CCollisionNode.cpp @@ -15,9 +15,10 @@ ENodeType CCollisionNode::NodeType() return eCollisionNode; } -void CCollisionNode::AddToRenderer(CRenderer *pRenderer) +void CCollisionNode::AddToRenderer(CRenderer *pRenderer, const CFrustumPlanes& frustum) { if (!mpCollision) return; + if (!frustum.BoxInFrustum(AABox())) return; pRenderer->AddOpaqueMesh(this, 0, AABox(), eDrawMesh); diff --git a/Scene/CCollisionNode.h b/Scene/CCollisionNode.h index 5c18c3ed..36137c05 100644 --- a/Scene/CCollisionNode.h +++ b/Scene/CCollisionNode.h @@ -12,7 +12,7 @@ class CCollisionNode : public CSceneNode public: CCollisionNode(CSceneManager *pScene, CSceneNode *pParent = 0, CCollisionMeshGroup *pCollision = 0); ENodeType NodeType(); - void AddToRenderer(CRenderer *pRenderer); + void AddToRenderer(CRenderer *pRenderer, const CFrustumPlanes& frustumPlanes); void Draw(ERenderOptions Options); void DrawAsset(ERenderOptions Options, u32 asset); SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID, ERenderOptions options); diff --git a/Scene/CLightNode.cpp b/Scene/CLightNode.cpp index 8658ed7d..80b03cee 100644 --- a/Scene/CLightNode.cpp +++ b/Scene/CLightNode.cpp @@ -24,8 +24,10 @@ ENodeType CLightNode::NodeType() return eLightNode; } -void CLightNode::AddToRenderer(CRenderer *pRenderer) +void CLightNode::AddToRenderer(CRenderer *pRenderer, const CFrustumPlanes& frustum) { + if (!frustum.BoxInFrustum(AABox())) return; + pRenderer->AddOpaqueMesh(this, 0, CAABox(mPosition + 0.5f, mPosition - 0.5f), eDrawMesh); if (IsSelected()) diff --git a/Scene/CLightNode.h b/Scene/CLightNode.h index f08576d8..86cb310e 100644 --- a/Scene/CLightNode.h +++ b/Scene/CLightNode.h @@ -10,7 +10,7 @@ class CLightNode : public CSceneNode public: CLightNode(CSceneManager *pScene, CSceneNode *pParent = 0, CLight *Light = 0); ENodeType NodeType(); - void AddToRenderer(CRenderer *pRenderer); + void AddToRenderer(CRenderer *pRenderer, const CFrustumPlanes& frustum); void Draw(ERenderOptions Options); void DrawAsset(ERenderOptions Options, u32 asset); SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID, ERenderOptions options); diff --git a/Scene/CModelNode.cpp b/Scene/CModelNode.cpp index 653b1d8b..401c6f3b 100644 --- a/Scene/CModelNode.cpp +++ b/Scene/CModelNode.cpp @@ -16,9 +16,10 @@ ENodeType CModelNode::NodeType() return eModelNode; } -void CModelNode::AddToRenderer(CRenderer *pRenderer) +void CModelNode::AddToRenderer(CRenderer *pRenderer, const CFrustumPlanes& frustum) { if (!mpModel) return; + if (!frustum.BoxInFrustum(AABox())) return; if (!mpModel->HasTransparency(mActiveMatSet)) pRenderer->AddOpaqueMesh(this, 0, AABox(), eDrawMesh); @@ -29,10 +30,13 @@ void CModelNode::AddToRenderer(CRenderer *pRenderer) for (u32 iSurf = 0; iSurf < SurfaceCount; iSurf++) { - if (!mpModel->IsSurfaceTransparent(iSurf, mActiveMatSet)) - pRenderer->AddOpaqueMesh(this, iSurf, mpModel->GetSurfaceAABox(iSurf).Transformed(Transform()), eDrawAsset); - else - pRenderer->AddTransparentMesh(this, iSurf, mpModel->GetSurfaceAABox(iSurf).Transformed(Transform()), eDrawAsset); + if (frustum.BoxInFrustum(mpModel->GetSurfaceAABox(iSurf).Transformed(Transform()))) + { + if (!mpModel->IsSurfaceTransparent(iSurf, mActiveMatSet)) + pRenderer->AddOpaqueMesh(this, iSurf, mpModel->GetSurfaceAABox(iSurf).Transformed(Transform()), eDrawAsset); + else + pRenderer->AddTransparentMesh(this, iSurf, mpModel->GetSurfaceAABox(iSurf).Transformed(Transform()), eDrawAsset); + } } } diff --git a/Scene/CModelNode.h b/Scene/CModelNode.h index a36d7fbb..ad973c73 100644 --- a/Scene/CModelNode.h +++ b/Scene/CModelNode.h @@ -16,7 +16,7 @@ public: explicit CModelNode(CSceneManager *pScene, CSceneNode *pParent = 0, CModel *pModel = 0); virtual ENodeType NodeType(); - virtual void AddToRenderer(CRenderer *pRenderer); + virtual void AddToRenderer(CRenderer *pRenderer, const CFrustumPlanes& frustum); virtual void Draw(ERenderOptions Options); virtual void DrawAsset(ERenderOptions Options, u32 asset); virtual void RayAABoxIntersectTest(CRayCollisionTester &Tester); diff --git a/Scene/CRootNode.h b/Scene/CRootNode.h index cddbaa84..0c011e6f 100644 --- a/Scene/CRootNode.h +++ b/Scene/CRootNode.h @@ -15,7 +15,7 @@ public: return eRootNode; } - inline void AddToRenderer(CRenderer *) {} + inline void AddToRenderer(CRenderer *, const CFrustumPlanes&) {} inline void Draw(ERenderOptions) {} inline void DrawAsset(ERenderOptions, u32) {} inline void RayAABoxIntersectTest(CRayCollisionTester &) {} diff --git a/Scene/CScriptNode.cpp b/Scene/CScriptNode.cpp index 7b7c1869..601fc676 100644 --- a/Scene/CScriptNode.cpp +++ b/Scene/CScriptNode.cpp @@ -92,48 +92,58 @@ std::string CScriptNode::PrefixedName() const return "[" + mpInstance->Template()->TemplateName() + "] " + mpInstance->InstanceName(); } -void CScriptNode::AddToRenderer(CRenderer *pRenderer) +void CScriptNode::AddToRenderer(CRenderer *pRenderer, const CFrustumPlanes& frustum) { if (!mpInstance) return; + ERenderOptions options = pRenderer->RenderOptions(); if (options & eDrawObjectCollision) - mpCollisionNode->AddToRenderer(pRenderer); + mpCollisionNode->AddToRenderer(pRenderer, frustum); if (options & eDrawObjects) { - if (!mpActiveModel) - pRenderer->AddOpaqueMesh(this, 0, AABox(), eDrawMesh); - - else + if (frustum.BoxInFrustum(AABox())) { - if (!mpActiveModel->IsBuffered()) - mpActiveModel->BufferGL(); - - if (!mpActiveModel->HasTransparency(0)) + if (!mpActiveModel) pRenderer->AddOpaqueMesh(this, 0, AABox(), eDrawMesh); else { - u32 SubmeshCount = mpActiveModel->GetSurfaceCount(); + if (!mpActiveModel->IsBuffered()) + mpActiveModel->BufferGL(); - for (u32 s = 0; s < SubmeshCount; s++) + if (!mpActiveModel->HasTransparency(0)) + pRenderer->AddOpaqueMesh(this, 0, AABox(), eDrawMesh); + + else { - if (!mpActiveModel->IsSurfaceTransparent(s, 0)) - pRenderer->AddOpaqueMesh(this, s, mpActiveModel->GetSurfaceAABox(s).Transformed(Transform()), eDrawAsset); - else - pRenderer->AddTransparentMesh(this, s, mpActiveModel->GetSurfaceAABox(s).Transformed(Transform()), eDrawAsset); + u32 SubmeshCount = mpActiveModel->GetSurfaceCount(); + + for (u32 s = 0; s < SubmeshCount; s++) + { + if (frustum.BoxInFrustum(mpActiveModel->GetSurfaceAABox(s).Transformed(Transform()))) + { + if (!mpActiveModel->IsSurfaceTransparent(s, 0)) + pRenderer->AddOpaqueMesh(this, s, mpActiveModel->GetSurfaceAABox(s).Transformed(Transform()), eDrawAsset); + else + pRenderer->AddTransparentMesh(this, s, mpActiveModel->GetSurfaceAABox(s).Transformed(Transform()), eDrawAsset); + } + } } } + } } - if (IsSelected() && (options & ((ERenderOptions) (eDrawObjects | eDrawObjectCollision))) != 0) + if (IsSelected()) { + // Script nodes always draw their selections regardless of frustum planes + // in order to ensure that script connection lines don't get improperly culled. pRenderer->AddOpaqueMesh(this, 0, AABox(), eDrawSelection); if (mHasVolumePreview) - mpVolumePreviewNode->AddToRenderer(pRenderer); + mpVolumePreviewNode->AddToRenderer(pRenderer, frustum); } } diff --git a/Scene/CScriptNode.h b/Scene/CScriptNode.h index e51b5a72..351d968e 100644 --- a/Scene/CScriptNode.h +++ b/Scene/CScriptNode.h @@ -21,7 +21,7 @@ public: CScriptNode(CSceneManager *pScene, CSceneNode *pParent = 0, CScriptObject *pObject = 0); ENodeType NodeType(); std::string PrefixedName() const; - void AddToRenderer(CRenderer *pRenderer); + void AddToRenderer(CRenderer *pRenderer, const CFrustumPlanes& frustum); void Draw(ERenderOptions Options); void DrawAsset(ERenderOptions Options, u32 Asset); void DrawSelection(); diff --git a/Scene/CStaticNode.cpp b/Scene/CStaticNode.cpp index 28535b12..44d91ca3 100644 --- a/Scene/CStaticNode.cpp +++ b/Scene/CStaticNode.cpp @@ -19,10 +19,11 @@ ENodeType CStaticNode::NodeType() return eStaticNode; } -void CStaticNode::AddToRenderer(CRenderer *pRenderer) +void CStaticNode::AddToRenderer(CRenderer *pRenderer, const CFrustumPlanes& frustum) { if (!mpModel) return; if (mpModel->IsOccluder()) return; + if (!frustum.BoxInFrustum(AABox())) return; if (!mpModel->IsTransparent()) pRenderer->AddOpaqueMesh(this, 0, AABox(), eDrawMesh); @@ -32,7 +33,8 @@ void CStaticNode::AddToRenderer(CRenderer *pRenderer) u32 sm_count = mpModel->GetSurfaceCount(); for (u32 s = 0; s < sm_count; s++) { - pRenderer->AddTransparentMesh(this, s, mpModel->GetSurfaceAABox(s).Transformed(Transform()), eDrawAsset); + if (frustum.BoxInFrustum(mpModel->GetSurfaceAABox(s).Transformed(Transform()))) + pRenderer->AddTransparentMesh(this, s, mpModel->GetSurfaceAABox(s).Transformed(Transform()), eDrawAsset); } } diff --git a/Scene/CStaticNode.h b/Scene/CStaticNode.h index 6ca1c60a..e7117c6b 100644 --- a/Scene/CStaticNode.h +++ b/Scene/CStaticNode.h @@ -11,7 +11,7 @@ class CStaticNode : public CSceneNode public: CStaticNode(CSceneManager *pScene, CSceneNode *pParent = 0, CStaticModel *pModel = 0); ENodeType NodeType(); - void AddToRenderer(CRenderer *pRenderer); + void AddToRenderer(CRenderer *pRenderer, const CFrustumPlanes& frustum); void Draw(ERenderOptions Options); void DrawAsset(ERenderOptions Options, u32 asset); void RayAABoxIntersectTest(CRayCollisionTester &Tester); diff --git a/UI/CGizmo.cpp b/UI/CGizmo.cpp index 2a0d8fee..61bba5b8 100644 --- a/UI/CGizmo.cpp +++ b/UI/CGizmo.cpp @@ -42,7 +42,7 @@ CGizmo::~CGizmo() { } -void CGizmo::AddToRenderer(CRenderer *pRenderer) +void CGizmo::AddToRenderer(CRenderer *pRenderer, const CFrustumPlanes&) { // Transform is updated every frame even if the user doesn't modify the gizmo // in order to account for scale changes based on camera distance diff --git a/UI/CGizmo.h b/UI/CGizmo.h index 762b9ae1..dc55502b 100644 --- a/UI/CGizmo.h +++ b/UI/CGizmo.h @@ -124,7 +124,7 @@ public: CGizmo(); ~CGizmo(); - void AddToRenderer(CRenderer *pRenderer); + void AddToRenderer(CRenderer *pRenderer, const CFrustumPlanes& frustum); void DrawAsset(ERenderOptions options, u32 asset); void IncrementSize(); diff --git a/UI/CModelEditorViewport.cpp b/UI/CModelEditorViewport.cpp index 820239ba..7525b86c 100644 --- a/UI/CModelEditorViewport.cpp +++ b/UI/CModelEditorViewport.cpp @@ -49,7 +49,7 @@ void CModelEditorViewport::Paint() else if (mMode == eDrawMesh) { CDrawUtil::DrawGrid(); - mpModelNode->AddToRenderer(mpRenderer); + mpModelNode->AddToRenderer(mpRenderer, mCamera.FrustumPlanes()); mpRenderer->RenderBuckets(mCamera); } diff --git a/UI/CSceneViewport.cpp b/UI/CSceneViewport.cpp index 0309db66..0d0f30e7 100644 --- a/UI/CSceneViewport.cpp +++ b/UI/CSceneViewport.cpp @@ -135,7 +135,7 @@ void CSceneViewport::Paint() } mCamera.LoadMatrices(); - mpScene->AddSceneToRenderer(mpRenderer); + mpScene->AddSceneToRenderer(mpRenderer, mCamera); mpRenderer->RenderBuckets(mCamera); mpRenderer->RenderBloom(); @@ -146,7 +146,7 @@ void CSceneViewport::Paint() mpRenderer->ClearDepthBuffer(); pGizmo->UpdateForCamera(mCamera); - pGizmo->AddToRenderer(mpRenderer); + pGizmo->AddToRenderer(mpRenderer, mCamera.FrustumPlanes()); mpRenderer->RenderBuckets(mCamera); } diff --git a/UI/CWorldEditorWindow.cpp b/UI/CWorldEditorWindow.cpp index f24cd883..9e13def9 100644 --- a/UI/CWorldEditorWindow.cpp +++ b/UI/CWorldEditorWindow.cpp @@ -89,7 +89,7 @@ void CWorldEditorWindow::PaintViewport(double DeltaTime) mCamera.ProcessKeyInput((EKeyInputs) mViewportKeysPressed, DeltaTime); mCamera.LoadMatrices(); mpRenderer->BeginFrame(); - mpSceneManager->AddSceneToRenderer(mpRenderer); + mpSceneManager->AddSceneToRenderer(mpRenderer, mCamera); if (mShouldDrawSky)