Added support for EGMC and a basic EGMC visualizer dialog

This commit is contained in:
parax0
2016-01-15 16:36:58 -07:00
parent b71e1268fa
commit c0b74c9883
35 changed files with 763 additions and 101 deletions

View File

@@ -182,7 +182,9 @@ HEADERS += \
Scene/FShowFlags.h \
Scene/CScene.h \
Scene/CSceneIterator.h \
Resource/CResourceInfo.h
Resource/CResourceInfo.h \
Resource/CPoiToWorld.h \
Resource/Factory/CPoiToWorldLoader.h
# Source Files
SOURCES += \
@@ -268,4 +270,6 @@ SOURCES += \
Resource/Script/IProperty.cpp \
Scene/FShowFlags.cpp \
Scene/CScene.cpp \
Scene/CSceneIterator.cpp
Scene/CSceneIterator.cpp \
Resource/CPoiToWorld.cpp \
Resource/Factory/CPoiToWorldLoader.cpp

View File

@@ -179,6 +179,11 @@ CLight* CGameArea::GetLight(u32 layer, u32 light)
return mLightLayers[layer][light];
}
CPoiToWorld* CGameArea::GetPoiToWorldMap()
{
return mpPoiToWorldMap;
}
CAABox CGameArea::AABox()
{
return mAABox;

View File

@@ -5,6 +5,7 @@
#include "CCollisionMeshGroup.h"
#include "CLight.h"
#include "CMaterialSet.h"
#include "CPoiToWorld.h"
#include "Core/Resource/Model/CModel.h"
#include "Core/Resource/Model/CStaticModel.h"
#include <Common/types.h>
@@ -40,6 +41,8 @@ class CGameArea : public CResource
CCollisionMeshGroup *mCollision;
// Lights
std::vector<std::vector<CLight*>> mLightLayers;
// Object to Static Geometry Map
TResPtr<CPoiToWorld> mpPoiToWorldMap;
public:
CGameArea();
@@ -65,6 +68,7 @@ public:
u32 GetLightLayerCount();
u32 GetLightCount(u32 layer);
CLight* GetLight(u32 layer, u32 light);
CPoiToWorld* GetPoiToWorldMap();
CAABox AABox();
};

View File

@@ -0,0 +1,27 @@
#include "CPoiToWorld.h"
CPoiToWorld::CPoiToWorld()
{
}
CPoiToWorld::~CPoiToWorld()
{
}
void CPoiToWorld::LinksForMeshID(std::list<u32>& rOutInstanceIDs, u32 MeshID)
{
for (u32 iLink = 0; iLink < mMeshLinks.size(); iLink++)
{
if (mMeshLinks[iLink].MeshID == MeshID)
rOutInstanceIDs.push_back(mMeshLinks[iLink].PoiInstanceID);
}
}
void CPoiToWorld::LinksForInstanceID(std::list<u32>& rOutMeshIDs, u32 InstanceID)
{
for (u32 iLink = 0; iLink < mMeshLinks.size(); iLink++)
{
if (mMeshLinks[iLink].PoiInstanceID == InstanceID)
rOutMeshIDs.push_back(mMeshLinks[iLink].MeshID);
}
}

View File

@@ -0,0 +1,40 @@
#ifndef CPOITOWORLD_H
#define CPOITOWORLD_H
#include "CResource.h"
#include <list>
class CPoiToWorld : public CResource
{
DECLARE_RESOURCE_TYPE(ePoiToWorld)
friend class CPoiToWorldLoader;
public:
struct SPoiMeshLink
{
u32 MeshID;
u32 PoiInstanceID;
};
private:
std::vector<SPoiMeshLink> mMeshLinks;
public:
CPoiToWorld();
~CPoiToWorld();
void LinksForMeshID(std::list<u32>& rOutInstanceIDs, u32 MeshID);
void LinksForInstanceID(std::list<u32>& rOutMeshIDs, u32 InstanceID);
inline u32 NumMeshLinks()
{
return mMeshLinks.size();
}
inline const SPoiMeshLink& MeshLinkByIndex(u32 Index)
{
return mMeshLinks[Index];
}
};
#endif // CPOITOWORLD_H

View File

@@ -4,6 +4,7 @@
#include "Core/Resource/Factory/CCollisionLoader.h"
#include "Core/Resource/Factory/CFontLoader.h"
#include "Core/Resource/Factory/CModelLoader.h"
#include "Core/Resource/Factory/CPoiToWorldLoader.h"
#include "Core/Resource/Factory/CScanLoader.h"
#include "Core/Resource/Factory/CStringLoader.h"
#include "Core/Resource/Factory/CTextureDecoder.h"
@@ -145,6 +146,7 @@ CResource* CResCache::GetResource(CUniqueID ResID, CFourCC type)
else if (type == "FONT") Res = CFontLoader::LoadFONT(mem);
else if (type == "SCAN") Res = CScanLoader::LoadSCAN(mem);
else if (type == "DCLN") Res = CCollisionLoader::LoadDCLN(mem);
else if (type == "EGMC") Res = CPoiToWorldLoader::LoadEGMC(mem);
else SupportedFormat = false;
// Log errors
@@ -197,6 +199,7 @@ CResource* CResCache::GetResource(const TString& ResPath)
else if (type == "FONT") Res = CFontLoader::LoadFONT(file);
else if (type == "SCAN") Res = CScanLoader::LoadSCAN(file);
else if (type == "DCLN") Res = CCollisionLoader::LoadDCLN(file);
else if (type == "EGMC") Res = CPoiToWorldLoader::LoadEGMC(file);
else SupportedFormat = false;
if (!Res) Res = new CResource(); // Default for unsupported formats

View File

@@ -33,18 +33,19 @@ enum EResType
eParticle = 27,
eParticleElectric = 28,
eParticleSwoosh = 29,
eProjectile = 30,
eResource = 31,
eSaveWorld = 32,
eScan = 33,
eSkeleton = 34,
eSkin = 35,
eStateMachine = 36,
eStringTable = 37,
eTexture = 38,
eTweak = 39,
eVideo = 40,
eWorld = 41
ePoiToWorld = 30,
eProjectile = 31,
eResource = 32,
eSaveWorld = 33,
eScan = 34,
eSkeleton = 35,
eSkin = 36,
eStateMachine = 37,
eStringTable = 38,
eTexture = 39,
eTweak = 40,
eVideo = 41,
eWorld = 42
};
#endif // ERESTYPE

View File

@@ -76,16 +76,25 @@ void CAreaLoader::ReadGeometryPrime()
// Geometry
std::vector<CModel*> FileModels;
for (u32 m = 0; m < mNumMeshes; m++) {
std::cout << "\rLoading mesh " << std::dec << m + 1 << "/" << mNumMeshes;
for (u32 iMesh = 0; iMesh < mNumMeshes; iMesh++)
{
CModel *pModel = CModelLoader::LoadWorldModel(*mpMREA, *mBlockMgr, *mpArea->mMaterialSet, mVersion);
FileModels.push_back(pModel);
if (mVersion <= ePrime)
mpArea->AddWorldModel(pModel);
if (mVersion >= eEchoes) {
// For Echoes+, load surface mesh IDs, then skip to the start of the next mesh
else
{
u16 NumSurfaces = mpMREA->ReadShort();
for (u32 iSurf = 0; iSurf < NumSurfaces; iSurf++)
{
mpMREA->Seek(0x2, SEEK_CUR);
pModel->GetSurface(iSurf)->MeshID = mpMREA->ReadShort();
}
mBlockMgr->ToNextBlock();
mBlockMgr->ToNextBlock();
}
@@ -102,7 +111,6 @@ void CAreaLoader::ReadGeometryPrime()
}
mpArea->MergeTerrain();
std::cout << "\n";
}
void CAreaLoader::ReadSCLYPrime()
@@ -341,22 +349,36 @@ void CAreaLoader::ReadGeometryCorruption()
mBlockMgr->ToNextBlock();
// Geometry
std::vector<CModel*> FileModels;
u32 CurWOBJSection = 1;
u32 CurGPUSection = mGPUBlockNum;
for (u32 iMesh = 0; iMesh < mNumMeshes; iMesh++)
{
std::cout << "\rLoading mesh " << std::dec << iMesh + 1 << "/" << mNumMeshes;
CModel *pWorldModel = CModelLoader::LoadCorruptionWorldModel(*mpMREA, *mBlockMgr, *mpArea->mMaterialSet, CurWOBJSection, CurGPUSection, mVersion);
mpArea->AddWorldModel(pWorldModel);
FileModels.push_back(pWorldModel);
CurWOBJSection += 4;
CurGPUSection = mBlockMgr->CurrentBlock();
// Load surface mesh IDs
mBlockMgr->ToBlock(CurWOBJSection - 2);
u16 NumSurfaces = mpMREA->ReadShort();
for (u32 iSurf = 0; iSurf < NumSurfaces; iSurf++)
{
mpMREA->Seek(0x2, SEEK_CUR);
pWorldModel->GetSurface(iSurf)->MeshID = mpMREA->ReadShort();
}
}
std::vector<CModel*> SplitModels;
CModelLoader::BuildWorldMeshes(FileModels, SplitModels, true);
for (u32 iMdl = 0; iMdl < SplitModels.size(); iMdl++)
mpArea->AddWorldModel(SplitModels[iMdl]);
mpArea->MergeTerrain();
std::cout << "\n";
}
void CAreaLoader::ReadLightsCorruption()
@@ -511,6 +533,14 @@ void CAreaLoader::ReadCollision()
mpArea->mCollision = CCollisionLoader::LoadAreaCollision(*mpMREA);
}
void CAreaLoader::ReadEGMC()
{
Log::FileWrite(mpMREA->GetSourceString(), "Reading EGMC");
mBlockMgr->ToBlock(mEGMCBlockNum);
CUniqueID EGMC(*mpMREA, (mVersion <= eEchoes ? e32Bit : e64Bit));
mpArea->mpPoiToWorldMap = gResCache.GetResource(EGMC, "EGMC");
}
void CAreaLoader::SetUpObjects()
{
// Iterate over all objects
@@ -598,6 +628,7 @@ CGameArea* CAreaLoader::LoadMREA(IInputStream& MREA)
Loader.ReadSCLYPrime();
Loader.ReadCollision();
Loader.ReadLightsPrime();
Loader.ReadEGMC();
break;
case eEchoes:
Loader.ReadHeaderEchoes();
@@ -605,6 +636,7 @@ CGameArea* CAreaLoader::LoadMREA(IInputStream& MREA)
Loader.ReadSCLYEchoes();
Loader.ReadCollision();
Loader.ReadLightsPrime();
Loader.ReadEGMC();
break;
case eCorruptionProto:
Loader.ReadHeaderCorruption();
@@ -612,6 +644,7 @@ CGameArea* CAreaLoader::LoadMREA(IInputStream& MREA)
Loader.ReadSCLYEchoes();
Loader.ReadCollision();
Loader.ReadLightsCorruption();
Loader.ReadEGMC();
break;
case eCorruption:
case eReturns:
@@ -619,7 +652,11 @@ CGameArea* CAreaLoader::LoadMREA(IInputStream& MREA)
Loader.ReadGeometryCorruption();
Loader.ReadSCLYEchoes();
Loader.ReadCollision();
if (Loader.mVersion == eCorruption) Loader.ReadLightsCorruption();
if (Loader.mVersion == eCorruption)
{
Loader.ReadLightsCorruption();
Loader.ReadEGMC();
}
break;
default:
Log::FileError(MREA.GetSourceString(), "Unsupported MREA version: " + TString::HexString(version));

View File

@@ -75,6 +75,7 @@ class CAreaLoader
void ReadCompressedBlocks();
void Decompress();
void ReadCollision();
void ReadEGMC();
void SetUpObjects();
public:

View File

@@ -0,0 +1,17 @@
#include "CPoiToWorldLoader.h"
CPoiToWorld* CPoiToWorldLoader::LoadEGMC(IInputStream& rEGMC)
{
CPoiToWorld *pOut = new CPoiToWorld();
u32 NumLinks = rEGMC.ReadLong();
for (u32 iLink = 0; iLink < NumLinks; iLink++)
{
CPoiToWorld::SPoiMeshLink Link;
Link.MeshID = rEGMC.ReadLong();
Link.PoiInstanceID = rEGMC.ReadLong();
pOut->mMeshLinks.push_back(Link);
}
return pOut;
}

View File

@@ -0,0 +1,17 @@
#ifndef CPOITOWORLDLOADER_H
#define CPOITOWORLDLOADER_H
#include "Core/Resource/CPoiToWorld.h"
#include "Core/Resource/TResPtr.h"
class CPoiToWorldLoader
{
TResPtr<CPoiToWorld> mpPoiToWorld;
CPoiToWorldLoader() {}
public:
static CPoiToWorld* LoadEGMC(IInputStream& rEGMC);
};
#endif // CPOITOWORLDLOADER_H

View File

@@ -10,6 +10,7 @@ CModelNode::CModelNode(CScene *pScene, CSceneNode *pParent, CModel *pModel) : CS
mScale = CVector3f(1.f);
mLightingEnabled = true;
mForceAlphaOn = false;
mTintColor = CColor::skWhite;
}
ENodeType CModelNode::NodeType()
@@ -103,6 +104,11 @@ SRayIntersection CModelNode::RayNodeIntersectTest(const CRay &Ray, u32 AssetID,
return out;
}
CColor CModelNode::TintColor(const SViewInfo& /*rkViewInfo*/) const
{
return mTintColor;
}
void CModelNode::SetModel(CModel *pModel)
{
mpModel = pModel;
@@ -116,8 +122,3 @@ void CModelNode::SetModel(CModel *pModel)
MarkTransformChanged();
}
void CModelNode::ForceAlphaEnabled(bool Enable)
{
mForceAlphaOn = Enable;
}

View File

@@ -10,6 +10,7 @@ class CModelNode : public CSceneNode
u32 mActiveMatSet;
bool mLightingEnabled;
bool mForceAlphaOn;
CColor mTintColor;
public:
explicit CModelNode(CScene *pScene, CSceneNode *pParent = 0, CModel *pModel = 0);
@@ -20,41 +21,20 @@ public:
virtual void DrawSelection();
virtual void RayAABoxIntersectTest(CRayCollisionTester& Tester, const SViewInfo& ViewInfo);
virtual SRayIntersection RayNodeIntersectTest(const CRay &Ray, u32 AssetID, const SViewInfo& ViewInfo);
virtual CColor TintColor(const SViewInfo& rkViewInfo) const;
// Setters
void SetModel(CModel *pModel);
void SetMatSet(u32 MatSet);
void SetDynamicLighting(bool Enable);
void ForceAlphaEnabled(bool Enable);
CModel* Model();
u32 MatSet();
bool IsDynamicLightingEnabled();
inline void SetMatSet(u32 MatSet) { mActiveMatSet = MatSet; }
inline void SetDynamicLighting(bool Enable) { mLightingEnabled = Enable; }
inline void ForceAlphaEnabled(bool Enable) { mForceAlphaOn = Enable; }
inline void SetTintColor(const CColor& rkTintColor) { mTintColor = rkTintColor; }
inline void ClearTintColor() { mTintColor = CColor::skWhite; }
inline CModel* Model() const { return mpModel; }
inline u32 MatSet() const { return mActiveMatSet; }
inline bool IsDynamicLightingEnabled() const { return mLightingEnabled; }
inline u32 FindMeshID() const { return mpModel->GetSurface(0)->MeshID; }
};
// ************ INLINE FUNCTIONS ************
inline void CModelNode::SetMatSet(u32 MatSet)
{
mActiveMatSet = MatSet;
}
inline void CModelNode::SetDynamicLighting(bool Enable)
{
mLightingEnabled = Enable;
}
inline CModel* CModelNode::Model()
{
return mpModel;
}
inline u32 CModelNode::MatSet()
{
return mActiveMatSet;
}
inline bool CModelNode::IsDynamicLightingEnabled()
{
return mLightingEnabled;
}
#endif // CMODELNODE_H

View File

@@ -1,6 +1,7 @@
#include "CScene.h"
#include "Core/Render/CGraphics.h"
#include "Core/Resource/CResCache.h"
#include "Core/Resource/CPoiToWorld.h"
#include "Core/Resource/Script/CScriptLayer.h"
#include "Core/CRayCollisionTester.h"
@@ -88,23 +89,24 @@ void CScene::SetActiveArea(CGameArea *pArea)
mpArea = pArea;
mpAreaRootNode = new CRootNode(this, mpSceneRootNode);
if (mSplitTerrain)
{
u32 Count = mpArea->GetStaticModelCount();
// Create static nodes
u32 Count = mpArea->GetStaticModelCount();
for (u32 iMdl = 0; iMdl < Count; iMdl++)
CreateStaticNode(mpArea->GetStaticModel(iMdl));
for (u32 iMdl = 0; iMdl < Count; iMdl++)
{
CStaticNode *pNode = CreateStaticNode(mpArea->GetStaticModel(iMdl));
pNode->SetName("Static World Model " + TString::FromInt32(iMdl, 0, 10));
}
else
{
u32 Count = mpArea->GetTerrainModelCount();
for (u32 iMdl = 0; iMdl < Count; iMdl++)
{
CModel *pModel = mpArea->GetTerrainModel(iMdl);
CModelNode *pNode = CreateModelNode(pModel);
pNode->SetDynamicLighting(false);
}
// Create model nodes
Count = mpArea->GetTerrainModelCount();
for (u32 iMdl = 0; iMdl < Count; iMdl++)
{
CModel *pModel = mpArea->GetTerrainModel(iMdl);
CModelNode *pNode = CreateModelNode(pModel);
pNode->SetName("World Model " + TString::FromInt32(iMdl, 0, 10));
pNode->SetDynamicLighting(false);
}
CreateCollisionNode(mpArea->GetCollision());
@@ -298,7 +300,8 @@ CGameArea* CScene::GetActiveArea()
FShowFlags CScene::ShowFlagsForNodeFlags(FNodeFlags NodeFlags)
{
FShowFlags Out;
if (NodeFlags & eStaticNode) Out |= eShowWorld;
if (NodeFlags & eModelNode) Out |= eShowSplitWorld;
if (NodeFlags & eStaticNode) Out |= eShowMergedWorld;
if (NodeFlags & eScriptNode) Out |= eShowObjects;
if (NodeFlags & eCollisionNode) Out |= eShowWorldCollision;
if (NodeFlags & eLightNode) Out |= eShowLights;
@@ -307,8 +310,9 @@ FShowFlags CScene::ShowFlagsForNodeFlags(FNodeFlags NodeFlags)
FNodeFlags CScene::NodeFlagsForShowFlags(FShowFlags ShowFlags)
{
FNodeFlags Out = eRootNode | eModelNode;
if (ShowFlags & eShowWorld) Out |= eStaticNode;
FNodeFlags Out = eRootNode;
if (ShowFlags & eShowSplitWorld) Out |= eModelNode;
if (ShowFlags & eShowMergedWorld) Out |= eStaticNode;
if (ShowFlags & eShowWorldCollision) Out |= eCollisionNode;
if (ShowFlags & eShowObjects) Out |= eScriptNode | eScriptExtraNode;
if (ShowFlags & eShowLights) Out |= eLightNode;

View File

@@ -458,6 +458,11 @@ CScriptTemplate* CScriptNode::Template() const
return mpInstance->Template();
}
CScriptExtra* CScriptNode::Extra() const
{
return mpExtra;
}
CModel* CScriptNode::ActiveModel() const
{
return mpActiveModel;

View File

@@ -7,10 +7,12 @@
#include "Core/Resource/Script/CScriptObject.h"
#include "Core/CLightParameters.h"
class CScriptExtra;
class CScriptNode : public CSceneNode
{
CScriptObject *mpInstance;
class CScriptExtra *mpExtra;
CScriptExtra *mpExtra;
TResPtr<CModel> mpActiveModel;
TResPtr<CTexture> mpBillboard;
@@ -39,6 +41,7 @@ public:
void GeneratePosition();
CScriptObject* Object() const;
CScriptTemplate* Template() const;
CScriptExtra* Extra() const;
CModel* ActiveModel() const;
bool UsesModel() const;
bool HasPreviewVolume() const;

View File

@@ -1,3 +1,3 @@
#include "FShowFlags.h"
const FShowFlags gkGameModeShowFlags = eShowWorld | eShowObjectGeometry | eShowSky;
const FShowFlags gkGameModeShowFlags = eShowMergedWorld | eShowObjectGeometry | eShowSky;

View File

@@ -6,14 +6,15 @@
enum EShowFlag
{
eShowNone = 0x00,
eShowWorld = 0x01,
eShowWorldCollision = 0x02,
eShowObjectGeometry = 0x04,
eShowObjectCollision = 0x08,
eShowObjects = 0x0C,
eShowLights = 0x10,
eShowSky = 0x20,
eShowAll = 0x3F
eShowSplitWorld = 0x01,
eShowMergedWorld = 0x02,
eShowWorldCollision = 0x04,
eShowObjectGeometry = 0x08,
eShowObjectCollision = 0x10,
eShowObjects = 0x18,
eShowLights = 0x20,
eShowSky = 0x40,
eShowAll = 0x7F
};
DECLARE_FLAGS(EShowFlag, FShowFlags)

View File

@@ -15,6 +15,7 @@ public:
explicit CPointOfInterestExtra(CScriptObject *pInstance, CScene *pScene, CSceneNode *pParent = 0);
void PropertyModified(IProperty* pProperty);
void ModifyTintColor(CColor& Color);
CScan* GetScan() const { return mpScanData; }
static const CColor skRegularColor;
static const CColor skImportantColor;