Added the ability to do accurate raycasts against billboards

This commit is contained in:
parax0 2015-11-25 14:37:34 -07:00
parent 1fedc8f616
commit 373426a98f
39 changed files with 431 additions and 176 deletions

View File

@ -1,7 +1,8 @@
#include "CQuaternion.h"
#include <cmath>
#include <math.h>
#include <Common/Math.h>
#include "Math.h"
#include "CMatrix4f.h"
CQuaternion::CQuaternion()
{
@ -137,5 +138,58 @@ CQuaternion CQuaternion::FromAxisAngle(float angle, CVector3f axis)
}
CQuaternion CQuaternion::FromRotationMatrix(const CMatrix4f& RotMtx)
{
// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/
CQuaternion out;
float trace = RotMtx[0][0] + RotMtx[1][1] + RotMtx[2][2];
if (trace > 0.f)
{
float s = Math::Sqrt(trace + 1.f) * 2; // s = 4*w
out.w = 0.25f * s;
out.x = (RotMtx[2][1] - RotMtx[1][2]) / s;
out.y = (RotMtx[0][2] - RotMtx[2][0]) / s;
out.z = (RotMtx[1][0] - RotMtx[0][1]) / s;
}
else if ((RotMtx[0][0] > RotMtx[1][1]) && (RotMtx[0][0] > RotMtx[2][2]))
{
float s = Math::Sqrt(1.f + RotMtx[0][0] - RotMtx[1][1] - RotMtx[2][2]) * 2; // s = 4*x
out.w = (RotMtx[2][1] - RotMtx[1][2]) / s;
out.x = 0.25f * s;
out.y = (RotMtx[0][1] + RotMtx[1][0]) / s;
out.z = (RotMtx[0][2] + RotMtx[2][0]) / s;
}
else if (RotMtx[1][1] > RotMtx[2][2]) {
float s = Math::Sqrt(1.f + RotMtx[1][1] - RotMtx[0][0] - RotMtx[2][2]) * 2; // s = 4*y
out.w = (RotMtx[0][2] - RotMtx[2][0]) / s;
out.x = (RotMtx[0][1] + RotMtx[1][0]) / s;
out.y = 0.25f * s;
out.z = (RotMtx[1][2] + RotMtx[2][1]) / s;
}
else {
float s = Math::Sqrt(1.f + RotMtx[2][2] - RotMtx[0][0] - RotMtx[1][1]) * 2; // S=4*qz
out.w = (RotMtx[1][0] - RotMtx[0][1]) / s;
out.x = (RotMtx[0][2] + RotMtx[2][0]) / s;
out.y = (RotMtx[1][2] + RotMtx[2][1]) / s;
out.z = 0.25f * s;
}
return out;
}
CQuaternion CQuaternion::FromAxes(const CVector3f& X, const CVector3f& Y, const CVector3f& Z)
{
CMatrix4f RotMtx(X.x, Y.x, Z.x, 0.f,
X.y, Y.y, Z.y, 0.f,
X.z, Y.z, Z.z, 0.f,
0.f, 0.f, 0.f, 1.f);
return CQuaternion::FromRotationMatrix(RotMtx);
}
CQuaternion CQuaternion::skIdentity = CQuaternion(1.f, 0.f, 0.f, 0.f);
CQuaternion CQuaternion::skZero = CQuaternion(0.f, 0.f, 0.f, 0.f);

View File

@ -25,6 +25,8 @@ public:
// Static
static CQuaternion FromEuler(CVector3f euler);
static CQuaternion FromAxisAngle(float angle, CVector3f axis);
static CQuaternion FromRotationMatrix(const CMatrix4f& RotMtx);
static CQuaternion FromAxes(const CVector3f& X, const CVector3f& Y, const CVector3f& Z);
static CQuaternion skIdentity;
static CQuaternion skZero;

View File

@ -19,7 +19,7 @@ void CRayCollisionTester::AddNode(CSceneNode *pNode, u32 AssetIndex, float Dista
Intersection.Distance = Distance;
}
SRayIntersection CRayCollisionTester::TestNodes(ERenderOptions options)
SRayIntersection CRayCollisionTester::TestNodes(const SViewInfo& ViewInfo)
{
// Sort nodes by distance from ray
mBoxIntersectList.sort(
@ -43,7 +43,7 @@ SRayIntersection CRayCollisionTester::TestNodes(ERenderOptions options)
// Otherwise, more intersection tests...
CSceneNode *pNode = Intersection.pNode;
SRayIntersection MidResult = pNode->RayNodeIntersectTest(mRay, Intersection.AssetIndex, options);
SRayIntersection MidResult = pNode->RayNodeIntersectTest(mRay, Intersection.AssetIndex, ViewInfo);
if (MidResult.Hit)
{

View File

@ -6,7 +6,7 @@
#include "CVector3f.h"
#include "SRayIntersection.h"
#include "types.h"
#include <Core/ERenderOptions.h>
#include <Core/SViewInfo.h>
#include <list>
@ -22,7 +22,7 @@ public:
~CRayCollisionTester();
const CRay& Ray() const;
void AddNode(CSceneNode *pNode, u32 AssetIndex, float Distance);
SRayIntersection TestNodes(ERenderOptions options);
SRayIntersection TestNodes(const SViewInfo& ViewInfo);
};
inline const CRay& CRayCollisionTester::Ray() const

View File

@ -15,6 +15,11 @@ float Pow(float Base, float Exponent)
return pow(Base, Exponent);
}
float Sqrt(float v)
{
return sqrtf(v);
}
float Distance(const CVector3f& A, const CVector3f& B)
{
return sqrtf( Pow(B.x - A.x, 2.f) +

View File

@ -15,6 +15,8 @@ float Abs(float v);
float Pow(float Base, float Exponent);
float Sqrt(float v);
float Distance(const CVector3f& A, const CVector3f& B);
float DegreesToRadians(float deg);

View File

@ -163,13 +163,6 @@ void CCamera::LoadMatrices()
CGraphics::UpdateMVPBlock();
}
void CCamera::LoadRotationOnlyMatrices()
{
CGraphics::sMVPBlock.ViewMatrix = RotationOnlyViewMatrix();
CGraphics::sMVPBlock.ProjectionMatrix = ProjectionMatrix();
CGraphics::UpdateMVPBlock();
}
// ************ GETTERS ************
CVector3f CCamera::Position() const
{
@ -181,6 +174,16 @@ CVector3f CCamera::Direction() const
return mDirection;
}
CVector3f CCamera::UpVector() const
{
return mUpVector;
}
CVector3f CCamera::RightVector() const
{
return mRightVector;
}
float CCamera::Yaw() const
{
return mYaw;
@ -204,17 +207,6 @@ const CMatrix4f& CCamera::ViewMatrix()
return mCachedViewMatrix;
}
CMatrix4f CCamera::RotationOnlyViewMatrix()
{
if (mViewOutdated)
CalculateView();
return CMatrix4f(mCachedViewMatrix[0][0], mCachedViewMatrix[0][1], mCachedViewMatrix[0][2], 0.f,
mCachedViewMatrix[1][0], mCachedViewMatrix[1][1], mCachedViewMatrix[1][2], 0.f,
mCachedViewMatrix[2][0], mCachedViewMatrix[2][1], mCachedViewMatrix[2][2], 0.f,
mCachedViewMatrix[3][0], mCachedViewMatrix[3][1], mCachedViewMatrix[3][2], 1.f);
}
const CMatrix4f& CCamera::ProjectionMatrix()
{
if (mProjectionOutdated)
@ -295,6 +287,14 @@ void CCamera::CalculateDirection()
cos(mPitch) * sin(mYaw),
sin(mPitch)
);
mRightVector = CVector3f(
cos(mYaw - Math::skHalfPi),
sin(mYaw - Math::skHalfPi),
0
);
mUpVector = mRightVector.Cross(mDirection);
}
void CCamera::CalculateView()
@ -302,17 +302,9 @@ void CCamera::CalculateView()
// todo: don't use glm
CalculateDirection();
CVector3f Right(
cos(mYaw - Math::skHalfPi),
sin(mYaw - Math::skHalfPi),
0
);
CVector3f Up = Right.Cross(mDirection);
glm::vec3 glmpos(mPosition.x, mPosition.y, mPosition.z);
glm::vec3 glmdir(mDirection.x, mDirection.y, mDirection.z);
glm::vec3 glmup(Up.x, Up.y, Up.z);
glm::vec3 glmup(mUpVector.x, mUpVector.y, mUpVector.z);
mCachedViewMatrix = CMatrix4f::FromGlmMat4(glm::lookAt(glmpos, glmpos + glmdir, glmup)).Transpose();
mViewOutdated = false;
}

View File

@ -21,6 +21,8 @@ class CCamera
ECameraMoveMode mMode;
CVector3f mPosition;
CVector3f mDirection;
CVector3f mRightVector;
CVector3f mUpVector;
float mAspectRatio;
float mYaw;
@ -48,16 +50,16 @@ public:
void ProcessMouseInput(EKeyInputs KeyFlags, EMouseInputs MouseFlags, float XMovement, float YMovement);
CRay CastRay(CVector2f DeviceCoords);
void LoadMatrices();
void LoadRotationOnlyMatrices();
// Getters
CVector3f Position() const;
CVector3f Direction() const;
CVector3f UpVector() const;
CVector3f RightVector() const;
float Yaw() const;
float Pitch() const;
float FieldOfView() const;
const CMatrix4f& ViewMatrix();
CMatrix4f RotationOnlyViewMatrix();
const CMatrix4f& ProjectionMatrix();
const CFrustumPlanes& FrustumPlanes();

View File

@ -24,7 +24,7 @@ void CRenderBucket::Add(const SRenderablePtr& ptr)
mSize++;
}
void CRenderBucket::Sort(CCamera& Camera)
void CRenderBucket::Sort(CCamera* pCamera)
{
struct {
CCamera *pCamera;
@ -39,7 +39,7 @@ void CRenderBucket::Sort(CCamera& Camera)
return (dotL > dotR);
}
} backToFront;
backToFront.pCamera = &Camera;
backToFront.pCamera = pCamera;
if (mSortType == BackToFront)
std::stable_sort(mRenderables.begin(), mRenderables.begin() + mSize, backToFront);

View File

@ -25,7 +25,7 @@ public:
CRenderBucket();
void SetSortType(ESortType Type);
void Add(const SRenderablePtr& ptr);
void Sort(CCamera& Camera);
void Sort(CCamera* pCamera);
void Clear();
void Draw(ERenderOptions Options);
};

View File

@ -54,7 +54,7 @@ void CRenderer::Init()
}
// ************ GETTERS/SETTERS ************
ERenderOptions CRenderer::RenderOptions()
ERenderOptions CRenderer::RenderOptions() const
{
return mOptions;
}
@ -159,11 +159,10 @@ void CRenderer::SetViewportSize(u32 Width, u32 Height)
}
// ************ RENDER ************
void CRenderer::RenderBuckets(CCamera& Camera)
void CRenderer::RenderBuckets(const SViewInfo& ViewInfo)
{
if (!mInitialized) Init();
mSceneFramebuffer.Bind();
//Camera.LoadMatrices();
// Set backface culling
if (mOptions & eEnableBackfaceCull) glEnable(GL_CULL_FACE);
@ -175,7 +174,7 @@ void CRenderer::RenderBuckets(CCamera& Camera)
mOpaqueBucket.Draw(mOptions);
mOpaqueBucket.Clear();
mTransparentBucket.Sort(Camera);
mTransparentBucket.Sort(ViewInfo.pCamera);
mTransparentBucket.Draw(mOptions);
mTransparentBucket.Clear();
}
@ -288,7 +287,7 @@ void CRenderer::RenderBloom()
glEnable(GL_DEPTH_TEST);
}
void CRenderer::RenderSky(CModel *pSkyboxModel, CCamera& Camera)
void CRenderer::RenderSky(CModel *pSkyboxModel, const SViewInfo& ViewInfo)
{
if (!mInitialized) Init();
if (!pSkyboxModel) return;
@ -302,7 +301,10 @@ void CRenderer::RenderSky(CModel *pSkyboxModel, CCamera& Camera)
CGraphics::UpdateVertexBlock();
CGraphics::UpdatePixelBlock();
CGraphics::UpdateLightBlock();
Camera.LoadRotationOnlyMatrices();
// Load rotation-only view matrix
CGraphics::sMVPBlock.ViewMatrix = ViewInfo.RotationOnlyViewMatrix;
CGraphics::UpdateMVPBlock();
glDepthRange(1.f, 1.f);
pSkyboxModel->Draw(mOptions, 0);

View File

@ -9,6 +9,7 @@
#include "ERenderOptions.h"
#include "ERenderCommand.h"
#include "SRenderablePtr.h"
#include "SViewInfo.h"
#include <Common/CAABox.h>
#include <Common/CColor.h>
#include <Common/CMatrix4f.h>
@ -53,7 +54,7 @@ public:
void Init();
// Getters/Setters
ERenderOptions RenderOptions();
ERenderOptions RenderOptions() const;
void ToggleWorld(bool b);
void ToggleWorldCollision(bool b);
void ToggleObjects(bool b);
@ -71,9 +72,9 @@ public:
void SetViewportSize(u32 Width, u32 Height);
// Render
void RenderBuckets(CCamera& Camera);
void RenderBuckets(const SViewInfo& ViewInfo);
void RenderBloom();
void RenderSky(CModel *pSkyboxModel, CCamera& Camera);
void RenderSky(CModel *pSkyboxModel, const SViewInfo& ViewInfo);
void AddOpaqueMesh(IRenderable *pRenderable, u32 AssetID, CAABox& AABox, ERenderCommand Command);
void AddTransparentMesh(IRenderable *pRenderable, u32 AssetID, CAABox& AABox, ERenderCommand Command);
void BeginFrame();

View File

@ -215,48 +215,50 @@ void CSceneManager::ClearScene()
mNodeCount = 0;
}
void CSceneManager::AddSceneToRenderer(CRenderer *pRenderer, CCamera& camera)
void CSceneManager::AddSceneToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo)
{
ERenderOptions options = pRenderer->RenderOptions();
ERenderOptions Options = pRenderer->RenderOptions();
if (options & eDrawWorld)
if (Options & eDrawWorld)
{
for (u32 n = 0; n < mModelNodes.size(); n++)
if (mModelNodes[n]->IsVisible())
mModelNodes[n]->AddToRenderer(pRenderer, camera.FrustumPlanes());
mModelNodes[n]->AddToRenderer(pRenderer, ViewInfo);
for (u32 n = 0; n < mStaticNodes.size(); n++)
if (mStaticNodes[n]->IsVisible())
mStaticNodes[n]->AddToRenderer(pRenderer, camera.FrustumPlanes());
mStaticNodes[n]->AddToRenderer(pRenderer, ViewInfo);
}
if (options & eDrawWorldCollision)
if (Options & eDrawWorldCollision)
{
for (u32 n = 0; n < mCollisionNodes.size(); n++)
if (mCollisionNodes[n]->IsVisible())
mCollisionNodes[n]->AddToRenderer(pRenderer, camera.FrustumPlanes());
mCollisionNodes[n]->AddToRenderer(pRenderer, ViewInfo);
}
if (options & eDrawLights)
if (Options & eDrawLights)
{
for (u32 n = 0; n < mLightNodes.size(); n++)
if (mLightNodes[n]->IsVisible())
mLightNodes[n]->AddToRenderer(pRenderer, camera.FrustumPlanes());
mLightNodes[n]->AddToRenderer(pRenderer, ViewInfo);
}
if ((options & eDrawObjects) || (options & eDrawObjectCollision))
if ((Options & eDrawObjects) || (Options & eDrawObjectCollision))
{
for (u32 n = 0; n < mScriptNodes.size(); n++)
if (mScriptNodes[n]->IsVisible())
mScriptNodes[n]->AddToRenderer(pRenderer, camera.FrustumPlanes());
mScriptNodes[n]->AddToRenderer(pRenderer, ViewInfo);
}
}
SRayIntersection CSceneManager::SceneRayCast(const CRay& Ray, ERenderOptions renderOptions)
SRayIntersection CSceneManager::SceneRayCast(const CRay& Ray, const SViewInfo& ViewInfo)
{
// Terribly hacky stuff to avoid having tons of redundant code
// because I'm too lazy to rewrite CSceneManager right now and fix it
// (I'm probably going to do it soon...)
ERenderOptions renderOptions = ViewInfo.pRenderer->RenderOptions();
std::vector<CSceneNode*> *pNodeVectors[5] = {
reinterpret_cast<std::vector<CSceneNode*>*>(&mModelNodes),
reinterpret_cast<std::vector<CSceneNode*>*>(&mStaticNodes),
@ -283,7 +285,7 @@ SRayIntersection CSceneManager::SceneRayCast(const CRay& Ray, ERenderOptions ren
vec[iNode]->RayAABoxIntersectTest(Tester);
}
return Tester.TestNodes(renderOptions);
return Tester.TestNodes(ViewInfo);
}
void CSceneManager::PickEnvironmentObjects()

View File

@ -7,6 +7,7 @@
#include "CAreaAttributes.h"
#include "CRenderer.h"
#include "SViewInfo.h"
#include <Common/SRayIntersection.h>
#include <Common/types.h>
#include <Scene/CSceneNode.h>
@ -57,8 +58,8 @@ public:
void SetActiveArea(CGameArea *_area);
void SetActiveWorld(CWorld *_world);
void ClearScene();
void AddSceneToRenderer(CRenderer *pRenderer, CCamera& camera);
SRayIntersection SceneRayCast(const CRay& Ray, ERenderOptions renderOptions);
void AddSceneToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo);
SRayIntersection SceneRayCast(const CRay& Ray, const SViewInfo& ViewInfo);
void PickEnvironmentObjects();
CScriptNode* ScriptNodeByID(u32 InstanceID);
CScriptNode* NodeForObject(CScriptObject *pObj);

View File

@ -2,9 +2,8 @@
#define IRENDERABLE_H
#include "ERenderOptions.h"
#include <Common/CAABox.h>
#include "SViewInfo.h"
#include <Common/types.h>
#include <Core/CFrustumPlanes.h>
class CRenderer;
@ -13,7 +12,7 @@ class IRenderable
public:
IRenderable() {}
virtual ~IRenderable() {}
virtual void AddToRenderer(CRenderer* pRenderer, const CFrustumPlanes& frustum) = 0;
virtual void AddToRenderer(CRenderer* pRenderer, const SViewInfo& ViewInfo) = 0;
virtual void Draw(ERenderOptions /*options*/) {}
virtual void DrawAsset(ERenderOptions /*options*/, u32 /*asset*/) {}
virtual void DrawSelection() {}

19
Core/SViewInfo.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef SVIEWINFO
#define SVIEWINFO
#include "CFrustumPlanes.h"
#include <Common/CMatrix4f.h>
#include <Common/CRay.h>
struct SViewInfo
{
class CSceneManager *pScene;
class CRenderer *pRenderer;
class CCamera *pCamera;
CFrustumPlanes ViewFrustum;
CMatrix4f RotationOnlyViewMatrix;
};
#endif // SVIEWINFO

View File

@ -113,7 +113,6 @@ SOURCES += \
Resource/model/SSurface.cpp \
Common/CRayCollisionTester.cpp \
Common/Math.cpp \
Scene/CBoundingBoxNode.cpp \
Core/Log.cpp \
Common/CVector2i.cpp \
UI/CNodeSelection.cpp \
@ -273,7 +272,6 @@ HEADERS += \
Common/CRayCollisionTester.h \
Scene/ENodeType.h \
Common/Math.h \
Scene/CBoundingBoxNode.h \
Core/Log.h \
Scene/CRootNode.h \
Common/CVector2i.h \
@ -321,7 +319,8 @@ HEADERS += \
UI/WAnimParamsEditor.h \
Resource/CCollisionMeshGroup.h \
Core/CFrustumPlanes.h \
Core/CLightParameters.h
Core/CLightParameters.h \
Core/SViewInfo.h
FORMS += \
UI/CStartWindow.ui \

View File

@ -152,6 +152,49 @@ void CTexture::Resize(u32 Width, u32 Height)
}
}
float CTexture::ReadTexelAlpha(const CVector2f& TexCoord)
{
// todo: support texel formats other than DXT1
// DXT1 is definitely the most complicated one anyway; try reusing CTextureDecoder functions for other formats
u32 TexelX = (u32) ((mWidth - 1) * TexCoord.x);
u32 TexelY = (u32) ((mHeight - 1) * (1.f - fmodf(TexCoord.y, 1.f)));
if (mTexelFormat == eDXT1 && mBufferExists)
{
CMemoryInStream Buffer(mImgDataBuffer, mImgDataSize, IOUtil::SystemEndianness);
// 8 bytes per 4x4 16-pixel block, left-to-right top-to-bottom
u32 BlockIdxX = TexelX / 4;
u32 BlockIdxY = TexelY / 4;
u32 BlocksPerRow = mWidth / 4;
u32 BufferPos = (8 * BlockIdxX) + (8 * BlockIdxY * BlocksPerRow);
Buffer.Seek(BufferPos, SEEK_SET);
u16 PaletteA = Buffer.ReadShort();
u16 PaletteB = Buffer.ReadShort();
if (PaletteA > PaletteB)
{
// No palette colors have alpha
return 1.f;
}
// We only care about alpha, which is only present on palette index 3.
// We don't need to calculate/decode the actual palette colors.
u32 BlockCol = (TexelX & 0xF) / 4;
u32 BlockRow = (TexelY & 0xF) / 4;
Buffer.Seek(BlockRow, SEEK_CUR);
u8 Row = Buffer.ReadByte();
u8 Shift = (u8) (6 - (BlockCol * 2));
u8 PaletteIndex = (Row >> Shift) & 0x3;
return (PaletteIndex == 3 ? 0.f : 1.f);
}
return 1.f;
}
bool CTexture::WriteDDS(COutputStream& out)
{
if (!out.IsValid()) return false;

View File

@ -2,6 +2,7 @@
#define CTEXTURE_H
#include <Common/types.h>
#include <Common/CVector2f.h>
#include <FileIO/FileIO.h>
#include <gl/glew.h>
#include "CResource.h"
@ -35,6 +36,7 @@ public:
bool BufferGL();
void Bind(u32 GLTextureUnit);
void Resize(u32 Width, u32 Height);
float ReadTexelAlpha(const CVector2f& TexCoord);
bool WriteDDS(COutputStream& out);
// Getters

View File

@ -1,12 +0,0 @@
#include "CBoundingBoxNode.h"
CBoundingBoxNode::CBoundingBoxNode()
{
}
CBoundingBoxNode::~CBoundingBoxNode()
{
}

View File

@ -1,16 +0,0 @@
#ifndef CBOUNDINGBOXNODE_H
#define CBOUNDINGBOXNODE_H
#include "CSceneNode.h"
class CBoundingBoxNode
{
CColor mColor;
public:
CBoundingBoxNode();
~CBoundingBoxNode();
};
#endif // CBOUNDINGBOXNODE_H

View File

@ -15,10 +15,10 @@ ENodeType CCollisionNode::NodeType()
return eCollisionNode;
}
void CCollisionNode::AddToRenderer(CRenderer *pRenderer, const CFrustumPlanes& frustum)
void CCollisionNode::AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo)
{
if (!mpCollision) return;
if (!frustum.BoxInFrustum(AABox())) return;
if (!ViewInfo.ViewFrustum.BoxInFrustum(AABox())) return;
pRenderer->AddOpaqueMesh(this, 0, AABox(), eDrawMesh);
@ -47,7 +47,7 @@ void CCollisionNode::DrawAsset(ERenderOptions /*Options*/, u32 /*asset*/)
{
}
SRayIntersection CCollisionNode::RayNodeIntersectTest(const CRay& /*Ray*/, u32 /*AssetID*/, ERenderOptions /*options*/)
SRayIntersection CCollisionNode::RayNodeIntersectTest(const CRay& /*Ray*/, u32 /*AssetID*/, const SViewInfo& /*ViewInfo*/)
{
// todo
SRayIntersection Result;

View File

@ -12,10 +12,10 @@ class CCollisionNode : public CSceneNode
public:
CCollisionNode(CSceneManager *pScene, CSceneNode *pParent = 0, CCollisionMeshGroup *pCollision = 0);
ENodeType NodeType();
void AddToRenderer(CRenderer *pRenderer, const CFrustumPlanes& frustumPlanes);
void AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo);
void Draw(ERenderOptions Options);
void DrawAsset(ERenderOptions Options, u32 asset);
SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID, ERenderOptions options);
SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID, const SViewInfo& ViewInfo);
void SetCollision(CCollisionMeshGroup *pCollision);
};

View File

@ -1,4 +1,5 @@
#include "CLightNode.h"
#include <Common/Math.h>
#include <Core/CDrawUtil.h>
#include <Core/CGraphics.h>
#include <Core/CRenderer.h>
@ -24,16 +25,16 @@ ENodeType CLightNode::NodeType()
return eLightNode;
}
void CLightNode::AddToRenderer(CRenderer *pRenderer, const CFrustumPlanes& frustum)
void CLightNode::AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo)
{
if (!frustum.BoxInFrustum(AABox())) return;
if (!ViewInfo.ViewFrustum.BoxInFrustum(AABox())) return;
pRenderer->AddOpaqueMesh(this, 0, CAABox(mPosition + 0.5f, mPosition - 0.5f), eDrawMesh);
}
void CLightNode::Draw(ERenderOptions /*Options*/)
{
CDrawUtil::DrawLightBillboard(mpLight->GetType(), mpLight->GetColor(), mPosition, mScale.xy() * CVector2f(0.75f), TintColor());
CDrawUtil::DrawLightBillboard(mpLight->GetType(), mpLight->GetColor(), mPosition, BillboardScale(), TintColor());
// Below commented-out code is for light radius visualization as a bounding box
/*float r = mLight->GetRadius();
@ -45,24 +46,86 @@ void CLightNode::DrawAsset(ERenderOptions /*Options*/, u32 /*asset*/)
{
}
SRayIntersection CLightNode::RayNodeIntersectTest(const CRay& Ray, u32 /*AssetID*/, ERenderOptions options)
void CLightNode::RayAABoxIntersectTest(CRayCollisionTester &Tester)
{
// Needs redo if I ever make these look like something other than boxes
bool allowBackfaces = ((options & eEnableBackfaceCull) == 0);
CVector2f BillScale = BillboardScale();
float ScaleXY = (BillScale.x > BillScale.y ? BillScale.x : BillScale.y);
if (!allowBackfaces && (AABox().IsPointInBox(Ray.Origin())))
return SRayIntersection(false, 0.f, nullptr, 0);
CAABox BillBox = CAABox(mPosition + CVector3f(-ScaleXY, -ScaleXY, -BillScale.y),
mPosition + CVector3f( ScaleXY, ScaleXY, BillScale.y));
std::pair<bool,float> BoxResult = AABox().IntersectsRay(Ray);
std::pair<bool,float> BoxResult = BillBox.IntersectsRay(Tester.Ray());
if (BoxResult.first) Tester.AddNode(this, 0, BoxResult.second);
}
if (BoxResult.first)
return SRayIntersection(true, BoxResult.second, this, 0);
SRayIntersection CLightNode::RayNodeIntersectTest(const CRay& Ray, u32 AssetID, const SViewInfo& ViewInfo)
{
// todo: come up with a better way to share this code between CScriptNode and CLightNode
SRayIntersection out;
out.pNode = this;
out.AssetIndex = AssetID;
CTexture *pBillboard = CDrawUtil::GetLightTexture(mpLight->GetType());
if (!pBillboard)
{
out.Hit = false;
return out;
}
// Step 1: check whether the ray intersects with the plane the billboard is on
CPlane BillboardPlane(-ViewInfo.pCamera->Direction(), mPosition);
std::pair<bool,float> PlaneTest = Math::RayPlaneIntersecton(Ray, BillboardPlane);
if (PlaneTest.first)
{
// Step 2: transform the hit point into the plane's local space
CVector3f PlaneHitPoint = Ray.PointOnRay(PlaneTest.second);
CVector3f RelHitPoint = PlaneHitPoint - mPosition;
CVector3f PlaneForward = -ViewInfo.pCamera->Direction();
CVector3f PlaneRight = -ViewInfo.pCamera->RightVector();
CVector3f PlaneUp = ViewInfo.pCamera->UpVector();
CQuaternion PlaneRot = CQuaternion::FromAxes(PlaneRight, PlaneForward, PlaneUp);
CVector3f RotatedHitPoint = PlaneRot.Inverse() * RelHitPoint;
CVector2f LocalHitPoint = RotatedHitPoint.xz() / BillboardScale();
// Step 3: check whether the transformed hit point is in the -1 to 1 range
if ((LocalHitPoint.x >= -1.f) && (LocalHitPoint.x <= 1.f) && (LocalHitPoint.y >= -1.f) && (LocalHitPoint.y <= 1.f))
{
// Step 4: look up the hit texel and check whether it's transparent or opaque
CVector2f TexCoord = (LocalHitPoint + CVector2f(1.f)) * 0.5f;
TexCoord.x = -TexCoord.x + 1.f;
float TexelAlpha = pBillboard->ReadTexelAlpha(TexCoord);
if (TexelAlpha < 0.25f)
out.Hit = false;
else
{
// It's opaque... we have a hit!
out.Hit = true;
out.Distance = PlaneTest.second;
}
}
else
out.Hit = false;
}
else
return SRayIntersection(false, 0.f, nullptr, 0);
out.Hit = false;
return out;
}
CLight* CLightNode::Light()
{
return mpLight;
}
CVector2f CLightNode::BillboardScale()
{
return mScale.xz() * 0.75f;
}

View File

@ -10,11 +10,13 @@ class CLightNode : public CSceneNode
public:
CLightNode(CSceneManager *pScene, CSceneNode *pParent = 0, CLight *Light = 0);
ENodeType NodeType();
void AddToRenderer(CRenderer *pRenderer, const CFrustumPlanes& frustum);
void AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo);
void Draw(ERenderOptions Options);
void DrawAsset(ERenderOptions Options, u32 asset);
SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID, ERenderOptions options);
void RayAABoxIntersectTest(CRayCollisionTester& Tester);
SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID, const SViewInfo& ViewInfo);
CLight* Light();
CVector2f BillboardScale();
};
#endif // CLIGHTNODE_H

View File

@ -16,10 +16,10 @@ ENodeType CModelNode::NodeType()
return eModelNode;
}
void CModelNode::AddToRenderer(CRenderer *pRenderer, const CFrustumPlanes& frustum)
void CModelNode::AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo)
{
if (!mpModel) return;
if (!frustum.BoxInFrustum(AABox())) return;
if (!ViewInfo.ViewFrustum.BoxInFrustum(AABox())) return;
if (!mpModel->HasTransparency(mActiveMatSet))
pRenderer->AddOpaqueMesh(this, 0, AABox(), eDrawMesh);
@ -30,7 +30,7 @@ void CModelNode::AddToRenderer(CRenderer *pRenderer, const CFrustumPlanes& frust
for (u32 iSurf = 0; iSurf < SurfaceCount; iSurf++)
{
if (frustum.BoxInFrustum(mpModel->GetSurfaceAABox(iSurf).Transformed(Transform())))
if (ViewInfo.ViewFrustum.BoxInFrustum(mpModel->GetSurfaceAABox(iSurf).Transformed(Transform())))
{
if (!mpModel->IsSurfaceTransparent(iSurf, mActiveMatSet))
pRenderer->AddOpaqueMesh(this, iSurf, mpModel->GetSurfaceAABox(iSurf).Transformed(Transform()), eDrawAsset);
@ -109,13 +109,14 @@ void CModelNode::RayAABoxIntersectTest(CRayCollisionTester &Tester)
}
}
SRayIntersection CModelNode::RayNodeIntersectTest(const CRay &Ray, u32 AssetID, ERenderOptions options)
SRayIntersection CModelNode::RayNodeIntersectTest(const CRay &Ray, u32 AssetID, const SViewInfo& ViewInfo)
{
SRayIntersection out;
out.pNode = this;
out.AssetIndex = AssetID;
CRay TransformedRay = Ray.Transformed(Transform().Inverse());
ERenderOptions options = ViewInfo.pRenderer->RenderOptions();
std::pair<bool,float> Result = mpModel->GetSurface(AssetID)->IntersectsRay(TransformedRay, ((options & eEnableBackfaceCull) == 0));
if (Result.first)

View File

@ -16,11 +16,11 @@ public:
explicit CModelNode(CSceneManager *pScene, CSceneNode *pParent = 0, CModel *pModel = 0);
virtual ENodeType NodeType();
virtual void AddToRenderer(CRenderer *pRenderer, const CFrustumPlanes& frustum);
virtual void AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo);
virtual void Draw(ERenderOptions Options);
virtual void DrawAsset(ERenderOptions Options, u32 asset);
virtual void RayAABoxIntersectTest(CRayCollisionTester &Tester);
virtual SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID, ERenderOptions options);
virtual SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID, const SViewInfo& ViewInfo);
void SetModel(CModel *pModel);
void SetMatSet(u32 MatSet);

View File

@ -15,12 +15,12 @@ public:
return eRootNode;
}
inline void AddToRenderer(CRenderer *, const CFrustumPlanes&) {}
inline void AddToRenderer(CRenderer *, const SViewInfo&) {}
inline void Draw(ERenderOptions) {}
inline void DrawAsset(ERenderOptions, u32) {}
inline void RayAABoxIntersectTest(CRayCollisionTester &) {}
inline SRayIntersection RayNodeIntersectTest(const CRay &, u32, ERenderOptions) {
inline SRayIntersection RayNodeIntersectTest(const CRay &, u32, const SViewInfo&) {
return SRayIntersection(false, 0.f, nullptr, 0);
}

View File

@ -58,7 +58,7 @@ public:
virtual void DrawAsset(ERenderOptions options, u32 asset) = 0;
virtual void DrawSelection();
virtual void RayAABoxIntersectTest(CRayCollisionTester& Tester);
virtual SRayIntersection RayNodeIntersectTest(const CRay& Ray, u32 AssetID, ERenderOptions options) = 0;
virtual SRayIntersection RayNodeIntersectTest(const CRay& Ray, u32 AssetID, const SViewInfo& ViewInfo) = 0;
virtual bool IsVisible() const;
void Unparent();

View File

@ -101,18 +101,18 @@ TString CScriptNode::PrefixedName() const
return "[" + mpInstance->Template()->TemplateName() + "] " + mpInstance->InstanceName();
}
void CScriptNode::AddToRenderer(CRenderer *pRenderer, const CFrustumPlanes& frustum)
void CScriptNode::AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo)
{
if (!mpInstance) return;
ERenderOptions options = pRenderer->RenderOptions();
if (options & eDrawObjectCollision)
mpCollisionNode->AddToRenderer(pRenderer, frustum);
mpCollisionNode->AddToRenderer(pRenderer, ViewInfo);
if (options & eDrawObjects)
{
if (frustum.BoxInFrustum(AABox()))
if (ViewInfo.ViewFrustum.BoxInFrustum(AABox()))
{
if (!mpActiveModel)
pRenderer->AddOpaqueMesh(this, 0, AABox(), eDrawMesh);
@ -131,7 +131,7 @@ void CScriptNode::AddToRenderer(CRenderer *pRenderer, const CFrustumPlanes& frus
for (u32 s = 0; s < SubmeshCount; s++)
{
if (frustum.BoxInFrustum(mpActiveModel->GetSurfaceAABox(s).Transformed(Transform())))
if (ViewInfo.ViewFrustum.BoxInFrustum(mpActiveModel->GetSurfaceAABox(s).Transformed(Transform())))
{
if (!mpActiveModel->IsSurfaceTransparent(s, 0))
pRenderer->AddOpaqueMesh(this, s, mpActiveModel->GetSurfaceAABox(s).Transformed(Transform()), eDrawAsset);
@ -152,7 +152,7 @@ void CScriptNode::AddToRenderer(CRenderer *pRenderer, const CFrustumPlanes& frus
pRenderer->AddOpaqueMesh(this, 0, AABox(), eDrawSelection);
if (mHasVolumePreview)
mpVolumePreviewNode->AddToRenderer(pRenderer, frustum);
mpVolumePreviewNode->AddToRenderer(pRenderer, ViewInfo);
}
}
@ -171,7 +171,7 @@ void CScriptNode::Draw(ERenderOptions Options)
// Draw billboard
else if (mpBillboard)
{
CDrawUtil::DrawBillboard(mpBillboard, mPosition, mScale.xy() * CVector2f(0.75f), TintColor());
CDrawUtil::DrawBillboard(mpBillboard, mPosition, BillboardScale(), TintColor());
}
// If no model or billboard, default to drawing a purple box
@ -243,27 +243,44 @@ void CScriptNode::RayAABoxIntersectTest(CRayCollisionTester &Tester)
return;
const CRay& Ray = Tester.Ray();
std::pair<bool,float> BoxResult = AABox().IntersectsRay(Ray);
if (BoxResult.first)
if (mpActiveModel || !mpBillboard)
{
if (mpActiveModel)
{
for (u32 iSurf = 0; iSurf < mpActiveModel->GetSurfaceCount(); iSurf++)
{
std::pair<bool,float> SurfResult = mpActiveModel->GetSurfaceAABox(iSurf).Transformed(Transform()).IntersectsRay(Ray);
std::pair<bool,float> BoxResult = AABox().IntersectsRay(Ray);
if (SurfResult.first)
Tester.AddNode(this, iSurf, SurfResult.second);
if (BoxResult.first)
{
if (mpActiveModel)
{
for (u32 iSurf = 0; iSurf < mpActiveModel->GetSurfaceCount(); iSurf++)
{
std::pair<bool,float> SurfResult = mpActiveModel->GetSurfaceAABox(iSurf).Transformed(Transform()).IntersectsRay(Ray);
if (SurfResult.first)
Tester.AddNode(this, iSurf, SurfResult.second);
}
}
else Tester.AddNode(this, 0, BoxResult.second);
}
else Tester.AddNode(this, 0, BoxResult.second);
}
else
{
// Because the billboard rotates a lot, expand the AABox on the X/Y axes to cover any possible orientation
CVector2f BillScale = BillboardScale();
float ScaleXY = (BillScale.x > BillScale.y ? BillScale.x : BillScale.y);
CAABox BillBox = CAABox(mPosition + CVector3f(-ScaleXY, -ScaleXY, -BillScale.y),
mPosition + CVector3f( ScaleXY, ScaleXY, BillScale.y));
std::pair<bool,float> BoxResult = BillBox.IntersectsRay(Ray);
if (BoxResult.first) Tester.AddNode(this, 0, BoxResult.second);
}
}
SRayIntersection CScriptNode::RayNodeIntersectTest(const CRay &Ray, u32 AssetID, ERenderOptions options)
SRayIntersection CScriptNode::RayNodeIntersectTest(const CRay& Ray, u32 AssetID, const SViewInfo& ViewInfo)
{
CRay TransformedRay = Ray.Transformed(Transform().Inverse());
ERenderOptions options = ViewInfo.pRenderer->RenderOptions();
SRayIntersection out;
out.pNode = this;
@ -271,20 +288,75 @@ SRayIntersection CScriptNode::RayNodeIntersectTest(const CRay &Ray, u32 AssetID,
if (options & eDrawObjects)
{
CModel *pModel = (mpActiveModel ? mpActiveModel : CDrawUtil::GetCubeModel());
std::pair<bool,float> Result = pModel->GetSurface(AssetID)->IntersectsRay(TransformedRay, ((options & eEnableBackfaceCull) == 0));
if (Result.first)
// Model test
if (mpActiveModel || !mpBillboard)
{
out.Hit = true;
CModel *pModel = (mpActiveModel ? mpActiveModel : CDrawUtil::GetCubeModel());
CVector3f HitPoint = TransformedRay.PointOnRay(Result.second);
CVector3f WorldHitPoint = Transform() * HitPoint;
out.Distance = Math::Distance(Ray.Origin(), WorldHitPoint);
CRay TransformedRay = Ray.Transformed(Transform().Inverse());
std::pair<bool,float> Result = pModel->GetSurface(AssetID)->IntersectsRay(TransformedRay, ((options & eEnableBackfaceCull) == 0));
if (Result.first)
{
out.Hit = true;
CVector3f HitPoint = TransformedRay.PointOnRay(Result.second);
CVector3f WorldHitPoint = Transform() * HitPoint;
out.Distance = Math::Distance(Ray.Origin(), WorldHitPoint);
}
else
out.Hit = false;
}
// Billboard test
// todo: come up with a better way to share this code between CScriptNode and CLightNode
else
out.Hit = false;
{
// Step 1: check whether the ray intersects with the plane the billboard is on
CPlane BillboardPlane(-ViewInfo.pCamera->Direction(), mPosition);
std::pair<bool,float> PlaneTest = Math::RayPlaneIntersecton(Ray, BillboardPlane);
if (PlaneTest.first)
{
// Step 2: transform the hit point into the plane's local space
CVector3f PlaneHitPoint = Ray.PointOnRay(PlaneTest.second);
CVector3f RelHitPoint = PlaneHitPoint - mPosition;
CVector3f PlaneForward = -ViewInfo.pCamera->Direction();
CVector3f PlaneRight = -ViewInfo.pCamera->RightVector();
CVector3f PlaneUp = ViewInfo.pCamera->UpVector();
CQuaternion PlaneRot = CQuaternion::FromAxes(PlaneRight, PlaneForward, PlaneUp);
CVector3f RotatedHitPoint = PlaneRot.Inverse() * RelHitPoint;
CVector2f LocalHitPoint = RotatedHitPoint.xz() / BillboardScale();
// Step 3: check whether the transformed hit point is in the -1 to 1 range
if ((LocalHitPoint.x >= -1.f) && (LocalHitPoint.x <= 1.f) && (LocalHitPoint.y >= -1.f) && (LocalHitPoint.y <= 1.f))
{
// Step 4: look up the hit texel and check whether it's transparent or opaque
CVector2f TexCoord = (LocalHitPoint + CVector2f(1.f)) * 0.5f;
TexCoord.x = -TexCoord.x + 1.f;
float TexelAlpha = mpBillboard->ReadTexelAlpha(TexCoord);
if (TexelAlpha < 0.25f)
out.Hit = false;
else
{
// It's opaque... we have a hit!
out.Hit = true;
out.Distance = PlaneTest.second;
}
}
else
out.Hit = false;
}
else
out.Hit = false;
}
}
else out.Hit = false;
@ -380,3 +452,9 @@ CAABox CScriptNode::PreviewVolumeAABox()
else
return mpVolumePreviewNode->AABox();
}
CVector2f CScriptNode::BillboardScale()
{
CVector2f out = (mpInstance->Template()->ScaleType() == CScriptTemplate::eScaleEnabled ? mScale.xz() : CVector2f(1.f));
return out * 0.5f;
}

View File

@ -26,18 +26,19 @@ public:
CScriptNode(CSceneManager *pScene, CSceneNode *pParent = 0, CScriptObject *pObject = 0);
ENodeType NodeType();
TString PrefixedName() const;
void AddToRenderer(CRenderer *pRenderer, const CFrustumPlanes& frustum);
void AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo);
void Draw(ERenderOptions Options);
void DrawAsset(ERenderOptions Options, u32 Asset);
void DrawSelection();
void RayAABoxIntersectTest(CRayCollisionTester &Tester);
SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID, ERenderOptions options);
SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID, const SViewInfo& ViewInfo);
bool IsVisible() const;
CScriptObject* Object();
CModel* ActiveModel();
void GeneratePosition();
bool HasPreviewVolume();
CAABox PreviewVolumeAABox();
CVector2f BillboardScale();
};
#endif // CSCRIPTNODE_H

View File

@ -19,11 +19,11 @@ ENodeType CStaticNode::NodeType()
return eStaticNode;
}
void CStaticNode::AddToRenderer(CRenderer *pRenderer, const CFrustumPlanes& frustum)
void CStaticNode::AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo)
{
if (!mpModel) return;
if (mpModel->IsOccluder()) return;
if (!frustum.BoxInFrustum(AABox())) return;
if (!ViewInfo.ViewFrustum.BoxInFrustum(AABox())) return;
if (!mpModel->IsTransparent())
pRenderer->AddOpaqueMesh(this, 0, AABox(), eDrawMesh);
@ -33,7 +33,7 @@ void CStaticNode::AddToRenderer(CRenderer *pRenderer, const CFrustumPlanes& frus
u32 sm_count = mpModel->GetSurfaceCount();
for (u32 s = 0; s < sm_count; s++)
{
if (frustum.BoxInFrustum(mpModel->GetSurfaceAABox(s).Transformed(Transform())))
if (ViewInfo.ViewFrustum.BoxInFrustum(mpModel->GetSurfaceAABox(s).Transformed(Transform())))
pRenderer->AddTransparentMesh(this, s, mpModel->GetSurfaceAABox(s).Transformed(Transform()), eDrawAsset);
}
}
@ -90,13 +90,14 @@ void CStaticNode::RayAABoxIntersectTest(CRayCollisionTester &Tester)
}
}
SRayIntersection CStaticNode::RayNodeIntersectTest(const CRay &Ray, u32 AssetID, ERenderOptions options)
SRayIntersection CStaticNode::RayNodeIntersectTest(const CRay &Ray, u32 AssetID, const SViewInfo& ViewInfo)
{
SRayIntersection out;
out.pNode = this;
out.AssetIndex = AssetID;
CRay TransformedRay = Ray.Transformed(Transform().Inverse());
ERenderOptions options = ViewInfo.pRenderer->RenderOptions();
std::pair<bool,float> Result = mpModel->GetSurface(AssetID)->IntersectsRay(TransformedRay, ((options & eEnableBackfaceCull) == 0));
if (Result.first)

View File

@ -11,11 +11,11 @@ class CStaticNode : public CSceneNode
public:
CStaticNode(CSceneManager *pScene, CSceneNode *pParent = 0, CStaticModel *pModel = 0);
ENodeType NodeType();
void AddToRenderer(CRenderer *pRenderer, const CFrustumPlanes& frustum);
void AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo);
void Draw(ERenderOptions Options);
void DrawAsset(ERenderOptions Options, u32 asset);
void RayAABoxIntersectTest(CRayCollisionTester &Tester);
SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID, ERenderOptions options);
SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID, const SViewInfo& ViewInfo);
};
#endif // CSTATICNODE_H

View File

@ -14,6 +14,7 @@ CBasicViewport::CBasicViewport(QWidget *pParent) :
{
setMouseTracking(true);
mCamera.SetAspectRatio((float) width() / height());
mViewInfo.pCamera = &mCamera;
}
CBasicViewport::~CBasicViewport()
@ -47,9 +48,11 @@ void CBasicViewport::paintGL()
glViewport(0, 0, width(), height());
glLineWidth(1.f);
glEnable(GL_DEPTH_TEST);
mViewInfo.ViewFrustum = mCamera.FrustumPlanes();
CGraphics::sMVPBlock.ProjectionMatrix = mCamera.ProjectionMatrix();
// Actual rendering is intended to be handled by subclassing CBasicViewport and
// reimplementing Render().
// reimplementing Paint().
Paint();
// Finally, draw XYZ axes in the corner
@ -247,6 +250,15 @@ void CBasicViewport::ProcessInput()
if (IsKeyboardInputActive())
mCamera.ProcessKeyInput((EKeyInputs) mKeysPressed, DeltaTime);
// Update view info
const CMatrix4f& View = mCamera.ViewMatrix();
mViewInfo.RotationOnlyViewMatrix = CMatrix4f(View[0][0], View[0][1], View[0][2], 0.f,
View[1][0], View[1][1], View[1][2], 0.f,
View[2][0], View[2][1], View[2][2], 0.f,
View[3][0], View[3][1], View[3][2], 1.f);
mViewInfo.ViewFrustum = mCamera.FrustumPlanes();
// Check user input
CheckUserInput();
}
@ -259,10 +271,6 @@ void CBasicViewport::Render()
}
// ************ PRIVATE ************
void CBasicViewport::ProcessInput(double /*DeltaTime*/)
{
}
void CBasicViewport::DrawAxes()
{
// Draw 64x64 axes in lower-left corner with 8px margins
@ -272,7 +280,7 @@ void CBasicViewport::DrawAxes()
glDepthRange(0.f, 1.f);
CGraphics::sMVPBlock.ModelMatrix = CTransform4f::TranslationMatrix(mCamera.Direction() * 5).ToMatrix4f();
CGraphics::sMVPBlock.ViewMatrix = mCamera.RotationOnlyViewMatrix();
CGraphics::sMVPBlock.ViewMatrix = mViewInfo.RotationOnlyViewMatrix;
CGraphics::sMVPBlock.ProjectionMatrix = Math::OrthographicMatrix(-1.f, 1.f, -1.f, 1.f, 0.1f, 100.f);
CGraphics::UpdateMVPBlock();

View File

@ -5,6 +5,7 @@
#include <QOpenGLWidget>
#include <Core/CRenderer.h>
#include <Core/SViewInfo.h>
#include <Common/CRay.h>
#include <Common/CTimer.h>
#include <Common/CVector2i.h>
@ -23,6 +24,7 @@ protected:
CCamera mCamera;
CTimer mFrameTimer;
double mLastDrawTime;
SViewInfo mViewInfo;
// Cursor settings
QCursor mCursorState;
@ -55,7 +57,6 @@ public:
bool IsCursorVisible();
bool IsMouseInputActive();
bool IsKeyboardInputActive();
CRenderer* Renderer();
CCamera& Camera();
CRay CastRay();
CVector2f MouseDeviceCoordinates();
@ -74,7 +75,6 @@ protected slots:
virtual void OnMouseRelease(QMouseEvent* /*pEvent*/) {}
private:
void ProcessInput(double DeltaTime);
void DrawAxes();
};

View File

@ -42,7 +42,7 @@ CGizmo::~CGizmo()
{
}
void CGizmo::AddToRenderer(CRenderer *pRenderer, const CFrustumPlanes&)
void CGizmo::AddToRenderer(CRenderer *pRenderer, const SViewInfo&)
{
// 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

View File

@ -124,7 +124,7 @@ public:
CGizmo();
~CGizmo();
void AddToRenderer(CRenderer *pRenderer, const CFrustumPlanes& frustum);
void AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo);
void DrawAsset(ERenderOptions options, u32 asset);
void IncrementSize();

View File

@ -49,8 +49,8 @@ void CModelEditorViewport::Paint()
else if (mMode == eDrawMesh)
{
CDrawUtil::DrawGrid();
mpModelNode->AddToRenderer(mpRenderer, mCamera.FrustumPlanes());
mpRenderer->RenderBuckets(mCamera);
mpModelNode->AddToRenderer(mpRenderer, mViewInfo);
mpRenderer->RenderBuckets(mViewInfo);
}
else if (mMode == eDrawSphere)

View File

@ -1,5 +1,6 @@
#include "CSceneViewport.h"
#include "undo/UndoCommands.h"
#include <Core/SViewInfo.h>
CSceneViewport::CSceneViewport(QWidget *pParent)
: CBasicViewport(pParent),
@ -13,6 +14,9 @@ CSceneViewport::CSceneViewport(QWidget *pParent)
mpRenderer = new CRenderer();
mpRenderer->SetClearColor(CColor::skBlack);
mpRenderer->SetViewportSize(width(), height());
mViewInfo.pScene = mpScene;
mViewInfo.pRenderer = mpRenderer;
}
CSceneViewport::~CSceneViewport()
@ -77,7 +81,7 @@ void CSceneViewport::SceneRayCast(const CRay& ray)
return;
}
SRayIntersection result = mpScene->SceneRayCast(ray, mpRenderer->RenderOptions());
SRayIntersection result = mpScene->SceneRayCast(ray, mViewInfo);
if (result.Hit)
{
@ -131,12 +135,12 @@ void CSceneViewport::Paint()
if (mDrawSky)
{
CModel *pSky = mpScene->GetActiveSkybox();
if (pSky) mpRenderer->RenderSky(pSky, mCamera);
if (pSky) mpRenderer->RenderSky(pSky, mViewInfo);
}
mCamera.LoadMatrices();
mpScene->AddSceneToRenderer(mpRenderer, mCamera);
mpRenderer->RenderBuckets(mCamera);
mpScene->AddSceneToRenderer(mpRenderer, mViewInfo);
mpRenderer->RenderBuckets(mViewInfo);
mpRenderer->RenderBloom();
if (mpEditor->IsGizmoVisible())
@ -146,8 +150,8 @@ void CSceneViewport::Paint()
mpRenderer->ClearDepthBuffer();
pGizmo->UpdateForCamera(mCamera);
pGizmo->AddToRenderer(mpRenderer, mCamera.FrustumPlanes());
mpRenderer->RenderBuckets(mCamera);
pGizmo->AddToRenderer(mpRenderer, mViewInfo);
mpRenderer->RenderBuckets(mViewInfo);
}
mpRenderer->EndFrame();