Set up game-neutral collision materials; Jump Not Allowed flag now flags that surface as unstandable; other minor fixes

This commit is contained in:
parax0
2017-01-11 06:29:30 -07:00
parent be40dfdf02
commit 08dee84367
13 changed files with 255 additions and 85 deletions

View File

@@ -0,0 +1,66 @@
#include "CCollisionMaterial.h"
#include "EGame.h"
#include <map>
ECollisionFlag CCollisionMaterial::SurfaceType(EGame Game) const
{
// Arrays determining the type hierarchy for each game.
// Flags earlier in the list take priority over flags later in the list.
static const ECollisionFlag skPrimeTypeHierarchy[] = {
eCF_Organic, eCF_Wood, eCF_Sand, eCF_Shield, eCF_Glass, eCF_Mud, eCF_SlowMud,
eCF_Snow, eCF_Lava, eCF_Dirt, eCF_Phazon, eCF_MetalGrating, eCF_Ice, eCF_Grass,
eCF_Metal, eCF_Stone
};
static const ECollisionFlag skEchoesTypeHierarchy[] = {
eCF_Rubber, eCF_Organic, eCF_Wood, eCF_Web, eCF_MothSeedOrganics, eCF_Sand,
eCF_Shield, eCF_Fabric, eCF_Snow, eCF_Glass, eCF_AltMetal, eCF_Dirt, eCF_Phazon,
eCF_MetalGrating, eCF_Ice, eCF_Grass, eCF_Metal, eCF_Stone
};
// Determine which list we should use.
const ECollisionFlag* pkFlagArray;
u32 Num;
if (Game <= ePrime)
{
pkFlagArray = skPrimeTypeHierarchy;
Num = sizeof(skPrimeTypeHierarchy) / sizeof(ECollisionFlag);
}
else
{
pkFlagArray = skEchoesTypeHierarchy;
Num = sizeof(skEchoesTypeHierarchy) / sizeof(ECollisionFlag);
}
// Locate type.
for (u32 iType = 0; iType < Num; iType++)
{
if (*this & pkFlagArray[iType])
return pkFlagArray[iType];
}
return eCF_Unknown;
}
// Type-to-color mappings
const std::map<ECollisionFlag, CColor> gkTypeToColor = {
{ eCF_Stone, CColor::Integral(220, 215, 160) }, // Brownish/greenish color
{ eCF_Metal, CColor::Integral(110, 110, 110) }, // Dark gray
{ eCF_Grass, CColor::Integral( 90, 150, 70) }, // Green
{ eCF_Ice, CColor::Integral(200, 255, 255) }, // Light blue
{ eCF_MetalGrating, CColor::Integral(170, 170, 170) }, // Gray
{ eCF_Phazon, CColor::Integral( 0, 128, 255) }, // Blue
{ eCF_Dirt, CColor::Integral(150, 130, 120) }, // Brownish-gray
{ eCF_Lava, CColor::Integral(200, 30, 30) }, // Red
{ eCF_Snow, CColor::Integral(230, 255, 255) }, // *Very* light blue
{ eCF_Glass, CColor::Integral( 20, 255, 190) }, // Greenish blue
{ eCF_Shield, CColor::Integral(230, 250, 60) }, // Yellow
{ eCF_Sand, CColor::Integral(230, 200, 170) }, // Light brown
{ eCF_Wood, CColor::Integral(190, 140, 105) }, // Brown
{ eCF_Organic, CColor::Integral(130, 130, 250) } // Purple
};
CColor CCollisionMaterial::SurfaceColor(EGame Game) const
{
ECollisionFlag SurfType = SurfaceType(Game);
auto FindColor = gkTypeToColor.find(SurfType);
return (FindColor == gkTypeToColor.end() ? CColor::skWhite : FindColor->second);
}

View File

@@ -0,0 +1,64 @@
#ifndef CCOLLISIONMATERIAL
#define CCOLLISIONMATERIAL
#include "EGame.h"
#include <Common/CColor.h>
#include <Common/Flags.h>
// Game-neutral collision property flags.
// IMPORTANT: This is an incomplete list. Keep in mind that MP2, MP3, and DKCR store
// collision materials via a 64-bit flag where every bit is used, and some flags differ
// between games. Therefore a single enum doesn't have the resolution to represent EVERY
// flag from EVERY game. In the future, the storage medium needs to be changed to a struct,
// OR we need to be okay with excluding certain flags (which we probably are, because a
// lot of them aren't meant to be used by collision geometry, such as the "Player" flag).
enum ECollisionFlag
{
eCF_Unknown = 0x00000001,
eCF_Stone = 0x00000002,
eCF_Metal = 0x00000004,
eCF_Grass = 0x00000008,
eCF_Ice = 0x00000010,
eCF_MetalGrating = 0x00000020,
eCF_Phazon = 0x00000040,
eCF_Dirt = 0x00000080,
eCF_Lava = 0x00000100,
eCF_AltMetal = 0x00000200,
eCF_Snow = 0x00000400,
eCF_Fabric = 0x00000800,
eCF_SlowMud = 0x00001000,
eCF_Mud = 0x00002000,
eCF_Glass = 0x00004000,
eCF_Shield = 0x00008000,
eCF_Sand = 0x00010000,
eCF_MothSeedOrganics = 0x00020000,
eCF_Web = 0x00040000,
eCF_Wood = 0x00080000,
eCF_Organic = 0x00100000,
eCF_Rubber = 0x00200000,
eCF_ShootThru = 0x00400000,
eCF_CameraThru = 0x00800000,
eCF_ScanThru = 0x01000000,
eCF_AiWalkThru = 0x02000000,
eCF_FlippedTri = 0x04000000,
eCF_Floor = 0x08000000,
eCF_AiBlock = 0x10000000,
eCF_JumpNotAllowed = 0x20000000,
eCF_SpiderBall = 0x40000000,
eCF_WallJump = 0x80000000
};
class CCollisionMaterial : public TFlags<ECollisionFlag>
{
friend class CCollisionLoader;
u64 mRawFlags;
public:
ECollisionFlag SurfaceType(EGame Game) const;
CColor SurfaceColor(EGame Game) const;
inline u64 RawFlags() const { return mRawFlags; }
};
#endif // CCOLLISIONMATERIAL

View File

@@ -73,7 +73,7 @@ void CCollisionMesh::BufferGL()
Verts[2] = pLineB->Vertices[1];
// Some faces have a property that indicates they need to be inverted
if (GetMaterial(pFace->MaterialIdx).FlippedTri)
if (GetMaterial(pFace->MaterialIdx) & eCF_FlippedTri)
{
u16 V0 = Verts[0];
Verts[0] = Verts[2];

View File

@@ -1,22 +1,12 @@
#ifndef CCOLLISIONMESH_H
#define CCOLLISIONMESH_H
#include "CCollisionMaterial.h"
#include "CResource.h"
#include "Core/OpenGL/CVertexBuffer.h"
#include "Core/OpenGL/CIndexBuffer.h"
#include <Math/CAABox.h>
struct SCollisionMaterial
{
// todo: figure out what the other properties are
u64 RawFlags;
bool AiWalkThru;
bool FlippedTri;
bool ShootThru;
bool CameraThru;
bool Solid;
};
class CCollisionMesh
{
friend class CCollisionLoader;
@@ -71,7 +61,7 @@ class CCollisionMesh
CAABox mAABox;
CCollisionOctree *mpOctree;
std::vector<SCollisionMaterial> mMaterials;
std::vector<CCollisionMaterial> mMaterials;
std::vector<CCollisionVertex> mCollisionVertices;
std::vector<CCollisionLine> mCollisionLines;
std::vector<CCollisionFace> mCollisionFaces;
@@ -92,7 +82,8 @@ public:
void DrawWireframe();
inline u32 NumMaterials() const { return mMaterials.size(); }
inline SCollisionMaterial& GetMaterial(u32 Index) { return mMaterials[Index]; }
inline CCollisionMaterial& GetMaterial(u32 Index) { return mMaterials[Index]; }
inline const CAABox& BoundingBox() const { return mAABox; }
};
#endif // CCOLLISIONMESH_H

View File

@@ -38,24 +38,74 @@ void CCollisionLoader::ParseOBBNode(IInputStream& rDCLN)
void CCollisionLoader::ReadPropertyFlags(IInputStream& rSrc)
{
SCollisionMaterial Material;
CCollisionMaterial Material;
u64 RawFlags = (mVersion <= ePrime ? rSrc.ReadLong() : rSrc.ReadLongLong());
Material.mRawFlags = RawFlags;
if (mVersion == ePrime)
if (mVersion <= ePrime)
{
Material.RawFlags = rSrc.ReadLong();
Material.FlippedTri = (Material.RawFlags >> 25) & 0x1;
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 & 0x80000000) Material |= eCF_Floor;
}
else if (mVersion == eEchoes)
else if (mVersion <= eCorruption)
{
Material.RawFlags = rSrc.ReadLongLong();
Material.FlippedTri = (Material.RawFlags >> 24) & 0x1;
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 & 0x80000000) Material |= eCF_Floor;
if (RawFlags & 0x0001000000000000) Material |= eCF_AiBlock;
if (RawFlags & 0x0400000000000000) Material |= eCF_JumpNotAllowed;
if (RawFlags & 0x2000000000000000) Material |= eCF_SpiderBall;
if (RawFlags & 0x4000000000000000) Material |= eCF_WallJump;
}
else if (mVersion == eReturns)
{
Material.RawFlags = rSrc.ReadLongLong();
Material.FlippedTri = (Material.RawFlags >> 28) & 0x1;
if (RawFlags & 0x10000000) Material |= eCF_FlippedTri;
}
mpMesh->mMaterials.push_back(Material);

View File

@@ -160,6 +160,7 @@ CResource* CScriptTemplate::FindDisplayAsset(CPropertyStruct *pProperties, u32&
for (auto it = mAssets.begin(); it != mAssets.end(); it++)
{
if (it->AssetType == SEditorAsset::eCollision) continue;
CResource *pRes = nullptr;
// File