Implemented frustum culling

This commit is contained in:
parax0
2015-09-27 16:02:53 -06:00
parent a284cebe64
commit d8ac185656
25 changed files with 229 additions and 50 deletions

View File

@@ -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;
}

View File

@@ -1,6 +1,7 @@
#ifndef CCAMERA_H
#define CCAMERA_H
#include "CFrustumPlanes.h"
#include <Common/CAABox.h>
#include <Common/CMatrix4f.h>
#include <Common/CRay.h>
@@ -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

98
Core/CFrustumPlanes.cpp Normal file
View File

@@ -0,0 +1,98 @@
#include "CFrustumPlanes.h"
#include <Common/Math.h>
#include <Common/types.h>
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;
}

30
Core/CFrustumPlanes.h Normal file
View File

@@ -0,0 +1,30 @@
#ifndef CFRUSTUMPLANES_H
#define CFRUSTUMPLANES_H
#include <Common/CAABox.h>
#include <Common/CPlane.h>
#include <Common/CVector3f.h>
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

View File

@@ -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());
}
}

View File

@@ -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);

View File

@@ -4,6 +4,7 @@
#include "ERenderOptions.h"
#include <Common/CAABox.h>
#include <Common/types.h>
#include <Core/CFrustumPlanes.h>
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() {}