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/EVolumeShape.h \
|
||||
Resource/StringTable/CStringTable.h \
|
||||
Resource/CCollisionMesh.h \
|
||||
Resource/CCollisionMeshGroup.h \
|
||||
Resource/Collision/CCollisionMesh.h \
|
||||
Resource/Collision/CCollisionMeshGroup.h \
|
||||
Resource/CFont.h \
|
||||
Resource/CLight.h \
|
||||
Resource/CMaterial.h \
|
||||
|
@ -174,7 +174,7 @@ HEADERS += \
|
|||
Render/EDepthGroup.h \
|
||||
Scene/CScriptAttachNode.h \
|
||||
ScriptExtra/CSandwormExtra.h \
|
||||
Resource/CCollisionMaterial.h \
|
||||
Resource/Collision/CCollisionMaterial.h \
|
||||
GameProject/CGameProject.h \
|
||||
GameProject/CPackage.h \
|
||||
GameProject/CGameExporter.h \
|
||||
|
@ -256,7 +256,11 @@ HEADERS += \
|
|||
Resource/Scan/SScanParametersMP1.h \
|
||||
Resource/Scan/ELogbookCategory.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
|
||||
SOURCES += \
|
||||
|
@ -287,7 +291,7 @@ SOURCES += \
|
|||
Resource/Model/SSurface.cpp \
|
||||
Resource/Script/CScriptObject.cpp \
|
||||
Resource/Script/CScriptTemplate.cpp \
|
||||
Resource/CCollisionMesh.cpp \
|
||||
Resource/Collision/CCollisionMesh.cpp \
|
||||
Resource/CFont.cpp \
|
||||
Resource/CLight.cpp \
|
||||
Resource/CMaterial.cpp \
|
||||
|
@ -333,7 +337,7 @@ SOURCES += \
|
|||
Resource/Model/EVertexAttribute.cpp \
|
||||
Scene/CScriptAttachNode.cpp \
|
||||
ScriptExtra/CSandwormExtra.cpp \
|
||||
Resource/CCollisionMaterial.cpp \
|
||||
Resource/Collision/CCollisionMaterial.cpp \
|
||||
GameProject/CGameProject.cpp \
|
||||
GameProject/CGameExporter.cpp \
|
||||
GameProject/CResourceStore.cpp \
|
||||
|
@ -375,7 +379,8 @@ SOURCES += \
|
|||
Resource/Cooker/CStringCooker.cpp \
|
||||
Resource/Scan/CScan.cpp \
|
||||
Resource/Cooker/CScanCooker.cpp \
|
||||
NCoreTests.cpp
|
||||
NCoreTests.cpp \
|
||||
Resource/Collision/CCollisionRenderData.cpp
|
||||
|
||||
# Codegen
|
||||
CODEGEN_DIR = $$EXTERNALS_DIR/CodeGen
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef SVIEWINFO
|
||||
#define SVIEWINFO
|
||||
|
||||
#include "Core/Resource/CCollisionMaterial.h"
|
||||
#include "Core/Resource/Collision/CCollisionMaterial.h"
|
||||
#include "Core/Scene/FShowFlags.h"
|
||||
#include <Common/Math/CFrustumPlanes.h>
|
||||
#include <Common/Math/CMatrix4f.h>
|
||||
|
@ -11,20 +11,24 @@ struct SCollisionRenderSettings
|
|||
{
|
||||
uint64 HighlightMask;
|
||||
uint64 HideMask;
|
||||
int BoundingHierarchyRenderDepth;
|
||||
|
||||
CCollisionMaterial HideMaterial;
|
||||
bool DrawWireframe;
|
||||
bool DrawBackfaces;
|
||||
bool DrawAreaCollisionBounds;
|
||||
bool DrawBoundingHierarchy;
|
||||
bool TintWithSurfaceColor;
|
||||
bool TintUnwalkableTris;
|
||||
|
||||
SCollisionRenderSettings()
|
||||
: HighlightMask(0)
|
||||
, HideMask(0)
|
||||
, BoundingHierarchyRenderDepth(0)
|
||||
, DrawWireframe(true)
|
||||
, DrawBackfaces(false)
|
||||
, DrawAreaCollisionBounds(true)
|
||||
, DrawBoundingHierarchy(false)
|
||||
, TintWithSurfaceColor(true)
|
||||
, TintUnwalkableTris(true) {}
|
||||
};
|
||||
|
|
|
@ -19,8 +19,6 @@ CGameArea::~CGameArea()
|
|||
{
|
||||
ClearTerrain();
|
||||
|
||||
delete mpCollision;
|
||||
|
||||
for (uint32 iSCLY = 0; iSCLY < mScriptLayers.size(); iSCLY++)
|
||||
delete mScriptLayers[iSCLY];
|
||||
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
#define CGAMEAREA_H
|
||||
|
||||
#include "Core/Resource/CResource.h"
|
||||
#include "Core/Resource/CCollisionMeshGroup.h"
|
||||
#include "Core/Resource/CLight.h"
|
||||
#include "Core/Resource/CMaterialSet.h"
|
||||
#include "Core/Resource/CPoiToWorld.h"
|
||||
#include "Core/Resource/Collision/CCollisionMeshGroup.h"
|
||||
#include "Core/Resource/Model/CModel.h"
|
||||
#include "Core/Resource/Model/CStaticModel.h"
|
||||
#include <Common/BasicTypes.h>
|
||||
|
@ -51,7 +51,7 @@ class CGameArea : public CResource
|
|||
std::vector<CScriptLayer*> mScriptLayers;
|
||||
std::unordered_map<uint32, CScriptObject*> mObjectMap;
|
||||
// Collision
|
||||
CCollisionMeshGroup *mpCollision;
|
||||
std::unique_ptr<CCollisionMeshGroup> mpCollision;
|
||||
// Lights
|
||||
std::vector<std::vector<CLight*>> mLightLayers;
|
||||
// Path Mesh
|
||||
|
@ -93,7 +93,7 @@ public:
|
|||
inline uint32 NumStaticModels() const { return mStaticWorldModels.size(); }
|
||||
inline CModel* TerrainModel(uint32 iMdl) const { return mWorldModels[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 CScriptLayer* ScriptLayer(uint32 Index) const { return mScriptLayers[Index]; }
|
||||
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
|
||||
#define CCOLLISIONMESHGROUP_H
|
||||
|
||||
#include "CResource.h"
|
||||
#include "CCollisionMesh.h"
|
||||
#include "TResPtr.h"
|
||||
#include "Core/Resource/CResource.h"
|
||||
#include "Core/Resource/TResPtr.h"
|
||||
#include <Common/Math/CTransform4f.h>
|
||||
#include <vector>
|
||||
|
||||
class CCollisionMeshGroup : public CResource
|
||||
|
@ -24,16 +25,22 @@ public:
|
|||
inline CCollisionMesh* MeshByIndex(uint32 Index) const { return mMeshes[Index]; }
|
||||
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()
|
||||
{
|
||||
for (auto it = mMeshes.begin(); it != mMeshes.end(); it++)
|
||||
(*it)->Draw();
|
||||
(*it)->GetRenderData().Render(false);
|
||||
}
|
||||
|
||||
inline void DrawWireframe()
|
||||
{
|
||||
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()
|
||||
{
|
||||
mpSectionMgr->ToSection(mCollisionBlockNum);
|
||||
mpArea->mpCollision = CCollisionLoader::LoadAreaCollision(*mpMREA);
|
||||
CCollisionMeshGroup* pAreaCollision = CCollisionLoader::LoadAreaCollision(*mpMREA);
|
||||
mpArea->mpCollision = std::unique_ptr<CCollisionMeshGroup>(pAreaCollision);
|
||||
}
|
||||
|
||||
void CAreaLoader::ReadPATH()
|
||||
|
|
|
@ -6,6 +6,7 @@ CCollisionLoader::CCollisionLoader()
|
|||
{
|
||||
}
|
||||
|
||||
#if 0
|
||||
CCollisionMesh::CCollisionOctree* CCollisionLoader::ParseOctree(IInputStream& /*rSrc*/)
|
||||
{
|
||||
return nullptr;
|
||||
|
@ -20,172 +21,180 @@ CCollisionMesh::CCollisionOctree::SLeaf* CCollisionLoader::ParseOctreeLeaf(IInpu
|
|||
{
|
||||
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);
|
||||
b = (rDCLN.ReadByte() == 1);
|
||||
if (!b) ParseOBBNode(rDCLN);
|
||||
SOBBTreeLeaf* pLeaf = new SOBBTreeLeaf;
|
||||
uint NumTris = DCLN.ReadLong();
|
||||
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();
|
||||
rDCLN.Seek(NumFaces * 2, SEEK_CUR);
|
||||
pOut->Transform = Transform;
|
||||
pOut->Radii = Radius;
|
||||
return pOut;
|
||||
}
|
||||
|
||||
void CCollisionLoader::ReadPropertyFlags(IInputStream& rSrc)
|
||||
void CCollisionLoader::LoadCollisionMaterial(IInputStream& Src, CCollisionMaterial& OutMaterial)
|
||||
{
|
||||
CCollisionMaterial Material;
|
||||
uint64 RawFlags = (mVersion <= EGame::Prime ? rSrc.ReadLong() : rSrc.ReadLongLong());
|
||||
Material.mRawFlags = RawFlags;
|
||||
uint64 RawFlags = (mVersion <= EGame::Prime ? Src.ReadLong() : Src.ReadLongLong());
|
||||
OutMaterial.mRawFlags = RawFlags;
|
||||
|
||||
if (mVersion <= EGame::Prime)
|
||||
{
|
||||
if (RawFlags & 0x00000001) Material |= eCF_Unknown;
|
||||
if (RawFlags & 0x00000002) Material |= eCF_Stone;
|
||||
if (RawFlags & 0x00000004) Material |= eCF_Metal;
|
||||
if (RawFlags & 0x00000008) Material |= eCF_Grass;
|
||||
if (RawFlags & 0x00000010) Material |= eCF_Ice;
|
||||
if (RawFlags & 0x00000040) Material |= eCF_MetalGrating;
|
||||
if (RawFlags & 0x00000080) Material |= eCF_Phazon;
|
||||
if (RawFlags & 0x00000100) Material |= eCF_Dirt;
|
||||
if (RawFlags & 0x00000200) Material |= eCF_Lava;
|
||||
if (RawFlags & 0x00000800) Material |= eCF_Snow;
|
||||
if (RawFlags & 0x00001000) Material |= eCF_SlowMud;
|
||||
if (RawFlags & 0x00004000) Material |= eCF_Mud;
|
||||
if (RawFlags & 0x00008000) Material |= eCF_Glass;
|
||||
if (RawFlags & 0x00010000) Material |= eCF_Shield;
|
||||
if (RawFlags & 0x00020000) Material |= eCF_Sand;
|
||||
if (RawFlags & 0x00040000) Material |= eCF_ShootThru;
|
||||
if (RawFlags & 0x00200000) Material |= eCF_CameraThru;
|
||||
if (RawFlags & 0x00400000) Material |= eCF_Wood;
|
||||
if (RawFlags & 0x00800000) Material |= eCF_Organic;
|
||||
if (RawFlags & 0x02000000) Material |= eCF_FlippedTri;
|
||||
if (RawFlags & 0x08000000) Material |= eCF_ScanThru;
|
||||
if (RawFlags & 0x10000000) Material |= eCF_AiWalkThru;
|
||||
if (RawFlags & 0x20000000) Material |= eCF_Ceiling;
|
||||
if (RawFlags & 0x40000000) Material |= eCF_Wall;
|
||||
if (RawFlags & 0x80000000) Material |= eCF_Floor;
|
||||
if (RawFlags & 0x00000001) OutMaterial |= eCF_Unknown;
|
||||
if (RawFlags & 0x00000002) OutMaterial |= eCF_Stone;
|
||||
if (RawFlags & 0x00000004) OutMaterial |= eCF_Metal;
|
||||
if (RawFlags & 0x00000008) OutMaterial |= eCF_Grass;
|
||||
if (RawFlags & 0x00000010) OutMaterial |= eCF_Ice;
|
||||
if (RawFlags & 0x00000040) OutMaterial |= eCF_MetalGrating;
|
||||
if (RawFlags & 0x00000080) OutMaterial |= eCF_Phazon;
|
||||
if (RawFlags & 0x00000100) OutMaterial |= eCF_Dirt;
|
||||
if (RawFlags & 0x00000200) OutMaterial |= eCF_Lava;
|
||||
if (RawFlags & 0x00000800) OutMaterial |= eCF_Snow;
|
||||
if (RawFlags & 0x00001000) OutMaterial |= eCF_SlowMud;
|
||||
if (RawFlags & 0x00004000) OutMaterial |= eCF_Mud;
|
||||
if (RawFlags & 0x00008000) OutMaterial |= eCF_Glass;
|
||||
if (RawFlags & 0x00010000) OutMaterial |= eCF_Shield;
|
||||
if (RawFlags & 0x00020000) OutMaterial |= eCF_Sand;
|
||||
if (RawFlags & 0x00040000) OutMaterial |= eCF_ShootThru;
|
||||
if (RawFlags & 0x00200000) OutMaterial |= eCF_CameraThru;
|
||||
if (RawFlags & 0x00400000) OutMaterial |= eCF_Wood;
|
||||
if (RawFlags & 0x00800000) OutMaterial |= eCF_Organic;
|
||||
if (RawFlags & 0x02000000) OutMaterial |= eCF_FlippedTri;
|
||||
if (RawFlags & 0x08000000) OutMaterial |= eCF_ScanThru;
|
||||
if (RawFlags & 0x10000000) OutMaterial |= eCF_AiWalkThru;
|
||||
if (RawFlags & 0x20000000) OutMaterial |= eCF_Ceiling;
|
||||
if (RawFlags & 0x40000000) OutMaterial |= eCF_Wall;
|
||||
if (RawFlags & 0x80000000) OutMaterial |= eCF_Floor;
|
||||
}
|
||||
|
||||
else if (mVersion <= EGame::Corruption)
|
||||
{
|
||||
if (RawFlags & 0x00000001) Material |= eCF_Unknown;
|
||||
if (RawFlags & 0x00000002) Material |= eCF_Stone;
|
||||
if (RawFlags & 0x00000004) Material |= eCF_Metal;
|
||||
if (RawFlags & 0x00000008) Material |= eCF_Grass;
|
||||
if (RawFlags & 0x00000010) Material |= eCF_Ice;
|
||||
if (RawFlags & 0x00000040) Material |= eCF_MetalGrating;
|
||||
if (RawFlags & 0x00000080) Material |= eCF_Phazon;
|
||||
if (RawFlags & 0x00000100) Material |= eCF_Dirt;
|
||||
if (RawFlags & 0x00000200) Material |= eCF_AltMetal;
|
||||
if (RawFlags & 0x00000400) Material |= eCF_Glass;
|
||||
if (RawFlags & 0x00000800) Material |= eCF_Snow;
|
||||
if (RawFlags & 0x00001000) Material |= eCF_Fabric;
|
||||
if (RawFlags & 0x00010000) Material |= eCF_Shield;
|
||||
if (RawFlags & 0x00020000) Material |= eCF_Sand;
|
||||
if (RawFlags & 0x00040000) Material |= eCF_MothSeedOrganics;
|
||||
if (RawFlags & 0x00080000) Material |= eCF_Web;
|
||||
if (RawFlags & 0x00100000) Material |= eCF_ShootThru;
|
||||
if (RawFlags & 0x00200000) Material |= eCF_CameraThru;
|
||||
if (RawFlags & 0x00400000) Material |= eCF_Wood;
|
||||
if (RawFlags & 0x00800000) Material |= eCF_Organic;
|
||||
if (RawFlags & 0x01000000) Material |= eCF_FlippedTri;
|
||||
if (RawFlags & 0x02000000) Material |= eCF_Rubber;
|
||||
if (RawFlags & 0x08000000) Material |= eCF_ScanThru;
|
||||
if (RawFlags & 0x10000000) Material |= eCF_AiWalkThru;
|
||||
if (RawFlags & 0x20000000) Material |= eCF_Ceiling;
|
||||
if (RawFlags & 0x40000000) Material |= eCF_Wall;
|
||||
if (RawFlags & 0x80000000) Material |= eCF_Floor;
|
||||
if (RawFlags & 0x00000001) OutMaterial |= eCF_Unknown;
|
||||
if (RawFlags & 0x00000002) OutMaterial |= eCF_Stone;
|
||||
if (RawFlags & 0x00000004) OutMaterial |= eCF_Metal;
|
||||
if (RawFlags & 0x00000008) OutMaterial |= eCF_Grass;
|
||||
if (RawFlags & 0x00000010) OutMaterial |= eCF_Ice;
|
||||
if (RawFlags & 0x00000040) OutMaterial |= eCF_MetalGrating;
|
||||
if (RawFlags & 0x00000080) OutMaterial |= eCF_Phazon;
|
||||
if (RawFlags & 0x00000100) OutMaterial |= eCF_Dirt;
|
||||
if (RawFlags & 0x00000200) OutMaterial |= eCF_AltMetal;
|
||||
if (RawFlags & 0x00000400) OutMaterial |= eCF_Glass;
|
||||
if (RawFlags & 0x00000800) OutMaterial |= eCF_Snow;
|
||||
if (RawFlags & 0x00001000) OutMaterial |= eCF_Fabric;
|
||||
if (RawFlags & 0x00010000) OutMaterial |= eCF_Shield;
|
||||
if (RawFlags & 0x00020000) OutMaterial |= eCF_Sand;
|
||||
if (RawFlags & 0x00040000) OutMaterial |= eCF_MothSeedOrganics;
|
||||
if (RawFlags & 0x00080000) OutMaterial |= eCF_Web;
|
||||
if (RawFlags & 0x00100000) OutMaterial |= eCF_ShootThru;
|
||||
if (RawFlags & 0x00200000) OutMaterial |= eCF_CameraThru;
|
||||
if (RawFlags & 0x00400000) OutMaterial |= eCF_Wood;
|
||||
if (RawFlags & 0x00800000) OutMaterial |= eCF_Organic;
|
||||
if (RawFlags & 0x01000000) OutMaterial |= eCF_FlippedTri;
|
||||
if (RawFlags & 0x02000000) OutMaterial |= eCF_Rubber;
|
||||
if (RawFlags & 0x08000000) OutMaterial |= eCF_ScanThru;
|
||||
if (RawFlags & 0x10000000) OutMaterial |= eCF_AiWalkThru;
|
||||
if (RawFlags & 0x20000000) OutMaterial |= eCF_Ceiling;
|
||||
if (RawFlags & 0x40000000) OutMaterial |= eCF_Wall;
|
||||
if (RawFlags & 0x80000000) OutMaterial |= eCF_Floor;
|
||||
|
||||
if (RawFlags & 0x0001000000000000) Material |= eCF_AiBlock;
|
||||
if (RawFlags & 0x0400000000000000) Material |= eCF_JumpNotAllowed;
|
||||
if (RawFlags & 0x0001000000000000) OutMaterial |= eCF_AiBlock;
|
||||
if (RawFlags & 0x0400000000000000) OutMaterial |= eCF_JumpNotAllowed;
|
||||
}
|
||||
|
||||
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
|
||||
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];
|
||||
OutData.EdgeIndices[i] = File.ReadShort();
|
||||
}
|
||||
|
||||
// Faces
|
||||
mpMesh->mFaceCount = rFile.ReadLong() / 3; // Not sure why they store it this way. It's inconsistent.
|
||||
mpMesh->mCollisionFaces.resize(mpMesh->mFaceCount);
|
||||
// Triangles
|
||||
uint NumTris = File.ReadLong();
|
||||
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];
|
||||
pFace->Lines[0] = rFile.ReadShort();
|
||||
pFace->Lines[1] = rFile.ReadShort();
|
||||
pFace->Lines[2] = rFile.ReadShort();
|
||||
pFace->MaterialIdx = FaceIndices[iFace];
|
||||
OutData.TriangleIndices[i] = File.ReadShort();
|
||||
}
|
||||
|
||||
// Echoes introduces a new data chunk; don't know what it is yet, skipping for now
|
||||
if (mVersion >= EGame::Echoes)
|
||||
{
|
||||
uint32 UnknownCount = rFile.ReadLong();
|
||||
rFile.Seek(UnknownCount * 2, SEEK_CUR);
|
||||
uint UnknownCount = File.ReadLong();
|
||||
File.Skip(UnknownCount * 2);
|
||||
}
|
||||
|
||||
// Vertices
|
||||
mpMesh->mVertexCount = rFile.ReadLong();
|
||||
mpMesh->mCollisionVertices.resize(mpMesh->mVertexCount);
|
||||
CAABox Bounds;
|
||||
uint NumVertices = File.ReadLong();
|
||||
OutData.Vertices.resize(NumVertices);
|
||||
|
||||
for (uint32 iVtx = 0; iVtx < mpMesh->mVertexCount; iVtx++)
|
||||
for (uint32 i=0; i<NumVertices; i++)
|
||||
{
|
||||
CCollisionMesh::CCollisionVertex *pVtx = &mpMesh->mCollisionVertices[iVtx];
|
||||
pVtx->Pos = CVector3f(rFile);
|
||||
pVtx->MaterialIdx = VtxIndices[iVtx];
|
||||
if (BuildAABox) Bounds.ExpandBounds(pVtx->Pos);
|
||||
OutData.Vertices[i].Read(File);
|
||||
}
|
||||
if (BuildAABox) mpMesh->mAABox = Bounds;
|
||||
}
|
||||
|
||||
// ************ STATIC ************
|
||||
CCollisionMeshGroup* CCollisionLoader::LoadAreaCollision(IInputStream& rMREA)
|
||||
{
|
||||
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();
|
||||
if (DeafBabe != 0xDEAFBABE)
|
||||
{
|
||||
|
@ -193,22 +202,22 @@ CCollisionMeshGroup* CCollisionLoader::LoadAreaCollision(IInputStream& rMREA)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
loader.mVersion = GetFormatVersion(rMREA.ReadLong());
|
||||
|
||||
loader.mpGroup = new CCollisionMeshGroup;
|
||||
loader.mpMesh = new CCollisionMesh;
|
||||
CCollisionLoader Loader;
|
||||
Loader.mVersion = GetFormatVersion(rMREA.ReadLong());
|
||||
Loader.mpMesh = new CCollisionMesh;
|
||||
|
||||
// Octree - structure is known, but not coding this right now
|
||||
loader.mpMesh->mAABox = CAABox(rMREA);
|
||||
rMREA.Seek(0x4, SEEK_CUR);
|
||||
Loader.mpMesh->mAABox = CAABox(rMREA);
|
||||
rMREA.Skip(0x4);
|
||||
uint32 OctreeSize = rMREA.ReadLong();
|
||||
rMREA.Seek(OctreeSize, SEEK_CUR); // Skipping the octree for now
|
||||
loader.mpMesh->mOctreeLoaded = false;
|
||||
rMREA.Skip(OctreeSize); // Skipping the octree for now
|
||||
|
||||
// Read collision indices and return
|
||||
loader.LoadCollisionIndices(rMREA, false);
|
||||
loader.mpGroup->AddMesh(loader.mpMesh);
|
||||
return loader.mpGroup;
|
||||
Loader.LoadCollisionIndices(rMREA, Loader.mpMesh->mIndexData);
|
||||
|
||||
CCollisionMeshGroup* pOut = new CCollisionMeshGroup();
|
||||
pOut->AddMesh(Loader.mpMesh);
|
||||
return pOut;
|
||||
}
|
||||
|
||||
CCollisionMeshGroup* CCollisionLoader::LoadDCLN(IInputStream& rDCLN, CResourceEntry *pEntry)
|
||||
|
@ -220,32 +229,45 @@ CCollisionMeshGroup* CCollisionLoader::LoadDCLN(IInputStream& rDCLN, CResourceEn
|
|||
|
||||
uint32 NumMeshes = rDCLN.ReadLong();
|
||||
|
||||
for (uint32 iMesh = 0; iMesh < NumMeshes; iMesh++)
|
||||
for (uint32 MeshIdx = 0; MeshIdx < NumMeshes; MeshIdx++)
|
||||
{
|
||||
uint32 DeafBabe = rDCLN.ReadLong();
|
||||
|
||||
if (DeafBabe != 0xDEAFBABE)
|
||||
{
|
||||
errorf("%s [0x%X]: Invalid collision magic: 0x%08X", *rDCLN.GetSourceString(), rDCLN.Tell() - 4, DeafBabe);
|
||||
Loader.mpGroup.Delete();
|
||||
delete Loader.mpGroup;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Loader.mVersion = GetFormatVersion(rDCLN.ReadLong());
|
||||
|
||||
Loader.mpMesh = new CCollisionMesh;
|
||||
Loader.mpMesh->mOctreeLoaded = false;
|
||||
Loader.mpMesh = new CCollidableOBBTree;
|
||||
|
||||
if (Loader.mVersion == EGame::DKCReturns)
|
||||
Loader.mpMesh->mAABox = CAABox(rDCLN);
|
||||
|
||||
// Read indices and return
|
||||
rDCLN.Seek(0x4, SEEK_CUR);
|
||||
Loader.LoadCollisionIndices(rDCLN, Loader.mVersion != EGame::DKCReturns);
|
||||
Loader.LoadCollisionIndices(rDCLN, Loader.mpMesh->mIndexData);
|
||||
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
|
||||
Loader.ParseOBBNode(rDCLN);
|
||||
CCollidableOBBTree* pOBBTree = static_cast<CCollidableOBBTree*>(Loader.mpMesh);
|
||||
pOBBTree->mpOBBTree = std::unique_ptr<SOBBTreeNode>( Loader.ParseOBBNode(rDCLN) );
|
||||
}
|
||||
return Loader.mpGroup;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
#ifndef CCOLLISIONLOADER_H
|
||||
#define CCOLLISIONLOADER_H
|
||||
|
||||
#include "Core/Resource/CCollisionMesh.h"
|
||||
#include "Core/Resource/CCollisionMeshGroup.h"
|
||||
#include "Core/Resource/Collision/CCollisionMesh.h"
|
||||
#include "Core/Resource/Collision/CCollisionMeshGroup.h"
|
||||
#include "Core/Resource/Collision/CCollidableOBBTree.h"
|
||||
#include <Common/EGame.h>
|
||||
|
||||
class CCollisionLoader
|
||||
|
@ -12,12 +13,16 @@ class CCollisionLoader
|
|||
EGame mVersion;
|
||||
|
||||
CCollisionLoader();
|
||||
|
||||
#if 0
|
||||
CCollisionMesh::CCollisionOctree* ParseOctree(IInputStream& rSrc);
|
||||
CCollisionMesh::CCollisionOctree::SBranch* ParseOctreeBranch(IInputStream& rSrc);
|
||||
CCollisionMesh::CCollisionOctree::SLeaf* ParseOctreeLeaf(IInputStream& rSrc);
|
||||
void ParseOBBNode(IInputStream& rDCLN);
|
||||
void ReadPropertyFlags(IInputStream& rSrc);
|
||||
void LoadCollisionIndices(IInputStream& rFile, bool BuildAABox);
|
||||
#endif
|
||||
|
||||
SOBBTreeNode* ParseOBBNode(IInputStream& DCLN);
|
||||
void LoadCollisionMaterial(IInputStream& Src, CCollisionMaterial& OutMaterial);
|
||||
void LoadCollisionIndices(IInputStream& File, SCollisionIndexData& OutData);
|
||||
|
||||
public:
|
||||
static CCollisionMeshGroup* LoadAreaCollision(IInputStream& rMREA);
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#ifndef RESOURCES_H
|
||||
#define RESOURCES_H
|
||||
|
||||
#include "CCollisionMeshGroup.h"
|
||||
#include "CDependencyGroup.h"
|
||||
#include "CFont.h"
|
||||
#include "CPoiToWorld.h"
|
||||
|
@ -13,6 +12,7 @@
|
|||
#include "Core/Resource/Animation/CSkeleton.h"
|
||||
#include "Core/Resource/Animation/CSkin.h"
|
||||
#include "Core/Resource/Area/CGameArea.h"
|
||||
#include "Core/Resource/Collision/CCollisionMeshGroup.h"
|
||||
#include "Core/Resource/Model/CModel.h"
|
||||
#include "Core/Resource/Scan/CScan.h"
|
||||
#include "Core/Resource/StringTable/CStringTable.h"
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
|
||||
#include "CScriptTemplate.h"
|
||||
#include "Core/Resource/Area/CGameArea.h"
|
||||
#include "Core/Resource/Collision/CCollisionMeshGroup.h"
|
||||
#include "Core/Resource/Model/CModel.h"
|
||||
#include "Core/Resource/CCollisionMeshGroup.h"
|
||||
#include "Core/Resource/Script/Property/Properties.h"
|
||||
|
||||
class CScriptLayer;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include "Core/Resource/Script/Property/Properties.h"
|
||||
#include "EVolumeShape.h"
|
||||
#include "Core/Resource/Model/CModel.h"
|
||||
#include "Core/Resource/CCollisionMeshGroup.h"
|
||||
#include "Core/Resource/Collision/CCollisionMeshGroup.h"
|
||||
#include <Common/BasicTypes.h>
|
||||
#include <Common/CFourCC.h>
|
||||
#include <list>
|
||||
|
|
|
@ -39,7 +39,7 @@ void CCollisionNode::Draw(FRenderOptions /*Options*/, int /*ComponentIndex*/, ER
|
|||
glDepthMask(GL_TRUE);
|
||||
|
||||
// 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);
|
||||
|
||||
if (ForceDisableBackfaceCull)
|
||||
|
@ -47,35 +47,48 @@ void CCollisionNode::Draw(FRenderOptions /*Options*/, int /*ComponentIndex*/, ER
|
|||
|
||||
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;
|
||||
|
||||
if (rkViewInfo.CollisionSettings.HideMask != 0 && (rMat.RawFlags() & rkViewInfo.CollisionSettings.HideMask) != 0)
|
||||
if (rkViewInfo.CollisionSettings.HideMask != 0 && (kMat.RawFlags() & rkViewInfo.CollisionSettings.HideMask) != 0)
|
||||
continue;
|
||||
|
||||
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;
|
||||
|
||||
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 IsUnstandable = (rkViewInfo.CollisionSettings.TintUnwalkableTris ? rMat.IsUnstandable(Game) : false) && Game != EGame::DKCReturns;
|
||||
bool IsFloor = (rkViewInfo.CollisionSettings.TintUnwalkableTris ? kMat.IsFloor() : true) || Game == EGame::DKCReturns;
|
||||
bool IsUnstandable = (rkViewInfo.CollisionSettings.TintUnwalkableTris ? kMat.IsUnstandable(Game) : false) && Game != EGame::DKCReturns;
|
||||
CDrawUtil::UseCollisionShader(IsFloor, IsUnstandable, Tint);
|
||||
pMesh->DrawMaterial(iMat, false);
|
||||
RenderData.Render(false, MatIdx);
|
||||
|
||||
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
|
||||
// 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
|
||||
if (rkViewInfo.CollisionSettings.DrawAreaCollisionBounds && Parent()->NodeType() == ENodeType::Root && Game != EGame::DKCReturns)
|
||||
CDrawUtil::DrawWireCube( mpCollision->MeshByIndex(0)->BoundingBox(), CColor::skRed );
|
||||
if (rkViewInfo.CollisionSettings.DrawAreaCollisionBounds)
|
||||
{
|
||||
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*/)
|
||||
|
@ -106,4 +124,9 @@ SRayIntersection CCollisionNode::RayNodeIntersectTest(const CRay& /*rkRay*/, uin
|
|||
void CCollisionNode::SetCollision(CCollisionMeshGroup *pCollision)
|
||||
{
|
||||
mpCollision = pCollision;
|
||||
|
||||
if (mpCollision)
|
||||
{
|
||||
mpCollision->BuildRenderData();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#define CCOLLISIONNODE_H
|
||||
|
||||
#include "CSceneNode.h"
|
||||
#include "Core/Resource/CCollisionMeshGroup.h"
|
||||
#include "Core/Resource/Collision/CCollisionMeshGroup.h"
|
||||
|
||||
class CCollisionNode : public CSceneNode
|
||||
{
|
||||
|
|
|
@ -3,12 +3,15 @@
|
|||
#include "CBasicViewport.h"
|
||||
#include "CProgressDialog.h"
|
||||
#include "CProjectSettingsDialog.h"
|
||||
|
||||
#include "Editor/CharacterEditor/CCharacterEditor.h"
|
||||
#include "Editor/CollisionEditor/CCollisionEditor.h"
|
||||
#include "Editor/ModelEditor/CModelEditorWindow.h"
|
||||
#include "Editor/ScanEditor/CScanEditor.h"
|
||||
#include "Editor/StringEditor/CStringEditor.h"
|
||||
#include "Editor/ResourceBrowser/CResourceBrowser.h"
|
||||
#include "Editor/WorldEditor/CWorldEditor.h"
|
||||
|
||||
#include <Common/Macros.h>
|
||||
#include <Common/CTimer.h>
|
||||
#include <Core/GameProject/CGameProject.h>
|
||||
|
@ -176,6 +179,12 @@ void CEditorApplication::EditResource(CResourceEntry *pEntry)
|
|||
break;
|
||||
}
|
||||
|
||||
case EResourceType::DynamicCollision:
|
||||
{
|
||||
pEd = new CCollisionEditor((CCollisionMeshGroup*) pRes, mpWorldEditor);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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 \
|
||||
ScanEditor/CScanEditor.h \
|
||||
Undo/ICreateDeleteResourceCommand.h \
|
||||
Undo/CSaveStoreCommand.h
|
||||
Undo/CSaveStoreCommand.h \
|
||||
CollisionEditor/CCollisionEditor.h \
|
||||
CollisionEditor/CCollisionEditorViewport.h
|
||||
|
||||
# Source Files
|
||||
SOURCES += \
|
||||
|
@ -280,7 +282,9 @@ SOURCES += \
|
|||
IEditor.cpp \
|
||||
StringEditor/CStringDelegate.cpp \
|
||||
CTweakEditor.cpp \
|
||||
ScanEditor/CScanEditor.cpp
|
||||
ScanEditor/CScanEditor.cpp \
|
||||
CollisionEditor/CCollisionEditor.cpp \
|
||||
CollisionEditor/CCollisionEditorViewport.cpp
|
||||
|
||||
# UI Files
|
||||
FORMS += \
|
||||
|
@ -308,7 +312,8 @@ FORMS += \
|
|||
CGeneratePropertyNamesDialog.ui \
|
||||
StringEditor/CStringEditor.ui \
|
||||
CTweakEditor.ui \
|
||||
ScanEditor/CScanEditor.ui
|
||||
ScanEditor/CScanEditor.ui \
|
||||
CollisionEditor/CCollisionEditor.ui
|
||||
|
||||
# Codegen
|
||||
CODEGEN_DIR = $$EXTERNALS_DIR/CodeGen
|
||||
|
|
Loading…
Reference in New Issue