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;
}
SRayIntersection CRayCollisionTester::TestNodes()
SRayIntersection CRayCollisionTester::TestNodes(ERenderOptions options)
{
// Sort nodes by distance from ray
mBoxIntersectList.sort(
@ -43,7 +43,7 @@ SRayIntersection CRayCollisionTester::TestNodes()
// Otherwise, more intersection tests...
CSceneNode *pNode = Intersection.pNode;
SRayIntersection MidResult = pNode->RayNodeIntersectTest(mRay, Intersection.AssetIndex);
SRayIntersection MidResult = pNode->RayNodeIntersectTest(mRay, Intersection.AssetIndex, options);
if (MidResult.Hit)
{

View File

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

View File

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

View File

@ -20,7 +20,8 @@ u32 CRenderer::sNumRenderers = 0;
// ************ INITIALIZATION ************
CRenderer::CRenderer()
{
mOptions = eEnableUVScroll | eEnableBackfaceCull;
mOptions = eDrawWorld | eDrawObjects | eDrawLights | eDrawSky |
eEnableUVScroll | eEnableBackfaceCull;
mBloomMode = eNoBloom;
mDrawGrid = true;
mInitialized = false;
@ -53,9 +54,45 @@ void CRenderer::Init()
}
// ************ 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)

View File

@ -53,7 +53,13 @@ public:
void Init();
// 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 ToggleUVAnimation(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 == "FONT") Res = CFontLoader::LoadFONT(mem);
else if (type == "SCAN") Res = CScanLoader::LoadSCAN(mem);
else if (type == "DCLN") Res = CCollisionLoader::LoadDCLN(mem);
else SupportedFormat = false;
// Log errors
@ -201,6 +202,7 @@ CResource* CResCache::GetResource(std::string ResPath)
else if (type == "MLVL") Res = CWorldLoader::LoadMLVL(file);
else if (type == "FONT") Res = CFontLoader::LoadFONT(file);
else if (type == "SCAN") Res = CScanLoader::LoadSCAN(file);
else if (type == "DCLN") Res = CCollisionLoader::LoadDCLN(file);
else SupportedFormat = false;
if (!Res) Res = new CResource(); // Default for unsupported formats

View File

@ -19,10 +19,6 @@
*/
CSceneManager::CSceneManager()
{
mShowTerrain = true;
mShowCollision = false;
mShowObjects = true;
mShowLights = true;
mSplitTerrain = true;
mNodeCount = 0;
mpSceneRootNode = new CRootNode(this, nullptr);
@ -56,7 +52,7 @@ CStaticNode* CSceneManager::AddStaticModel(CStaticModel *mdl)
return node;
}
CCollisionNode* CSceneManager::AddCollision(CCollisionMesh *mesh)
CCollisionNode* CSceneManager::AddCollision(CCollisionMeshGroup *mesh)
{
if (mesh == nullptr) return nullptr;
@ -143,7 +139,7 @@ void CSceneManager::SetActiveArea(CGameArea* _area)
switch (pObj->ObjectTypeID())
{
case 0x4E: // MP1 AreaAttributes ID
case 0x52454141: // MP2 AreaAttributes ID ("REAA")
case 0x52454141: // MP2/MP3/DKCR AreaAttributes ID ("REAA")
mAreaAttributesObjects.emplace_back( CAreaAttributes(pObj) );
break;
}
@ -221,7 +217,9 @@ void CSceneManager::ClearScene()
void CSceneManager::AddSceneToRenderer(CRenderer *pRenderer)
{
if (mShowTerrain)
ERenderOptions options = pRenderer->RenderOptions();
if (options & eDrawWorld)
{
for (u32 n = 0; n < mModelNodes.size(); n++)
if (mModelNodes[n]->IsVisible())
@ -232,29 +230,29 @@ void CSceneManager::AddSceneToRenderer(CRenderer *pRenderer)
mStaticNodes[n]->AddToRenderer(pRenderer);
}
if (mShowCollision)
if (options & eDrawWorldCollision)
{
for (u32 n = 0; n < mCollisionNodes.size(); n++)
if (mCollisionNodes[n]->IsVisible())
mCollisionNodes[n]->AddToRenderer(pRenderer);
}
if (mShowObjects)
{
for (u32 n = 0; n < mScriptNodes.size(); n++)
if (mScriptNodes[n]->IsVisible())
mScriptNodes[n]->AddToRenderer(pRenderer);
}
if (mShowLights)
if (options & eDrawLights)
{
for (u32 n = 0; n < mLightNodes.size(); n++)
if (mLightNodes[n]->IsVisible())
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
// 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),
};
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
@ -284,7 +283,7 @@ SRayIntersection CSceneManager::SceneRayCast(const CRay& Ray)
vec[iNode]->RayAABoxIntersectTest(Tester);
}
return Tester.TestNodes();
return Tester.TestNodes(renderOptions);
}
void CSceneManager::PickEnvironmentObjects()
@ -343,43 +342,3 @@ CGameArea* CSceneManager::GetActiveArea()
{
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
{
bool mShowTerrain;
bool mShowCollision;
bool mShowObjects;
bool mShowLights;
bool mSplitTerrain;
u32 mNodeCount;
@ -55,14 +51,14 @@ public:
// Scene Management
CModelNode* AddModel(CModel *mdl);
CStaticNode* AddStaticModel(CStaticModel *mdl);
CCollisionNode* AddCollision(CCollisionMesh *mesh);
CCollisionNode* AddCollision(CCollisionMeshGroup *mesh);
CScriptNode* AddScriptObject(CScriptObject *obj);
CLightNode* AddLight(CLight *Light);
void SetActiveArea(CGameArea *_area);
void SetActiveWorld(CWorld *_world);
void ClearScene();
void AddSceneToRenderer(CRenderer *pRenderer);
SRayIntersection SceneRayCast(const CRay& Ray);
SRayIntersection SceneRayCast(const CRay& Ray, ERenderOptions renderOptions);
void PickEnvironmentObjects();
CScriptNode* ScriptNodeByID(u32 InstanceID);
CScriptNode* NodeForObject(CScriptObject *pObj);
@ -71,17 +67,6 @@ public:
// Setters/Getters
CModel* GetActiveSkybox();
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

View File

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

View File

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

View File

@ -6,7 +6,7 @@
#include <OpenGL/CIndexBuffer.h>
#include "CResource.h"
class CCollisionMesh : public CResource
class CCollisionMesh
{
friend class CCollisionLoader;
@ -79,11 +79,10 @@ class CCollisionMesh : public CResource
public:
CCollisionMesh();
~CCollisionMesh();
EResType Type();
void BufferGL();
void Draw();
void DrawLines();
void DrawWireframe();
};
#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];
}
CCollisionMesh* CGameArea::GetCollision()
CCollisionMeshGroup* CGameArea::GetCollision()
{
return mCollision;
}

View File

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

View File

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

View File

@ -13,7 +13,7 @@ enum EResType
eAudioStream = 7,
eAudioTable = 8,
eCharacter = 9,
eCollisionMesh = 10,
eCollisionMeshGroup = 10,
eCollisionResponse = 11,
eDataDump = 12,
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++)
{
std::string type = (it->AssetType == CScriptTemplate::SEditorAsset::eAnimParams ? "animparams" : "model");
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;
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;
CCollisionLoader loader;
MREA.Seek(0x8, SEEK_CUR);
u32 deafbabe = MREA.ReadLong();
if (deafbabe != 0xdeafbabe)
if (deafbabe != 0xDEAFBABE)
{
Log::FileError(MREA.GetSourceString(), MREA.Tell() - 4, "Invalid collision magic: " + StringUtil::ToHexString(deafbabe));
return nullptr;
}
u32 version = MREA.ReadLong();
loader.version = ECollisionVersion(version);
if ((loader.version != Prime) && (loader.version != Echoes))
loader.mVersion = GetFormatVersion(version);
if ((loader.mVersion != ePrime) && (loader.mVersion != eEchoes))
{
Log::FileError(MREA.GetSourceString(), MREA.Tell() - 4, "Unsupported collision version: " + StringUtil::ToHexString(version));
return nullptr;
}
loader.mesh = new CCollisionMesh;
CCollisionMesh *cmesh = loader.mesh;
loader.mpGroup = new CCollisionMeshGroup;
loader.mpMesh = new CCollisionMesh;
// Octree - structure is known, but not coding this right now
cmesh->mAABox = CAABox(MREA);
loader.mpMesh->mAABox = CAABox(MREA);
MREA.Seek(0x4, SEEK_CUR);
u32 octreeSize = MREA.ReadLong();
MREA.Seek(octreeSize, SEEK_CUR); // Skipping the octree for now
cmesh->mOctreeLoaded = false;
loader.mpMesh->mOctreeLoaded = false;
// Properties
u32 propertySetCount = MREA.ReadLong();
for (u32 p = 0; p < propertySetCount; p++)
loader.readPropertyFlags(MREA);
// 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;
// Read collision indices and return
loader.LoadCollisionIndices(MREA, false);
loader.mpGroup->AddMesh(loader.mpMesh);
return loader.mpGroup;
}
CCollisionMesh::CCollisionOctree* CCollisionLoader::parseOctree(CInputStream&)
CCollisionMeshGroup* CCollisionLoader::LoadDCLN(CInputStream &DCLN)
{
// Not using: Parameter 1 (CInputStream& - src)
return nullptr;
}
if (!DCLN.IsValid()) return nullptr;
CCollisionMesh::CCollisionOctree::SBranch* CCollisionLoader::parseOctreeBranch(CInputStream&)
{
// Not using: Parameter 1 (CInputStream& - src)
return nullptr;
}
CCollisionLoader loader;
loader.mpGroup = new CCollisionMeshGroup;
CCollisionMesh::CCollisionOctree::SLeaf* CCollisionLoader::parseOctreeLeaf(CInputStream&)
{
// Not using: Parameter 1 (CInputStream& - src)
return nullptr;
}
u32 numMeshes = DCLN.ReadLong();
void CCollisionLoader::readPropertyFlags(CInputStream& src)
{
CCollisionMesh::SCollisionProperties property;
if (version == Prime)
for (u32 iMesh = 0; iMesh < numMeshes; iMesh++)
{
u32 flag = src.ReadLong();
property.Invert = (flag >> 25) & 0x1;
}
u32 deafbabe = DCLN.ReadLong();
if (version == Echoes)
{
u64 flag = src.ReadLongLong();
property.Invert = (flag >> 24) & 0x1;
}
if (deafbabe != 0xDEAFBABE)
{
Log::FileError(DCLN.GetSourceString(), DCLN.Tell() - 4, "Invalid collision magic: " + StringUtil::ToHexString(deafbabe));
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
#include "../CCollisionMesh.h"
#include "../CCollisionMeshGroup.h"
#include "../EFormatVersion.h"
class CCollisionLoader
{
enum ECollisionVersion;
CCollisionMesh *mesh;
ECollisionVersion version;
std::vector<CCollisionMesh::SCollisionProperties> properties;
enum ECollisionVersion
{
Prime = 0x3,
Echoes = 0x4,
DonkeyKongCountryReturns = 0x5
};
CCollisionMeshGroup *mpGroup;
CCollisionMesh *mpMesh;
EGame mVersion;
std::vector<CCollisionMesh::SCollisionProperties> mProperties;
CCollisionLoader();
CCollisionMesh::CCollisionOctree* parseOctree(CInputStream& src);
CCollisionMesh::CCollisionOctree::SBranch* parseOctreeBranch(CInputStream& src);
CCollisionMesh::CCollisionOctree::SLeaf* parseOctreeLeaf(CInputStream& src);
void readPropertyFlags(CInputStream& src);
CCollisionMesh::CCollisionOctree* ParseOctree(CInputStream& src);
CCollisionMesh::CCollisionOctree::SBranch* ParseOctreeBranch(CInputStream& src);
CCollisionMesh::CCollisionOctree::SLeaf* ParseOctreeLeaf(CInputStream& src);
void ParseOBBNode(CInputStream& DCLN);
void ReadPropertyFlags(CInputStream& src);
void LoadCollisionIndices(CInputStream& file, bool buildAABox);
public:
static CCollisionMesh* LoadAreaCollision(CInputStream& MREA);
static CCollisionMeshGroup* LoadAreaCollision(CInputStream& MREA);
static CCollisionMeshGroup* LoadDCLN(CInputStream& DCLN);
static EGame GetFormatVersion(u32 version);
};
#endif // CCOLLISIONLOADER_H

View File

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

View File

@ -3,7 +3,7 @@
#include <Common/Math.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;
float HitDist;
@ -61,7 +61,7 @@ std::pair<bool,float> SSurface::IntersectsRay(const CRay& Ray, float LineThresho
}
// 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)
{

View File

@ -33,7 +33,7 @@ struct SSurface
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

View File

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

View File

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

View File

@ -242,6 +242,39 @@ CModel* CScriptTemplate::FindDisplayModel(CPropertyStruct *pProperties)
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()
{
return (!mPositionIDString.empty());

View File

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

View File

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

View File

@ -2,20 +2,21 @@
#define CCOLLISIONNODE_H
#include "CSceneNode.h"
#include <Resource/CCollisionMesh.h>
#include <Resource/CCollisionMeshGroup.h>
class CCollisionNode : public CSceneNode
{
CCollisionMesh *mpMesh;
CToken mMeshToken;
CCollisionMeshGroup *mpCollision;
CToken mCollisionToken;
public:
CCollisionNode(CSceneManager *pScene, CSceneNode *pParent = 0, CCollisionMesh *pMesh = 0);
CCollisionNode(CSceneManager *pScene, CSceneNode *pParent = 0, CCollisionMeshGroup *pCollision = 0);
ENodeType NodeType();
void AddToRenderer(CRenderer *pRenderer);
void Draw(ERenderOptions Options);
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

View File

@ -57,10 +57,12 @@ void CLightNode::DrawAsset(ERenderOptions, u32)
// 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
if (AABox().IsPointInBox(Ray.Origin()))
bool allowBackfaces = ((options & eEnableBackfaceCull) == 0);
if (!allowBackfaces && (AABox().IsPointInBox(Ray.Origin())))
return SRayIntersection(false, 0.f, nullptr, 0);
std::pair<bool,float> BoxResult = AABox().IntersectsRay(Ray);

View File

@ -13,7 +13,7 @@ public:
void AddToRenderer(CRenderer *pRenderer);
void Draw(ERenderOptions Options);
void DrawAsset(ERenderOptions Options, u32 asset);
SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID);
SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID, ERenderOptions options);
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;
out.pNode = this;
out.AssetIndex = AssetID;
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)
{

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -176,17 +176,17 @@ void CWorldEditorWindow::on_actionBackface_culling_triggered()
void CWorldEditorWindow::on_actionWorld_triggered()
{
mpSceneManager->SetWorld(ui->actionWorld->isChecked());
mpRenderer->ToggleWorld(ui->actionWorld->isChecked());
}
void CWorldEditorWindow::on_actionCollision_triggered()
{
mpSceneManager->SetCollision(ui->actionCollision->isChecked());
mpRenderer->ToggleWorldCollision(ui->actionCollision->isChecked());
}
void CWorldEditorWindow::on_actionObjects_triggered()
{
mpSceneManager->SetObjects(ui->actionObjects->isChecked());
mpRenderer->ToggleObjects(ui->actionObjects->isChecked());
}
void CWorldEditorWindow::setupInstanceViewLayers()
@ -233,7 +233,7 @@ void CWorldEditorWindow::on_actionMaterial_Animations_triggered()
void CWorldEditorWindow::on_actionLights_triggered()
{
mpSceneManager->SetLights(ui->actionLights->isChecked());
mpRenderer->ToggleLights(ui->actionLights->isChecked());
}
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)
ui->LayersTreeView->update(Index);
else if (sender() == ui->TypesTreeView)