From d66b3dee8e30de3e7cb354cad670a001dc6dc157 Mon Sep 17 00:00:00 2001 From: parax0 Date: Wed, 6 Jan 2016 03:42:07 -0700 Subject: [PATCH] Reorganized CScene; better organization, less redundant code, responsibility for show/hide shifted to other classes, and in position to implement CSceneIterator --- src/Core/CAreaAttributes.cpp | 6 +- src/Core/CAreaAttributes.h | 6 +- src/Core/Core.pro | 2 + src/Core/Render/CRenderer.cpp | 39 +-- src/Core/Render/CRenderer.h | 6 - src/Core/Render/FRenderOptions.h | 18 +- src/Core/Render/SViewInfo.h | 2 + src/Core/Scene/CScene.cpp | 294 +++++++----------- src/Core/Scene/CScene.h | 29 +- src/Core/Scene/CSceneNode.h | 1 + src/Core/Scene/CScriptNode.cpp | 114 ++++--- src/Core/Scene/EVisibilityFlags.h | 19 -- src/Core/Scene/FShowFlags.cpp | 3 + src/Core/Scene/FShowFlags.h | 23 ++ .../ScriptExtra/CDamageableTriggerExtra.cpp | 3 + src/Core/ScriptExtra/CDoorExtra.cpp | 1 + src/Core/ScriptExtra/CRadiusSphereExtra.cpp | 2 +- src/Core/ScriptExtra/CWaypointExtra.cpp | 2 +- src/Editor/CBasicViewport.cpp | 1 + src/Editor/CSceneViewport.cpp | 13 +- src/Editor/CSceneViewport.h | 7 +- src/Editor/WorldEditor/CWorldEditor.cpp | 12 +- src/Editor/WorldEditor/CWorldEditor.ui | 2 +- 23 files changed, 253 insertions(+), 352 deletions(-) delete mode 100644 src/Core/Scene/EVisibilityFlags.h create mode 100644 src/Core/Scene/FShowFlags.cpp create mode 100644 src/Core/Scene/FShowFlags.h diff --git a/src/Core/CAreaAttributes.cpp b/src/Core/CAreaAttributes.cpp index dc72e9d8..ae6a74d1 100644 --- a/src/Core/CAreaAttributes.cpp +++ b/src/Core/CAreaAttributes.cpp @@ -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(); diff --git a/src/Core/CAreaAttributes.h b/src/Core/CAreaAttributes.h index ad0cb8dd..dd6752e4 100644 --- a/src/Core/CAreaAttributes.h +++ b/src/Core/CAreaAttributes.h @@ -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 diff --git a/src/Core/Core.pro b/src/Core/Core.pro index 0387b397..732380b2 100644 --- a/src/Core/Core.pro +++ b/src/Core/Core.pro @@ -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 diff --git a/src/Core/Render/CRenderer.cpp b/src/Core/Render/CRenderer.cpp index 136c2665..a365237b 100644 --- a/src/Core/Render/CRenderer.cpp +++ b/src/Core/Render/CRenderer.cpp @@ -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; diff --git a/src/Core/Render/CRenderer.h b/src/Core/Render/CRenderer.h index 7bdf4082..c90b94e0 100644 --- a/src/Core/Render/CRenderer.h +++ b/src/Core/Render/CRenderer.h @@ -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); diff --git a/src/Core/Render/FRenderOptions.h b/src/Core/Render/FRenderOptions.h index 2345ffc2..a2cca9cc 100644 --- a/src/Core/Render/FRenderOptions.h +++ b/src/Core/Render/FRenderOptions.h @@ -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) diff --git a/src/Core/Render/SViewInfo.h b/src/Core/Render/SViewInfo.h index 65a3f54d..4607b417 100644 --- a/src/Core/Render/SViewInfo.h +++ b/src/Core/Render/SViewInfo.h @@ -1,6 +1,7 @@ #ifndef SVIEWINFO #define SVIEWINFO +#include "Core/Scene/FShowFlags.h" #include #include #include @@ -12,6 +13,7 @@ struct SViewInfo class CCamera *pCamera; bool GameMode; + FShowFlags ShowFlags; CFrustumPlanes ViewFrustum; CMatrix4f RotationOnlyViewMatrix; }; diff --git a/src/Core/Scene/CScene.cpp b/src/Core/Scene/CScene.cpp index 3faa2dee..f7cdf36a 100644 --- a/src/Core/Scene/CScene.cpp +++ b/src/Core/Scene/CScene.cpp @@ -11,21 +11,14 @@ #include #include -/** - * 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& 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 *pNodeVectors[5] = { - reinterpret_cast*>(&mModelNodes), - reinterpret_cast*>(&mStaticNodes), - reinterpret_cast*>(&mCollisionNodes), - reinterpret_cast*>(&mScriptNodes), - reinterpret_cast*>(&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& rNodeVec = it->second; - std::vector& 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& rLights = mNodes[eShowLights]; + + for (auto it = rLights.begin(); it != rLights.end(); it++) + { + CLightNode *pNode = static_cast(*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; } diff --git a/src/Core/Scene/CScene.h b/src/Core/Scene/CScene.h index 7eb07c28..6ef698bc 100644 --- a/src/Core/Scene/CScene.h +++ b/src/Core/Scene/CScene.h @@ -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 mModelNodes; - std::vector mStaticNodes; - std::vector mCollisionNodes; - std::vector mScriptNodes; - std::vector mLightNodes; + u32 mNumNodes; CRootNode *mpSceneRootNode; + std::unordered_map> mNodes; TResPtr mpArea; TResPtr mpWorld; @@ -37,7 +34,6 @@ class CScene // Environment std::vector mAreaAttributesObjects; - CAreaAttributes *mpActiveAreaAttributes; // Objects std::unordered_map 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); diff --git a/src/Core/Scene/CSceneNode.h b/src/Core/Scene/CSceneNode.h index da0c2236..917c279d 100644 --- a/src/Core/Scene/CSceneNode.h +++ b/src/Core/Scene/CSceneNode.h @@ -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; } diff --git a/src/Core/Scene/CScriptNode.cpp b/src/Core/Scene/CScriptNode.cpp index e0d33227..45dbe0c1 100644 --- a/src/Core/Scene/CScriptNode.cpp +++ b/src/Core/Scene/CScriptNode.cpp @@ -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 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 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 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 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; } diff --git a/src/Core/Scene/EVisibilityFlags.h b/src/Core/Scene/EVisibilityFlags.h deleted file mode 100644 index 9139af71..00000000 --- a/src/Core/Scene/EVisibilityFlags.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef EVISIBILITYFLAGS -#define EVISIBILITYFLAGS - -#include - -enum EVisibilityFlags -{ - eShowNomr = 0x00, - eShowWorld = 0x01, - eShowWorldCollision = 0x02, - eShowObjects = 0x04, - eShowObjectCollision = 0x08, - eShowLights = 0x10, - eShowAll = 0x1F -}; -DEFINE_ENUM_FLAGS(EVisibilityFlags) - -#endif // EVISIBILITYFLAGS - diff --git a/src/Core/Scene/FShowFlags.cpp b/src/Core/Scene/FShowFlags.cpp new file mode 100644 index 00000000..ba3f1fe0 --- /dev/null +++ b/src/Core/Scene/FShowFlags.cpp @@ -0,0 +1,3 @@ +#include "FShowFlags.h" + +const FShowFlags gkGameModeShowFlags = eShowWorld | eShowObjectGeometry | eShowSky; diff --git a/src/Core/Scene/FShowFlags.h b/src/Core/Scene/FShowFlags.h new file mode 100644 index 00000000..a2913306 --- /dev/null +++ b/src/Core/Scene/FShowFlags.h @@ -0,0 +1,23 @@ +#ifndef FSHOWFLAGS +#define FSHOWFLAGS + +#include + +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 + diff --git a/src/Core/ScriptExtra/CDamageableTriggerExtra.cpp b/src/Core/ScriptExtra/CDamageableTriggerExtra.cpp index cf31ab65..8e7bd4bf 100644 --- a/src/Core/ScriptExtra/CDamageableTriggerExtra.cpp +++ b/src/Core/ScriptExtra/CDamageableTriggerExtra.cpp @@ -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())) diff --git a/src/Core/ScriptExtra/CDoorExtra.cpp b/src/Core/ScriptExtra/CDoorExtra.cpp index a85fd6f4..5fd070fa 100644 --- a/src/Core/ScriptExtra/CDoorExtra.cpp +++ b/src/Core/ScriptExtra/CDoorExtra.cpp @@ -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())) { diff --git a/src/Core/ScriptExtra/CRadiusSphereExtra.cpp b/src/Core/ScriptExtra/CRadiusSphereExtra.cpp index 2365573a..fce173a8 100644 --- a/src/Core/ScriptExtra/CRadiusSphereExtra.cpp +++ b/src/Core/ScriptExtra/CRadiusSphereExtra.cpp @@ -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(); diff --git a/src/Core/ScriptExtra/CWaypointExtra.cpp b/src/Core/ScriptExtra/CWaypointExtra.cpp index f4a2bcdd..f80ef2a5 100644 --- a/src/Core/ScriptExtra/CWaypointExtra.cpp +++ b/src/Core/ScriptExtra/CWaypointExtra.cpp @@ -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++) { diff --git a/src/Editor/CBasicViewport.cpp b/src/Editor/CBasicViewport.cpp index 3e0fb11c..eeb5695b 100644 --- a/src/Editor/CBasicViewport.cpp +++ b/src/Editor/CBasicViewport.cpp @@ -17,6 +17,7 @@ CBasicViewport::CBasicViewport(QWidget *pParent) : { setMouseTracking(true); mCamera.SetAspectRatio((float) width() / height()); + mViewInfo.ShowFlags = eShowAll; mViewInfo.pCamera = &mCamera; mViewInfo.GameMode = false; } diff --git a/src/Editor/CSceneViewport.cpp b/src/Editor/CSceneViewport.cpp index 5d683b58..e7ca4e2d 100644 --- a/src/Editor/CSceneViewport.cpp +++ b/src/Editor/CSceneViewport.cpp @@ -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() diff --git a/src/Editor/CSceneViewport.h b/src/Editor/CSceneViewport.h index e701b5d3..d6351211 100644 --- a/src/Editor/CSceneViewport.h +++ b/src/Editor/CSceneViewport.h @@ -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(); diff --git a/src/Editor/WorldEditor/CWorldEditor.cpp b/src/Editor/WorldEditor/CWorldEditor.cpp index 28c48721..e7b424db 100644 --- a/src/Editor/WorldEditor/CWorldEditor.cpp +++ b/src/Editor/WorldEditor/CWorldEditor.cpp @@ -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() diff --git a/src/Editor/WorldEditor/CWorldEditor.ui b/src/Editor/WorldEditor/CWorldEditor.ui index a032e535..9aff7622 100644 --- a/src/Editor/WorldEditor/CWorldEditor.ui +++ b/src/Editor/WorldEditor/CWorldEditor.ui @@ -354,7 +354,7 @@ QTabWidget::Rounded - 2 + 1