Added experimental code for re-splitting world meshes in MP2/3/DKCR

This commit is contained in:
parax0 2016-01-14 21:15:06 -07:00
parent 29bf0234ec
commit b71e1268fa
4 changed files with 82 additions and 3 deletions

View File

@ -74,17 +74,33 @@ void CAreaLoader::ReadGeometryPrime()
mBlockMgr->ToNextBlock(); mBlockMgr->ToNextBlock();
// Geometry // Geometry
std::vector<CModel*> FileModels;
for (u32 m = 0; m < mNumMeshes; m++) { for (u32 m = 0; m < mNumMeshes; m++) {
std::cout << "\rLoading mesh " << std::dec << m + 1 << "/" << mNumMeshes; std::cout << "\rLoading mesh " << std::dec << m + 1 << "/" << mNumMeshes;
CModel *pTerrainModel = CModelLoader::LoadWorldModel(*mpMREA, *mBlockMgr, *mpArea->mMaterialSet, mVersion); CModel *pModel = CModelLoader::LoadWorldModel(*mpMREA, *mBlockMgr, *mpArea->mMaterialSet, mVersion);
mpArea->AddWorldModel(pTerrainModel); FileModels.push_back(pModel);
if (mVersion <= ePrime)
mpArea->AddWorldModel(pModel);
if (mVersion >= eEchoes) { if (mVersion >= eEchoes) {
mBlockMgr->ToNextBlock(); mBlockMgr->ToNextBlock();
mBlockMgr->ToNextBlock(); mBlockMgr->ToNextBlock();
} }
} }
// Split meshes
if (mVersion >= eEchoesDemo)
{
std::vector<CModel*> SplitModels;
CModelLoader::BuildWorldMeshes(FileModels, SplitModels, true);
for (u32 iMdl = 0; iMdl < SplitModels.size(); iMdl++)
mpArea->AddWorldModel(SplitModels[iMdl]);
}
mpArea->MergeTerrain(); mpArea->MergeTerrain();
std::cout << "\n"; std::cout << "\n";
} }

View File

@ -1,6 +1,7 @@
#include "CModelLoader.h" #include "CModelLoader.h"
#include "CMaterialLoader.h" #include "CMaterialLoader.h"
#include "Core/Log.h" #include "Core/Log.h"
#include <map>
CModelLoader::CModelLoader() CModelLoader::CModelLoader()
{ {
@ -236,7 +237,15 @@ void CModelLoader::LoadSurfaceHeaderPrime(IInputStream& Model, SSurface *pSurf)
Model.Seek(0xC, SEEK_CUR); Model.Seek(0xC, SEEK_CUR);
u32 ExtraSize = Model.ReadLong(); u32 ExtraSize = Model.ReadLong();
pSurf->ReflectionDirection = CVector3f(Model); pSurf->ReflectionDirection = CVector3f(Model);
if (mVersion >= eEchoesDemo) Model.Seek(0x4, SEEK_CUR); // Extra values in Echoes. Not sure what they are.
if (mVersion >= eEchoesDemo)
{
Model.Seek(0x2, SEEK_CUR); // Skipping unknown value
pSurf->MeshID = Model.ReadShort();
}
else
pSurf->MeshID = -1;
bool HasAABox = (ExtraSize >= 0x18); // MREAs have a set of bounding box coordinates here. bool HasAABox = (ExtraSize >= 0x18); // MREAs have a set of bounding box coordinates here.
// If this surface has a bounding box, we can just read it here. Otherwise we'll fill it in manually. // If this surface has a bounding box, we can just read it here. Otherwise we'll fill it in manually.
@ -555,6 +564,57 @@ CModel* CModelLoader::LoadCorruptionWorldModel(IInputStream &MREA, CBlockMgrIn &
return pModel; return pModel;
} }
void CModelLoader::BuildWorldMeshes(const std::vector<CModel*>& rkIn, std::vector<CModel*>& rOut, bool DeleteInputModels)
{
// This function takes the gigantic models with all surfaces combined from MP2/3/DKCR and splits the surfaces to reform the original uncombined meshes.
std::map<u32, CModel*> OutputMap;
for (u32 iMdl = 0; iMdl < rkIn.size(); iMdl++)
{
CModel *pModel = rkIn[iMdl];
pModel->mHasOwnSurfaces = false;
pModel->mHasOwnMaterials = false;
for (u32 iSurf = 0; iSurf < pModel->mSurfaces.size(); iSurf++)
{
SSurface *pSurf = pModel->mSurfaces[iSurf];
u32 ID = (u32) pSurf->MeshID;
auto Iter = OutputMap.find(ID);
// No model for this ID; create one!
if (Iter == OutputMap.end())
{
CModel *pOutMdl = new CModel();
pOutMdl->mMaterialSets.resize(1);
pOutMdl->mMaterialSets[0] = pModel->mMaterialSets[0];
pOutMdl->mHasOwnMaterials = false;
pOutMdl->mSurfaces.push_back(pSurf);
pOutMdl->mHasOwnSurfaces = true;
pOutMdl->mVertexCount = pSurf->VertexCount;
pOutMdl->mTriangleCount = pSurf->TriangleCount;
pOutMdl->mAABox.ExpandBounds(pSurf->AABox);
OutputMap[ID] = pOutMdl;
rOut.push_back(pOutMdl);
}
// Existing model; add this surface to it
else
{
CModel *pOutMdl = Iter->second;
pOutMdl->mSurfaces.push_back(pSurf);
pOutMdl->mVertexCount += pSurf->VertexCount;
pOutMdl->mTriangleCount += pSurf->TriangleCount;
pOutMdl->mAABox.ExpandBounds(pSurf->AABox);
}
}
// Done with this model, should we delete it?
if (DeleteInputModels)
delete pModel;
}
}
CModel* CModelLoader::ImportAssimpNode(const aiNode *pNode, const aiScene *pScene, CMaterialSet& matSet) CModel* CModelLoader::ImportAssimpNode(const aiNode *pNode, const aiScene *pScene, CMaterialSet& matSet)
{ {
CModelLoader loader; CModelLoader loader;

View File

@ -59,6 +59,7 @@ public:
static CModel* LoadCMDL(IInputStream& CMDL); static CModel* LoadCMDL(IInputStream& CMDL);
static CModel* LoadWorldModel(IInputStream& MREA, CBlockMgrIn& BlockMgr, CMaterialSet& MatSet, EGame Version); static CModel* LoadWorldModel(IInputStream& MREA, CBlockMgrIn& BlockMgr, CMaterialSet& MatSet, EGame Version);
static CModel* LoadCorruptionWorldModel(IInputStream& MREA, CBlockMgrIn& BlockMgr, CMaterialSet& MatSet, u32 HeaderSecNum, u32 GPUSecNum, EGame Version); static CModel* LoadCorruptionWorldModel(IInputStream& MREA, CBlockMgrIn& BlockMgr, CMaterialSet& MatSet, u32 HeaderSecNum, u32 GPUSecNum, EGame Version);
static void BuildWorldMeshes(const std::vector<CModel*>& rkIn, std::vector<CModel*>& rOut, bool DeleteInputModels);
static CModel* ImportAssimpNode(const aiNode *pNode, const aiScene *pScene, CMaterialSet& matSet); static CModel* ImportAssimpNode(const aiNode *pNode, const aiScene *pScene, CMaterialSet& matSet);
static EGame GetFormatVersion(u32 Version); static EGame GetFormatVersion(u32 Version);
}; };

View File

@ -12,6 +12,7 @@
#include <Math/CVector3f.h> #include <Math/CVector3f.h>
#include <vector> #include <vector>
// Should prolly be a class
struct SSurface struct SSurface
{ {
u32 VertexCount; u32 VertexCount;
@ -20,6 +21,7 @@ struct SSurface
CVector3f CenterPoint; CVector3f CenterPoint;
u32 MaterialID; u32 MaterialID;
CVector3f ReflectionDirection; CVector3f ReflectionDirection;
u16 MeshID;
struct SPrimitive struct SPrimitive
{ {