Reorganized CScene; better organization, less redundant code, responsibility for show/hide shifted to other classes, and in position to implement CSceneIterator

This commit is contained in:
parax0 2016-01-06 03:42:07 -07:00
parent 3fa109d5b8
commit d66b3dee8e
23 changed files with 253 additions and 352 deletions

View File

@ -17,12 +17,12 @@ void CAreaAttributes::SetObject(CScriptObject *pObj)
mGame = pObj->Template()->MasterTemplate()->GetGame();
}
bool CAreaAttributes::IsLayerEnabled()
bool CAreaAttributes::IsLayerEnabled() const
{
return mpObj->Layer()->IsActive();
}
bool CAreaAttributes::IsSkyEnabled()
bool CAreaAttributes::IsSkyEnabled() const
{
CPropertyStruct *pBaseStruct = mpObj->Properties();
@ -39,7 +39,7 @@ bool CAreaAttributes::IsSkyEnabled()
}
}
CModel* CAreaAttributes::SkyModel()
CModel* CAreaAttributes::SkyModel() const
{
CPropertyStruct *pBaseStruct = mpObj->Properties();

View File

@ -12,9 +12,9 @@ public:
CAreaAttributes(CScriptObject *pObj);
~CAreaAttributes();
void SetObject(CScriptObject *pObj);
bool IsLayerEnabled();
bool IsSkyEnabled();
CModel* SkyModel();
bool IsLayerEnabled() const;
bool IsSkyEnabled() const;
CModel* SkyModel() const;
};
#endif // CAREAATTRIBUTES_H

View File

@ -179,6 +179,7 @@ HEADERS += \
Resource/Script/IProperty.h \
Resource/Model/EVertexAttribute.h \
Render/FRenderOptions.h \
Scene/FShowFlags.h \
Scene/CScene.h
# Source Files
@ -263,4 +264,5 @@ SOURCES += \
Resource/Cooker/CAreaCooker.cpp \
Resource/Script/IPropertyTemplate.cpp \
Resource/Script/IProperty.cpp \
Scene/FShowFlags.cpp \
Scene/CScene.cpp

View File

@ -20,8 +20,7 @@ u32 CRenderer::sNumRenderers = 0;
// ************ INITIALIZATION ************
CRenderer::CRenderer()
{
mOptions = eDrawWorld | eDrawObjects | eDrawLights | eDrawSky |
eEnableUVScroll | eEnableBackfaceCull;
mOptions = eEnableUVScroll | eEnableBackfaceCull;
mBloomMode = eNoBloom;
mDrawGrid = true;
mInitialized = false;
@ -58,42 +57,6 @@ FRenderOptions CRenderer::RenderOptions() const
return mOptions;
}
void CRenderer::ToggleWorld(bool b)
{
if (b) mOptions |= eDrawWorld;
else mOptions &= ~eDrawWorld;
}
void CRenderer::ToggleWorldCollision(bool b)
{
if (b) mOptions |= eDrawWorldCollision;
else mOptions &= ~eDrawWorldCollision;
}
void CRenderer::ToggleObjects(bool b)
{
if (b) mOptions |= eDrawObjects;
else mOptions &= ~eDrawObjects;
}
void CRenderer::ToggleObjectCollision(bool b)
{
if (b) mOptions |= eDrawObjectCollision;
else mOptions &= ~eDrawObjectCollision;
}
void CRenderer::ToggleLights(bool b)
{
if (b) mOptions |= eDrawLights;
else mOptions &= ~eDrawLights;
}
void CRenderer::ToggleSky(bool b)
{
if (b) mOptions |= eDrawSky;
else mOptions &= ~eDrawSky;
}
void CRenderer::ToggleBackfaceCull(bool b)
{
if (b) mOptions |= eEnableBackfaceCull;

View File

@ -55,12 +55,6 @@ public:
// Getters/Setters
FRenderOptions RenderOptions() const;
void ToggleWorld(bool b);
void ToggleWorldCollision(bool b);
void ToggleObjects(bool b);
void ToggleObjectCollision(bool b);
void ToggleLights(bool b);
void ToggleSky(bool b);
void ToggleBackfaceCull(bool b);
void ToggleUVAnimation(bool b);
void ToggleGrid(bool b);

View File

@ -6,18 +6,12 @@
enum ERenderOption
{
eNoRenderOptions = 0x0,
eDrawWorld = 0x1,
eDrawWorldCollision = 0x2,
eDrawObjects = 0x4,
eDrawObjectCollision = 0x8,
eDrawLights = 0x10,
eDrawSky = 0x20,
eEnableUVScroll = 0x40,
eEnableBackfaceCull = 0x80,
eEnableOccluders = 0x100,
eNoMaterialSetup = 0x200,
eEnableBloom = 0x400,
eNoAlpha = 0x800
eEnableUVScroll = 0x1,
eEnableBackfaceCull = 0x2,
eEnableOccluders = 0x4,
eNoMaterialSetup = 0x8,
eEnableBloom = 0x10,
eNoAlpha = 0x20
};
DECLARE_FLAGS(ERenderOption, FRenderOptions)

View File

@ -1,6 +1,7 @@
#ifndef SVIEWINFO
#define SVIEWINFO
#include "Core/Scene/FShowFlags.h"
#include <Math/CFrustumPlanes.h>
#include <Math/CMatrix4f.h>
#include <Math/CRay.h>
@ -12,6 +13,7 @@ struct SViewInfo
class CCamera *pCamera;
bool GameMode;
FShowFlags ShowFlags;
CFrustumPlanes ViewFrustum;
CMatrix4f RotationOnlyViewMatrix;
};

View File

@ -11,21 +11,14 @@
#include <list>
#include <string>
/**
* This class direly needs a rewrite
* Future plan is to integrate a "scene layer" system, where nodes are grouped into layers
* We would have terrain layer, lights layer, collision layer, multiple script layers, etc
* Advantage of this is that I don't need to write separate functions for every single node type
* They can all be tracked together and the code could be streamlined a lot.
*/
CScene::CScene()
: mSplitTerrain(true)
, mNumNodes(0)
, mpSceneRootNode(new CRootNode(this, nullptr))
, mpArea(nullptr)
, mpWorld(nullptr)
, mpAreaRootNode(nullptr)
{
mSplitTerrain = true;
mNodeCount = 0;
mpSceneRootNode = new CRootNode(this, nullptr);
mpArea = nullptr;
mpWorld = nullptr;
mpAreaRootNode = nullptr;
}
CScene::~CScene()
@ -33,107 +26,105 @@ CScene::~CScene()
ClearScene();
}
CModelNode* CScene::AddModel(CModel *m)
CModelNode* CScene::CreateModelNode(CModel *pModel)
{
if (m == nullptr) return nullptr;
if (pModel == nullptr) return nullptr;
CModelNode *node = new CModelNode(this, mpSceneRootNode, m);
mModelNodes.push_back(node);
mNodeCount++;
return node;
CModelNode *pNode = new CModelNode(this, mpSceneRootNode, pModel);
mNodes[eShowObjects].push_back(pNode);
mNumNodes++;
return pNode;
}
CStaticNode* CScene::AddStaticModel(CStaticModel *mdl)
CStaticNode* CScene::CreateStaticNode(CStaticModel *pModel)
{
if (mdl == nullptr) return nullptr;
if (pModel == nullptr) return nullptr;
CStaticNode *node = new CStaticNode(this, mpAreaRootNode, mdl);
mStaticNodes.push_back(node);
mNodeCount++;
return node;
CStaticNode *pNode = new CStaticNode(this, mpAreaRootNode, pModel);
mNodes[eShowWorld].push_back(pNode);
mNumNodes++;
return pNode;
}
CCollisionNode* CScene::AddCollision(CCollisionMeshGroup *mesh)
CCollisionNode* CScene::CreateCollisionNode(CCollisionMeshGroup *pMesh)
{
if (mesh == nullptr) return nullptr;
if (pMesh == nullptr) return nullptr;
CCollisionNode *node = new CCollisionNode(this, mpAreaRootNode, mesh);
mCollisionNodes.push_back(node);
mNodeCount++;
return node;
CCollisionNode *pNode = new CCollisionNode(this, mpAreaRootNode, pMesh);
mNodes[eShowWorldCollision].push_back(pNode);
mNumNodes++;
return pNode;
}
CScriptNode* CScene::AddScriptObject(CScriptObject *obj)
CScriptNode* CScene::CreateScriptNode(CScriptObject *pObj)
{
if (obj == nullptr) return nullptr;
if (pObj == nullptr) return nullptr;
CScriptNode *node = new CScriptNode(this, mpAreaRootNode, obj);
mScriptNodes.push_back(node);
mNodeCount++;
return node;
CScriptNode *pNode = new CScriptNode(this, mpAreaRootNode, pObj);
mNodes[eShowObjects].push_back(pNode);
mNumNodes++;
return pNode;
}
CLightNode* CScene::AddLight(CLight *Light)
CLightNode* CScene::CreateLightNode(CLight *pLight)
{
if (Light == nullptr) return nullptr;
if (pLight == nullptr) return nullptr;
CLightNode *node = new CLightNode(this, mpAreaRootNode, Light);
mLightNodes.push_back(node);
mNodeCount++;
return node;
CLightNode *pNode = new CLightNode(this, mpAreaRootNode, pLight);
mNodes[eShowLights].push_back(pNode);
mNumNodes++;
return pNode;
}
void CScene::SetActiveArea(CGameArea* _area)
void CScene::SetActiveArea(CGameArea *pArea)
{
// Clear existing area
delete mpAreaRootNode;
mModelNodes.clear();
mStaticNodes.clear();
mCollisionNodes.clear();
mScriptNodes.clear();
mLightNodes.clear();
mNodes.clear();
mAreaAttributesObjects.clear();
mpActiveAreaAttributes = nullptr;
mScriptNodeMap.clear();
// Create nodes for new area
mpArea = _area;
mpArea = pArea;
mpAreaRootNode = new CRootNode(this, mpSceneRootNode);
if (mSplitTerrain)
{
u32 count = mpArea->GetStaticModelCount();
for (u32 m = 0; m < count; m++)
AddStaticModel(mpArea->GetStaticModel(m));
u32 Count = mpArea->GetStaticModelCount();
for (u32 iMdl = 0; iMdl < Count; iMdl++)
CreateStaticNode(mpArea->GetStaticModel(iMdl));
}
else
{
u32 count = mpArea->GetTerrainModelCount();
for (u32 m = 0; m < count; m++)
u32 Count = mpArea->GetTerrainModelCount();
for (u32 iMdl = 0; iMdl < Count; iMdl++)
{
CModel *mdl = mpArea->GetTerrainModel(m);
CModelNode *node = AddModel(mdl);
node->SetDynamicLighting(false);
CModel *pModel = mpArea->GetTerrainModel(iMdl);
CModelNode *pNode = CreateModelNode(pModel);
pNode->SetDynamicLighting(false);
}
}
AddCollision(mpArea->GetCollision());
CreateCollisionNode(mpArea->GetCollision());
u32 NumLayers = mpArea->GetScriptLayerCount();
for (u32 l = 0; l < NumLayers; l++)
{
CScriptLayer *layer = mpArea->GetScriptLayer(l);
u32 NumObjects = layer->GetNumObjects();
mScriptNodes.reserve(mScriptNodes.size() + NumObjects);
for (u32 o = 0; o < NumObjects; o++)
for (u32 iLyr = 0; iLyr < NumLayers; iLyr++)
{
CScriptLayer *pLayer = mpArea->GetScriptLayer(iLyr);
u32 NumObjects = pLayer->GetNumObjects();
mNodes[eShowObjects].reserve(mNodes[eShowObjects].size() + NumObjects);
for (u32 iObj = 0; iObj < NumObjects; iObj++)
{
CScriptObject *pObj = layer->ObjectByIndex(o);
CScriptNode *Node = AddScriptObject( pObj );
Node->BuildLightList(mpArea);
CScriptObject *pObj = pLayer->ObjectByIndex(iObj);
CScriptNode *pNode = CreateScriptNode(pObj);
pNode->BuildLightList(mpArea);
// Add to map
mScriptNodeMap[pObj->InstanceID()] = Node;
mScriptNodeMap[pObj->InstanceID()] = pNode;
// AreaAttributes check
switch (pObj->ObjectTypeID())
@ -149,16 +140,15 @@ void CScene::SetActiveArea(CGameArea* _area)
CScriptLayer *pGenLayer = mpArea->GetGeneratorLayer();
if (pGenLayer)
{
for (u32 o = 0; o < pGenLayer->GetNumObjects(); o++)
for (u32 iObj = 0; iObj < pGenLayer->GetNumObjects(); iObj++)
{
CScriptObject *pObj = pGenLayer->ObjectByIndex(o);
CScriptNode *Node = AddScriptObject(pObj);
CScriptObject *pObj = pGenLayer->ObjectByIndex(iObj);
CScriptNode *pNode = CreateScriptNode(pObj);
// Add to map
mScriptNodeMap[pObj->InstanceID()] = Node;
mScriptNodeMap[pObj->InstanceID()] = pNode;
}
}
PickEnvironmentObjects();
// Ensure script nodes have valid positions + build light lists
for (auto it = mScriptNodeMap.begin(); it != mScriptNodeMap.end(); it++)
@ -170,27 +160,27 @@ void CScene::SetActiveArea(CGameArea* _area)
u32 NumLightLayers = mpArea->GetLightLayerCount();
CGraphics::sAreaAmbientColor = CColor::skBlack;
for (u32 ly = 0; ly < NumLightLayers; ly++)
for (u32 iLyr = 0; iLyr < NumLightLayers; iLyr++)
{
u32 NumLights = mpArea->GetLightCount(ly);
u32 NumLights = mpArea->GetLightCount(iLyr);
for (u32 l = 0; l < NumLights; l++)
for (u32 iLit = 0; iLit < NumLights; iLit++)
{
CLight *Light = mpArea->GetLight(ly, l);
CLight *pLight = mpArea->GetLight(iLyr, iLit);
if (Light->GetType() == eLocalAmbient)
CGraphics::sAreaAmbientColor += Light->GetColor();
if (pLight->GetType() == eLocalAmbient)
CGraphics::sAreaAmbientColor += pLight->GetColor();
AddLight(Light);
CreateLightNode(pLight);
}
}
std::cout << CSceneNode::NumNodes() << " nodes\n";
Log::Write( TString::FromInt32(CSceneNode::NumNodes()) + " nodes" );
}
void CScene::SetActiveWorld(CWorld* _world)
void CScene::SetActiveWorld(CWorld* pWorld)
{
mpWorld = _world;
mpWorld = pWorld;
}
void CScene::ClearScene()
@ -201,113 +191,51 @@ void CScene::ClearScene()
delete mpAreaRootNode;
}
mModelNodes.clear();
mStaticNodes.clear();
mCollisionNodes.clear();
mScriptNodes.clear();
mLightNodes.clear();
mNodes.clear();
mNumNodes = 0;
mpArea = nullptr;
mpWorld = nullptr;
mNodeCount = 0;
}
void CScene::AddSceneToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo)
{
FRenderOptions Options = pRenderer->RenderOptions();
// Override show flags in game mode
FShowFlags ShowFlags = (ViewInfo.GameMode ? gGameModeShowFlags : ViewInfo.ShowFlags);
if (Options & eDrawWorld || ViewInfo.GameMode)
for (auto it = mNodes.begin(); it != mNodes.end(); it++)
{
for (u32 n = 0; n < mModelNodes.size(); n++)
if (mModelNodes[n]->IsVisible())
mModelNodes[n]->AddToRenderer(pRenderer, ViewInfo);
if (ShowFlags & it->first)
{
std::vector<CSceneNode*>& rNodeVec = it->second;
for (u32 n = 0; n < mStaticNodes.size(); n++)
if (mStaticNodes[n]->IsVisible())
mStaticNodes[n]->AddToRenderer(pRenderer, ViewInfo);
}
if (Options & eDrawWorldCollision && !ViewInfo.GameMode)
{
for (u32 n = 0; n < mCollisionNodes.size(); n++)
if (mCollisionNodes[n]->IsVisible())
mCollisionNodes[n]->AddToRenderer(pRenderer, ViewInfo);
}
if (Options & eDrawLights && !ViewInfo.GameMode)
{
for (u32 n = 0; n < mLightNodes.size(); n++)
if (mLightNodes[n]->IsVisible())
mLightNodes[n]->AddToRenderer(pRenderer, ViewInfo);
}
if ((Options & eDrawObjects) || (Options & eDrawObjectCollision) || ViewInfo.GameMode)
{
for (u32 n = 0; n < mScriptNodes.size(); n++)
if (mScriptNodes[n]->IsVisible())
mScriptNodes[n]->AddToRenderer(pRenderer, ViewInfo);
for (u32 iNode = 0; iNode < rNodeVec.size(); iNode++)
if (rNodeVec[iNode]->IsVisible())
rNodeVec[iNode]->AddToRenderer(pRenderer, ViewInfo);
}
}
}
SRayIntersection CScene::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...)
FRenderOptions renderOptions = ViewInfo.pRenderer->RenderOptions();
std::vector<CSceneNode*> *pNodeVectors[5] = {
reinterpret_cast<std::vector<CSceneNode*>*>(&mModelNodes),
reinterpret_cast<std::vector<CSceneNode*>*>(&mStaticNodes),
reinterpret_cast<std::vector<CSceneNode*>*>(&mCollisionNodes),
reinterpret_cast<std::vector<CSceneNode*>*>(&mScriptNodes),
reinterpret_cast<std::vector<CSceneNode*>*>(&mLightNodes),
};
bool NodesVisible[5] = {
true, ((renderOptions & eDrawWorld) != 0), ((renderOptions & eDrawWorldCollision) != 0),
((renderOptions & ((FRenderOptions) (eDrawObjects | eDrawObjectCollision))) != 0), ((renderOptions & eDrawLights) != 0)
};
// Override visibility for game mode
if (ViewInfo.GameMode)
{
NodesVisible[0] = false;
NodesVisible[1] = true;
NodesVisible[2] = false;
NodesVisible[3] = true;
NodesVisible[4] = false;
}
// Less hacky stuff
FShowFlags ShowFlags = (ViewInfo.GameMode ? gGameModeShowFlags : ViewInfo.ShowFlags);
CRayCollisionTester Tester(Ray);
for (u32 iVec = 0; iVec < 5; iVec++)
for (auto it = mNodes.begin(); it != mNodes.end(); it++)
{
if (!NodesVisible[iVec]) continue;
if (ShowFlags & it->first)
{
std::vector<CSceneNode*>& rNodeVec = it->second;
std::vector<CSceneNode*>& vec = *pNodeVectors[iVec];
for (u32 iNode = 0; iNode < vec.size(); iNode++)
if (vec[iNode]->IsVisible())
vec[iNode]->RayAABoxIntersectTest(Tester, ViewInfo);
for (u32 iNode = 0; iNode < rNodeVec.size(); iNode++)
if (rNodeVec[iNode]->IsVisible())
rNodeVec[iNode]->RayAABoxIntersectTest(Tester, ViewInfo);
}
}
return Tester.TestNodes(ViewInfo);
}
void CScene::PickEnvironmentObjects()
{
// Pick AreaAttributes
for (auto it = mAreaAttributesObjects.begin(); it != mAreaAttributesObjects.end(); it++)
{
if ((*it).IsLayerEnabled())
{
mpActiveAreaAttributes = &(*it);
break;
}
}
}
CScriptNode* CScene::ScriptNodeByID(u32 InstanceID)
{
auto it = mScriptNodeMap.find(InstanceID);
@ -324,26 +252,38 @@ CScriptNode* CScene::NodeForObject(CScriptObject *pObj)
CLightNode* CScene::NodeForLight(CLight *pLight)
{
// Slow. Is there a better way to do this?
for (auto it = mLightNodes.begin(); it != mLightNodes.end(); it++)
if ((*it)->Light() == pLight) return *it;
std::vector<CSceneNode*>& rLights = mNodes[eShowLights];
for (auto it = rLights.begin(); it != rLights.end(); it++)
{
CLightNode *pNode = static_cast<CLightNode*>(*it);
if (pNode->Light() == pLight) return pNode;
}
return nullptr;
}
CModel* CScene::GetActiveSkybox()
{
if (mpActiveAreaAttributes)
bool SkyEnabled = false;
for (u32 iAtt = 0; iAtt < mAreaAttributesObjects.size(); iAtt++)
{
if (mpActiveAreaAttributes->IsSkyEnabled())
const CAreaAttributes& rkAttributes = mAreaAttributesObjects[iAtt];
if (rkAttributes.IsSkyEnabled()) SkyEnabled = true;
if (rkAttributes.IsLayerEnabled())
{
CModel *pSky = mpActiveAreaAttributes->SkyModel();
if (pSky) return pSky;
else return mpWorld->GetDefaultSkybox();
if (rkAttributes.IsSkyEnabled())
{
SkyEnabled = true;
CModel *pSky = rkAttributes.SkyModel();
if (pSky) return pSky;
}
}
else
return nullptr;
}
if (SkyEnabled) return mpWorld->GetDefaultSkybox();
else return nullptr;
}

View File

@ -8,6 +8,7 @@
#include "CScriptNode.h"
#include "CStaticNode.h"
#include "CCollisionNode.h"
#include "FShowFlags.h"
#include "Core/Render/CRenderer.h"
#include "Core/Render/SViewInfo.h"
#include "Core/Resource/CGameArea.h"
@ -23,13 +24,9 @@ class CScene
{
bool mSplitTerrain;
u32 mNodeCount;
std::vector<CModelNode*> mModelNodes;
std::vector<CStaticNode*> mStaticNodes;
std::vector<CCollisionNode*> mCollisionNodes;
std::vector<CScriptNode*> mScriptNodes;
std::vector<CLightNode*> mLightNodes;
u32 mNumNodes;
CRootNode *mpSceneRootNode;
std::unordered_map<EShowFlag, std::vector<CSceneNode*>> mNodes;
TResPtr<CGameArea> mpArea;
TResPtr<CWorld> mpWorld;
@ -37,7 +34,6 @@ class CScene
// Environment
std::vector<CAreaAttributes> mAreaAttributesObjects;
CAreaAttributes *mpActiveAreaAttributes;
// Objects
std::unordered_map<u32, CScriptNode*> mScriptNodeMap;
@ -47,17 +43,16 @@ public:
~CScene();
// Scene Management
CModelNode* AddModel(CModel *mdl);
CStaticNode* AddStaticModel(CStaticModel *mdl);
CCollisionNode* AddCollision(CCollisionMeshGroup *mesh);
CScriptNode* AddScriptObject(CScriptObject *obj);
CLightNode* AddLight(CLight *Light);
void SetActiveArea(CGameArea *_area);
void SetActiveWorld(CWorld *_world);
CModelNode* CreateModelNode(CModel *pModel);
CStaticNode* CreateStaticNode(CStaticModel *pModel);
CCollisionNode* CreateCollisionNode(CCollisionMeshGroup *pMesh);
CScriptNode* CreateScriptNode(CScriptObject *pObj);
CLightNode* CreateLightNode(CLight *pLight);
void SetActiveArea(CGameArea *pArea);
void SetActiveWorld(CWorld *pWorld);
void ClearScene();
void AddSceneToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo);
SRayIntersection SceneRayCast(const CRay& Ray, const SViewInfo& ViewInfo);
void PickEnvironmentObjects();
void AddSceneToRenderer(CRenderer *pRenderer, const SViewInfo& rkViewInfo);
SRayIntersection SceneRayCast(const CRay& rkRay, const SViewInfo& rkViewInfo);
CScriptNode* ScriptNodeByID(u32 InstanceID);
CScriptNode* NodeForObject(CScriptObject *pObj);
CLightNode* NodeForLight(CLight *pLight);

View File

@ -58,6 +58,7 @@ public:
virtual void DrawSelection();
virtual void RayAABoxIntersectTest(CRayCollisionTester& Tester, const SViewInfo& ViewInfo);
virtual SRayIntersection RayNodeIntersectTest(const CRay& Ray, u32 AssetID, const SViewInfo& ViewInfo) = 0;
virtual void PostLoad() {}
virtual bool AllowsTranslate() const { return true; }
virtual bool AllowsRotate() const { return true; }
virtual bool AllowsScale() const { return true; }

View File

@ -119,12 +119,10 @@ void CScriptNode::AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo)
if (ShouldDraw)
{
// Otherwise, we proceed as normal
FRenderOptions options = pRenderer->RenderOptions();
if ((options & eDrawObjectCollision) && (!ViewInfo.GameMode))
if ((ViewInfo.ShowFlags & eShowObjectCollision) && (!ViewInfo.GameMode))
mpCollisionNode->AddToRenderer(pRenderer, ViewInfo);
if (options & eDrawObjects || ViewInfo.GameMode)
if (ViewInfo.ShowFlags & eShowObjectGeometry || ViewInfo.GameMode)
{
if (ViewInfo.ViewFrustum.BoxInFrustum(AABox()))
{
@ -282,85 +280,81 @@ void CScriptNode::RayAABoxIntersectTest(CRayCollisionTester& Tester, const SView
SRayIntersection CScriptNode::RayNodeIntersectTest(const CRay& Ray, u32 AssetID, const SViewInfo& ViewInfo)
{
FRenderOptions options = ViewInfo.pRenderer->RenderOptions();
FRenderOptions Options = ViewInfo.pRenderer->RenderOptions();
SRayIntersection out;
out.pNode = this;
out.ComponentIndex = AssetID;
if (options & eDrawObjects || ViewInfo.GameMode)
// Model test
if (UsesModel())
{
// Model test
if (UsesModel())
CModel *pModel = (mpActiveModel ? mpActiveModel : CDrawUtil::GetCubeModel());
CRay TransformedRay = Ray.Transformed(Transform().Inverse());
std::pair<bool,float> Result = pModel->GetSurface(AssetID)->IntersectsRay(TransformedRay, ((Options & eEnableBackfaceCull) == 0));
if (Result.first)
{
CModel *pModel = (mpActiveModel ? mpActiveModel : CDrawUtil::GetCubeModel());
out.Hit = true;
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;
CVector3f HitPoint = TransformedRay.PointOnRay(Result.second);
CVector3f WorldHitPoint = Transform() * HitPoint;
out.Distance = Math::Distance(Ray.Origin(), WorldHitPoint);
}
// Billboard test
// todo: come up with a better way to share this code between CScriptNode and CLightNode
else
out.Hit = false;
}
// Billboard test
// todo: come up with a better way to share this code between CScriptNode and CLightNode
else
{
// 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 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);
// Step 2: transform the hit point into the plane's local space
CVector3f PlaneHitPoint = Ray.PointOnRay(PlaneTest.second);
CVector3f RelHitPoint = PlaneHitPoint - mPosition;
if (PlaneTest.first)
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 2: transform the hit point into the plane's local space
CVector3f PlaneHitPoint = Ray.PointOnRay(PlaneTest.second);
CVector3f RelHitPoint = PlaneHitPoint - mPosition;
// 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);
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;
}
}
if (TexelAlpha < 0.25f)
out.Hit = false;
else
out.Hit = false;
{
// 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;
return out;
}

View File

@ -1,19 +0,0 @@
#ifndef EVISIBILITYFLAGS
#define EVISIBILITYFLAGS
#include <Common/EnumUtil.h>
enum EVisibilityFlags
{
eShowNomr = 0x00,
eShowWorld = 0x01,
eShowWorldCollision = 0x02,
eShowObjects = 0x04,
eShowObjectCollision = 0x08,
eShowLights = 0x10,
eShowAll = 0x1F
};
DEFINE_ENUM_FLAGS(EVisibilityFlags)
#endif // EVISIBILITYFLAGS

View File

@ -0,0 +1,3 @@
#include "FShowFlags.h"
const FShowFlags gkGameModeShowFlags = eShowWorld | eShowObjectGeometry | eShowSky;

View File

@ -0,0 +1,23 @@
#ifndef FSHOWFLAGS
#define FSHOWFLAGS
#include <Common/Flags.h>
enum EShowFlag
{
eShowNone = 0x00,
eShowWorld = 0x01,
eShowWorldCollision = 0x02,
eShowObjectGeometry = 0x04,
eShowObjectCollision = 0x08,
eShowObjects = 0x0C,
eShowLights = 0x10,
eShowSky = 0x20,
eShowAll = 0x3F
};
DECLARE_FLAGS(EShowFlag, FShowFlags)
extern const FShowFlags gkGameModeShowFlags;
#endif // FSHOWFLAGS

View File

@ -189,6 +189,9 @@ void CDamageableTriggerExtra::AddToRenderer(CRenderer *pRenderer, const SViewInf
if (ViewInfo.GameMode && !mpInstance->IsActive())
return;
if ((ViewInfo.ShowFlags & eShowObjectGeometry) == 0)
return;
if (mRenderSide != eNoRender)
{
if (ViewInfo.ViewFrustum.BoxInFrustum(AABox()))

View File

@ -72,6 +72,7 @@ void CDoorExtra::AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewInfo)
{
if (!mpShieldModel) return;
if (ViewInfo.GameMode && !mpInstance->IsActive()) return;
if ((ViewInfo.ShowFlags & eShowObjectGeometry) == 0) return;
if (mpParent->IsVisible() && ViewInfo.ViewFrustum.BoxInFrustum(AABox()))
{

View File

@ -27,7 +27,7 @@ CRadiusSphereExtra::CRadiusSphereExtra(CScriptObject *pInstance, CScene *pScene,
void CRadiusSphereExtra::AddToRenderer(CRenderer *pRenderer, const SViewInfo& rkViewInfo)
{
if (!rkViewInfo.GameMode && mpRadius && mpParent->IsVisible() && mpParent->IsSelected())
if (!rkViewInfo.GameMode && (rkViewInfo.ShowFlags & eShowObjectGeometry) && mpRadius && mpParent->IsVisible() && mpParent->IsSelected())
{
CAABox BoundingBox = Bounds();

View File

@ -82,7 +82,7 @@ void CWaypointExtra::AddToRenderer(CRenderer *pRenderer, const SViewInfo& ViewIn
// won't work properly because we haven't finished loading the scene yet.
if (!mLinksBuilt) BuildLinks();
if (!ViewInfo.GameMode && mpParent->IsVisible() && !mpParent->IsSelected())
if (!ViewInfo.GameMode && (ViewInfo.ShowFlags & eShowObjectGeometry) && mpParent->IsVisible() && !mpParent->IsSelected())
{
for (u32 iLink = 0; iLink < mLinks.size(); iLink++)
{

View File

@ -17,6 +17,7 @@ CBasicViewport::CBasicViewport(QWidget *pParent) :
{
setMouseTracking(true);
mCamera.SetAspectRatio((float) width() / height());
mViewInfo.ShowFlags = eShowAll;
mViewInfo.pCamera = &mCamera;
mViewInfo.GameMode = false;
}

View File

@ -9,7 +9,6 @@ CSceneViewport::CSceneViewport(QWidget *pParent)
: CBasicViewport(pParent),
mpEditor(nullptr),
mpScene(nullptr),
mDrawSky(true),
mGizmoTransforming(false),
mpHoverNode(nullptr),
mHoverPoint(CVector3f::skZero),
@ -22,6 +21,7 @@ CSceneViewport::CSceneViewport(QWidget *pParent)
mViewInfo.pScene = mpScene;
mViewInfo.pRenderer = mpRenderer;
mViewInfo.ShowFlags = eShowWorld | eShowObjectGeometry | eShowLights | eShowSky;
CreateContextMenu();
}
@ -37,9 +37,12 @@ void CSceneViewport::SetScene(INodeEditor *pEditor, CScene *pScene)
mpScene = pScene;
}
void CSceneViewport::SetSkyEnabled(bool b)
void CSceneViewport::SetShowFlag(EShowFlag Flag, bool Visible)
{
mDrawSky = b;
if (Visible)
mViewInfo.ShowFlags |= Flag;
else
mViewInfo.ShowFlags &= ~Flag;
}
CRenderer* CSceneViewport::Renderer()
@ -191,7 +194,7 @@ void CSceneViewport::Paint()
mpRenderer->BeginFrame();
if (mDrawSky || mViewInfo.GameMode)
if ((mViewInfo.ShowFlags & eShowSky) || mViewInfo.GameMode)
{
CModel *pSky = mpScene->GetActiveSkybox();
if (pSky) mpRenderer->RenderSky(pSky, mViewInfo);
@ -336,7 +339,7 @@ void CSceneViewport::OnHideLayer()
void CSceneViewport::OnUnhideAll()
{
// implement when scene iterator exists!
// implement when scene iterator is implemented!
}
void CSceneViewport::OnContextMenuClose()

View File

@ -12,9 +12,6 @@ class CSceneViewport : public CBasicViewport
CScene *mpScene;
CRenderer *mpRenderer;
// Render settings
bool mDrawSky;
// Scene interaction
bool mGizmoHovering;
bool mGizmoTransforming;
@ -34,7 +31,11 @@ public:
CSceneViewport(QWidget *pParent = 0);
~CSceneViewport();
void SetScene(INodeEditor *pEditor, CScene *pScene);
<<<<<<< Updated upstream
void SetSkyEnabled(bool b);
=======
void SetShowFlag(EShowFlag Flag, bool Visible);
>>>>>>> Stashed changes
CRenderer* Renderer();
CSceneNode* HoverNode();
CVector3f HoverPoint();

View File

@ -351,27 +351,27 @@ void CWorldEditor::OnTransformSpinBoxEdited(CVector3f)
// These functions are from "Go to slot" in the designer
void CWorldEditor::on_ActionDrawWorld_triggered()
{
ui->MainViewport->Renderer()->ToggleWorld(ui->ActionDrawWorld->isChecked());
ui->MainViewport->SetShowFlag(eShowWorld, ui->ActionDrawWorld->isChecked());
}
void CWorldEditor::on_ActionDrawCollision_triggered()
{
ui->MainViewport->Renderer()->ToggleWorldCollision(ui->ActionDrawCollision->isChecked());
ui->MainViewport->SetShowFlag(eShowWorldCollision, ui->ActionDrawCollision->isChecked());
}
void CWorldEditor::on_ActionDrawObjects_triggered()
{
ui->MainViewport->Renderer()->ToggleObjects(ui->ActionDrawObjects->isChecked());
ui->MainViewport->SetShowFlag(eShowObjectGeometry, ui->ActionDrawObjects->isChecked());
}
void CWorldEditor::on_ActionDrawLights_triggered()
{
ui->MainViewport->Renderer()->ToggleLights(ui->ActionDrawLights->isChecked());
ui->MainViewport->SetShowFlag(eShowLights, ui->ActionDrawLights->isChecked());
}
void CWorldEditor::on_ActionDrawSky_triggered()
{
ui->MainViewport->SetSkyEnabled(ui->ActionDrawSky->isChecked());
ui->MainViewport->SetShowFlag(eShowSky, ui->ActionDrawSky->isChecked());
}
void CWorldEditor::on_ActionNoLighting_triggered()
@ -464,7 +464,7 @@ void CWorldEditor::on_ActionDecrementGizmo_triggered()
void CWorldEditor::on_ActionDrawObjectCollision_triggered()
{
ui->MainViewport->Renderer()->ToggleObjectCollision(ui->ActionDrawObjectCollision->isChecked());
ui->MainViewport->SetShowFlag(eShowObjectCollision, ui->ActionDrawObjectCollision->isChecked());
}
void CWorldEditor::on_ActionGameMode_triggered()

View File

@ -354,7 +354,7 @@
<enum>QTabWidget::Rounded</enum>
</property>
<property name="currentIndex">
<number>2</number>
<number>1</number>
</property>
<property name="iconSize">
<size>