Reorganized collision data classes & added basic collision editor window with an OBB tree visualization
This commit is contained in:
parent
ff021dcdda
commit
4e1560a99c
|
@ -1 +1 @@
|
||||||
Subproject commit 3c6a40742551d7afd0737d1293d036df69f34ec6
|
Subproject commit fe3ccf42b71382683f976bb0509a8e68578e1deb
|
|
@ -110,8 +110,8 @@ HEADERS += \
|
||||||
Resource/Script/CScriptTemplate.h \
|
Resource/Script/CScriptTemplate.h \
|
||||||
Resource/Script/EVolumeShape.h \
|
Resource/Script/EVolumeShape.h \
|
||||||
Resource/StringTable/CStringTable.h \
|
Resource/StringTable/CStringTable.h \
|
||||||
Resource/CCollisionMesh.h \
|
Resource/Collision/CCollisionMesh.h \
|
||||||
Resource/CCollisionMeshGroup.h \
|
Resource/Collision/CCollisionMeshGroup.h \
|
||||||
Resource/CFont.h \
|
Resource/CFont.h \
|
||||||
Resource/CLight.h \
|
Resource/CLight.h \
|
||||||
Resource/CMaterial.h \
|
Resource/CMaterial.h \
|
||||||
|
@ -174,7 +174,7 @@ HEADERS += \
|
||||||
Render/EDepthGroup.h \
|
Render/EDepthGroup.h \
|
||||||
Scene/CScriptAttachNode.h \
|
Scene/CScriptAttachNode.h \
|
||||||
ScriptExtra/CSandwormExtra.h \
|
ScriptExtra/CSandwormExtra.h \
|
||||||
Resource/CCollisionMaterial.h \
|
Resource/Collision/CCollisionMaterial.h \
|
||||||
GameProject/CGameProject.h \
|
GameProject/CGameProject.h \
|
||||||
GameProject/CPackage.h \
|
GameProject/CPackage.h \
|
||||||
GameProject/CGameExporter.h \
|
GameProject/CGameExporter.h \
|
||||||
|
@ -256,7 +256,11 @@ HEADERS += \
|
||||||
Resource/Scan/SScanParametersMP1.h \
|
Resource/Scan/SScanParametersMP1.h \
|
||||||
Resource/Scan/ELogbookCategory.h \
|
Resource/Scan/ELogbookCategory.h \
|
||||||
Resource/Cooker/CScanCooker.h \
|
Resource/Cooker/CScanCooker.h \
|
||||||
NCoreTests.h
|
NCoreTests.h \
|
||||||
|
Resource/Collision/SCollisionIndexData.h \
|
||||||
|
Resource/Collision/CCollisionRenderData.h \
|
||||||
|
Resource/Collision/SOBBTreeNode.h \
|
||||||
|
Resource/Collision/CCollidableOBBTree.h
|
||||||
|
|
||||||
# Source Files
|
# Source Files
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
|
@ -287,7 +291,7 @@ SOURCES += \
|
||||||
Resource/Model/SSurface.cpp \
|
Resource/Model/SSurface.cpp \
|
||||||
Resource/Script/CScriptObject.cpp \
|
Resource/Script/CScriptObject.cpp \
|
||||||
Resource/Script/CScriptTemplate.cpp \
|
Resource/Script/CScriptTemplate.cpp \
|
||||||
Resource/CCollisionMesh.cpp \
|
Resource/Collision/CCollisionMesh.cpp \
|
||||||
Resource/CFont.cpp \
|
Resource/CFont.cpp \
|
||||||
Resource/CLight.cpp \
|
Resource/CLight.cpp \
|
||||||
Resource/CMaterial.cpp \
|
Resource/CMaterial.cpp \
|
||||||
|
@ -333,7 +337,7 @@ SOURCES += \
|
||||||
Resource/Model/EVertexAttribute.cpp \
|
Resource/Model/EVertexAttribute.cpp \
|
||||||
Scene/CScriptAttachNode.cpp \
|
Scene/CScriptAttachNode.cpp \
|
||||||
ScriptExtra/CSandwormExtra.cpp \
|
ScriptExtra/CSandwormExtra.cpp \
|
||||||
Resource/CCollisionMaterial.cpp \
|
Resource/Collision/CCollisionMaterial.cpp \
|
||||||
GameProject/CGameProject.cpp \
|
GameProject/CGameProject.cpp \
|
||||||
GameProject/CGameExporter.cpp \
|
GameProject/CGameExporter.cpp \
|
||||||
GameProject/CResourceStore.cpp \
|
GameProject/CResourceStore.cpp \
|
||||||
|
@ -375,7 +379,8 @@ SOURCES += \
|
||||||
Resource/Cooker/CStringCooker.cpp \
|
Resource/Cooker/CStringCooker.cpp \
|
||||||
Resource/Scan/CScan.cpp \
|
Resource/Scan/CScan.cpp \
|
||||||
Resource/Cooker/CScanCooker.cpp \
|
Resource/Cooker/CScanCooker.cpp \
|
||||||
NCoreTests.cpp
|
NCoreTests.cpp \
|
||||||
|
Resource/Collision/CCollisionRenderData.cpp
|
||||||
|
|
||||||
# Codegen
|
# Codegen
|
||||||
CODEGEN_DIR = $$EXTERNALS_DIR/CodeGen
|
CODEGEN_DIR = $$EXTERNALS_DIR/CodeGen
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef SVIEWINFO
|
#ifndef SVIEWINFO
|
||||||
#define SVIEWINFO
|
#define SVIEWINFO
|
||||||
|
|
||||||
#include "Core/Resource/CCollisionMaterial.h"
|
#include "Core/Resource/Collision/CCollisionMaterial.h"
|
||||||
#include "Core/Scene/FShowFlags.h"
|
#include "Core/Scene/FShowFlags.h"
|
||||||
#include <Common/Math/CFrustumPlanes.h>
|
#include <Common/Math/CFrustumPlanes.h>
|
||||||
#include <Common/Math/CMatrix4f.h>
|
#include <Common/Math/CMatrix4f.h>
|
||||||
|
@ -11,20 +11,24 @@ struct SCollisionRenderSettings
|
||||||
{
|
{
|
||||||
uint64 HighlightMask;
|
uint64 HighlightMask;
|
||||||
uint64 HideMask;
|
uint64 HideMask;
|
||||||
|
int BoundingHierarchyRenderDepth;
|
||||||
|
|
||||||
CCollisionMaterial HideMaterial;
|
CCollisionMaterial HideMaterial;
|
||||||
bool DrawWireframe;
|
bool DrawWireframe;
|
||||||
bool DrawBackfaces;
|
bool DrawBackfaces;
|
||||||
bool DrawAreaCollisionBounds;
|
bool DrawAreaCollisionBounds;
|
||||||
|
bool DrawBoundingHierarchy;
|
||||||
bool TintWithSurfaceColor;
|
bool TintWithSurfaceColor;
|
||||||
bool TintUnwalkableTris;
|
bool TintUnwalkableTris;
|
||||||
|
|
||||||
SCollisionRenderSettings()
|
SCollisionRenderSettings()
|
||||||
: HighlightMask(0)
|
: HighlightMask(0)
|
||||||
, HideMask(0)
|
, HideMask(0)
|
||||||
|
, BoundingHierarchyRenderDepth(0)
|
||||||
, DrawWireframe(true)
|
, DrawWireframe(true)
|
||||||
, DrawBackfaces(false)
|
, DrawBackfaces(false)
|
||||||
, DrawAreaCollisionBounds(true)
|
, DrawAreaCollisionBounds(true)
|
||||||
|
, DrawBoundingHierarchy(false)
|
||||||
, TintWithSurfaceColor(true)
|
, TintWithSurfaceColor(true)
|
||||||
, TintUnwalkableTris(true) {}
|
, TintUnwalkableTris(true) {}
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,8 +19,6 @@ CGameArea::~CGameArea()
|
||||||
{
|
{
|
||||||
ClearTerrain();
|
ClearTerrain();
|
||||||
|
|
||||||
delete mpCollision;
|
|
||||||
|
|
||||||
for (uint32 iSCLY = 0; iSCLY < mScriptLayers.size(); iSCLY++)
|
for (uint32 iSCLY = 0; iSCLY < mScriptLayers.size(); iSCLY++)
|
||||||
delete mScriptLayers[iSCLY];
|
delete mScriptLayers[iSCLY];
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
#define CGAMEAREA_H
|
#define CGAMEAREA_H
|
||||||
|
|
||||||
#include "Core/Resource/CResource.h"
|
#include "Core/Resource/CResource.h"
|
||||||
#include "Core/Resource/CCollisionMeshGroup.h"
|
|
||||||
#include "Core/Resource/CLight.h"
|
#include "Core/Resource/CLight.h"
|
||||||
#include "Core/Resource/CMaterialSet.h"
|
#include "Core/Resource/CMaterialSet.h"
|
||||||
#include "Core/Resource/CPoiToWorld.h"
|
#include "Core/Resource/CPoiToWorld.h"
|
||||||
|
#include "Core/Resource/Collision/CCollisionMeshGroup.h"
|
||||||
#include "Core/Resource/Model/CModel.h"
|
#include "Core/Resource/Model/CModel.h"
|
||||||
#include "Core/Resource/Model/CStaticModel.h"
|
#include "Core/Resource/Model/CStaticModel.h"
|
||||||
#include <Common/BasicTypes.h>
|
#include <Common/BasicTypes.h>
|
||||||
|
@ -51,7 +51,7 @@ class CGameArea : public CResource
|
||||||
std::vector<CScriptLayer*> mScriptLayers;
|
std::vector<CScriptLayer*> mScriptLayers;
|
||||||
std::unordered_map<uint32, CScriptObject*> mObjectMap;
|
std::unordered_map<uint32, CScriptObject*> mObjectMap;
|
||||||
// Collision
|
// Collision
|
||||||
CCollisionMeshGroup *mpCollision;
|
std::unique_ptr<CCollisionMeshGroup> mpCollision;
|
||||||
// Lights
|
// Lights
|
||||||
std::vector<std::vector<CLight*>> mLightLayers;
|
std::vector<std::vector<CLight*>> mLightLayers;
|
||||||
// Path Mesh
|
// Path Mesh
|
||||||
|
@ -93,7 +93,7 @@ public:
|
||||||
inline uint32 NumStaticModels() const { return mStaticWorldModels.size(); }
|
inline uint32 NumStaticModels() const { return mStaticWorldModels.size(); }
|
||||||
inline CModel* TerrainModel(uint32 iMdl) const { return mWorldModels[iMdl]; }
|
inline CModel* TerrainModel(uint32 iMdl) const { return mWorldModels[iMdl]; }
|
||||||
inline CStaticModel* StaticModel(uint32 iMdl) const { return mStaticWorldModels[iMdl]; }
|
inline CStaticModel* StaticModel(uint32 iMdl) const { return mStaticWorldModels[iMdl]; }
|
||||||
inline CCollisionMeshGroup* Collision() const { return mpCollision; }
|
inline CCollisionMeshGroup* Collision() const { return mpCollision.get(); }
|
||||||
inline uint32 NumScriptLayers() const { return mScriptLayers.size(); }
|
inline uint32 NumScriptLayers() const { return mScriptLayers.size(); }
|
||||||
inline CScriptLayer* ScriptLayer(uint32 Index) const { return mScriptLayers[Index]; }
|
inline CScriptLayer* ScriptLayer(uint32 Index) const { return mScriptLayers[Index]; }
|
||||||
inline uint32 NumLightLayers() const { return mLightLayers.size(); }
|
inline uint32 NumLightLayers() const { return mLightLayers.size(); }
|
||||||
|
|
|
@ -1,169 +0,0 @@
|
||||||
#include "CCollisionMesh.h"
|
|
||||||
#include "Core/Render/CRenderer.h"
|
|
||||||
#include "Core/Render/CDrawUtil.h"
|
|
||||||
#include <Common/Macros.h>
|
|
||||||
|
|
||||||
CCollisionMesh::CCollisionMesh()
|
|
||||||
{
|
|
||||||
mVBO.SetVertexDesc(EVertexAttribute::Position | EVertexAttribute::Normal);
|
|
||||||
mVertexCount = 0;
|
|
||||||
mLineCount = 0;
|
|
||||||
mFaceCount = 0;
|
|
||||||
mBuffered = false;
|
|
||||||
mIBO.SetPrimitiveType(GL_TRIANGLES);
|
|
||||||
}
|
|
||||||
|
|
||||||
CCollisionMesh::~CCollisionMesh()
|
|
||||||
{
|
|
||||||
if (mBuffered)
|
|
||||||
{
|
|
||||||
mIBO.Clear();
|
|
||||||
mVBO.Clear();
|
|
||||||
mBuffered = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CCollisionMesh::BufferGL()
|
|
||||||
{
|
|
||||||
if (mBuffered)
|
|
||||||
{
|
|
||||||
mIBO.Clear();
|
|
||||||
mVBO.Clear();
|
|
||||||
mBuffered = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create new list of collision faces sorted by material index
|
|
||||||
std::vector<CCollisionFace> SortedTris = mCollisionFaces;
|
|
||||||
std::sort(SortedTris.begin(), SortedTris.end(), [](CCollisionFace& rLeft, CCollisionFace& rRight) -> bool {
|
|
||||||
return rLeft.MaterialIdx < rRight.MaterialIdx;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add all the relevant indices to the IBO
|
|
||||||
mVBO.Reserve(SortedTris.size() * 3);
|
|
||||||
mIBO.Reserve(SortedTris.size() * 3);
|
|
||||||
|
|
||||||
mMaterialOffsets.reserve(mMaterials.size());
|
|
||||||
uint32 CurMat = 0;
|
|
||||||
|
|
||||||
for (uint32 iTri = 0; iTri < SortedTris.size(); iTri++)
|
|
||||||
{
|
|
||||||
uint16 Verts[3];
|
|
||||||
|
|
||||||
CCollisionFace *pFace = &SortedTris[iTri];
|
|
||||||
CCollisionLine *pLineA = GetLine(pFace->Lines[0]);
|
|
||||||
CCollisionLine *pLineB = GetLine(pFace->Lines[1]);
|
|
||||||
Verts[0] = pLineA->Vertices[0];
|
|
||||||
Verts[1] = pLineA->Vertices[1];
|
|
||||||
|
|
||||||
// Check if we've reached a new material
|
|
||||||
if (pFace->MaterialIdx != CurMat)
|
|
||||||
{
|
|
||||||
while (CurMat != pFace->MaterialIdx)
|
|
||||||
{
|
|
||||||
mMaterialOffsets.push_back(mIBO.GetSize());
|
|
||||||
CurMat++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We have two vertex indices; the last one is one of the ones on line B, but we're not sure which one
|
|
||||||
if ((pLineB->Vertices[0] != Verts[0]) &&
|
|
||||||
(pLineB->Vertices[0] != Verts[1]))
|
|
||||||
Verts[2] = pLineB->Vertices[0];
|
|
||||||
else
|
|
||||||
Verts[2] = pLineB->Vertices[1];
|
|
||||||
|
|
||||||
// Some faces have a property that indicates they need to be inverted
|
|
||||||
if (GetMaterial(pFace->MaterialIdx) & eCF_FlippedTri)
|
|
||||||
{
|
|
||||||
uint16 V0 = Verts[0];
|
|
||||||
Verts[0] = Verts[2];
|
|
||||||
Verts[2] = V0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate vertices - we don't share vertices between triangles in order to get the generated normals looking correct
|
|
||||||
CCollisionVertex& rVert0 = mCollisionVertices[Verts[0]];
|
|
||||||
CCollisionVertex& rVert1 = mCollisionVertices[Verts[1]];
|
|
||||||
CCollisionVertex& rVert2 = mCollisionVertices[Verts[2]];
|
|
||||||
|
|
||||||
CVector3f V0toV1 = (rVert1.Pos - rVert0.Pos).Normalized();
|
|
||||||
CVector3f V0toV2 = (rVert2.Pos - rVert0.Pos).Normalized();
|
|
||||||
CVector3f FaceNormal = V0toV1.Cross(V0toV2).Normalized();
|
|
||||||
|
|
||||||
for (uint32 iVtx = 0; iVtx < 3; iVtx++)
|
|
||||||
{
|
|
||||||
CVertex Vtx;
|
|
||||||
Vtx.Position = mCollisionVertices[ Verts[iVtx] ].Pos;
|
|
||||||
Vtx.Normal = FaceNormal;
|
|
||||||
uint16 Index = mVBO.AddVertex(Vtx);
|
|
||||||
mIBO.AddIndex(Index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (CurMat != mMaterials.size())
|
|
||||||
{
|
|
||||||
mMaterialOffsets.push_back(mIBO.GetSize());
|
|
||||||
CurMat++;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(mMaterialOffsets.size() == mMaterials.size());
|
|
||||||
|
|
||||||
// Buffer, and done
|
|
||||||
mVBO.Buffer();
|
|
||||||
mIBO.Buffer();
|
|
||||||
mBuffered = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CCollisionMesh::Draw()
|
|
||||||
{
|
|
||||||
if (!mBuffered) BufferGL();
|
|
||||||
|
|
||||||
mVBO.Bind();
|
|
||||||
mIBO.DrawElements();
|
|
||||||
mVBO.Unbind();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CCollisionMesh::DrawMaterial(uint32 MatIdx, bool Wireframe)
|
|
||||||
{
|
|
||||||
if (!mBuffered) BufferGL();
|
|
||||||
ASSERT(MatIdx < mMaterials.size());
|
|
||||||
|
|
||||||
mVBO.Bind();
|
|
||||||
uint32 StartIdx = (MatIdx == 0 ? 0 : mMaterialOffsets[MatIdx - 1]);
|
|
||||||
uint32 NumElements = mMaterialOffsets[MatIdx] - StartIdx;
|
|
||||||
|
|
||||||
if (Wireframe)
|
|
||||||
{
|
|
||||||
CDrawUtil::UseColorShader(CColor::skBlack);
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
|
||||||
}
|
|
||||||
|
|
||||||
mIBO.DrawElements(StartIdx, NumElements);
|
|
||||||
|
|
||||||
if (Wireframe)
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
||||||
|
|
||||||
mVBO.Unbind();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CCollisionMesh::DrawWireframe()
|
|
||||||
{
|
|
||||||
CDrawUtil::UseColorShader(CColor::skBlack);
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
|
||||||
Draw();
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
||||||
}
|
|
||||||
|
|
||||||
CCollisionMesh::CCollisionVertex* CCollisionMesh::GetVertex(uint16 Index)
|
|
||||||
{
|
|
||||||
return &mCollisionVertices[Index];
|
|
||||||
}
|
|
||||||
|
|
||||||
CCollisionMesh::CCollisionLine* CCollisionMesh::GetLine(uint16 Index)
|
|
||||||
{
|
|
||||||
return &mCollisionLines[Index];
|
|
||||||
}
|
|
||||||
|
|
||||||
CCollisionMesh::CCollisionFace* CCollisionMesh::GetFace(uint16 Index)
|
|
||||||
{
|
|
||||||
return &mCollisionFaces[Index];
|
|
||||||
}
|
|
|
@ -1,89 +0,0 @@
|
||||||
#ifndef CCOLLISIONMESH_H
|
|
||||||
#define CCOLLISIONMESH_H
|
|
||||||
|
|
||||||
#include "CCollisionMaterial.h"
|
|
||||||
#include "CResource.h"
|
|
||||||
#include "Core/OpenGL/CVertexBuffer.h"
|
|
||||||
#include "Core/OpenGL/CIndexBuffer.h"
|
|
||||||
#include <Common/Math/CAABox.h>
|
|
||||||
|
|
||||||
class CCollisionMesh
|
|
||||||
{
|
|
||||||
friend class CCollisionLoader;
|
|
||||||
|
|
||||||
class CCollisionOctree
|
|
||||||
{
|
|
||||||
friend class CCollisionLoader;
|
|
||||||
struct SOctreeNode {};
|
|
||||||
|
|
||||||
struct SLeaf : public SOctreeNode
|
|
||||||
{
|
|
||||||
CAABox AABox;
|
|
||||||
std::vector<uint16> FaceIndices;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SBranch : public SOctreeNode
|
|
||||||
{
|
|
||||||
uint16 Flags;
|
|
||||||
SOctreeNode *pChildren[8];
|
|
||||||
};
|
|
||||||
|
|
||||||
SOctreeNode* mpRoot;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CCollisionVertex
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
uint32 MaterialIdx;
|
|
||||||
CVector3f Pos;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CCollisionLine
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
uint32 MaterialIdx;
|
|
||||||
uint16 Vertices[2];
|
|
||||||
};
|
|
||||||
|
|
||||||
class CCollisionFace
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
uint32 MaterialIdx;
|
|
||||||
uint16 Lines[3];
|
|
||||||
};
|
|
||||||
|
|
||||||
CVertexBuffer mVBO;
|
|
||||||
CIndexBuffer mIBO;
|
|
||||||
uint32 mVertexCount;
|
|
||||||
uint32 mLineCount;
|
|
||||||
uint32 mFaceCount;
|
|
||||||
bool mBuffered;
|
|
||||||
|
|
||||||
CAABox mAABox;
|
|
||||||
CCollisionOctree *mpOctree;
|
|
||||||
std::vector<CCollisionMaterial> mMaterials;
|
|
||||||
std::vector<CCollisionVertex> mCollisionVertices;
|
|
||||||
std::vector<CCollisionLine> mCollisionLines;
|
|
||||||
std::vector<CCollisionFace> mCollisionFaces;
|
|
||||||
std::vector<uint32> mMaterialOffsets;
|
|
||||||
bool mOctreeLoaded;
|
|
||||||
|
|
||||||
CCollisionVertex *GetVertex(uint16 Index);
|
|
||||||
CCollisionLine *GetLine(uint16 Index);
|
|
||||||
CCollisionFace *GetFace(uint16 Index);
|
|
||||||
|
|
||||||
public:
|
|
||||||
CCollisionMesh();
|
|
||||||
~CCollisionMesh();
|
|
||||||
|
|
||||||
void BufferGL();
|
|
||||||
void Draw();
|
|
||||||
void DrawMaterial(uint32 MatIdx, bool Wireframe);
|
|
||||||
void DrawWireframe();
|
|
||||||
|
|
||||||
inline uint32 NumMaterials() const { return mMaterials.size(); }
|
|
||||||
inline CCollisionMaterial& GetMaterial(uint32 Index) { return mMaterials[Index]; }
|
|
||||||
inline const CAABox& BoundingBox() const { return mAABox; }
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // CCOLLISIONMESH_H
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
#ifndef CCOLLIDABLEOBBTREE_H
|
||||||
|
#define CCOLLIDABLEOBBTREE_H
|
||||||
|
|
||||||
|
#include "CCollisionMesh.h"
|
||||||
|
#include "SOBBTreeNode.h"
|
||||||
|
|
||||||
|
/** A collision mesh with an OBB tree for spatial queries. Represents one mesh from a DCLN file */
|
||||||
|
class CCollidableOBBTree : public CCollisionMesh
|
||||||
|
{
|
||||||
|
friend class CCollisionLoader;
|
||||||
|
std::unique_ptr<SOBBTreeNode> mpOBBTree;
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual void BuildRenderData() override
|
||||||
|
{
|
||||||
|
if (!mRenderData.IsBuilt())
|
||||||
|
{
|
||||||
|
mRenderData.BuildRenderData(mIndexData);
|
||||||
|
mRenderData.BuildBoundingHierarchyRenderData(mpOBBTree.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Accessors */
|
||||||
|
inline SOBBTreeNode* GetOBBTree() const
|
||||||
|
{
|
||||||
|
return mpOBBTree.get();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CCOLLIDABLEOBBTREE_H
|
|
@ -0,0 +1,9 @@
|
||||||
|
#include "CCollisionMesh.h"
|
||||||
|
|
||||||
|
void CCollisionMesh::BuildRenderData()
|
||||||
|
{
|
||||||
|
if (!mRenderData.IsBuilt())
|
||||||
|
{
|
||||||
|
mRenderData.BuildRenderData(mIndexData);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
#ifndef CCOLLISIONMESH_H
|
||||||
|
#define CCOLLISIONMESH_H
|
||||||
|
|
||||||
|
#include "CCollisionMaterial.h"
|
||||||
|
#include "CCollisionRenderData.h"
|
||||||
|
#include "SCollisionIndexData.h"
|
||||||
|
#include <Common/Math/CAABox.h>
|
||||||
|
|
||||||
|
/** Base class of collision geometry */
|
||||||
|
class CCollisionMesh
|
||||||
|
{
|
||||||
|
friend class CCollisionLoader;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
CAABox mAABox;
|
||||||
|
SCollisionIndexData mIndexData;
|
||||||
|
CCollisionRenderData mRenderData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual void BuildRenderData();
|
||||||
|
|
||||||
|
/** Accessors */
|
||||||
|
inline CAABox Bounds() const
|
||||||
|
{
|
||||||
|
return mAABox;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const SCollisionIndexData& GetIndexData() const
|
||||||
|
{
|
||||||
|
return mIndexData;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const CCollisionRenderData& GetRenderData() const
|
||||||
|
{
|
||||||
|
return mRenderData;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline CCollisionRenderData& GetRenderData()
|
||||||
|
{
|
||||||
|
return mRenderData;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CCOLLISIONMESH_H
|
|
@ -1,9 +1,10 @@
|
||||||
#ifndef CCOLLISIONMESHGROUP_H
|
#ifndef CCOLLISIONMESHGROUP_H
|
||||||
#define CCOLLISIONMESHGROUP_H
|
#define CCOLLISIONMESHGROUP_H
|
||||||
|
|
||||||
#include "CResource.h"
|
|
||||||
#include "CCollisionMesh.h"
|
#include "CCollisionMesh.h"
|
||||||
#include "TResPtr.h"
|
#include "Core/Resource/CResource.h"
|
||||||
|
#include "Core/Resource/TResPtr.h"
|
||||||
|
#include <Common/Math/CTransform4f.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class CCollisionMeshGroup : public CResource
|
class CCollisionMeshGroup : public CResource
|
||||||
|
@ -24,16 +25,22 @@ public:
|
||||||
inline CCollisionMesh* MeshByIndex(uint32 Index) const { return mMeshes[Index]; }
|
inline CCollisionMesh* MeshByIndex(uint32 Index) const { return mMeshes[Index]; }
|
||||||
inline void AddMesh(CCollisionMesh *pMesh) { mMeshes.push_back(pMesh); }
|
inline void AddMesh(CCollisionMesh *pMesh) { mMeshes.push_back(pMesh); }
|
||||||
|
|
||||||
|
inline void BuildRenderData()
|
||||||
|
{
|
||||||
|
for (auto It = mMeshes.begin(); It != mMeshes.end(); It++)
|
||||||
|
(*It)->BuildRenderData();
|
||||||
|
}
|
||||||
|
|
||||||
inline void Draw()
|
inline void Draw()
|
||||||
{
|
{
|
||||||
for (auto it = mMeshes.begin(); it != mMeshes.end(); it++)
|
for (auto it = mMeshes.begin(); it != mMeshes.end(); it++)
|
||||||
(*it)->Draw();
|
(*it)->GetRenderData().Render(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void DrawWireframe()
|
inline void DrawWireframe()
|
||||||
{
|
{
|
||||||
for (auto it = mMeshes.begin(); it != mMeshes.end(); it++)
|
for (auto it = mMeshes.begin(); it != mMeshes.end(); it++)
|
||||||
(*it)->DrawWireframe();
|
(*it)->GetRenderData().Render(true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,261 @@
|
||||||
|
#include "CCollisionRenderData.h"
|
||||||
|
#include <Core/Render/CDrawUtil.h>
|
||||||
|
|
||||||
|
/** Build from collision data */
|
||||||
|
void CCollisionRenderData::BuildRenderData(const SCollisionIndexData& kIndexData)
|
||||||
|
{
|
||||||
|
// Clear any existing data
|
||||||
|
if (mBuilt)
|
||||||
|
{
|
||||||
|
mVertexBuffer.Clear();
|
||||||
|
mIndexBuffer.Clear();
|
||||||
|
mWireframeIndexBuffer.Clear();
|
||||||
|
mMaterialIndexOffsets.clear();
|
||||||
|
mMaterialWireIndexOffsets.clear();
|
||||||
|
mBuilt = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mIndexBuffer.SetPrimitiveType(GL_TRIANGLES);
|
||||||
|
mWireframeIndexBuffer.SetPrimitiveType(GL_LINES);
|
||||||
|
|
||||||
|
// Build list of triangle indices sorted by material index
|
||||||
|
std::vector<uint16> SortedTris(kIndexData.TriangleMaterialIndices.size(), 0);
|
||||||
|
|
||||||
|
for (uint16 i=0; i<SortedTris.size(); i++)
|
||||||
|
{
|
||||||
|
SortedTris[i] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort(SortedTris.begin(), SortedTris.end(), [kIndexData](uint16 Left, uint16 Right) -> bool {
|
||||||
|
return kIndexData.TriangleMaterialIndices[Left] < kIndexData.TriangleMaterialIndices[Right];
|
||||||
|
});
|
||||||
|
|
||||||
|
mVertexBuffer.Reserve(SortedTris.size() * 3);
|
||||||
|
mIndexBuffer.Reserve(SortedTris.size() * 3);
|
||||||
|
mWireframeIndexBuffer.Reserve(SortedTris.size() * 6);
|
||||||
|
mMaterialIndexOffsets.reserve(kIndexData.Materials.size());
|
||||||
|
uint8 CurrentMatIdx = 0xFF;
|
||||||
|
|
||||||
|
for (uint i=0; i < SortedTris.size(); i++)
|
||||||
|
{
|
||||||
|
uint TriIdx = SortedTris[i];
|
||||||
|
uint8 MaterialIdx = kIndexData.TriangleMaterialIndices[TriIdx];
|
||||||
|
const CCollisionMaterial& kMaterial = kIndexData.Materials[MaterialIdx];
|
||||||
|
|
||||||
|
if (MaterialIdx != CurrentMatIdx)
|
||||||
|
{
|
||||||
|
// Note some collision materials have no geometry associated with them as
|
||||||
|
// some materials are exclusively used with edges/vertices.
|
||||||
|
ASSERT( CurrentMatIdx < MaterialIdx || CurrentMatIdx == 0xFF );
|
||||||
|
|
||||||
|
while (CurrentMatIdx != MaterialIdx)
|
||||||
|
{
|
||||||
|
mMaterialIndexOffsets.push_back( mIndexBuffer.GetSize() );
|
||||||
|
CurrentMatIdx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16 LineA = kIndexData.TriangleIndices[ (TriIdx*3)+0 ];
|
||||||
|
uint16 LineB = kIndexData.TriangleIndices[ (TriIdx*3)+1 ];
|
||||||
|
uint16 LineAVertA = kIndexData.EdgeIndices[ (LineA*2)+0 ];
|
||||||
|
uint16 LineAVertB = kIndexData.EdgeIndices[ (LineA*2)+1 ];
|
||||||
|
uint16 LineBVertA = kIndexData.EdgeIndices[ (LineB*2)+0 ];
|
||||||
|
uint16 LineBVertB = kIndexData.EdgeIndices[ (LineB*2)+1 ];
|
||||||
|
uint16 VertIdx0 = LineAVertA;
|
||||||
|
uint16 VertIdx1 = LineAVertB;
|
||||||
|
uint16 VertIdx2 = (LineBVertA != LineAVertA && LineBVertA != LineAVertB ? LineBVertA : LineBVertB);
|
||||||
|
|
||||||
|
// Reverse vertex order if material indicates tri is flipped
|
||||||
|
if (kMaterial & eCF_FlippedTri)
|
||||||
|
{
|
||||||
|
uint16 Tmp = VertIdx0;
|
||||||
|
VertIdx0 = VertIdx2;
|
||||||
|
VertIdx2 = Tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate vertex data
|
||||||
|
const CVector3f& kVert0 = kIndexData.Vertices[VertIdx0];
|
||||||
|
const CVector3f& kVert1 = kIndexData.Vertices[VertIdx1];
|
||||||
|
const CVector3f& kVert2 = kIndexData.Vertices[VertIdx2];
|
||||||
|
CVector3f V0toV1 = (kVert1 - kVert0);
|
||||||
|
CVector3f V0toV2 = (kVert2 - kVert0);
|
||||||
|
CVector3f TriNormal = V0toV1.Cross(V0toV2).Normalized();
|
||||||
|
uint16 Index0 = mVertexBuffer.Size();
|
||||||
|
uint16 Index1 = Index0 + 1;
|
||||||
|
uint16 Index2 = Index1 + 1;
|
||||||
|
|
||||||
|
CVertex Vtx;
|
||||||
|
Vtx.Normal = TriNormal;
|
||||||
|
|
||||||
|
Vtx.Position = kVert0;
|
||||||
|
mVertexBuffer.AddVertex(Vtx);
|
||||||
|
Vtx.Position = kVert1;
|
||||||
|
mVertexBuffer.AddVertex(Vtx);
|
||||||
|
Vtx.Position = kVert2;
|
||||||
|
mVertexBuffer.AddVertex(Vtx);
|
||||||
|
|
||||||
|
mIndexBuffer.AddIndex(Index0);
|
||||||
|
mIndexBuffer.AddIndex(Index1);
|
||||||
|
mIndexBuffer.AddIndex(Index2);
|
||||||
|
|
||||||
|
mWireframeIndexBuffer.AddIndex(Index0);
|
||||||
|
mWireframeIndexBuffer.AddIndex(Index1);
|
||||||
|
mWireframeIndexBuffer.AddIndex(Index1);
|
||||||
|
mWireframeIndexBuffer.AddIndex(Index2);
|
||||||
|
mWireframeIndexBuffer.AddIndex(Index2);
|
||||||
|
mWireframeIndexBuffer.AddIndex(Index0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill the rest of the material offsets, adding an extra index at the end
|
||||||
|
for (; CurrentMatIdx <= kIndexData.Materials.size(); CurrentMatIdx++)
|
||||||
|
{
|
||||||
|
mMaterialIndexOffsets.push_back( mIndexBuffer.GetSize() );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Done
|
||||||
|
mVertexBuffer.Buffer();
|
||||||
|
mIndexBuffer.Buffer();
|
||||||
|
mWireframeIndexBuffer.Buffer();
|
||||||
|
mBuilt = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCollisionRenderData::BuildBoundingHierarchyRenderData(const SOBBTreeNode* pOBBTree)
|
||||||
|
{
|
||||||
|
if (mBoundingHierarchyBuilt)
|
||||||
|
{
|
||||||
|
mBoundingVertexBuffer.Clear();
|
||||||
|
mBoundingIndexBuffer.Clear();
|
||||||
|
mBoundingDepthOffsets.clear();
|
||||||
|
mBoundingHierarchyBuilt = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mBoundingIndexBuffer.SetPrimitiveType(GL_LINES);
|
||||||
|
|
||||||
|
// Iterate through the OBB tree, building a list of nodes as we go.
|
||||||
|
// We iterate through this using a breadth-first search in order to group together
|
||||||
|
// OBBs in the same depth level in the index buffer. This allows us to render a
|
||||||
|
// subset of the bounding hierarchy based on a max depth level.
|
||||||
|
std::vector<const SOBBTreeNode*> TreeNodes;
|
||||||
|
TreeNodes.push_back(pOBBTree);
|
||||||
|
uint NodeIdx = 0;
|
||||||
|
|
||||||
|
while (NodeIdx < TreeNodes.size())
|
||||||
|
{
|
||||||
|
// Keep track of the current depth level and iterate through it
|
||||||
|
mBoundingDepthOffsets.push_back(mBoundingIndexBuffer.GetSize());
|
||||||
|
uint DepthLevel = TreeNodes.size();
|
||||||
|
|
||||||
|
mBoundingVertexBuffer.Reserve(8 * (DepthLevel - NodeIdx));
|
||||||
|
mBoundingIndexBuffer.Reserve(24 * (DepthLevel - NodeIdx));
|
||||||
|
|
||||||
|
for (; NodeIdx < DepthLevel; NodeIdx++)
|
||||||
|
{
|
||||||
|
const SOBBTreeNode* pkNode = TreeNodes[NodeIdx];
|
||||||
|
|
||||||
|
// Append children
|
||||||
|
if (pkNode->NodeType == EOBBTreeNodeType::Branch)
|
||||||
|
{
|
||||||
|
const SOBBTreeBranch* pkBranch = static_cast<const SOBBTreeBranch*>(pkNode);
|
||||||
|
TreeNodes.push_back(pkBranch->pLeft.get());
|
||||||
|
TreeNodes.push_back(pkBranch->pRight.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new transform with the radii combined in as a scale matrie
|
||||||
|
CTransform4f CombinedTransform =
|
||||||
|
pkNode->Transform * CTransform4f::ScaleMatrix(pkNode->Radii);
|
||||||
|
|
||||||
|
// Transform a 1x1x1 unit cube using the transform...
|
||||||
|
static const CVector3f skUnitCubeVertices[] = {
|
||||||
|
CVector3f(-1, -1, -1),
|
||||||
|
CVector3f(-1, -1, 1),
|
||||||
|
CVector3f(-1, 1, -1),
|
||||||
|
CVector3f(-1, 1, 1),
|
||||||
|
CVector3f( 1, -1, -1),
|
||||||
|
CVector3f( 1, -1, 1),
|
||||||
|
CVector3f( 1, 1, -1),
|
||||||
|
CVector3f( 1, 1, 1)
|
||||||
|
};
|
||||||
|
|
||||||
|
for (uint i=0; i<8; i++)
|
||||||
|
{
|
||||||
|
CVector3f Transformed = CombinedTransform * skUnitCubeVertices[i];
|
||||||
|
mBoundingVertexBuffer.AddVertex( CVertex(Transformed) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add corresponding indices
|
||||||
|
static const uint16 skUnitCubeWireIndices[24] = {
|
||||||
|
0, 1,
|
||||||
|
1, 3,
|
||||||
|
3, 2,
|
||||||
|
2, 0,
|
||||||
|
4, 5,
|
||||||
|
5, 7,
|
||||||
|
7, 6,
|
||||||
|
6, 4,
|
||||||
|
0, 4,
|
||||||
|
1, 5,
|
||||||
|
2, 6,
|
||||||
|
3, 7
|
||||||
|
};
|
||||||
|
uint FirstIndex = mBoundingIndexBuffer.GetSize();
|
||||||
|
for (uint i=0; i<24; i++)
|
||||||
|
{
|
||||||
|
mBoundingIndexBuffer.AddIndex(skUnitCubeWireIndices[i] + FirstIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add an extra index at the end...
|
||||||
|
mBoundingDepthOffsets.push_back(mBoundingIndexBuffer.GetSize());
|
||||||
|
|
||||||
|
// Done
|
||||||
|
mBoundingVertexBuffer.Buffer();
|
||||||
|
mBoundingIndexBuffer.Buffer();
|
||||||
|
mBoundingHierarchyBuilt = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Render */
|
||||||
|
void CCollisionRenderData::Render(bool Wireframe, int MaterialIndex /*= -1*/)
|
||||||
|
{
|
||||||
|
mVertexBuffer.Bind();
|
||||||
|
|
||||||
|
//@todo get these ugly OpenGL calls outta here
|
||||||
|
if (Wireframe)
|
||||||
|
{
|
||||||
|
CDrawUtil::UseColorShader(CColor::skBlack);
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MaterialIndex >= 0)
|
||||||
|
{
|
||||||
|
ASSERT( MaterialIndex < mMaterialIndexOffsets.size()-1 );
|
||||||
|
uint FirstIndex = mMaterialIndexOffsets[MaterialIndex];
|
||||||
|
uint NumIndices = mMaterialIndexOffsets[MaterialIndex+1] - FirstIndex;
|
||||||
|
mIndexBuffer.DrawElements(FirstIndex, NumIndices);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mIndexBuffer.DrawElements();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Wireframe)
|
||||||
|
{
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||||
|
}
|
||||||
|
|
||||||
|
mVertexBuffer.Unbind();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCollisionRenderData::RenderBoundingHierarchy(int MaxDepthLevel /*= -1*/)
|
||||||
|
{
|
||||||
|
mBoundingVertexBuffer.Bind();
|
||||||
|
CDrawUtil::UseColorShader(CColor::skBlue);
|
||||||
|
glLineWidth(1.f);
|
||||||
|
uint FirstIndex = mBoundingDepthOffsets[0];
|
||||||
|
uint LastIndex = (MaxDepthLevel > 0 ?
|
||||||
|
mBoundingDepthOffsets[MaxDepthLevel] :
|
||||||
|
mBoundingIndexBuffer.GetSize());
|
||||||
|
uint NumIndices = LastIndex - FirstIndex;
|
||||||
|
mBoundingIndexBuffer.DrawElements(FirstIndex, NumIndices);
|
||||||
|
mBoundingVertexBuffer.Unbind();
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
#ifndef CCOLLISIONRENDERDATA_H
|
||||||
|
#define CCOLLISIONRENDERDATA_H
|
||||||
|
|
||||||
|
#include "SCollisionIndexData.h"
|
||||||
|
#include "SOBBTreeNode.h"
|
||||||
|
#include "Core/OpenGL/CVertexBuffer.h"
|
||||||
|
#include "Core/OpenGL/CIndexBuffer.h"
|
||||||
|
|
||||||
|
class CCollidableOBBTree;
|
||||||
|
|
||||||
|
/** Data for rendering a collision model */
|
||||||
|
class CCollisionRenderData
|
||||||
|
{
|
||||||
|
/** Vertex/index buffer for the collision geometry */
|
||||||
|
CVertexBuffer mVertexBuffer;
|
||||||
|
CIndexBuffer mIndexBuffer;
|
||||||
|
CIndexBuffer mWireframeIndexBuffer;
|
||||||
|
|
||||||
|
/** Index buffer offset for the start of each collision material.
|
||||||
|
* This has an extra index at the end, which is the end index for the last material. */
|
||||||
|
std::vector<uint> mMaterialIndexOffsets;
|
||||||
|
std::vector<uint> mMaterialWireIndexOffsets;
|
||||||
|
|
||||||
|
/** Cached vertex/index buffer for the bounding hierarchy (octree or OBB tree) */
|
||||||
|
CVertexBuffer mBoundingVertexBuffer;
|
||||||
|
CIndexBuffer mBoundingIndexBuffer;
|
||||||
|
|
||||||
|
/** Index buffer offset for different depth levels of the bounding hierarchy.
|
||||||
|
* This allows you to i.e. render only the first (n) levels of the hierarchy. */
|
||||||
|
std::vector<uint> mBoundingDepthOffsets;
|
||||||
|
|
||||||
|
/** Whether render data has been built */
|
||||||
|
bool mBuilt;
|
||||||
|
|
||||||
|
/** Whether bounding hierarchy render data has been built */
|
||||||
|
bool mBoundingHierarchyBuilt;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** Default constructor */
|
||||||
|
CCollisionRenderData()
|
||||||
|
: mBuilt(false)
|
||||||
|
, mBoundingHierarchyBuilt(false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/** Build from collision data */
|
||||||
|
void BuildRenderData(const SCollisionIndexData& kIndexData);
|
||||||
|
void BuildBoundingHierarchyRenderData(const SOBBTreeNode* pOBBTree);
|
||||||
|
|
||||||
|
/** Render */
|
||||||
|
void Render(bool Wireframe, int MaterialIndex = -1);
|
||||||
|
void RenderBoundingHierarchy(int MaxDepthLevel = -1);
|
||||||
|
|
||||||
|
/** Accessors */
|
||||||
|
inline bool IsBuilt() const { return mBuilt; }
|
||||||
|
inline int MaxBoundingHierarchyDepth() const { return mBoundingHierarchyBuilt ? mBoundingDepthOffsets.size() - 1 : 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CCOLLISIONRENDERDATA_H
|
|
@ -0,0 +1,20 @@
|
||||||
|
#ifndef SCOLLISIONINDEXDATA_H
|
||||||
|
#define SCOLLISIONINDEXDATA_H
|
||||||
|
|
||||||
|
#include "CCollisionMaterial.h"
|
||||||
|
#include <Common/Math/CVector3f.h>
|
||||||
|
|
||||||
|
/** Common index data found in all collision file formats */
|
||||||
|
struct SCollisionIndexData
|
||||||
|
{
|
||||||
|
std::vector<CCollisionMaterial> Materials;
|
||||||
|
std::vector<uint8> VertexMaterialIndices;
|
||||||
|
std::vector<uint8> EdgeMaterialIndices;
|
||||||
|
std::vector<uint8> TriangleMaterialIndices;
|
||||||
|
std::vector<uint16> EdgeIndices;
|
||||||
|
std::vector<uint16> TriangleIndices;
|
||||||
|
std::vector<uint16> UnknownData;
|
||||||
|
std::vector<CVector3f> Vertices;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SCOLLISIONINDEXDATA_H
|
|
@ -0,0 +1,43 @@
|
||||||
|
#ifndef SOBBTREENODE_H
|
||||||
|
#define SOBBTREENODE_H
|
||||||
|
|
||||||
|
#include <Common/BasicTypes.h>
|
||||||
|
#include <Common/Math/CTransform4f.h>
|
||||||
|
#include <Common/Math/CVector3f.h>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
enum class EOBBTreeNodeType : uint8
|
||||||
|
{
|
||||||
|
Branch = 0,
|
||||||
|
Leaf = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SOBBTreeNode
|
||||||
|
{
|
||||||
|
CTransform4f Transform;
|
||||||
|
CVector3f Radii;
|
||||||
|
EOBBTreeNodeType NodeType;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SOBBTreeBranch : public SOBBTreeNode
|
||||||
|
{
|
||||||
|
std::unique_ptr<SOBBTreeNode> pLeft;
|
||||||
|
std::unique_ptr<SOBBTreeNode> pRight;
|
||||||
|
|
||||||
|
SOBBTreeBranch() : SOBBTreeNode()
|
||||||
|
{
|
||||||
|
NodeType = EOBBTreeNodeType::Branch;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SOBBTreeLeaf : public SOBBTreeNode
|
||||||
|
{
|
||||||
|
std::vector<uint16> TriangleIndices;
|
||||||
|
|
||||||
|
SOBBTreeLeaf() : SOBBTreeNode()
|
||||||
|
{
|
||||||
|
NodeType = EOBBTreeNodeType::Leaf;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SOBBTREENODE_H
|
|
@ -620,7 +620,8 @@ void CAreaLoader::LoadSectionDataBuffers()
|
||||||
void CAreaLoader::ReadCollision()
|
void CAreaLoader::ReadCollision()
|
||||||
{
|
{
|
||||||
mpSectionMgr->ToSection(mCollisionBlockNum);
|
mpSectionMgr->ToSection(mCollisionBlockNum);
|
||||||
mpArea->mpCollision = CCollisionLoader::LoadAreaCollision(*mpMREA);
|
CCollisionMeshGroup* pAreaCollision = CCollisionLoader::LoadAreaCollision(*mpMREA);
|
||||||
|
mpArea->mpCollision = std::unique_ptr<CCollisionMeshGroup>(pAreaCollision);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAreaLoader::ReadPATH()
|
void CAreaLoader::ReadPATH()
|
||||||
|
|
|
@ -6,6 +6,7 @@ CCollisionLoader::CCollisionLoader()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
CCollisionMesh::CCollisionOctree* CCollisionLoader::ParseOctree(IInputStream& /*rSrc*/)
|
CCollisionMesh::CCollisionOctree* CCollisionLoader::ParseOctree(IInputStream& /*rSrc*/)
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -20,172 +21,180 @@ CCollisionMesh::CCollisionOctree::SLeaf* CCollisionLoader::ParseOctreeLeaf(IInpu
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void CCollisionLoader::ParseOBBNode(IInputStream& rDCLN)
|
SOBBTreeNode* CCollisionLoader::ParseOBBNode(IInputStream& DCLN)
|
||||||
{
|
{
|
||||||
bool b = false;
|
SOBBTreeNode* pOut = nullptr;
|
||||||
|
|
||||||
while (b == false)
|
CTransform4f Transform(DCLN);
|
||||||
|
CVector3f Radius(DCLN);
|
||||||
|
bool IsLeaf = DCLN.ReadBool();
|
||||||
|
|
||||||
|
if (IsLeaf)
|
||||||
{
|
{
|
||||||
rDCLN.Seek(0x3C, SEEK_CUR);
|
SOBBTreeLeaf* pLeaf = new SOBBTreeLeaf;
|
||||||
b = (rDCLN.ReadByte() == 1);
|
uint NumTris = DCLN.ReadLong();
|
||||||
if (!b) ParseOBBNode(rDCLN);
|
pLeaf->TriangleIndices.resize(NumTris);
|
||||||
|
|
||||||
|
for (uint i=0; i<NumTris; i++)
|
||||||
|
pLeaf->TriangleIndices[i] = DCLN.ReadShort();
|
||||||
|
|
||||||
|
pOut = pLeaf;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SOBBTreeBranch* pBranch = new SOBBTreeBranch;
|
||||||
|
pBranch->pLeft = std::unique_ptr<SOBBTreeNode>( ParseOBBNode(DCLN) );
|
||||||
|
pBranch->pRight = std::unique_ptr<SOBBTreeNode>( ParseOBBNode(DCLN) );
|
||||||
|
pOut = pBranch;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 NumFaces = rDCLN.ReadLong();
|
pOut->Transform = Transform;
|
||||||
rDCLN.Seek(NumFaces * 2, SEEK_CUR);
|
pOut->Radii = Radius;
|
||||||
|
return pOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCollisionLoader::ReadPropertyFlags(IInputStream& rSrc)
|
void CCollisionLoader::LoadCollisionMaterial(IInputStream& Src, CCollisionMaterial& OutMaterial)
|
||||||
{
|
{
|
||||||
CCollisionMaterial Material;
|
uint64 RawFlags = (mVersion <= EGame::Prime ? Src.ReadLong() : Src.ReadLongLong());
|
||||||
uint64 RawFlags = (mVersion <= EGame::Prime ? rSrc.ReadLong() : rSrc.ReadLongLong());
|
OutMaterial.mRawFlags = RawFlags;
|
||||||
Material.mRawFlags = RawFlags;
|
|
||||||
|
|
||||||
if (mVersion <= EGame::Prime)
|
if (mVersion <= EGame::Prime)
|
||||||
{
|
{
|
||||||
if (RawFlags & 0x00000001) Material |= eCF_Unknown;
|
if (RawFlags & 0x00000001) OutMaterial |= eCF_Unknown;
|
||||||
if (RawFlags & 0x00000002) Material |= eCF_Stone;
|
if (RawFlags & 0x00000002) OutMaterial |= eCF_Stone;
|
||||||
if (RawFlags & 0x00000004) Material |= eCF_Metal;
|
if (RawFlags & 0x00000004) OutMaterial |= eCF_Metal;
|
||||||
if (RawFlags & 0x00000008) Material |= eCF_Grass;
|
if (RawFlags & 0x00000008) OutMaterial |= eCF_Grass;
|
||||||
if (RawFlags & 0x00000010) Material |= eCF_Ice;
|
if (RawFlags & 0x00000010) OutMaterial |= eCF_Ice;
|
||||||
if (RawFlags & 0x00000040) Material |= eCF_MetalGrating;
|
if (RawFlags & 0x00000040) OutMaterial |= eCF_MetalGrating;
|
||||||
if (RawFlags & 0x00000080) Material |= eCF_Phazon;
|
if (RawFlags & 0x00000080) OutMaterial |= eCF_Phazon;
|
||||||
if (RawFlags & 0x00000100) Material |= eCF_Dirt;
|
if (RawFlags & 0x00000100) OutMaterial |= eCF_Dirt;
|
||||||
if (RawFlags & 0x00000200) Material |= eCF_Lava;
|
if (RawFlags & 0x00000200) OutMaterial |= eCF_Lava;
|
||||||
if (RawFlags & 0x00000800) Material |= eCF_Snow;
|
if (RawFlags & 0x00000800) OutMaterial |= eCF_Snow;
|
||||||
if (RawFlags & 0x00001000) Material |= eCF_SlowMud;
|
if (RawFlags & 0x00001000) OutMaterial |= eCF_SlowMud;
|
||||||
if (RawFlags & 0x00004000) Material |= eCF_Mud;
|
if (RawFlags & 0x00004000) OutMaterial |= eCF_Mud;
|
||||||
if (RawFlags & 0x00008000) Material |= eCF_Glass;
|
if (RawFlags & 0x00008000) OutMaterial |= eCF_Glass;
|
||||||
if (RawFlags & 0x00010000) Material |= eCF_Shield;
|
if (RawFlags & 0x00010000) OutMaterial |= eCF_Shield;
|
||||||
if (RawFlags & 0x00020000) Material |= eCF_Sand;
|
if (RawFlags & 0x00020000) OutMaterial |= eCF_Sand;
|
||||||
if (RawFlags & 0x00040000) Material |= eCF_ShootThru;
|
if (RawFlags & 0x00040000) OutMaterial |= eCF_ShootThru;
|
||||||
if (RawFlags & 0x00200000) Material |= eCF_CameraThru;
|
if (RawFlags & 0x00200000) OutMaterial |= eCF_CameraThru;
|
||||||
if (RawFlags & 0x00400000) Material |= eCF_Wood;
|
if (RawFlags & 0x00400000) OutMaterial |= eCF_Wood;
|
||||||
if (RawFlags & 0x00800000) Material |= eCF_Organic;
|
if (RawFlags & 0x00800000) OutMaterial |= eCF_Organic;
|
||||||
if (RawFlags & 0x02000000) Material |= eCF_FlippedTri;
|
if (RawFlags & 0x02000000) OutMaterial |= eCF_FlippedTri;
|
||||||
if (RawFlags & 0x08000000) Material |= eCF_ScanThru;
|
if (RawFlags & 0x08000000) OutMaterial |= eCF_ScanThru;
|
||||||
if (RawFlags & 0x10000000) Material |= eCF_AiWalkThru;
|
if (RawFlags & 0x10000000) OutMaterial |= eCF_AiWalkThru;
|
||||||
if (RawFlags & 0x20000000) Material |= eCF_Ceiling;
|
if (RawFlags & 0x20000000) OutMaterial |= eCF_Ceiling;
|
||||||
if (RawFlags & 0x40000000) Material |= eCF_Wall;
|
if (RawFlags & 0x40000000) OutMaterial |= eCF_Wall;
|
||||||
if (RawFlags & 0x80000000) Material |= eCF_Floor;
|
if (RawFlags & 0x80000000) OutMaterial |= eCF_Floor;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (mVersion <= EGame::Corruption)
|
else if (mVersion <= EGame::Corruption)
|
||||||
{
|
{
|
||||||
if (RawFlags & 0x00000001) Material |= eCF_Unknown;
|
if (RawFlags & 0x00000001) OutMaterial |= eCF_Unknown;
|
||||||
if (RawFlags & 0x00000002) Material |= eCF_Stone;
|
if (RawFlags & 0x00000002) OutMaterial |= eCF_Stone;
|
||||||
if (RawFlags & 0x00000004) Material |= eCF_Metal;
|
if (RawFlags & 0x00000004) OutMaterial |= eCF_Metal;
|
||||||
if (RawFlags & 0x00000008) Material |= eCF_Grass;
|
if (RawFlags & 0x00000008) OutMaterial |= eCF_Grass;
|
||||||
if (RawFlags & 0x00000010) Material |= eCF_Ice;
|
if (RawFlags & 0x00000010) OutMaterial |= eCF_Ice;
|
||||||
if (RawFlags & 0x00000040) Material |= eCF_MetalGrating;
|
if (RawFlags & 0x00000040) OutMaterial |= eCF_MetalGrating;
|
||||||
if (RawFlags & 0x00000080) Material |= eCF_Phazon;
|
if (RawFlags & 0x00000080) OutMaterial |= eCF_Phazon;
|
||||||
if (RawFlags & 0x00000100) Material |= eCF_Dirt;
|
if (RawFlags & 0x00000100) OutMaterial |= eCF_Dirt;
|
||||||
if (RawFlags & 0x00000200) Material |= eCF_AltMetal;
|
if (RawFlags & 0x00000200) OutMaterial |= eCF_AltMetal;
|
||||||
if (RawFlags & 0x00000400) Material |= eCF_Glass;
|
if (RawFlags & 0x00000400) OutMaterial |= eCF_Glass;
|
||||||
if (RawFlags & 0x00000800) Material |= eCF_Snow;
|
if (RawFlags & 0x00000800) OutMaterial |= eCF_Snow;
|
||||||
if (RawFlags & 0x00001000) Material |= eCF_Fabric;
|
if (RawFlags & 0x00001000) OutMaterial |= eCF_Fabric;
|
||||||
if (RawFlags & 0x00010000) Material |= eCF_Shield;
|
if (RawFlags & 0x00010000) OutMaterial |= eCF_Shield;
|
||||||
if (RawFlags & 0x00020000) Material |= eCF_Sand;
|
if (RawFlags & 0x00020000) OutMaterial |= eCF_Sand;
|
||||||
if (RawFlags & 0x00040000) Material |= eCF_MothSeedOrganics;
|
if (RawFlags & 0x00040000) OutMaterial |= eCF_MothSeedOrganics;
|
||||||
if (RawFlags & 0x00080000) Material |= eCF_Web;
|
if (RawFlags & 0x00080000) OutMaterial |= eCF_Web;
|
||||||
if (RawFlags & 0x00100000) Material |= eCF_ShootThru;
|
if (RawFlags & 0x00100000) OutMaterial |= eCF_ShootThru;
|
||||||
if (RawFlags & 0x00200000) Material |= eCF_CameraThru;
|
if (RawFlags & 0x00200000) OutMaterial |= eCF_CameraThru;
|
||||||
if (RawFlags & 0x00400000) Material |= eCF_Wood;
|
if (RawFlags & 0x00400000) OutMaterial |= eCF_Wood;
|
||||||
if (RawFlags & 0x00800000) Material |= eCF_Organic;
|
if (RawFlags & 0x00800000) OutMaterial |= eCF_Organic;
|
||||||
if (RawFlags & 0x01000000) Material |= eCF_FlippedTri;
|
if (RawFlags & 0x01000000) OutMaterial |= eCF_FlippedTri;
|
||||||
if (RawFlags & 0x02000000) Material |= eCF_Rubber;
|
if (RawFlags & 0x02000000) OutMaterial |= eCF_Rubber;
|
||||||
if (RawFlags & 0x08000000) Material |= eCF_ScanThru;
|
if (RawFlags & 0x08000000) OutMaterial |= eCF_ScanThru;
|
||||||
if (RawFlags & 0x10000000) Material |= eCF_AiWalkThru;
|
if (RawFlags & 0x10000000) OutMaterial |= eCF_AiWalkThru;
|
||||||
if (RawFlags & 0x20000000) Material |= eCF_Ceiling;
|
if (RawFlags & 0x20000000) OutMaterial |= eCF_Ceiling;
|
||||||
if (RawFlags & 0x40000000) Material |= eCF_Wall;
|
if (RawFlags & 0x40000000) OutMaterial |= eCF_Wall;
|
||||||
if (RawFlags & 0x80000000) Material |= eCF_Floor;
|
if (RawFlags & 0x80000000) OutMaterial |= eCF_Floor;
|
||||||
|
|
||||||
if (RawFlags & 0x0001000000000000) Material |= eCF_AiBlock;
|
if (RawFlags & 0x0001000000000000) OutMaterial |= eCF_AiBlock;
|
||||||
if (RawFlags & 0x0400000000000000) Material |= eCF_JumpNotAllowed;
|
if (RawFlags & 0x0400000000000000) OutMaterial |= eCF_JumpNotAllowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (mVersion == EGame::DKCReturns)
|
else if (mVersion == EGame::DKCReturns)
|
||||||
{
|
{
|
||||||
if (RawFlags & 0x10000000) Material |= eCF_FlippedTri;
|
if (RawFlags & 0x10000000) OutMaterial |= eCF_FlippedTri;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mpMesh->mMaterials.push_back(Material);
|
void CCollisionLoader::LoadCollisionIndices(IInputStream& File, SCollisionIndexData& OutData)
|
||||||
|
{
|
||||||
|
// Materials
|
||||||
|
uint NumMaterials = File.ReadLong();
|
||||||
|
OutData.Materials.resize( NumMaterials );
|
||||||
|
|
||||||
|
for (uint i=0; i<NumMaterials; i++)
|
||||||
|
{
|
||||||
|
LoadCollisionMaterial(File, OutData.Materials[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCollisionLoader::LoadCollisionIndices(IInputStream &rFile, bool BuildAABox)
|
// Property indices for vertices/edges/triangles
|
||||||
|
uint VertexMaterialCount = File.ReadLong();
|
||||||
|
OutData.VertexMaterialIndices.resize(VertexMaterialCount);
|
||||||
|
File.ReadBytes(OutData.VertexMaterialIndices.data(), VertexMaterialCount);
|
||||||
|
|
||||||
|
uint32 EdgeMaterialCount = File.ReadLong();
|
||||||
|
OutData.EdgeMaterialIndices.resize(EdgeMaterialCount);
|
||||||
|
File.ReadBytes(OutData.EdgeMaterialIndices.data(), EdgeMaterialCount);
|
||||||
|
|
||||||
|
uint32 TriMaterialCount = File.ReadLong();
|
||||||
|
OutData.TriangleMaterialIndices.resize(TriMaterialCount);
|
||||||
|
File.ReadBytes(OutData.TriangleMaterialIndices.data(), TriMaterialCount);
|
||||||
|
|
||||||
|
// Edges
|
||||||
|
uint NumEdges = File.ReadLong();
|
||||||
|
OutData.EdgeIndices.resize( NumEdges * 2 );
|
||||||
|
|
||||||
|
for (uint i=0; i<OutData.EdgeIndices.size(); i++)
|
||||||
{
|
{
|
||||||
// Properties
|
OutData.EdgeIndices[i] = File.ReadShort();
|
||||||
uint32 PropSetCount = rFile.ReadLong();
|
|
||||||
for (uint32 iProp = 0; iProp < PropSetCount; iProp++)
|
|
||||||
ReadPropertyFlags(rFile);
|
|
||||||
|
|
||||||
// Property indices for vertices/lines/faces
|
|
||||||
uint32 VtxIndexCount = rFile.ReadLong();
|
|
||||||
std::vector<uint8> VtxIndices(VtxIndexCount);
|
|
||||||
rFile.ReadBytes(VtxIndices.data(), VtxIndices.size());
|
|
||||||
|
|
||||||
uint32 LineIndexCount = rFile.ReadLong();
|
|
||||||
std::vector<uint8> LineIndices(LineIndexCount);
|
|
||||||
rFile.ReadBytes(LineIndices.data(), LineIndices.size());
|
|
||||||
|
|
||||||
uint32 FaceIndexCount = rFile.ReadLong();
|
|
||||||
std::vector<uint8> FaceIndices(FaceIndexCount);
|
|
||||||
rFile.ReadBytes(FaceIndices.data(), FaceIndices.size());
|
|
||||||
|
|
||||||
// Lines
|
|
||||||
mpMesh->mLineCount = rFile.ReadLong();
|
|
||||||
mpMesh->mCollisionLines.resize(mpMesh->mLineCount);
|
|
||||||
for (uint32 iLine = 0; iLine < mpMesh->mLineCount; iLine++)
|
|
||||||
{
|
|
||||||
CCollisionMesh::CCollisionLine *pLine = &mpMesh->mCollisionLines[iLine];
|
|
||||||
pLine->Vertices[0] = rFile.ReadShort();
|
|
||||||
pLine->Vertices[1] = rFile.ReadShort();
|
|
||||||
pLine->MaterialIdx = LineIndices[iLine];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Faces
|
// Triangles
|
||||||
mpMesh->mFaceCount = rFile.ReadLong() / 3; // Not sure why they store it this way. It's inconsistent.
|
uint NumTris = File.ReadLong();
|
||||||
mpMesh->mCollisionFaces.resize(mpMesh->mFaceCount);
|
OutData.TriangleIndices.resize( NumTris );
|
||||||
|
|
||||||
for (uint32 iFace = 0; iFace < mpMesh->mFaceCount; iFace++)
|
for (uint i=0; i<NumTris; i++)
|
||||||
{
|
{
|
||||||
CCollisionMesh::CCollisionFace *pFace = &mpMesh->mCollisionFaces[iFace];
|
OutData.TriangleIndices[i] = File.ReadShort();
|
||||||
pFace->Lines[0] = rFile.ReadShort();
|
|
||||||
pFace->Lines[1] = rFile.ReadShort();
|
|
||||||
pFace->Lines[2] = rFile.ReadShort();
|
|
||||||
pFace->MaterialIdx = FaceIndices[iFace];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Echoes introduces a new data chunk; don't know what it is yet, skipping for now
|
// Echoes introduces a new data chunk; don't know what it is yet, skipping for now
|
||||||
if (mVersion >= EGame::Echoes)
|
if (mVersion >= EGame::Echoes)
|
||||||
{
|
{
|
||||||
uint32 UnknownCount = rFile.ReadLong();
|
uint UnknownCount = File.ReadLong();
|
||||||
rFile.Seek(UnknownCount * 2, SEEK_CUR);
|
File.Skip(UnknownCount * 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vertices
|
// Vertices
|
||||||
mpMesh->mVertexCount = rFile.ReadLong();
|
uint NumVertices = File.ReadLong();
|
||||||
mpMesh->mCollisionVertices.resize(mpMesh->mVertexCount);
|
OutData.Vertices.resize(NumVertices);
|
||||||
CAABox Bounds;
|
|
||||||
|
|
||||||
for (uint32 iVtx = 0; iVtx < mpMesh->mVertexCount; iVtx++)
|
for (uint32 i=0; i<NumVertices; i++)
|
||||||
{
|
{
|
||||||
CCollisionMesh::CCollisionVertex *pVtx = &mpMesh->mCollisionVertices[iVtx];
|
OutData.Vertices[i].Read(File);
|
||||||
pVtx->Pos = CVector3f(rFile);
|
|
||||||
pVtx->MaterialIdx = VtxIndices[iVtx];
|
|
||||||
if (BuildAABox) Bounds.ExpandBounds(pVtx->Pos);
|
|
||||||
}
|
}
|
||||||
if (BuildAABox) mpMesh->mAABox = Bounds;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ************ STATIC ************
|
// ************ STATIC ************
|
||||||
CCollisionMeshGroup* CCollisionLoader::LoadAreaCollision(IInputStream& rMREA)
|
CCollisionMeshGroup* CCollisionLoader::LoadAreaCollision(IInputStream& rMREA)
|
||||||
{
|
{
|
||||||
if (!rMREA.IsValid()) return nullptr;
|
if (!rMREA.IsValid()) return nullptr;
|
||||||
CCollisionLoader loader;
|
rMREA.Skip(0x8); // Skipping unknown value + collion section size
|
||||||
|
|
||||||
rMREA.Seek(0x8, SEEK_CUR);
|
// Validate magic
|
||||||
uint32 DeafBabe = rMREA.ReadLong();
|
uint32 DeafBabe = rMREA.ReadLong();
|
||||||
if (DeafBabe != 0xDEAFBABE)
|
if (DeafBabe != 0xDEAFBABE)
|
||||||
{
|
{
|
||||||
|
@ -193,22 +202,22 @@ CCollisionMeshGroup* CCollisionLoader::LoadAreaCollision(IInputStream& rMREA)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
loader.mVersion = GetFormatVersion(rMREA.ReadLong());
|
CCollisionLoader Loader;
|
||||||
|
Loader.mVersion = GetFormatVersion(rMREA.ReadLong());
|
||||||
loader.mpGroup = new CCollisionMeshGroup;
|
Loader.mpMesh = new CCollisionMesh;
|
||||||
loader.mpMesh = new CCollisionMesh;
|
|
||||||
|
|
||||||
// Octree - structure is known, but not coding this right now
|
// Octree - structure is known, but not coding this right now
|
||||||
loader.mpMesh->mAABox = CAABox(rMREA);
|
Loader.mpMesh->mAABox = CAABox(rMREA);
|
||||||
rMREA.Seek(0x4, SEEK_CUR);
|
rMREA.Skip(0x4);
|
||||||
uint32 OctreeSize = rMREA.ReadLong();
|
uint32 OctreeSize = rMREA.ReadLong();
|
||||||
rMREA.Seek(OctreeSize, SEEK_CUR); // Skipping the octree for now
|
rMREA.Skip(OctreeSize); // Skipping the octree for now
|
||||||
loader.mpMesh->mOctreeLoaded = false;
|
|
||||||
|
|
||||||
// Read collision indices and return
|
// Read collision indices and return
|
||||||
loader.LoadCollisionIndices(rMREA, false);
|
Loader.LoadCollisionIndices(rMREA, Loader.mpMesh->mIndexData);
|
||||||
loader.mpGroup->AddMesh(loader.mpMesh);
|
|
||||||
return loader.mpGroup;
|
CCollisionMeshGroup* pOut = new CCollisionMeshGroup();
|
||||||
|
pOut->AddMesh(Loader.mpMesh);
|
||||||
|
return pOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
CCollisionMeshGroup* CCollisionLoader::LoadDCLN(IInputStream& rDCLN, CResourceEntry *pEntry)
|
CCollisionMeshGroup* CCollisionLoader::LoadDCLN(IInputStream& rDCLN, CResourceEntry *pEntry)
|
||||||
|
@ -220,32 +229,45 @@ CCollisionMeshGroup* CCollisionLoader::LoadDCLN(IInputStream& rDCLN, CResourceEn
|
||||||
|
|
||||||
uint32 NumMeshes = rDCLN.ReadLong();
|
uint32 NumMeshes = rDCLN.ReadLong();
|
||||||
|
|
||||||
for (uint32 iMesh = 0; iMesh < NumMeshes; iMesh++)
|
for (uint32 MeshIdx = 0; MeshIdx < NumMeshes; MeshIdx++)
|
||||||
{
|
{
|
||||||
uint32 DeafBabe = rDCLN.ReadLong();
|
uint32 DeafBabe = rDCLN.ReadLong();
|
||||||
|
|
||||||
if (DeafBabe != 0xDEAFBABE)
|
if (DeafBabe != 0xDEAFBABE)
|
||||||
{
|
{
|
||||||
errorf("%s [0x%X]: Invalid collision magic: 0x%08X", *rDCLN.GetSourceString(), rDCLN.Tell() - 4, DeafBabe);
|
errorf("%s [0x%X]: Invalid collision magic: 0x%08X", *rDCLN.GetSourceString(), rDCLN.Tell() - 4, DeafBabe);
|
||||||
Loader.mpGroup.Delete();
|
delete Loader.mpGroup;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader.mVersion = GetFormatVersion(rDCLN.ReadLong());
|
Loader.mVersion = GetFormatVersion(rDCLN.ReadLong());
|
||||||
|
|
||||||
Loader.mpMesh = new CCollisionMesh;
|
Loader.mpMesh = new CCollidableOBBTree;
|
||||||
Loader.mpMesh->mOctreeLoaded = false;
|
|
||||||
|
|
||||||
if (Loader.mVersion == EGame::DKCReturns)
|
if (Loader.mVersion == EGame::DKCReturns)
|
||||||
Loader.mpMesh->mAABox = CAABox(rDCLN);
|
Loader.mpMesh->mAABox = CAABox(rDCLN);
|
||||||
|
|
||||||
// Read indices and return
|
// Read indices and return
|
||||||
rDCLN.Seek(0x4, SEEK_CUR);
|
rDCLN.Seek(0x4, SEEK_CUR);
|
||||||
Loader.LoadCollisionIndices(rDCLN, Loader.mVersion != EGame::DKCReturns);
|
Loader.LoadCollisionIndices(rDCLN, Loader.mpMesh->mIndexData);
|
||||||
Loader.mpGroup->AddMesh(Loader.mpMesh);
|
Loader.mpGroup->AddMesh(Loader.mpMesh);
|
||||||
|
|
||||||
|
// Build bounding box
|
||||||
|
if (Loader.mVersion != EGame::DKCReturns)
|
||||||
|
{
|
||||||
|
Loader.mpMesh->mAABox = CAABox::skInfinite;
|
||||||
|
|
||||||
|
for (uint i=0; i<Loader.mpMesh->mIndexData.Vertices.size(); i++)
|
||||||
|
{
|
||||||
|
Loader.mpMesh->mAABox.ExpandBounds(
|
||||||
|
Loader.mpMesh->mIndexData.Vertices[i]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Parse OBB tree
|
// Parse OBB tree
|
||||||
Loader.ParseOBBNode(rDCLN);
|
CCollidableOBBTree* pOBBTree = static_cast<CCollidableOBBTree*>(Loader.mpMesh);
|
||||||
|
pOBBTree->mpOBBTree = std::unique_ptr<SOBBTreeNode>( Loader.ParseOBBNode(rDCLN) );
|
||||||
}
|
}
|
||||||
return Loader.mpGroup;
|
return Loader.mpGroup;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
#ifndef CCOLLISIONLOADER_H
|
#ifndef CCOLLISIONLOADER_H
|
||||||
#define CCOLLISIONLOADER_H
|
#define CCOLLISIONLOADER_H
|
||||||
|
|
||||||
#include "Core/Resource/CCollisionMesh.h"
|
#include "Core/Resource/Collision/CCollisionMesh.h"
|
||||||
#include "Core/Resource/CCollisionMeshGroup.h"
|
#include "Core/Resource/Collision/CCollisionMeshGroup.h"
|
||||||
|
#include "Core/Resource/Collision/CCollidableOBBTree.h"
|
||||||
#include <Common/EGame.h>
|
#include <Common/EGame.h>
|
||||||
|
|
||||||
class CCollisionLoader
|
class CCollisionLoader
|
||||||
|
@ -12,12 +13,16 @@ class CCollisionLoader
|
||||||
EGame mVersion;
|
EGame mVersion;
|
||||||
|
|
||||||
CCollisionLoader();
|
CCollisionLoader();
|
||||||
|
|
||||||
|
#if 0
|
||||||
CCollisionMesh::CCollisionOctree* ParseOctree(IInputStream& rSrc);
|
CCollisionMesh::CCollisionOctree* ParseOctree(IInputStream& rSrc);
|
||||||
CCollisionMesh::CCollisionOctree::SBranch* ParseOctreeBranch(IInputStream& rSrc);
|
CCollisionMesh::CCollisionOctree::SBranch* ParseOctreeBranch(IInputStream& rSrc);
|
||||||
CCollisionMesh::CCollisionOctree::SLeaf* ParseOctreeLeaf(IInputStream& rSrc);
|
CCollisionMesh::CCollisionOctree::SLeaf* ParseOctreeLeaf(IInputStream& rSrc);
|
||||||
void ParseOBBNode(IInputStream& rDCLN);
|
#endif
|
||||||
void ReadPropertyFlags(IInputStream& rSrc);
|
|
||||||
void LoadCollisionIndices(IInputStream& rFile, bool BuildAABox);
|
SOBBTreeNode* ParseOBBNode(IInputStream& DCLN);
|
||||||
|
void LoadCollisionMaterial(IInputStream& Src, CCollisionMaterial& OutMaterial);
|
||||||
|
void LoadCollisionIndices(IInputStream& File, SCollisionIndexData& OutData);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static CCollisionMeshGroup* LoadAreaCollision(IInputStream& rMREA);
|
static CCollisionMeshGroup* LoadAreaCollision(IInputStream& rMREA);
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#ifndef RESOURCES_H
|
#ifndef RESOURCES_H
|
||||||
#define RESOURCES_H
|
#define RESOURCES_H
|
||||||
|
|
||||||
#include "CCollisionMeshGroup.h"
|
|
||||||
#include "CDependencyGroup.h"
|
#include "CDependencyGroup.h"
|
||||||
#include "CFont.h"
|
#include "CFont.h"
|
||||||
#include "CPoiToWorld.h"
|
#include "CPoiToWorld.h"
|
||||||
|
@ -13,6 +12,7 @@
|
||||||
#include "Core/Resource/Animation/CSkeleton.h"
|
#include "Core/Resource/Animation/CSkeleton.h"
|
||||||
#include "Core/Resource/Animation/CSkin.h"
|
#include "Core/Resource/Animation/CSkin.h"
|
||||||
#include "Core/Resource/Area/CGameArea.h"
|
#include "Core/Resource/Area/CGameArea.h"
|
||||||
|
#include "Core/Resource/Collision/CCollisionMeshGroup.h"
|
||||||
#include "Core/Resource/Model/CModel.h"
|
#include "Core/Resource/Model/CModel.h"
|
||||||
#include "Core/Resource/Scan/CScan.h"
|
#include "Core/Resource/Scan/CScan.h"
|
||||||
#include "Core/Resource/StringTable/CStringTable.h"
|
#include "Core/Resource/StringTable/CStringTable.h"
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
|
|
||||||
#include "CScriptTemplate.h"
|
#include "CScriptTemplate.h"
|
||||||
#include "Core/Resource/Area/CGameArea.h"
|
#include "Core/Resource/Area/CGameArea.h"
|
||||||
|
#include "Core/Resource/Collision/CCollisionMeshGroup.h"
|
||||||
#include "Core/Resource/Model/CModel.h"
|
#include "Core/Resource/Model/CModel.h"
|
||||||
#include "Core/Resource/CCollisionMeshGroup.h"
|
|
||||||
#include "Core/Resource/Script/Property/Properties.h"
|
#include "Core/Resource/Script/Property/Properties.h"
|
||||||
|
|
||||||
class CScriptLayer;
|
class CScriptLayer;
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include "Core/Resource/Script/Property/Properties.h"
|
#include "Core/Resource/Script/Property/Properties.h"
|
||||||
#include "EVolumeShape.h"
|
#include "EVolumeShape.h"
|
||||||
#include "Core/Resource/Model/CModel.h"
|
#include "Core/Resource/Model/CModel.h"
|
||||||
#include "Core/Resource/CCollisionMeshGroup.h"
|
#include "Core/Resource/Collision/CCollisionMeshGroup.h"
|
||||||
#include <Common/BasicTypes.h>
|
#include <Common/BasicTypes.h>
|
||||||
#include <Common/CFourCC.h>
|
#include <Common/CFourCC.h>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
|
@ -39,7 +39,7 @@ void CCollisionNode::Draw(FRenderOptions /*Options*/, int /*ComponentIndex*/, ER
|
||||||
glDepthMask(GL_TRUE);
|
glDepthMask(GL_TRUE);
|
||||||
|
|
||||||
// Turn off backface culling
|
// Turn off backface culling
|
||||||
EGame Game = mpScene->ActiveArea()->Game();
|
EGame Game = mpCollision->Game();
|
||||||
bool ForceDisableBackfaceCull = (rkViewInfo.CollisionSettings.DrawBackfaces || Game == EGame::DKCReturns) && glIsEnabled(GL_CULL_FACE);
|
bool ForceDisableBackfaceCull = (rkViewInfo.CollisionSettings.DrawBackfaces || Game == EGame::DKCReturns) && glIsEnabled(GL_CULL_FACE);
|
||||||
|
|
||||||
if (ForceDisableBackfaceCull)
|
if (ForceDisableBackfaceCull)
|
||||||
|
@ -47,35 +47,48 @@ void CCollisionNode::Draw(FRenderOptions /*Options*/, int /*ComponentIndex*/, ER
|
||||||
|
|
||||||
CColor BaseTint = TintColor(rkViewInfo);
|
CColor BaseTint = TintColor(rkViewInfo);
|
||||||
|
|
||||||
for (uint32 iMesh = 0; iMesh < mpCollision->NumMeshes(); iMesh++)
|
for (uint32 MeshIdx = 0; MeshIdx < mpCollision->NumMeshes(); MeshIdx++)
|
||||||
{
|
{
|
||||||
CCollisionMesh *pMesh = mpCollision->MeshByIndex(iMesh);
|
CCollisionMesh *pMesh = mpCollision->MeshByIndex(MeshIdx);
|
||||||
|
CCollisionRenderData& RenderData = pMesh->GetRenderData();
|
||||||
|
const SCollisionIndexData& kIndexData = pMesh->GetIndexData();
|
||||||
|
|
||||||
for (uint32 iMat = 0; iMat < pMesh->NumMaterials(); iMat++)
|
for (int MatIdx = 0; MatIdx < (int) kIndexData.Materials.size(); MatIdx++)
|
||||||
{
|
{
|
||||||
CCollisionMaterial& rMat = pMesh->GetMaterial(iMat);
|
const CCollisionMaterial& kMat = kIndexData.Materials[MatIdx];
|
||||||
|
|
||||||
if (rkViewInfo.CollisionSettings.HideMaterial & rMat)
|
if (rkViewInfo.CollisionSettings.HideMaterial & kMat)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (rkViewInfo.CollisionSettings.HideMask != 0 && (rMat.RawFlags() & rkViewInfo.CollisionSettings.HideMask) != 0)
|
if (rkViewInfo.CollisionSettings.HideMask != 0 && (kMat.RawFlags() & rkViewInfo.CollisionSettings.HideMask) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
CColor Tint = BaseTint;
|
CColor Tint = BaseTint;
|
||||||
|
|
||||||
if (rkViewInfo.CollisionSettings.HighlightMask != 0 && (rMat.RawFlags() & rkViewInfo.CollisionSettings.HighlightMask) == rkViewInfo.CollisionSettings.HighlightMask)
|
if (rkViewInfo.CollisionSettings.HighlightMask != 0 && (kMat.RawFlags() & rkViewInfo.CollisionSettings.HighlightMask) == rkViewInfo.CollisionSettings.HighlightMask)
|
||||||
Tint *= CColor::skRed;
|
Tint *= CColor::skRed;
|
||||||
|
|
||||||
else if (Game != EGame::DKCReturns && rkViewInfo.CollisionSettings.TintWithSurfaceColor)
|
else if (Game != EGame::DKCReturns && rkViewInfo.CollisionSettings.TintWithSurfaceColor)
|
||||||
Tint *= rMat.SurfaceColor(Game);
|
Tint *= kMat.SurfaceColor(Game);
|
||||||
|
|
||||||
bool IsFloor = (rkViewInfo.CollisionSettings.TintUnwalkableTris ? rMat.IsFloor() : true) || Game == EGame::DKCReturns;
|
bool IsFloor = (rkViewInfo.CollisionSettings.TintUnwalkableTris ? kMat.IsFloor() : true) || Game == EGame::DKCReturns;
|
||||||
bool IsUnstandable = (rkViewInfo.CollisionSettings.TintUnwalkableTris ? rMat.IsUnstandable(Game) : false) && Game != EGame::DKCReturns;
|
bool IsUnstandable = (rkViewInfo.CollisionSettings.TintUnwalkableTris ? kMat.IsUnstandable(Game) : false) && Game != EGame::DKCReturns;
|
||||||
CDrawUtil::UseCollisionShader(IsFloor, IsUnstandable, Tint);
|
CDrawUtil::UseCollisionShader(IsFloor, IsUnstandable, Tint);
|
||||||
pMesh->DrawMaterial(iMat, false);
|
RenderData.Render(false, MatIdx);
|
||||||
|
|
||||||
if (rkViewInfo.CollisionSettings.DrawWireframe)
|
if (rkViewInfo.CollisionSettings.DrawWireframe)
|
||||||
pMesh->DrawMaterial(iMat, true);
|
RenderData.Render(true, MatIdx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render bounding hierarchy
|
||||||
|
if (rkViewInfo.CollisionSettings.DrawBoundingHierarchy)
|
||||||
|
{
|
||||||
|
int Depth = rkViewInfo.CollisionSettings.BoundingHierarchyRenderDepth;
|
||||||
|
|
||||||
|
for (uint MeshIdx = 0; MeshIdx < mpCollision->NumMeshes(); MeshIdx++)
|
||||||
|
{
|
||||||
|
mpCollision->MeshByIndex(MeshIdx)->GetRenderData().RenderBoundingHierarchy(Depth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,8 +99,13 @@ void CCollisionNode::Draw(FRenderOptions /*Options*/, int /*ComponentIndex*/, ER
|
||||||
// Draw collision bounds for area collision
|
// Draw collision bounds for area collision
|
||||||
// note: right now checking parent is the best way to check whether this node is area collision instead of actor collision
|
// note: right now checking parent is the best way to check whether this node is area collision instead of actor collision
|
||||||
// actor collision will have a script node parent whereas area collision will have a root node parent
|
// actor collision will have a script node parent whereas area collision will have a root node parent
|
||||||
if (rkViewInfo.CollisionSettings.DrawAreaCollisionBounds && Parent()->NodeType() == ENodeType::Root && Game != EGame::DKCReturns)
|
if (rkViewInfo.CollisionSettings.DrawAreaCollisionBounds)
|
||||||
CDrawUtil::DrawWireCube( mpCollision->MeshByIndex(0)->BoundingBox(), CColor::skRed );
|
{
|
||||||
|
if (Parent() && Parent()->NodeType() == ENodeType::Root && Game != EGame::DKCReturns)
|
||||||
|
{
|
||||||
|
CDrawUtil::DrawWireCube( mpCollision->MeshByIndex(0)->Bounds(), CColor::skRed );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCollisionNode::RayAABoxIntersectTest(CRayCollisionTester& /*rTester*/, const SViewInfo& /*rkViewInfo*/)
|
void CCollisionNode::RayAABoxIntersectTest(CRayCollisionTester& /*rTester*/, const SViewInfo& /*rkViewInfo*/)
|
||||||
|
@ -106,4 +124,9 @@ SRayIntersection CCollisionNode::RayNodeIntersectTest(const CRay& /*rkRay*/, uin
|
||||||
void CCollisionNode::SetCollision(CCollisionMeshGroup *pCollision)
|
void CCollisionNode::SetCollision(CCollisionMeshGroup *pCollision)
|
||||||
{
|
{
|
||||||
mpCollision = pCollision;
|
mpCollision = pCollision;
|
||||||
|
|
||||||
|
if (mpCollision)
|
||||||
|
{
|
||||||
|
mpCollision->BuildRenderData();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#define CCOLLISIONNODE_H
|
#define CCOLLISIONNODE_H
|
||||||
|
|
||||||
#include "CSceneNode.h"
|
#include "CSceneNode.h"
|
||||||
#include "Core/Resource/CCollisionMeshGroup.h"
|
#include "Core/Resource/Collision/CCollisionMeshGroup.h"
|
||||||
|
|
||||||
class CCollisionNode : public CSceneNode
|
class CCollisionNode : public CSceneNode
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,12 +3,15 @@
|
||||||
#include "CBasicViewport.h"
|
#include "CBasicViewport.h"
|
||||||
#include "CProgressDialog.h"
|
#include "CProgressDialog.h"
|
||||||
#include "CProjectSettingsDialog.h"
|
#include "CProjectSettingsDialog.h"
|
||||||
|
|
||||||
#include "Editor/CharacterEditor/CCharacterEditor.h"
|
#include "Editor/CharacterEditor/CCharacterEditor.h"
|
||||||
|
#include "Editor/CollisionEditor/CCollisionEditor.h"
|
||||||
#include "Editor/ModelEditor/CModelEditorWindow.h"
|
#include "Editor/ModelEditor/CModelEditorWindow.h"
|
||||||
#include "Editor/ScanEditor/CScanEditor.h"
|
#include "Editor/ScanEditor/CScanEditor.h"
|
||||||
#include "Editor/StringEditor/CStringEditor.h"
|
#include "Editor/StringEditor/CStringEditor.h"
|
||||||
#include "Editor/ResourceBrowser/CResourceBrowser.h"
|
#include "Editor/ResourceBrowser/CResourceBrowser.h"
|
||||||
#include "Editor/WorldEditor/CWorldEditor.h"
|
#include "Editor/WorldEditor/CWorldEditor.h"
|
||||||
|
|
||||||
#include <Common/Macros.h>
|
#include <Common/Macros.h>
|
||||||
#include <Common/CTimer.h>
|
#include <Common/CTimer.h>
|
||||||
#include <Core/GameProject/CGameProject.h>
|
#include <Core/GameProject/CGameProject.h>
|
||||||
|
@ -176,6 +179,12 @@ void CEditorApplication::EditResource(CResourceEntry *pEntry)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case EResourceType::DynamicCollision:
|
||||||
|
{
|
||||||
|
pEd = new CCollisionEditor((CCollisionMeshGroup*) pRes, mpWorldEditor);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pEd)
|
if (pEd)
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
#include "CCollisionEditor.h"
|
||||||
|
#include "ui_CCollisionEditor.h"
|
||||||
|
|
||||||
|
CCollisionEditor::CCollisionEditor(CCollisionMeshGroup* pCollisionMesh, QWidget* pParent /*= 0*/)
|
||||||
|
: IEditor(pParent)
|
||||||
|
, mpUI(new Ui::CCollisionEditor)
|
||||||
|
{
|
||||||
|
mpUI = std::make_unique<Ui::CCollisionEditor>();
|
||||||
|
mpUI->setupUi(this);
|
||||||
|
|
||||||
|
mpCollisionMesh = pCollisionMesh;
|
||||||
|
|
||||||
|
mpScene = std::make_unique<CScene>();
|
||||||
|
mpCollisionNode = std::make_unique<CCollisionNode>(mpScene.get(), -1);
|
||||||
|
mpCollisionNode->SetCollision(mpCollisionMesh);
|
||||||
|
mpUI->Viewport->SetNode(mpCollisionNode.get());
|
||||||
|
|
||||||
|
CCamera& rCamera = mpUI->Viewport->Camera();
|
||||||
|
rCamera.SetMoveSpeed(0.5f);
|
||||||
|
rCamera.SetPitch(-0.3f);
|
||||||
|
// rCamera.SetMoveMode(ECameraMoveMode::Orbit);
|
||||||
|
// rCamera.SetOrbit(
|
||||||
|
}
|
||||||
|
|
||||||
|
CCollisionEditorViewport* CCollisionEditor::Viewport() const
|
||||||
|
{
|
||||||
|
return mpUI->Viewport;
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
#ifndef CCOLLISIONEDITOR_H
|
||||||
|
#define CCOLLISIONEDITOR_H
|
||||||
|
|
||||||
|
#include "Editor/IEditor.h"
|
||||||
|
#include "CCollisionEditorViewport.h"
|
||||||
|
#include <Core/Scene/CCollisionNode.h>
|
||||||
|
#include <Core/Scene/CScene.h>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class CCollisionEditor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Editor window for dynamic collision (DCLN assets) */
|
||||||
|
class CCollisionEditor : public IEditor
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
/** Qt UI */
|
||||||
|
std::unique_ptr<Ui::CCollisionEditor> mpUI;
|
||||||
|
|
||||||
|
/** Collision mesh being edited */
|
||||||
|
TResPtr<CCollisionMeshGroup> mpCollisionMesh;
|
||||||
|
|
||||||
|
/** Scene data */
|
||||||
|
std::unique_ptr<CScene> mpScene;
|
||||||
|
std::unique_ptr<CCollisionNode> mpCollisionNode;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** Constructor/destructor */
|
||||||
|
explicit CCollisionEditor(CCollisionMeshGroup* pCollisionMesh, QWidget* pParent = 0);
|
||||||
|
virtual CCollisionEditorViewport* Viewport() const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CCOLLISIONEDITOR_H
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>CCollisionEditor</class>
|
||||||
|
<widget class="QMainWindow" name="CCollisionEditor">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>800</width>
|
||||||
|
<height>600</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>MainWindow</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="centralwidget">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="CCollisionEditorViewport" name="Viewport" native="true"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QStatusBar" name="statusbar"/>
|
||||||
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>CCollisionEditorViewport</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>Editor/CollisionEditor/CCollisionEditorViewport.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
|
@ -0,0 +1,44 @@
|
||||||
|
#include "CCollisionEditorViewport.h"
|
||||||
|
|
||||||
|
/** Constructor */
|
||||||
|
CCollisionEditorViewport::CCollisionEditorViewport(QWidget* pParent /*= 0*/)
|
||||||
|
: CBasicViewport(pParent)
|
||||||
|
{
|
||||||
|
mpRenderer = std::make_unique<CRenderer>();
|
||||||
|
mpRenderer->SetViewportSize(width(), height());
|
||||||
|
mpRenderer->SetClearColor(CColor(0.3f, 0.3f, 0.3f));
|
||||||
|
mpRenderer->ToggleGrid(true);
|
||||||
|
|
||||||
|
mViewInfo.ShowFlags = EShowFlag::WorldCollision | EShowFlag::ObjectCollision;
|
||||||
|
mViewInfo.pRenderer = mpRenderer.get();
|
||||||
|
mViewInfo.pScene = nullptr;
|
||||||
|
mViewInfo.GameMode = false;
|
||||||
|
mViewInfo.CollisionSettings.DrawBoundingHierarchy = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Update the collision node to render in the scene */
|
||||||
|
void CCollisionEditorViewport::SetNode(CCollisionNode* pNode)
|
||||||
|
{
|
||||||
|
mpCollisionNode = pNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** CBasicViewport interface */
|
||||||
|
void CCollisionEditorViewport::Paint()
|
||||||
|
{
|
||||||
|
mpRenderer->BeginFrame();
|
||||||
|
mCamera.LoadMatrices();
|
||||||
|
//mGrid.AddToRenderer(mpRenderer.get(), mViewInfo);
|
||||||
|
|
||||||
|
if (mpCollisionNode)
|
||||||
|
{
|
||||||
|
mpCollisionNode->AddToRenderer(mpRenderer.get(), mViewInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
mpRenderer->RenderBuckets(mViewInfo);
|
||||||
|
mpRenderer->EndFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCollisionEditorViewport::OnResize()
|
||||||
|
{
|
||||||
|
mpRenderer->SetViewportSize(width(), height());
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
#ifndef CCOLLISIONEDITORVIEWPORT_H
|
||||||
|
#define CCOLLISIONEDITORVIEWPORT_H
|
||||||
|
|
||||||
|
#include "Editor/CBasicViewport.h"
|
||||||
|
#include "Editor/CGridRenderable.h"
|
||||||
|
#include <Core/Scene/CCollisionNode.h>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
/** Preview viewport for the collision editor */
|
||||||
|
class CCollisionEditorViewport : public CBasicViewport
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
std::unique_ptr<CRenderer> mpRenderer;
|
||||||
|
CCollisionNode* mpCollisionNode;
|
||||||
|
CGridRenderable mGrid;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** Constructor */
|
||||||
|
CCollisionEditorViewport(QWidget* pParent = 0);
|
||||||
|
|
||||||
|
/** Update the collision node to render in the scene */
|
||||||
|
void SetNode(CCollisionNode* pNode);
|
||||||
|
|
||||||
|
/** CBasicViewport interface */
|
||||||
|
virtual void Paint() override;
|
||||||
|
virtual void OnResize() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CCOLLISIONEDITORVIEWPORT_H
|
|
@ -204,7 +204,9 @@ HEADERS += \
|
||||||
StringEditor/CStringMimeData.h \
|
StringEditor/CStringMimeData.h \
|
||||||
ScanEditor/CScanEditor.h \
|
ScanEditor/CScanEditor.h \
|
||||||
Undo/ICreateDeleteResourceCommand.h \
|
Undo/ICreateDeleteResourceCommand.h \
|
||||||
Undo/CSaveStoreCommand.h
|
Undo/CSaveStoreCommand.h \
|
||||||
|
CollisionEditor/CCollisionEditor.h \
|
||||||
|
CollisionEditor/CCollisionEditorViewport.h
|
||||||
|
|
||||||
# Source Files
|
# Source Files
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
|
@ -280,7 +282,9 @@ SOURCES += \
|
||||||
IEditor.cpp \
|
IEditor.cpp \
|
||||||
StringEditor/CStringDelegate.cpp \
|
StringEditor/CStringDelegate.cpp \
|
||||||
CTweakEditor.cpp \
|
CTweakEditor.cpp \
|
||||||
ScanEditor/CScanEditor.cpp
|
ScanEditor/CScanEditor.cpp \
|
||||||
|
CollisionEditor/CCollisionEditor.cpp \
|
||||||
|
CollisionEditor/CCollisionEditorViewport.cpp
|
||||||
|
|
||||||
# UI Files
|
# UI Files
|
||||||
FORMS += \
|
FORMS += \
|
||||||
|
@ -308,7 +312,8 @@ FORMS += \
|
||||||
CGeneratePropertyNamesDialog.ui \
|
CGeneratePropertyNamesDialog.ui \
|
||||||
StringEditor/CStringEditor.ui \
|
StringEditor/CStringEditor.ui \
|
||||||
CTweakEditor.ui \
|
CTweakEditor.ui \
|
||||||
ScanEditor/CScanEditor.ui
|
ScanEditor/CScanEditor.ui \
|
||||||
|
CollisionEditor/CCollisionEditor.ui
|
||||||
|
|
||||||
# Codegen
|
# Codegen
|
||||||
CODEGEN_DIR = $$EXTERNALS_DIR/CodeGen
|
CODEGEN_DIR = $$EXTERNALS_DIR/CodeGen
|
||||||
|
|
Loading…
Reference in New Issue