Added support for loading DCLN files and displaying them in the World Editor

This commit is contained in:
parax0 2015-09-26 16:55:14 -06:00
parent 19b3ae59be
commit 07d7f14dc7
45 changed files with 541 additions and 305 deletions

View File

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

View File

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

View File

@ -262,12 +262,7 @@ std::pair<bool,float> RayTriangleIntersection(const CRay& Ray,
if (!AllowBackfaces) if (!AllowBackfaces)
return std::pair<bool,float>(false, 0); return std::pair<bool,float>(false, 0);
} }
else if (denom < - std::numeric_limits<float>::epsilon()) else if (denom >= - std::numeric_limits<float>::epsilon())
{
if (false)
return std::pair<bool,float>(false, 0);
}
else
{ {
// Parallel or triangle area is close to zero when // Parallel or triangle area is close to zero when
// the plane normal not normalised. // the plane normal not normalised.

View File

@ -20,7 +20,8 @@ u32 CRenderer::sNumRenderers = 0;
// ************ INITIALIZATION ************ // ************ INITIALIZATION ************
CRenderer::CRenderer() CRenderer::CRenderer()
{ {
mOptions = eEnableUVScroll | eEnableBackfaceCull; mOptions = eDrawWorld | eDrawObjects | eDrawLights | eDrawSky |
eEnableUVScroll | eEnableBackfaceCull;
mBloomMode = eNoBloom; mBloomMode = eNoBloom;
mDrawGrid = true; mDrawGrid = true;
mInitialized = false; mInitialized = false;
@ -53,9 +54,45 @@ void CRenderer::Init()
} }
// ************ GETTERS/SETTERS ************ // ************ GETTERS/SETTERS ************
bool CRenderer::IsUVAnimationOn() ERenderOptions CRenderer::RenderOptions()
{ {
return ((mOptions & eUVScroll) != 0); 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) void CRenderer::ToggleBackfaceCull(bool b)

View File

@ -53,7 +53,13 @@ public:
void Init(); void Init();
// Getters/Setters // Getters/Setters
bool IsUVAnimationOn(); ERenderOptions RenderOptions();
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 ToggleBackfaceCull(bool b);
void ToggleUVAnimation(bool b); void ToggleUVAnimation(bool b);
void ToggleGrid(bool b); void ToggleGrid(bool b);

View File

@ -150,6 +150,7 @@ CResource* CResCache::GetResource(CUniqueID ResID, CFourCC type)
else if (type == "STRG") Res = CStringLoader::LoadSTRG(mem); else if (type == "STRG") Res = CStringLoader::LoadSTRG(mem);
else if (type == "FONT") Res = CFontLoader::LoadFONT(mem); else if (type == "FONT") Res = CFontLoader::LoadFONT(mem);
else if (type == "SCAN") Res = CScanLoader::LoadSCAN(mem); else if (type == "SCAN") Res = CScanLoader::LoadSCAN(mem);
else if (type == "DCLN") Res = CCollisionLoader::LoadDCLN(mem);
else SupportedFormat = false; else SupportedFormat = false;
// Log errors // Log errors
@ -201,6 +202,7 @@ CResource* CResCache::GetResource(std::string ResPath)
else if (type == "MLVL") Res = CWorldLoader::LoadMLVL(file); else if (type == "MLVL") Res = CWorldLoader::LoadMLVL(file);
else if (type == "FONT") Res = CFontLoader::LoadFONT(file); else if (type == "FONT") Res = CFontLoader::LoadFONT(file);
else if (type == "SCAN") Res = CScanLoader::LoadSCAN(file); else if (type == "SCAN") Res = CScanLoader::LoadSCAN(file);
else if (type == "DCLN") Res = CCollisionLoader::LoadDCLN(file);
else SupportedFormat = false; else SupportedFormat = false;
if (!Res) Res = new CResource(); // Default for unsupported formats if (!Res) Res = new CResource(); // Default for unsupported formats

View File

@ -19,10 +19,6 @@
*/ */
CSceneManager::CSceneManager() CSceneManager::CSceneManager()
{ {
mShowTerrain = true;
mShowCollision = false;
mShowObjects = true;
mShowLights = true;
mSplitTerrain = true; mSplitTerrain = true;
mNodeCount = 0; mNodeCount = 0;
mpSceneRootNode = new CRootNode(this, nullptr); mpSceneRootNode = new CRootNode(this, nullptr);
@ -56,7 +52,7 @@ CStaticNode* CSceneManager::AddStaticModel(CStaticModel *mdl)
return node; return node;
} }
CCollisionNode* CSceneManager::AddCollision(CCollisionMesh *mesh) CCollisionNode* CSceneManager::AddCollision(CCollisionMeshGroup *mesh)
{ {
if (mesh == nullptr) return nullptr; if (mesh == nullptr) return nullptr;
@ -143,7 +139,7 @@ void CSceneManager::SetActiveArea(CGameArea* _area)
switch (pObj->ObjectTypeID()) switch (pObj->ObjectTypeID())
{ {
case 0x4E: // MP1 AreaAttributes ID case 0x4E: // MP1 AreaAttributes ID
case 0x52454141: // MP2 AreaAttributes ID ("REAA") case 0x52454141: // MP2/MP3/DKCR AreaAttributes ID ("REAA")
mAreaAttributesObjects.emplace_back( CAreaAttributes(pObj) ); mAreaAttributesObjects.emplace_back( CAreaAttributes(pObj) );
break; break;
} }
@ -221,7 +217,9 @@ void CSceneManager::ClearScene()
void CSceneManager::AddSceneToRenderer(CRenderer *pRenderer) void CSceneManager::AddSceneToRenderer(CRenderer *pRenderer)
{ {
if (mShowTerrain) ERenderOptions options = pRenderer->RenderOptions();
if (options & eDrawWorld)
{ {
for (u32 n = 0; n < mModelNodes.size(); n++) for (u32 n = 0; n < mModelNodes.size(); n++)
if (mModelNodes[n]->IsVisible()) if (mModelNodes[n]->IsVisible())
@ -232,29 +230,29 @@ void CSceneManager::AddSceneToRenderer(CRenderer *pRenderer)
mStaticNodes[n]->AddToRenderer(pRenderer); mStaticNodes[n]->AddToRenderer(pRenderer);
} }
if (mShowCollision) if (options & eDrawWorldCollision)
{ {
for (u32 n = 0; n < mCollisionNodes.size(); n++) for (u32 n = 0; n < mCollisionNodes.size(); n++)
if (mCollisionNodes[n]->IsVisible()) if (mCollisionNodes[n]->IsVisible())
mCollisionNodes[n]->AddToRenderer(pRenderer); mCollisionNodes[n]->AddToRenderer(pRenderer);
} }
if (mShowObjects) if (options & eDrawLights)
{
for (u32 n = 0; n < mScriptNodes.size(); n++)
if (mScriptNodes[n]->IsVisible())
mScriptNodes[n]->AddToRenderer(pRenderer);
}
if (mShowLights)
{ {
for (u32 n = 0; n < mLightNodes.size(); n++) for (u32 n = 0; n < mLightNodes.size(); n++)
if (mLightNodes[n]->IsVisible()) if (mLightNodes[n]->IsVisible())
mLightNodes[n]->AddToRenderer(pRenderer); mLightNodes[n]->AddToRenderer(pRenderer);
} }
if ((options & eDrawObjects) || (options & eDrawObjectCollision))
{
for (u32 n = 0; n < mScriptNodes.size(); n++)
if (mScriptNodes[n]->IsVisible())
mScriptNodes[n]->AddToRenderer(pRenderer);
}
} }
SRayIntersection CSceneManager::SceneRayCast(const CRay& Ray) SRayIntersection CSceneManager::SceneRayCast(const CRay& Ray, ERenderOptions renderOptions)
{ {
// Terribly hacky stuff to avoid having tons of redundant code // Terribly hacky stuff to avoid having tons of redundant code
// because I'm too lazy to rewrite CSceneManager right now and fix it // because I'm too lazy to rewrite CSceneManager right now and fix it
@ -267,7 +265,8 @@ SRayIntersection CSceneManager::SceneRayCast(const CRay& Ray)
reinterpret_cast<std::vector<CSceneNode*>*>(&mLightNodes), reinterpret_cast<std::vector<CSceneNode*>*>(&mLightNodes),
}; };
bool NodesVisible[5] = { bool NodesVisible[5] = {
true, mShowTerrain, mShowCollision, mShowObjects, mShowLights true, ((renderOptions & eDrawWorld) != 0), ((renderOptions & eDrawWorldCollision) != 0),
((renderOptions & ((ERenderOptions) (eDrawObjects | eDrawObjectCollision))) != 0), ((renderOptions & eDrawLights) != 0)
}; };
// Less hacky stuff // Less hacky stuff
@ -284,7 +283,7 @@ SRayIntersection CSceneManager::SceneRayCast(const CRay& Ray)
vec[iNode]->RayAABoxIntersectTest(Tester); vec[iNode]->RayAABoxIntersectTest(Tester);
} }
return Tester.TestNodes(); return Tester.TestNodes(renderOptions);
} }
void CSceneManager::PickEnvironmentObjects() void CSceneManager::PickEnvironmentObjects()
@ -343,43 +342,3 @@ CGameArea* CSceneManager::GetActiveArea()
{ {
return mpArea; return mpArea;
} }
void CSceneManager::SetWorld(bool on)
{
mShowTerrain = on;
}
void CSceneManager::SetCollision(bool on)
{
mShowCollision = on;
}
void CSceneManager::SetLights(bool on)
{
mShowLights = on;
}
void CSceneManager::SetObjects(bool on)
{
mShowObjects = on;
}
bool CSceneManager::IsTerrainEnabled()
{
return mShowTerrain;
}
bool CSceneManager::IsCollisionEnabled()
{
return mShowCollision;
}
bool CSceneManager::AreLightsEnabled()
{
return mShowLights;
}
bool CSceneManager::AreScriptObjectsEnabled()
{
return mShowObjects;
}

View File

@ -21,10 +21,6 @@
class CSceneManager class CSceneManager
{ {
bool mShowTerrain;
bool mShowCollision;
bool mShowObjects;
bool mShowLights;
bool mSplitTerrain; bool mSplitTerrain;
u32 mNodeCount; u32 mNodeCount;
@ -55,14 +51,14 @@ public:
// Scene Management // Scene Management
CModelNode* AddModel(CModel *mdl); CModelNode* AddModel(CModel *mdl);
CStaticNode* AddStaticModel(CStaticModel *mdl); CStaticNode* AddStaticModel(CStaticModel *mdl);
CCollisionNode* AddCollision(CCollisionMesh *mesh); CCollisionNode* AddCollision(CCollisionMeshGroup *mesh);
CScriptNode* AddScriptObject(CScriptObject *obj); CScriptNode* AddScriptObject(CScriptObject *obj);
CLightNode* AddLight(CLight *Light); CLightNode* AddLight(CLight *Light);
void SetActiveArea(CGameArea *_area); void SetActiveArea(CGameArea *_area);
void SetActiveWorld(CWorld *_world); void SetActiveWorld(CWorld *_world);
void ClearScene(); void ClearScene();
void AddSceneToRenderer(CRenderer *pRenderer); void AddSceneToRenderer(CRenderer *pRenderer);
SRayIntersection SceneRayCast(const CRay& Ray); SRayIntersection SceneRayCast(const CRay& Ray, ERenderOptions renderOptions);
void PickEnvironmentObjects(); void PickEnvironmentObjects();
CScriptNode* ScriptNodeByID(u32 InstanceID); CScriptNode* ScriptNodeByID(u32 InstanceID);
CScriptNode* NodeForObject(CScriptObject *pObj); CScriptNode* NodeForObject(CScriptObject *pObj);
@ -71,17 +67,6 @@ public:
// Setters/Getters // Setters/Getters
CModel* GetActiveSkybox(); CModel* GetActiveSkybox();
CGameArea* GetActiveArea(); CGameArea* GetActiveArea();
void SetBackfaceCulling(bool on);
void SetWorld(bool on);
void SetCollision(bool on);
void SetObjects(bool on);
void SetLights(bool on);
bool IsBackfaceCullEnabled();
bool IsTerrainEnabled();
bool IsCollisionEnabled();
bool AreLightsEnabled();
bool AreScriptObjectsEnabled();
}; };
#endif // CSCENEMANAGER_H #endif // CSCENEMANAGER_H

View File

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

View File

@ -1,7 +1,7 @@
#include "CCollisionMesh.h" #include "CCollisionMesh.h"
#include <Core/CRenderer.h> #include <Core/CRenderer.h>
CCollisionMesh::CCollisionMesh() : CResource() CCollisionMesh::CCollisionMesh()
{ {
mVBO.SetVertexDesc(ePosition); mVBO.SetVertexDesc(ePosition);
mVertexCount = 0; mVertexCount = 0;
@ -21,11 +21,6 @@ CCollisionMesh::~CCollisionMesh()
} }
} }
EResType CCollisionMesh::Type()
{
return eCollisionMesh;
}
void CCollisionMesh::BufferGL() void CCollisionMesh::BufferGL()
{ {
if (mBuffered) if (mBuffered)
@ -88,7 +83,7 @@ void CCollisionMesh::Draw()
mVBO.Unbind(); mVBO.Unbind();
} }
void CCollisionMesh::DrawLines() void CCollisionMesh::DrawWireframe()
{ {
if (!mBuffered) BufferGL(); if (!mBuffered) BufferGL();

View File

@ -6,7 +6,7 @@
#include <OpenGL/CIndexBuffer.h> #include <OpenGL/CIndexBuffer.h>
#include "CResource.h" #include "CResource.h"
class CCollisionMesh : public CResource class CCollisionMesh
{ {
friend class CCollisionLoader; friend class CCollisionLoader;
@ -79,11 +79,10 @@ class CCollisionMesh : public CResource
public: public:
CCollisionMesh(); CCollisionMesh();
~CCollisionMesh(); ~CCollisionMesh();
EResType Type();
void BufferGL(); void BufferGL();
void Draw(); void Draw();
void DrawLines(); void DrawWireframe();
}; };
#endif // CCOLLISIONMESH_H #endif // CCOLLISIONMESH_H

View File

@ -0,0 +1,43 @@
#include "CCollisionMeshGroup.h"
CCollisionMeshGroup::CCollisionMeshGroup()
{
}
CCollisionMeshGroup::~CCollisionMeshGroup()
{
for (auto it = mMeshes.begin(); it != mMeshes.end(); it++)
delete *it;
}
EResType CCollisionMeshGroup::Type()
{
return eCollisionMeshGroup;
}
u32 CCollisionMeshGroup::NumMeshes()
{
return mMeshes.size();
}
CCollisionMesh* CCollisionMeshGroup::MeshByIndex(u32 index)
{
return mMeshes[index];
}
void CCollisionMeshGroup::AddMesh(CCollisionMesh *pMesh)
{
mMeshes.push_back(pMesh);
}
void CCollisionMeshGroup::Draw()
{
for (auto it = mMeshes.begin(); it != mMeshes.end(); it++)
(*it)->Draw();
}
void CCollisionMeshGroup::DrawWireframe()
{
for (auto it = mMeshes.begin(); it != mMeshes.end(); it++)
(*it)->DrawWireframe();
}

View File

@ -0,0 +1,25 @@
#ifndef CCOLLISIONMESHGROUP_H
#define CCOLLISIONMESHGROUP_H
#include "CResource.h"
#include "CCollisionMesh.h"
#include <Core/CToken.h>
#include <vector>
class CCollisionMeshGroup : public CResource
{
std::vector<CCollisionMesh*> mMeshes;
public:
CCollisionMeshGroup();
~CCollisionMeshGroup();
EResType Type();
u32 NumMeshes();
CCollisionMesh* MeshByIndex(u32 index);
void AddMesh(CCollisionMesh *pMesh);
void Draw();
void DrawWireframe();
};
#endif // CCOLLISIONMESHGROUP_H

View File

@ -135,7 +135,7 @@ CStaticModel* CGameArea::GetStaticModel(u32 mdl)
return mStaticTerrainModels[mdl]; return mStaticTerrainModels[mdl];
} }
CCollisionMesh* CGameArea::GetCollision() CCollisionMeshGroup* CGameArea::GetCollision()
{ {
return mCollision; return mCollision;
} }

View File

@ -1,7 +1,7 @@
#ifndef CGAMEAREA_H #ifndef CGAMEAREA_H
#define CGAMEAREA_H #define CGAMEAREA_H
#include "CCollisionMesh.h" #include "CCollisionMeshGroup.h"
#include "CLight.h" #include "CLight.h"
#include "CMaterialSet.h" #include "CMaterialSet.h"
#include "model/CModel.h" #include "model/CModel.h"
@ -32,7 +32,7 @@ class CGameArea : public CResource
std::unordered_map<u32, CScriptObject*> mObjectMap; std::unordered_map<u32, CScriptObject*> mObjectMap;
// Collision // Collision
CCollisionMesh *mCollision; CCollisionMeshGroup *mCollision;
// Lights // Lights
std::vector<std::vector<CLight*>> mLightLayers; std::vector<std::vector<CLight*>> mLightLayers;
@ -52,7 +52,7 @@ public:
u32 GetStaticModelCount(); u32 GetStaticModelCount();
CModel* GetTerrainModel(u32 mdl); CModel* GetTerrainModel(u32 mdl);
CStaticModel* GetStaticModel(u32 mdl); CStaticModel* GetStaticModel(u32 mdl);
CCollisionMesh* GetCollision(); CCollisionMeshGroup* GetCollision();
u32 GetScriptLayerCount(); u32 GetScriptLayerCount();
CScriptLayer* GetScriptLayer(u32 index); CScriptLayer* GetScriptLayer(u32 index);
CScriptLayer* GetGeneratorLayer(); CScriptLayer* GetGeneratorLayer();

View File

@ -72,7 +72,7 @@ EResType CResource::ResTypeForExtension(CFourCC Extension)
if (Extension == "CSMP") return eAudioSample; if (Extension == "CSMP") return eAudioSample;
if (Extension == "CSNG") return eMidi; if (Extension == "CSNG") return eMidi;
if (Extension == "CTWK") return eTweak; if (Extension == "CTWK") return eTweak;
if (Extension == "DCLN") return eCollisionMesh; if (Extension == "DCLN") return eCollisionMeshGroup;
if (Extension == "DGRP") return eDependencyGroup; if (Extension == "DGRP") return eDependencyGroup;
if (Extension == "DSP ") return eMusicTrack; if (Extension == "DSP ") return eMusicTrack;
if (Extension == "DUMB") return eDataDump; if (Extension == "DUMB") return eDataDump;

View File

@ -13,7 +13,7 @@ enum EResType
eAudioStream = 7, eAudioStream = 7,
eAudioTable = 8, eAudioTable = 8,
eCharacter = 9, eCharacter = 9,
eCollisionMesh = 10, eCollisionMeshGroup = 10,
eCollisionResponse = 11, eCollisionResponse = 11,
eDataDump = 12, eDataDump = 12,
eDecal = 13, eDecal = 13,

View File

@ -262,8 +262,15 @@ void CTemplateWriter::SaveScriptTemplate(CScriptTemplate *pTemp, const std::stri
for (auto it = pTemp->mAssets.begin(); it != pTemp->mAssets.end(); it++) for (auto it = pTemp->mAssets.begin(); it != pTemp->mAssets.end(); it++)
{ {
std::string type = (it->AssetType == CScriptTemplate::SEditorAsset::eAnimParams ? "animparams" : "model");
std::string source = (it->AssetSource == CScriptTemplate::SEditorAsset::eFile ? "file" : "property"); std::string source = (it->AssetSource == CScriptTemplate::SEditorAsset::eFile ? "file" : "property");
std::string type;
switch (it->AssetType)
{
case CScriptTemplate::SEditorAsset::eModel: type = "model"; break;
case CScriptTemplate::SEditorAsset::eAnimParams: type = "animparams"; break;
case CScriptTemplate::SEditorAsset::eCollision: type = "collision"; break;
}
s32 force = -1; s32 force = -1;
if (it->AssetSource == CScriptTemplate::SEditorAsset::eAnimParams) force = it->ForceNodeIndex; if (it->AssetSource == CScriptTemplate::SEditorAsset::eAnimParams) force = it->ForceNodeIndex;

View File

@ -6,131 +6,213 @@ CCollisionLoader::CCollisionLoader()
{ {
} }
CCollisionMesh* CCollisionLoader::LoadAreaCollision(CInputStream& MREA) CCollisionMesh::CCollisionOctree* CCollisionLoader::ParseOctree(CInputStream&)
{
// Not using: Parameter 1 (CInputStream& - src)
return nullptr;
}
CCollisionMesh::CCollisionOctree::SBranch* CCollisionLoader::ParseOctreeBranch(CInputStream&)
{
// Not using: Parameter 1 (CInputStream& - src)
return nullptr;
}
CCollisionMesh::CCollisionOctree::SLeaf* CCollisionLoader::ParseOctreeLeaf(CInputStream&)
{
// Not using: Parameter 1 (CInputStream& - src)
return nullptr;
}
void CCollisionLoader::ParseOBBNode(CInputStream& DCLN)
{
bool b = false;
while (b == false)
{
DCLN.Seek(0x3C, SEEK_CUR);
b = (DCLN.ReadByte() == 1);
if (!b) ParseOBBNode(DCLN);
}
u32 numFaces = DCLN.ReadLong();
DCLN.Seek(numFaces * 2, SEEK_CUR);
}
void CCollisionLoader::ReadPropertyFlags(CInputStream& src)
{
CCollisionMesh::SCollisionProperties property;
if (mVersion == ePrime)
{
u32 flag = src.ReadLong();
property.Invert = (flag >> 25) & 0x1;
}
if (mVersion == eEchoes)
{
u64 flag = src.ReadLongLong();
property.Invert = (flag >> 24) & 0x1;
}
mProperties.push_back(property);
}
void CCollisionLoader::LoadCollisionIndices(CInputStream &file, bool buildAABox)
{
// Properties
u32 propSetCount = file.ReadLong();
for (u32 iProp = 0; iProp < propSetCount; iProp++)
ReadPropertyFlags(file);
// Property indices for vertices/lines/faces
u32 vtxIndexCount = file.ReadLong();
std::vector<u8> vtxIndices(vtxIndexCount);
file.ReadBytes(vtxIndices.data(), vtxIndices.size());
u32 lineIndexCount = file.ReadLong();
std::vector<u8> lineIndices(lineIndexCount);
file.ReadBytes(lineIndices.data(), lineIndices.size());
u32 faceIndexCount = file.ReadLong();
std::vector<u8> faceIndices(faceIndexCount);
file.ReadBytes(faceIndices.data(), faceIndices.size());
// Lines
mpMesh->mLineCount = file.ReadLong();
mpMesh->mCollisionLines.resize(mpMesh->mLineCount);
for (u32 iLine = 0; iLine < mpMesh->mLineCount; iLine++)
{
CCollisionMesh::CCollisionLine *pLine = &mpMesh->mCollisionLines[iLine];
pLine->Vertices[0] = file.ReadShort();
pLine->Vertices[1] = file.ReadShort();
pLine->Properties = mProperties[lineIndices[iLine]];
}
// Faces
mpMesh->mFaceCount = file.ReadLong() / 3; // Not sure why they store it this way. It's inconsistent.
mpMesh->mCollisionFaces.resize(mpMesh->mFaceCount);
for (u32 iFace = 0; iFace < mpMesh->mFaceCount; iFace++)
{
CCollisionMesh::CCollisionFace *pFace = &mpMesh->mCollisionFaces[iFace];
pFace->Lines[0] = file.ReadShort();
pFace->Lines[1] = file.ReadShort();
pFace->Lines[2] = file.ReadShort();
pFace->Properties = mProperties[faceIndices[iFace]];
}
// Echoes introduces a new data chunk; don't know what it is yet, skipping for now
if (mVersion == eEchoes)
{
u32 unknownCount = file.ReadLong();
file.Seek(unknownCount * 2, SEEK_CUR);
}
// Vertices
mpMesh->mVertexCount = file.ReadLong();
mpMesh->mCollisionVertices.resize(mpMesh->mVertexCount);
CAABox bounds;
for (u32 iVtx = 0; iVtx < mpMesh->mVertexCount; iVtx++)
{
CCollisionMesh::CCollisionVertex *pVtx = &mpMesh->mCollisionVertices[iVtx];
pVtx->Pos = CVector3f(file);
pVtx->Properties = mProperties[vtxIndices[iVtx]];
if (buildAABox) bounds.ExpandBounds(pVtx->Pos);
}
if (buildAABox) mpMesh->mAABox = bounds;
}
// ************ STATIC ************
CCollisionMeshGroup* CCollisionLoader::LoadAreaCollision(CInputStream& MREA)
{ {
if (!MREA.IsValid()) return nullptr; if (!MREA.IsValid()) return nullptr;
CCollisionLoader loader; CCollisionLoader loader;
MREA.Seek(0x8, SEEK_CUR); MREA.Seek(0x8, SEEK_CUR);
u32 deafbabe = MREA.ReadLong(); u32 deafbabe = MREA.ReadLong();
if (deafbabe != 0xdeafbabe) if (deafbabe != 0xDEAFBABE)
{ {
Log::FileError(MREA.GetSourceString(), MREA.Tell() - 4, "Invalid collision magic: " + StringUtil::ToHexString(deafbabe)); Log::FileError(MREA.GetSourceString(), MREA.Tell() - 4, "Invalid collision magic: " + StringUtil::ToHexString(deafbabe));
return nullptr; return nullptr;
} }
u32 version = MREA.ReadLong(); u32 version = MREA.ReadLong();
loader.version = ECollisionVersion(version); loader.mVersion = GetFormatVersion(version);
if ((loader.version != Prime) && (loader.version != Echoes)) if ((loader.mVersion != ePrime) && (loader.mVersion != eEchoes))
{ {
Log::FileError(MREA.GetSourceString(), MREA.Tell() - 4, "Unsupported collision version: " + StringUtil::ToHexString(version)); Log::FileError(MREA.GetSourceString(), MREA.Tell() - 4, "Unsupported collision version: " + StringUtil::ToHexString(version));
return nullptr; return nullptr;
} }
loader.mesh = new CCollisionMesh; loader.mpGroup = new CCollisionMeshGroup;
CCollisionMesh *cmesh = loader.mesh; loader.mpMesh = new CCollisionMesh;
// Octree - structure is known, but not coding this right now // Octree - structure is known, but not coding this right now
cmesh->mAABox = CAABox(MREA); loader.mpMesh->mAABox = CAABox(MREA);
MREA.Seek(0x4, SEEK_CUR); MREA.Seek(0x4, SEEK_CUR);
u32 octreeSize = MREA.ReadLong(); u32 octreeSize = MREA.ReadLong();
MREA.Seek(octreeSize, SEEK_CUR); // Skipping the octree for now MREA.Seek(octreeSize, SEEK_CUR); // Skipping the octree for now
cmesh->mOctreeLoaded = false; loader.mpMesh->mOctreeLoaded = false;
// Properties // Read collision indices and return
u32 propertySetCount = MREA.ReadLong(); loader.LoadCollisionIndices(MREA, false);
for (u32 p = 0; p < propertySetCount; p++) loader.mpGroup->AddMesh(loader.mpMesh);
loader.readPropertyFlags(MREA); return loader.mpGroup;
// Property indices for vertices/lines/faces
u32 vtxIndexCount = MREA.ReadLong();
std::vector<u8> vtxIndices(vtxIndexCount);
MREA.ReadBytes(vtxIndices.data(), vtxIndices.size());
u32 lineIndexCount = MREA.ReadLong();
std::vector<u8> lineIndices(lineIndexCount);
MREA.ReadBytes(lineIndices.data(), lineIndices.size());
u32 faceIndexCount = MREA.ReadLong();
std::vector<u8> faceIndices(faceIndexCount);
MREA.ReadBytes(faceIndices.data(), faceIndices.size());
// Lines
cmesh->mLineCount = MREA.ReadLong();
cmesh->mCollisionLines.resize(cmesh->mLineCount);
for (u32 l = 0; l < cmesh->mLineCount; l++)
{
CCollisionMesh::CCollisionLine *Line = &cmesh->mCollisionLines[l];
Line->Vertices[0] = MREA.ReadShort();
Line->Vertices[1] = MREA.ReadShort();
Line->Properties = loader.properties[lineIndices[l]];
}
// Faces
cmesh->mFaceCount = MREA.ReadLong() / 3; // Not sure why they store it this way. It's inconsistent.
cmesh->mCollisionFaces.resize(cmesh->mFaceCount);
for (u32 f = 0; f < cmesh->mFaceCount; f++)
{
CCollisionMesh::CCollisionFace *face = &cmesh->mCollisionFaces[f];
face->Lines[0] = MREA.ReadShort();
face->Lines[1] = MREA.ReadShort();
face->Lines[2] = MREA.ReadShort();
face->Properties = loader.properties[faceIndices[f]];
}
// Echoes introduces a new data chunk; don't know what it is yet, skipping for now
if (loader.version == Echoes)
{
u32 unknown_count = MREA.ReadLong();
MREA.Seek(unknown_count * 2, SEEK_CUR);
}
// Vertices
cmesh->mVertexCount = MREA.ReadLong();
cmesh->mCollisionVertices.resize(cmesh->mVertexCount);
for (u32 v = 0; v < cmesh->mVertexCount; v++)
{
CCollisionMesh::CCollisionVertex *vtx = &cmesh->mCollisionVertices[v];
vtx->Pos = CVector3f(MREA);
vtx->Properties = loader.properties[vtxIndices[v]];
}
return cmesh;
} }
CCollisionMesh::CCollisionOctree* CCollisionLoader::parseOctree(CInputStream&) CCollisionMeshGroup* CCollisionLoader::LoadDCLN(CInputStream &DCLN)
{ {
// Not using: Parameter 1 (CInputStream& - src) if (!DCLN.IsValid()) return nullptr;
return nullptr;
}
CCollisionMesh::CCollisionOctree::SBranch* CCollisionLoader::parseOctreeBranch(CInputStream&) CCollisionLoader loader;
{ loader.mpGroup = new CCollisionMeshGroup;
// Not using: Parameter 1 (CInputStream& - src)
return nullptr;
}
CCollisionMesh::CCollisionOctree::SLeaf* CCollisionLoader::parseOctreeLeaf(CInputStream&) u32 numMeshes = DCLN.ReadLong();
{
// Not using: Parameter 1 (CInputStream& - src)
return nullptr;
}
void CCollisionLoader::readPropertyFlags(CInputStream& src) for (u32 iMesh = 0; iMesh < numMeshes; iMesh++)
{
CCollisionMesh::SCollisionProperties property;
if (version == Prime)
{ {
u32 flag = src.ReadLong(); u32 deafbabe = DCLN.ReadLong();
property.Invert = (flag >> 25) & 0x1;
}
if (version == Echoes) if (deafbabe != 0xDEAFBABE)
{ {
u64 flag = src.ReadLongLong(); Log::FileError(DCLN.GetSourceString(), DCLN.Tell() - 4, "Invalid collision magic: " + StringUtil::ToHexString(deafbabe));
property.Invert = (flag >> 24) & 0x1; delete loader.mpGroup;
} return nullptr;
}
properties.push_back(property); u32 version = DCLN.ReadLong();
loader.mVersion = GetFormatVersion(version);
if ((loader.mVersion != ePrime) && (loader.mVersion != eEchoes))
{
Log::FileError(DCLN.GetSourceString(), DCLN.Tell() - 4, "Unsupported collision version: " + StringUtil::ToHexString(version));
return nullptr;
}
loader.mpMesh = new CCollisionMesh;
loader.mpMesh->mOctreeLoaded = false;
// Read indices and return
DCLN.Seek(0x4, SEEK_CUR);
loader.LoadCollisionIndices(DCLN, true);
loader.mpGroup->AddMesh(loader.mpMesh);
// Parse OBB tree
loader.ParseOBBNode(DCLN);
}
return loader.mpGroup;
}
EGame CCollisionLoader::GetFormatVersion(u32 version)
{
switch (version)
{
case 0x2: return ePrime;
case 0x3: return ePrime;
case 0x4: return eEchoes;
case 0x5: return eReturns;
default: return eUnknownVersion;
}
} }

View File

@ -2,30 +2,28 @@
#define CCOLLISIONLOADER_H #define CCOLLISIONLOADER_H
#include "../CCollisionMesh.h" #include "../CCollisionMesh.h"
#include "../CCollisionMeshGroup.h"
#include "../EFormatVersion.h"
class CCollisionLoader class CCollisionLoader
{ {
enum ECollisionVersion; CCollisionMeshGroup *mpGroup;
CCollisionMesh *mpMesh;
CCollisionMesh *mesh; EGame mVersion;
ECollisionVersion version; std::vector<CCollisionMesh::SCollisionProperties> mProperties;
std::vector<CCollisionMesh::SCollisionProperties> properties;
enum ECollisionVersion
{
Prime = 0x3,
Echoes = 0x4,
DonkeyKongCountryReturns = 0x5
};
CCollisionLoader(); CCollisionLoader();
CCollisionMesh::CCollisionOctree* parseOctree(CInputStream& src); CCollisionMesh::CCollisionOctree* ParseOctree(CInputStream& src);
CCollisionMesh::CCollisionOctree::SBranch* parseOctreeBranch(CInputStream& src); CCollisionMesh::CCollisionOctree::SBranch* ParseOctreeBranch(CInputStream& src);
CCollisionMesh::CCollisionOctree::SLeaf* parseOctreeLeaf(CInputStream& src); CCollisionMesh::CCollisionOctree::SLeaf* ParseOctreeLeaf(CInputStream& src);
void readPropertyFlags(CInputStream& src); void ParseOBBNode(CInputStream& DCLN);
void ReadPropertyFlags(CInputStream& src);
void LoadCollisionIndices(CInputStream& file, bool buildAABox);
public: public:
static CCollisionMesh* LoadAreaCollision(CInputStream& MREA); static CCollisionMeshGroup* LoadAreaCollision(CInputStream& MREA);
static CCollisionMeshGroup* LoadDCLN(CInputStream& DCLN);
static EGame GetFormatVersion(u32 version);
}; };
#endif // CCOLLISIONLOADER_H #endif // CCOLLISIONLOADER_H

View File

@ -221,6 +221,8 @@ CScriptTemplate* CTemplateLoader::LoadScriptTemplate(tinyxml2::XMLDocument *pDoc
asset.AssetType = CScriptTemplate::SEditorAsset::eAnimParams; asset.AssetType = CScriptTemplate::SEditorAsset::eAnimParams;
else if (strcmp(pAsset->Name(), "model") == 0) else if (strcmp(pAsset->Name(), "model") == 0)
asset.AssetType = CScriptTemplate::SEditorAsset::eModel; asset.AssetType = CScriptTemplate::SEditorAsset::eModel;
else if (strcmp(pAsset->Name(), "collision") == 0)
asset.AssetType = CScriptTemplate::SEditorAsset::eCollision;
else else
{ {
pAsset = pAsset->NextSiblingElement(); pAsset = pAsset->NextSiblingElement();

View File

@ -3,7 +3,7 @@
#include <Common/Math.h> #include <Common/Math.h>
#include <Core/CDrawUtil.h> #include <Core/CDrawUtil.h>
std::pair<bool,float> SSurface::IntersectsRay(const CRay& Ray, float LineThreshold) std::pair<bool,float> SSurface::IntersectsRay(const CRay& Ray, bool allowBackfaces, float LineThreshold)
{ {
bool Hit = false; bool Hit = false;
float HitDist; float HitDist;
@ -61,7 +61,7 @@ std::pair<bool,float> SSurface::IntersectsRay(const CRay& Ray, float LineThresho
} }
// Intersection test // Intersection test
std::pair<bool,float> TriResult = Math::RayTriangleIntersection(Ray, vtxA, vtxB, vtxC); std::pair<bool,float> TriResult = Math::RayTriangleIntersection(Ray, vtxA, vtxB, vtxC, allowBackfaces);
if (TriResult.first) if (TriResult.first)
{ {

View File

@ -33,7 +33,7 @@ struct SSurface
TriangleCount = 0; TriangleCount = 0;
} }
std::pair<bool,float> IntersectsRay(const CRay& Ray, float LineThreshold = 0.02f); std::pair<bool,float> IntersectsRay(const CRay& Ray, bool allowBackfaces = false, float LineThreshold = 0.02f);
}; };
#endif // SSURFACE_H #endif // SSURFACE_H

View File

@ -9,6 +9,8 @@ CScriptObject::CScriptObject(CGameArea *pArea, CScriptLayer *pLayer, CScriptTemp
mpLayer = pLayer; mpLayer = pLayer;
mpProperties = nullptr; mpProperties = nullptr;
mpTemplate->AddObject(this); mpTemplate->AddObject(this);
mpDisplayModel = nullptr;
mpCollision = nullptr;
} }
CScriptObject::~CScriptObject() CScriptObject::~CScriptObject()
@ -35,6 +37,7 @@ void CScriptObject::EvaluateProperties()
mpLightParameters = mpTemplate->FindLightParameters(mpProperties); mpLightParameters = mpTemplate->FindLightParameters(mpProperties);
mVolumeShape = mpTemplate->VolumeShape(this); mVolumeShape = mpTemplate->VolumeShape(this);
EvaluateDisplayModel(); EvaluateDisplayModel();
EvaluateCollisionModel();
} }
void CScriptObject::EvaluateDisplayModel() void CScriptObject::EvaluateDisplayModel()
@ -43,6 +46,12 @@ void CScriptObject::EvaluateDisplayModel()
mModelToken = CToken(mpDisplayModel); mModelToken = CToken(mpDisplayModel);
} }
void CScriptObject::EvaluateCollisionModel()
{
mpCollision = mpTemplate->FindCollision(mpProperties);
mCollisionToken = CToken(mpCollision);
}
// ************ GETTERS ************ // ************ GETTERS ************
CPropertyBase* CScriptObject::PropertyByIndex(u32 index) const CPropertyBase* CScriptObject::PropertyByIndex(u32 index) const
{ {
@ -189,6 +198,11 @@ CModel* CScriptObject::GetDisplayModel() const
return mpDisplayModel; return mpDisplayModel;
} }
CCollisionMeshGroup* CScriptObject::GetCollision() const
{
return mpCollision;
}
EVolumeShape CScriptObject::VolumeShape() const EVolumeShape CScriptObject::VolumeShape() const
{ {
return mVolumeShape; return mVolumeShape;

View File

@ -6,6 +6,7 @@
#include "CPropertyTemplate.h" #include "CPropertyTemplate.h"
#include "CScriptTemplate.h" #include "CScriptTemplate.h"
#include "../model/CModel.h" #include "../model/CModel.h"
#include "../CCollisionMeshGroup.h"
class CGameArea; class CGameArea;
class CScriptLayer; class CScriptLayer;
@ -31,7 +32,9 @@ class CScriptObject
CBoolProperty *mpActive; CBoolProperty *mpActive;
CPropertyStruct *mpLightParameters; CPropertyStruct *mpLightParameters;
CModel *mpDisplayModel; CModel *mpDisplayModel;
CCollisionMeshGroup *mpCollision;
CToken mModelToken; CToken mModelToken;
CToken mCollisionToken;
EVolumeShape mVolumeShape; EVolumeShape mVolumeShape;
public: public:
@ -41,6 +44,7 @@ public:
void CopyFromTemplate(CScriptTemplate *pTemp, u32 propCount); void CopyFromTemplate(CScriptTemplate *pTemp, u32 propCount);
void EvaluateProperties(); void EvaluateProperties();
void EvaluateDisplayModel(); void EvaluateDisplayModel();
void EvaluateCollisionModel();
CScriptTemplate* Template() const; CScriptTemplate* Template() const;
CMasterTemplate* MasterTemplate() const; CMasterTemplate* MasterTemplate() const;
@ -69,6 +73,7 @@ public:
void SetActive(bool isActive); void SetActive(bool isActive);
CPropertyStruct* LightParameters() const; CPropertyStruct* LightParameters() const;
CModel* GetDisplayModel() const; CModel* GetDisplayModel() const;
CCollisionMeshGroup* GetCollision() const;
EVolumeShape VolumeShape() const; EVolumeShape VolumeShape() const;
}; };

View File

@ -242,6 +242,39 @@ CModel* CScriptTemplate::FindDisplayModel(CPropertyStruct *pProperties)
return nullptr; return nullptr;
} }
CCollisionMeshGroup* CScriptTemplate::FindCollision(CPropertyStruct *pProperties)
{
for (auto it = mAssets.begin(); it != mAssets.end(); it++)
{
CResource *pRes = nullptr;
// File
if (it->AssetSource == SEditorAsset::eFile)
{
std::string path = "../resources/" + it->AssetLocation;
pRes = gResCache.GetResource(path);
}
// Property
else
{
CPropertyBase *pProp = pProperties->PropertyByIDString(it->AssetLocation);
if (pProp->Type() == eFileProperty)
{
CFileProperty *pFile = static_cast<CFileProperty*>(pProp);
pRes = pFile->Get();
}
}
// Verify resource exists + is correct type
if (pRes && (pRes->Type() == eCollisionMeshGroup))
return static_cast<CCollisionMeshGroup*>(pRes);
}
return nullptr;
}
bool CScriptTemplate::HasPosition() bool CScriptTemplate::HasPosition()
{ {
return (!mPositionIDString.empty()); return (!mPositionIDString.empty());

View File

@ -11,6 +11,7 @@
#include <vector> #include <vector>
#include <tinyxml2.h> #include <tinyxml2.h>
#include <Resource/model/CModel.h> #include <Resource/model/CModel.h>
#include <Resource/CCollisionMeshGroup.h>
class CMasterTemplate; class CMasterTemplate;
class CScriptObject; class CScriptObject;
@ -47,7 +48,7 @@ private:
struct SEditorAsset struct SEditorAsset
{ {
enum { enum {
eModel, eAnimParams eModel, eAnimParams, eCollision
} AssetType; } AssetType;
enum { enum {
@ -114,6 +115,7 @@ public:
CBoolProperty* FindActive(CPropertyStruct *pProperties); CBoolProperty* FindActive(CPropertyStruct *pProperties);
CPropertyStruct* FindLightParameters(CPropertyStruct *pProperties); CPropertyStruct* FindLightParameters(CPropertyStruct *pProperties);
CModel* FindDisplayModel(CPropertyStruct *pProperties); CModel* FindDisplayModel(CPropertyStruct *pProperties);
CCollisionMeshGroup* FindCollision(CPropertyStruct *pProperties);
bool HasPosition(); bool HasPosition();
// Object Tracking // Object Tracking

View File

@ -3,11 +3,10 @@
#include <Core/CGraphics.h> #include <Core/CGraphics.h>
#include <Core/CRenderer.h> #include <Core/CRenderer.h>
CCollisionNode::CCollisionNode(CSceneManager *pScene, CSceneNode *pParent, CCollisionMesh *pMesh) CCollisionNode::CCollisionNode(CSceneManager *pScene, CSceneNode *pParent, CCollisionMeshGroup *pCollision)
: CSceneNode(pScene, pParent) : CSceneNode(pScene, pParent)
{ {
mpMesh = pMesh; SetCollision(pCollision);
mMeshToken = CToken(pMesh);
SetName("Collision"); SetName("Collision");
} }
@ -18,7 +17,7 @@ ENodeType CCollisionNode::NodeType()
void CCollisionNode::AddToRenderer(CRenderer *pRenderer) void CCollisionNode::AddToRenderer(CRenderer *pRenderer)
{ {
if (!mpMesh) return; if (!mpCollision) return;
pRenderer->AddOpaqueMesh(this, 0, AABox(), eDrawMesh); pRenderer->AddOpaqueMesh(this, 0, AABox(), eDrawMesh);
@ -29,7 +28,7 @@ void CCollisionNode::AddToRenderer(CRenderer *pRenderer)
void CCollisionNode::Draw(ERenderOptions) void CCollisionNode::Draw(ERenderOptions)
{ {
// Not using parameter 1 (ERenderOptions - Options) // Not using parameter 1 (ERenderOptions - Options)
if (!mpMesh) return; if (!mpCollision) return;
LoadModelMatrix(); LoadModelMatrix();
@ -38,9 +37,9 @@ void CCollisionNode::Draw(ERenderOptions)
glDepthMask(GL_TRUE); glDepthMask(GL_TRUE);
CDrawUtil::UseCollisionShader(); CDrawUtil::UseCollisionShader();
mpMesh->Draw(); mpCollision->Draw();
CDrawUtil::UseColorShader(CColor::skTransparentBlack); CDrawUtil::UseColorShader(CColor::skTransparentBlack);
mpMesh->DrawLines(); mpCollision->DrawWireframe();
} }
void CCollisionNode::DrawAsset(ERenderOptions, u32) void CCollisionNode::DrawAsset(ERenderOptions, u32)
@ -49,10 +48,16 @@ void CCollisionNode::DrawAsset(ERenderOptions, u32)
// Not using parameter 2 (u32 - asset) // Not using parameter 2 (u32 - asset)
} }
SRayIntersection CCollisionNode::RayNodeIntersectTest(const CRay &Ray, u32 AssetID) SRayIntersection CCollisionNode::RayNodeIntersectTest(const CRay &Ray, u32 AssetID, ERenderOptions options)
{ {
// todo // todo
SRayIntersection Result; SRayIntersection Result;
Result.Hit = false; Result.Hit = false;
return Result; return Result;
} }
void CCollisionNode::SetCollision(CCollisionMeshGroup *pCollision)
{
mpCollision = pCollision;
mCollisionToken = CToken(pCollision);
}

View File

@ -2,20 +2,21 @@
#define CCOLLISIONNODE_H #define CCOLLISIONNODE_H
#include "CSceneNode.h" #include "CSceneNode.h"
#include <Resource/CCollisionMesh.h> #include <Resource/CCollisionMeshGroup.h>
class CCollisionNode : public CSceneNode class CCollisionNode : public CSceneNode
{ {
CCollisionMesh *mpMesh; CCollisionMeshGroup *mpCollision;
CToken mMeshToken; CToken mCollisionToken;
public: public:
CCollisionNode(CSceneManager *pScene, CSceneNode *pParent = 0, CCollisionMesh *pMesh = 0); CCollisionNode(CSceneManager *pScene, CSceneNode *pParent = 0, CCollisionMeshGroup *pCollision = 0);
ENodeType NodeType(); ENodeType NodeType();
void AddToRenderer(CRenderer *pRenderer); void AddToRenderer(CRenderer *pRenderer);
void Draw(ERenderOptions Options); void Draw(ERenderOptions Options);
void DrawAsset(ERenderOptions Options, u32 asset); void DrawAsset(ERenderOptions Options, u32 asset);
SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID); SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID, ERenderOptions options);
void SetCollision(CCollisionMeshGroup *pCollision);
}; };
#endif // CCOLLISIONNODE_H #endif // CCOLLISIONNODE_H

View File

@ -57,10 +57,12 @@ void CLightNode::DrawAsset(ERenderOptions, u32)
// Not using parameter 2 (u32 - asset) // Not using parameter 2 (u32 - asset)
} }
SRayIntersection CLightNode::RayNodeIntersectTest(const CRay &Ray, u32 AssetID) SRayIntersection CLightNode::RayNodeIntersectTest(const CRay &Ray, u32 AssetID, ERenderOptions options)
{ {
// Needs redo if I ever make these look like something other than boxes // Needs redo if I ever make these look like something other than boxes
if (AABox().IsPointInBox(Ray.Origin())) bool allowBackfaces = ((options & eEnableBackfaceCull) == 0);
if (!allowBackfaces && (AABox().IsPointInBox(Ray.Origin())))
return SRayIntersection(false, 0.f, nullptr, 0); return SRayIntersection(false, 0.f, nullptr, 0);
std::pair<bool,float> BoxResult = AABox().IntersectsRay(Ray); std::pair<bool,float> BoxResult = AABox().IntersectsRay(Ray);

View File

@ -13,7 +13,7 @@ public:
void AddToRenderer(CRenderer *pRenderer); void AddToRenderer(CRenderer *pRenderer);
void Draw(ERenderOptions Options); void Draw(ERenderOptions Options);
void DrawAsset(ERenderOptions Options, u32 asset); void DrawAsset(ERenderOptions Options, u32 asset);
SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID); SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID, ERenderOptions options);
CLight* Light(); CLight* Light();
}; };

View File

@ -105,14 +105,14 @@ void CModelNode::RayAABoxIntersectTest(CRayCollisionTester &Tester)
} }
} }
SRayIntersection CModelNode::RayNodeIntersectTest(const CRay &Ray, u32 AssetID) SRayIntersection CModelNode::RayNodeIntersectTest(const CRay &Ray, u32 AssetID, ERenderOptions options)
{ {
SRayIntersection out; SRayIntersection out;
out.pNode = this; out.pNode = this;
out.AssetIndex = AssetID; out.AssetIndex = AssetID;
CRay TransformedRay = Ray.Transformed(Transform().Inverse()); CRay TransformedRay = Ray.Transformed(Transform().Inverse());
std::pair<bool,float> Result = mpModel->GetSurface(AssetID)->IntersectsRay(TransformedRay); std::pair<bool,float> Result = mpModel->GetSurface(AssetID)->IntersectsRay(TransformedRay, ((options & eEnableBackfaceCull) == 0));
if (Result.first) if (Result.first)
{ {

View File

@ -20,7 +20,7 @@ public:
virtual void Draw(ERenderOptions Options); virtual void Draw(ERenderOptions Options);
virtual void DrawAsset(ERenderOptions Options, u32 asset); virtual void DrawAsset(ERenderOptions Options, u32 asset);
virtual void RayAABoxIntersectTest(CRayCollisionTester &Tester); virtual void RayAABoxIntersectTest(CRayCollisionTester &Tester);
virtual SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID); virtual SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID, ERenderOptions options);
void SetModel(CModel *pModel); void SetModel(CModel *pModel);
void SetMatSet(u32 MatSet); void SetMatSet(u32 MatSet);

View File

@ -20,7 +20,7 @@ public:
inline void DrawAsset(ERenderOptions, u32) {} inline void DrawAsset(ERenderOptions, u32) {}
inline void RayAABoxIntersectTest(CRayCollisionTester &) {} inline void RayAABoxIntersectTest(CRayCollisionTester &) {}
inline SRayIntersection RayNodeIntersectTest(const CRay &, u32) { inline SRayIntersection RayNodeIntersectTest(const CRay &, u32, ERenderOptions) {
return SRayIntersection(false, 0.f, nullptr, 0); return SRayIntersection(false, 0.f, nullptr, 0);
} }

View File

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

View File

@ -16,12 +16,14 @@ CScriptNode::CScriptNode(CSceneManager *pScene, CSceneNode *pParent, CScriptObje
// Evaluate instance // Evaluate instance
mpInstance = pObject; mpInstance = pObject;
mpActiveModel = nullptr; mpActiveModel = nullptr;
mpCollisionNode = new CCollisionNode(pScene, this);
mpCollisionNode->SetInheritance(true, true, false);
if (mpInstance) if (mpInstance)
{ {
CScriptTemplate *pTemp = mpInstance->Template(); CScriptTemplate *pTemp = mpInstance->Template();
mpActiveModel = mpInstance->GetDisplayModel(); // Determine transform
mPosition = mpInstance->Position(); mPosition = mpInstance->Position();
mRotation = CQuaternion::FromEuler(mpInstance->Rotation()); mRotation = CQuaternion::FromEuler(mpInstance->Rotation());
SetName("[" + pTemp->TemplateName(mpInstance->NumProperties()) + "] " + mpInstance->InstanceName()); SetName("[" + pTemp->TemplateName(mpInstance->NumProperties()) + "] " + mpInstance->InstanceName());
@ -31,10 +33,16 @@ CScriptNode::CScriptNode(CSceneManager *pScene, CSceneNode *pParent, CScriptObje
MarkTransformChanged(); MarkTransformChanged();
// Determine display assets
mpActiveModel = mpInstance->GetDisplayModel();
mModelToken = CToken(mpActiveModel);
mpCollisionNode->SetCollision(mpInstance->GetCollision());
// Create preview volume node
mHasValidPosition = pTemp->HasPosition(); mHasValidPosition = pTemp->HasPosition();
mHasVolumePreview = (pTemp->ScaleType() == CScriptTemplate::eScaleVolume); mHasVolumePreview = (pTemp->ScaleType() == CScriptTemplate::eScaleVolume);
// Create volume preview node
if (mHasVolumePreview) if (mHasVolumePreview)
{ {
EVolumeShape shape = mpInstance->VolumeShape(); EVolumeShape shape = mpInstance->VolumeShape();
@ -87,33 +95,40 @@ std::string CScriptNode::PrefixedName() const
void CScriptNode::AddToRenderer(CRenderer *pRenderer) void CScriptNode::AddToRenderer(CRenderer *pRenderer)
{ {
if (!mpInstance) return; if (!mpInstance) return;
ERenderOptions options = pRenderer->RenderOptions();
if (!mpActiveModel) if (options & eDrawObjectCollision)
pRenderer->AddOpaqueMesh(this, 0, AABox(), eDrawMesh); mpCollisionNode->AddToRenderer(pRenderer);
else if (options & eDrawObjects)
{ {
if (!mpActiveModel->IsBuffered()) if (!mpActiveModel)
mpActiveModel->BufferGL();
if (!mpActiveModel->HasTransparency(0))
pRenderer->AddOpaqueMesh(this, 0, AABox(), eDrawMesh); pRenderer->AddOpaqueMesh(this, 0, AABox(), eDrawMesh);
else else
{ {
u32 SubmeshCount = mpActiveModel->GetSurfaceCount(); if (!mpActiveModel->IsBuffered())
mpActiveModel->BufferGL();
for (u32 s = 0; s < SubmeshCount; s++) if (!mpActiveModel->HasTransparency(0))
pRenderer->AddOpaqueMesh(this, 0, AABox(), eDrawMesh);
else
{ {
if (!mpActiveModel->IsSurfaceTransparent(s, 0)) u32 SubmeshCount = mpActiveModel->GetSurfaceCount();
pRenderer->AddOpaqueMesh(this, s, mpActiveModel->GetSurfaceAABox(s).Transformed(Transform()), eDrawAsset);
else for (u32 s = 0; s < SubmeshCount; s++)
pRenderer->AddTransparentMesh(this, s, mpActiveModel->GetSurfaceAABox(s).Transformed(Transform()), eDrawAsset); {
if (!mpActiveModel->IsSurfaceTransparent(s, 0))
pRenderer->AddOpaqueMesh(this, s, mpActiveModel->GetSurfaceAABox(s).Transformed(Transform()), eDrawAsset);
else
pRenderer->AddTransparentMesh(this, s, mpActiveModel->GetSurfaceAABox(s).Transformed(Transform()), eDrawAsset);
}
} }
} }
} }
if (IsSelected()) if (IsSelected() && (options & ((ERenderOptions) (eDrawObjects | eDrawObjectCollision))) != 0)
{ {
pRenderer->AddOpaqueMesh(this, 0, AABox(), eDrawSelection); pRenderer->AddOpaqueMesh(this, 0, AABox(), eDrawSelection);
@ -217,27 +232,32 @@ void CScriptNode::RayAABoxIntersectTest(CRayCollisionTester &Tester)
} }
} }
SRayIntersection CScriptNode::RayNodeIntersectTest(const CRay &Ray, u32 AssetID) SRayIntersection CScriptNode::RayNodeIntersectTest(const CRay &Ray, u32 AssetID, ERenderOptions options)
{ {
CRay TransformedRay = Ray.Transformed(Transform().Inverse());
SRayIntersection out; SRayIntersection out;
out.pNode = this; out.pNode = this;
out.AssetIndex = AssetID; out.AssetIndex = AssetID;
CRay TransformedRay = Ray.Transformed(Transform().Inverse()); if (options & eDrawObjects)
CModel *pModel = (mpActiveModel ? mpActiveModel : CDrawUtil::GetCubeModel());
std::pair<bool,float> Result = pModel->GetSurface(AssetID)->IntersectsRay(TransformedRay);
if (Result.first)
{ {
out.Hit = true; CModel *pModel = (mpActiveModel ? mpActiveModel : CDrawUtil::GetCubeModel());
std::pair<bool,float> Result = pModel->GetSurface(AssetID)->IntersectsRay(TransformedRay, ((options & eEnableBackfaceCull) == 0));
CVector3f HitPoint = TransformedRay.PointOnRay(Result.second); if (Result.first)
CVector3f WorldHitPoint = Transform() * HitPoint; {
out.Distance = Math::Distance(Ray.Origin(), WorldHitPoint); out.Hit = true;
CVector3f HitPoint = TransformedRay.PointOnRay(Result.second);
CVector3f WorldHitPoint = Transform() * HitPoint;
out.Distance = Math::Distance(Ray.Origin(), WorldHitPoint);
}
else
out.Hit = false;
} }
else out.Hit = false;
else
out.Hit = false;
return out; return out;
} }

View File

@ -3,12 +3,15 @@
#include "CSceneNode.h" #include "CSceneNode.h"
#include "CModelNode.h" #include "CModelNode.h"
#include "CCollisionNode.h"
#include <Resource/script/CScriptObject.h> #include <Resource/script/CScriptObject.h>
class CScriptNode : public CSceneNode class CScriptNode : public CSceneNode
{ {
CScriptObject *mpInstance; CScriptObject *mpInstance;
CModel *mpActiveModel; CModel *mpActiveModel;
CToken mModelToken;
CCollisionNode *mpCollisionNode;
bool mHasValidPosition; bool mHasValidPosition;
bool mHasVolumePreview; bool mHasVolumePreview;
@ -23,7 +26,7 @@ public:
void DrawAsset(ERenderOptions Options, u32 Asset); void DrawAsset(ERenderOptions Options, u32 Asset);
void DrawSelection(); void DrawSelection();
void RayAABoxIntersectTest(CRayCollisionTester &Tester); void RayAABoxIntersectTest(CRayCollisionTester &Tester);
SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID); SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID, ERenderOptions options);
bool IsVisible() const; bool IsVisible() const;
CScriptObject* Object(); CScriptObject* Object();
CModel* ActiveModel(); CModel* ActiveModel();

View File

@ -88,14 +88,14 @@ void CStaticNode::RayAABoxIntersectTest(CRayCollisionTester &Tester)
} }
} }
SRayIntersection CStaticNode::RayNodeIntersectTest(const CRay &Ray, u32 AssetID) SRayIntersection CStaticNode::RayNodeIntersectTest(const CRay &Ray, u32 AssetID, ERenderOptions options)
{ {
SRayIntersection out; SRayIntersection out;
out.pNode = this; out.pNode = this;
out.AssetIndex = AssetID; out.AssetIndex = AssetID;
CRay TransformedRay = Ray.Transformed(Transform().Inverse()); CRay TransformedRay = Ray.Transformed(Transform().Inverse());
std::pair<bool,float> Result = mpModel->GetSurface(AssetID)->IntersectsRay(TransformedRay); std::pair<bool,float> Result = mpModel->GetSurface(AssetID)->IntersectsRay(TransformedRay, ((options & eEnableBackfaceCull) == 0));
if (Result.first) if (Result.first)
{ {

View File

@ -15,7 +15,7 @@ public:
void Draw(ERenderOptions Options); void Draw(ERenderOptions Options);
void DrawAsset(ERenderOptions Options, u32 asset); void DrawAsset(ERenderOptions Options, u32 asset);
void RayAABoxIntersectTest(CRayCollisionTester &Tester); void RayAABoxIntersectTest(CRayCollisionTester &Tester);
SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID); SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID, ERenderOptions options);
}; };
#endif // CSTATICNODE_H #endif // CSTATICNODE_H

View File

@ -77,7 +77,7 @@ void CSceneViewport::SceneRayCast(const CRay& ray)
return; return;
} }
SRayIntersection result = mpScene->SceneRayCast(ray); SRayIntersection result = mpScene->SceneRayCast(ray, mpRenderer->RenderOptions());
if (result.Hit) if (result.Hit)
{ {

View File

@ -329,22 +329,22 @@ void CWorldEditor::OnTransformSpinBoxEdited(CVector3f)
// These functions are from "Go to slot" in the designer // These functions are from "Go to slot" in the designer
void CWorldEditor::on_ActionDrawWorld_triggered() void CWorldEditor::on_ActionDrawWorld_triggered()
{ {
mScene.SetWorld(ui->ActionDrawWorld->isChecked()); ui->MainViewport->Renderer()->ToggleWorld(ui->ActionDrawWorld->isChecked());
} }
void CWorldEditor::on_ActionDrawCollision_triggered() void CWorldEditor::on_ActionDrawCollision_triggered()
{ {
mScene.SetCollision(ui->ActionDrawCollision->isChecked()); ui->MainViewport->Renderer()->ToggleWorldCollision(ui->ActionDrawCollision->isChecked());
} }
void CWorldEditor::on_ActionDrawObjects_triggered() void CWorldEditor::on_ActionDrawObjects_triggered()
{ {
mScene.SetObjects(ui->ActionDrawObjects->isChecked()); ui->MainViewport->Renderer()->ToggleObjects(ui->ActionDrawObjects->isChecked());
} }
void CWorldEditor::on_ActionDrawLights_triggered() void CWorldEditor::on_ActionDrawLights_triggered()
{ {
mScene.SetLights(ui->ActionDrawLights->isChecked()); ui->MainViewport->Renderer()->ToggleLights(ui->ActionDrawLights->isChecked());
} }
void CWorldEditor::on_ActionDrawSky_triggered() void CWorldEditor::on_ActionDrawSky_triggered()
@ -470,3 +470,8 @@ void CWorldEditor::on_ActionDecrementGizmo_triggered()
{ {
mGizmo.DecrementSize(); mGizmo.DecrementSize();
} }
void CWorldEditor::on_ActionDrawObjectCollision_triggered()
{
ui->MainViewport->Renderer()->ToggleObjectCollision(ui->ActionDrawObjectCollision->isChecked());
}

View File

@ -78,6 +78,7 @@ private slots:
void on_ActionEditLayers_triggered(); void on_ActionEditLayers_triggered();
void on_ActionIncrementGizmo_triggered(); void on_ActionIncrementGizmo_triggered();
void on_ActionDecrementGizmo_triggered(); void on_ActionDecrementGizmo_triggered();
void on_ActionDrawObjectCollision_triggered();
}; };
#endif // CWORLDEDITOR_H #endif // CWORLDEDITOR_H

View File

@ -270,8 +270,9 @@
<addaction name="ActionZoomOnSelection"/> <addaction name="ActionZoomOnSelection"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="ActionDrawWorld"/> <addaction name="ActionDrawWorld"/>
<addaction name="ActionDrawCollision"/>
<addaction name="ActionDrawObjects"/> <addaction name="ActionDrawObjects"/>
<addaction name="ActionDrawCollision"/>
<addaction name="ActionDrawObjectCollision"/>
<addaction name="ActionDrawLights"/> <addaction name="ActionDrawLights"/>
<addaction name="ActionDrawSky"/> <addaction name="ActionDrawSky"/>
<addaction name="separator"/> <addaction name="separator"/>
@ -535,7 +536,7 @@
<string>Collision</string> <string>Collision</string>
</property> </property>
<property name="shortcut"> <property name="shortcut">
<string>2</string> <string>3</string>
</property> </property>
</action> </action>
<action name="ActionDrawObjects"> <action name="ActionDrawObjects">
@ -549,7 +550,7 @@
<string>Objects</string> <string>Objects</string>
</property> </property>
<property name="shortcut"> <property name="shortcut">
<string>3</string> <string>2</string>
</property> </property>
</action> </action>
<action name="ActionDrawLights"> <action name="ActionDrawLights">
@ -563,7 +564,7 @@
<string>Lights</string> <string>Lights</string>
</property> </property>
<property name="shortcut"> <property name="shortcut">
<string>4</string> <string>5</string>
</property> </property>
</action> </action>
<action name="ActionDrawSky"> <action name="ActionDrawSky">
@ -577,7 +578,7 @@
<string>Sky</string> <string>Sky</string>
</property> </property>
<property name="shortcut"> <property name="shortcut">
<string>5</string> <string>6</string>
</property> </property>
</action> </action>
<action name="ActionNoLighting"> <action name="ActionNoLighting">
@ -705,6 +706,17 @@
<enum>Qt::WindowShortcut</enum> <enum>Qt::WindowShortcut</enum>
</property> </property>
</action> </action>
<action name="ActionDrawObjectCollision">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Object Collision</string>
</property>
<property name="shortcut">
<string>4</string>
</property>
</action>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget> <customwidget>

View File

@ -176,17 +176,17 @@ void CWorldEditorWindow::on_actionBackface_culling_triggered()
void CWorldEditorWindow::on_actionWorld_triggered() void CWorldEditorWindow::on_actionWorld_triggered()
{ {
mpSceneManager->SetWorld(ui->actionWorld->isChecked()); mpRenderer->ToggleWorld(ui->actionWorld->isChecked());
} }
void CWorldEditorWindow::on_actionCollision_triggered() void CWorldEditorWindow::on_actionCollision_triggered()
{ {
mpSceneManager->SetCollision(ui->actionCollision->isChecked()); mpRenderer->ToggleWorldCollision(ui->actionCollision->isChecked());
} }
void CWorldEditorWindow::on_actionObjects_triggered() void CWorldEditorWindow::on_actionObjects_triggered()
{ {
mpSceneManager->SetObjects(ui->actionObjects->isChecked()); mpRenderer->ToggleObjects(ui->actionObjects->isChecked());
} }
void CWorldEditorWindow::setupInstanceViewLayers() void CWorldEditorWindow::setupInstanceViewLayers()
@ -233,7 +233,7 @@ void CWorldEditorWindow::on_actionMaterial_Animations_triggered()
void CWorldEditorWindow::on_actionLights_triggered() void CWorldEditorWindow::on_actionLights_triggered()
{ {
mpSceneManager->SetLights(ui->actionLights->isChecked()); mpRenderer->ToggleLights(ui->actionLights->isChecked());
} }
void CWorldEditorWindow::on_actionLightingNone_triggered() void CWorldEditorWindow::on_actionLightingNone_triggered()

View File

@ -97,15 +97,6 @@ void WInstancesTab::OnTreeClick(QModelIndex Index)
} }
} }
// Show/Hide Node Type
else if (mpTypesModel->IndexType(Index) == CTypesInstanceModel::eNodeTypeIndex)
{
CTypesInstanceModel::ENodeType type = mpTypesModel->IndexNodeType(Index);
if (type == CTypesInstanceModel::eScriptType)
mpScene->SetObjects(!mpScene->AreScriptObjectsEnabled());
}
if (sender() == ui->LayersTreeView) if (sender() == ui->LayersTreeView)
ui->LayersTreeView->update(Index); ui->LayersTreeView->update(Index);
else if (sender() == ui->TypesTreeView) else if (sender() == ui->TypesTreeView)