Implemented area cooker, added the ability to resave Prime 1 MREAs from the World Editor
This commit is contained in:
parent
7a28db3d40
commit
e430cbfb73
|
@ -94,7 +94,6 @@ HEADERS += \
|
|||
Resource/Cooker/CWorldCooker.h \
|
||||
Resource/Factory/CAnimSetLoader.h \
|
||||
Resource/Factory/CAreaLoader.h \
|
||||
Resource/Factory/CBlockMgrIn.h \
|
||||
Resource/Factory/CCollisionLoader.h \
|
||||
Resource/Factory/CFontLoader.h \
|
||||
Resource/Factory/CMaterialLoader.h \
|
||||
|
@ -185,7 +184,9 @@ HEADERS += \
|
|||
Resource/CResourceInfo.h \
|
||||
Resource/CPoiToWorld.h \
|
||||
Resource/Factory/CPoiToWorldLoader.h \
|
||||
Resource/Cooker/CPoiToWorldCooker.h
|
||||
Resource/Cooker/CPoiToWorldCooker.h \
|
||||
Resource/Factory/CSectionMgrIn.h \
|
||||
Resource/Cooker/CScriptCooker.h
|
||||
|
||||
# Source Files
|
||||
SOURCES += \
|
||||
|
@ -202,7 +203,6 @@ SOURCES += \
|
|||
Resource/Cooker/CWorldCooker.cpp \
|
||||
Resource/Factory/CAnimSetLoader.cpp \
|
||||
Resource/Factory/CAreaLoader.cpp \
|
||||
Resource/Factory/CBlockMgr.cpp \
|
||||
Resource/Factory/CCollisionLoader.cpp \
|
||||
Resource/Factory/CFontLoader.cpp \
|
||||
Resource/Factory/CMaterialLoader.cpp \
|
||||
|
@ -274,4 +274,5 @@ SOURCES += \
|
|||
Scene/CSceneIterator.cpp \
|
||||
Resource/CPoiToWorld.cpp \
|
||||
Resource/Factory/CPoiToWorldLoader.cpp \
|
||||
Resource/Cooker/CPoiToWorldCooker.cpp
|
||||
Resource/Cooker/CPoiToWorldCooker.cpp \
|
||||
Resource/Cooker/CScriptCooker.cpp
|
||||
|
|
|
@ -70,6 +70,25 @@ CAnimationParameters::CAnimationParameters(IInputStream& SCLY, EGame Game)
|
|||
}
|
||||
}
|
||||
|
||||
void CAnimationParameters::Write(IOutputStream& rSCLY)
|
||||
{
|
||||
if (mGame <= eEchoes)
|
||||
{
|
||||
if (mpCharSet)
|
||||
{
|
||||
rSCLY.WriteLong(AnimSet()->ResID().ToLong());
|
||||
rSCLY.WriteLong(mNodeIndex);
|
||||
rSCLY.WriteLong(mUnknown1);
|
||||
}
|
||||
else
|
||||
{
|
||||
rSCLY.WriteLong(0xFFFFFFFF);
|
||||
rSCLY.WriteLong(0);
|
||||
rSCLY.WriteLong(0xFFFFFFFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CModel* CAnimationParameters::GetCurrentModel(s32 NodeIndex /*= -1*/)
|
||||
{
|
||||
if (!mpCharSet) return nullptr;
|
||||
|
|
|
@ -20,6 +20,8 @@ class CAnimationParameters
|
|||
public:
|
||||
CAnimationParameters();
|
||||
CAnimationParameters(IInputStream& SCLY, EGame Game);
|
||||
void Write(IOutputStream& rSCLY);
|
||||
|
||||
CModel* GetCurrentModel(s32 NodeIndex = -1);
|
||||
TString GetCurrentCharacterName(s32 NodeIndex = -1);
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ class CGameArea : public CResource
|
|||
{
|
||||
DECLARE_RESOURCE_TYPE(eArea)
|
||||
friend class CAreaLoader;
|
||||
friend class CAreaCooker;
|
||||
|
||||
EGame mVersion;
|
||||
u32 mVertexCount;
|
||||
|
@ -28,9 +29,11 @@ class CGameArea : public CResource
|
|||
CTransform4f mTransform;
|
||||
CAABox mAABox;
|
||||
|
||||
// Section data buffers; this is used to avoid having to regenerate the entire contents of the file on cook
|
||||
std::vector<std::vector<u8>> mSectionDataBuffers;
|
||||
// Geometry
|
||||
CMaterialSet *mMaterialSet;
|
||||
std::vector<CModel*> mTerrainModels; // TerrainModels is the original version of each model; this is used by the editor (bounding box checks, material editing, etc)
|
||||
std::vector<CModel*> mTerrainModels; // TerrainModels is the original version of each model; this is currently mainly used in the POI map editor
|
||||
std::vector<CStaticModel*> mStaticTerrainModels; // StaticTerrainModels is the merged terrain for faster rendering in the world editor
|
||||
// Script
|
||||
std::vector<CScriptLayer*> mScriptLayers;
|
||||
|
|
|
@ -1,9 +1,135 @@
|
|||
#include "CAreaCooker.h"
|
||||
#include "CScriptCooker.h"
|
||||
#include <Core/Log.h>
|
||||
|
||||
CAreaCooker::CAreaCooker()
|
||||
{
|
||||
}
|
||||
|
||||
void CAreaCooker::DetermineSectionNumbers()
|
||||
{
|
||||
mGeometrySecNum = 0;
|
||||
|
||||
// Determine how many sections are taken up by geometry...
|
||||
u32 GeometrySections = 1; // Starting at 1 to account for materials
|
||||
|
||||
// Each world mesh has (7 + surface count) sections
|
||||
// header, verts, normals, colors, float UVs, short UVs, surface offsets + surfaces
|
||||
for (u32 iMesh = 0; iMesh < mpArea->mTerrainModels.size(); iMesh++)
|
||||
{
|
||||
CModel *pModel = mpArea->mTerrainModels[iMesh];
|
||||
GeometrySections += (7 + pModel->GetSurfaceCount());
|
||||
}
|
||||
|
||||
// Set section numbers
|
||||
mArotSecNum = mGeometrySecNum + GeometrySections;
|
||||
mSclySecNum = mArotSecNum + 1;
|
||||
mCollisionSecNum = mSclySecNum + 1;
|
||||
mUnknownSecNum = mCollisionSecNum + 1;
|
||||
mLightsSecNum = mUnknownSecNum + 1;
|
||||
mVisiSecNum = mLightsSecNum + 1;
|
||||
mPathSecNum = mVisiSecNum + 1;
|
||||
}
|
||||
|
||||
void CAreaCooker::WritePrimeHeader(IOutputStream& rOut)
|
||||
{
|
||||
rOut.WriteLong(0xDEADBEEF);
|
||||
rOut.WriteLong(GetMREAVersion(mVersion));
|
||||
mpArea->mTransform.Write(rOut);
|
||||
rOut.WriteLong(mpArea->mTerrainModels.size());
|
||||
rOut.WriteLong(mpArea->mSectionDataBuffers.size());
|
||||
|
||||
rOut.WriteLong(mGeometrySecNum);
|
||||
rOut.WriteLong(mSclySecNum);
|
||||
rOut.WriteLong(mCollisionSecNum);
|
||||
rOut.WriteLong(mUnknownSecNum);
|
||||
rOut.WriteLong(mLightsSecNum);
|
||||
rOut.WriteLong(mVisiSecNum);
|
||||
rOut.WriteLong(mPathSecNum);
|
||||
rOut.WriteLong(mArotSecNum);
|
||||
|
||||
mSectionSizesOffset = rOut.Tell();
|
||||
for (u32 iSec = 0; iSec < mpArea->mSectionDataBuffers.size(); iSec++)
|
||||
rOut.WriteLong(0);
|
||||
|
||||
rOut.WriteToBoundary(32, 0);
|
||||
|
||||
mSectionMgr.SetSectionCount(mpArea->mSectionDataBuffers.size());
|
||||
mSectionMgr.Init(rOut);
|
||||
}
|
||||
|
||||
void CAreaCooker::WritePrimeSCLY(IOutputStream& rOut)
|
||||
{
|
||||
u32 NumLayers = mpArea->mScriptLayers.size();
|
||||
rOut.WriteString("SCLY", 4);
|
||||
rOut.WriteLong(0x1); // Unknown value, but it's always 1
|
||||
rOut.WriteLong(NumLayers);
|
||||
|
||||
u32 LayerSizesStart = rOut.Tell();
|
||||
for (u32 iLyr = 0; iLyr < NumLayers; iLyr++)
|
||||
rOut.WriteLong(0);
|
||||
|
||||
std::vector<u32> LayerSizes(NumLayers);
|
||||
|
||||
for (u32 iLyr = 0; iLyr < mpArea->mScriptLayers.size(); iLyr++)
|
||||
{
|
||||
u32 LayerStart = rOut.Tell();
|
||||
CScriptCooker::WriteLayer(mpArea->Version(), mpArea->mScriptLayers[iLyr], rOut);
|
||||
LayerSizes[iLyr] = rOut.Tell() - LayerStart;
|
||||
}
|
||||
|
||||
u32 LayersEnd = rOut.Tell();
|
||||
rOut.Seek(LayerSizesStart, SEEK_SET);
|
||||
|
||||
for (u32 iLyr = 0; iLyr < NumLayers; iLyr++)
|
||||
rOut.WriteLong(LayerSizes[iLyr]);
|
||||
|
||||
rOut.Seek(LayersEnd, SEEK_SET);
|
||||
rOut.WriteToBoundary(32, 0);
|
||||
}
|
||||
|
||||
// ************ STATIC ************
|
||||
void CAreaCooker::WriteCookedArea(CGameArea *pArea, IOutputStream& rOut)
|
||||
{
|
||||
CAreaCooker Cooker;
|
||||
Cooker.mpArea = pArea;
|
||||
Cooker.mVersion = pArea->Version();
|
||||
|
||||
if (Cooker.mVersion > ePrime)
|
||||
{
|
||||
Log::Error("Area cooking is not supported for games other than Metroid Prime");
|
||||
return;
|
||||
}
|
||||
|
||||
// Write header
|
||||
Cooker.DetermineSectionNumbers();
|
||||
Cooker.WritePrimeHeader(rOut);
|
||||
|
||||
// Write pre-SCLY data sections
|
||||
for (u32 iSec = 0; iSec < Cooker.mSclySecNum; iSec++)
|
||||
{
|
||||
rOut.WriteBytes(pArea->mSectionDataBuffers[iSec].data(), pArea->mSectionDataBuffers[iSec].size());
|
||||
Cooker.mSectionMgr.AddSize(rOut);
|
||||
}
|
||||
|
||||
// Write SCLY
|
||||
Cooker.WritePrimeSCLY(rOut);
|
||||
Cooker.mSectionMgr.AddSize(rOut);
|
||||
|
||||
// Write post-SCLY data sections
|
||||
for (u32 iSec = Cooker.mSclySecNum + 1; iSec < pArea->mSectionDataBuffers.size(); iSec++)
|
||||
{
|
||||
rOut.WriteBytes(pArea->mSectionDataBuffers[iSec].data(), pArea->mSectionDataBuffers[iSec].size());
|
||||
Cooker.mSectionMgr.AddSize(rOut);
|
||||
}
|
||||
|
||||
// Write section sizes
|
||||
u32 AreaEnd = rOut.Tell();
|
||||
rOut.Seek(Cooker.mSectionSizesOffset, SEEK_SET);
|
||||
Cooker.mSectionMgr.WriteSizes(rOut);
|
||||
rOut.Seek(AreaEnd, SEEK_SET);
|
||||
}
|
||||
|
||||
u32 CAreaCooker::GetMREAVersion(EGame version)
|
||||
{
|
||||
switch (version)
|
||||
|
|
|
@ -1,13 +1,35 @@
|
|||
#ifndef CAREACOOKER_H
|
||||
#define CAREACOOKER_H
|
||||
|
||||
#include "CSectionMgrOut.h"
|
||||
#include "Core/Resource/CGameArea.h"
|
||||
#include "Core/Resource/EGame.h"
|
||||
#include <Common/types.h>
|
||||
#include <FileIO/FileIO.h>
|
||||
|
||||
class CAreaCooker
|
||||
{
|
||||
TResPtr<CGameArea> mpArea;
|
||||
EGame mVersion;
|
||||
|
||||
CSectionMgrOut mSectionMgr;
|
||||
u32 mSectionSizesOffset;
|
||||
|
||||
u32 mGeometrySecNum;
|
||||
u32 mSclySecNum;
|
||||
u32 mCollisionSecNum;
|
||||
u32 mUnknownSecNum;
|
||||
u32 mLightsSecNum;
|
||||
u32 mVisiSecNum;
|
||||
u32 mPathSecNum;
|
||||
u32 mArotSecNum;
|
||||
|
||||
CAreaCooker();
|
||||
void DetermineSectionNumbers();
|
||||
void WritePrimeHeader(IOutputStream& rOut);
|
||||
void WritePrimeSCLY(IOutputStream& rOut);
|
||||
|
||||
public:
|
||||
static void WriteCookedArea(CGameArea *pArea, IOutputStream& rOut);
|
||||
static u32 GetMREAVersion(EGame version);
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,170 @@
|
|||
#include "CScriptCooker.h"
|
||||
|
||||
void CScriptCooker::WriteProperty(IProperty *pProp)
|
||||
{
|
||||
switch (pProp->Type())
|
||||
{
|
||||
|
||||
case eBoolProperty:
|
||||
{
|
||||
TBoolProperty *pBoolCast = static_cast<TBoolProperty*>(pProp);
|
||||
mpSCLY->WriteByte(pBoolCast->Get() ? 1 : 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case eByteProperty:
|
||||
{
|
||||
TByteProperty *pByteCast = static_cast<TByteProperty*>(pProp);
|
||||
mpSCLY->WriteByte(pByteCast->Get());
|
||||
break;
|
||||
}
|
||||
|
||||
case eShortProperty:
|
||||
{
|
||||
TShortProperty *pShortCast = static_cast<TShortProperty*>(pProp);
|
||||
mpSCLY->WriteShort(pShortCast->Get());
|
||||
break;
|
||||
}
|
||||
|
||||
case eLongProperty:
|
||||
{
|
||||
TLongProperty *pLongCast = static_cast<TLongProperty*>(pProp);
|
||||
mpSCLY->WriteLong(pLongCast->Get());
|
||||
break;
|
||||
}
|
||||
|
||||
case eEnumProperty:
|
||||
{
|
||||
TEnumProperty *pEnumCast = static_cast<TEnumProperty*>(pProp);
|
||||
CEnumTemplate *pEnumTemp = static_cast<CEnumTemplate*>(pEnumCast->Template());
|
||||
u32 ID = pEnumTemp->EnumeratorID(pEnumCast->Get());
|
||||
mpSCLY->WriteLong(ID);
|
||||
break;
|
||||
}
|
||||
|
||||
case eBitfieldProperty:
|
||||
{
|
||||
TBitfieldProperty *pBitfieldCast = static_cast<TBitfieldProperty*>(pProp);
|
||||
mpSCLY->WriteLong(pBitfieldCast->Get());
|
||||
break;
|
||||
}
|
||||
|
||||
case eFloatProperty:
|
||||
{
|
||||
TFloatProperty *pFloatCast = static_cast<TFloatProperty*>(pProp);
|
||||
mpSCLY->WriteFloat(pFloatCast->Get());
|
||||
break;
|
||||
}
|
||||
|
||||
case eStringProperty:
|
||||
{
|
||||
TStringProperty *pStringCast = static_cast<TStringProperty*>(pProp);
|
||||
mpSCLY->WriteString(pStringCast->Get().ToStdString());
|
||||
break;
|
||||
}
|
||||
|
||||
case eVector3Property:
|
||||
{
|
||||
TVector3Property *pVectorCast = static_cast<TVector3Property*>(pProp);
|
||||
pVectorCast->Get().Write(*mpSCLY);
|
||||
break;
|
||||
}
|
||||
|
||||
case eColorProperty:
|
||||
{
|
||||
TColorProperty *pColorCast = static_cast<TColorProperty*>(pProp);
|
||||
pColorCast->Get().Write(*mpSCLY, false);
|
||||
break;
|
||||
}
|
||||
|
||||
case eFileProperty:
|
||||
{
|
||||
TFileProperty *pFileCast = static_cast<TFileProperty*>(pProp);
|
||||
if (mVersion <= eEchoes)
|
||||
mpSCLY->WriteLong(pFileCast->Get().ID().ToLong());
|
||||
else
|
||||
mpSCLY->WriteLongLong(pFileCast->Get().ID().ToLongLong());
|
||||
break;
|
||||
}
|
||||
|
||||
case eCharacterProperty:
|
||||
{
|
||||
TCharacterProperty *pCharCast = static_cast<TCharacterProperty*>(pProp);
|
||||
pCharCast->Get().Write(*mpSCLY);
|
||||
break;
|
||||
}
|
||||
|
||||
case eStructProperty:
|
||||
case eArrayProperty:
|
||||
{
|
||||
CPropertyStruct *pStruct = static_cast<CPropertyStruct*>(pProp);
|
||||
CStructTemplate *pTemp = static_cast<CStructTemplate*>(pStruct->Template());
|
||||
|
||||
if (!pTemp->IsSingleProperty() || pProp->Type() == eArrayProperty)
|
||||
mpSCLY->WriteLong(pStruct->Count());
|
||||
|
||||
for (u32 iProp = 0; iProp < pStruct->Count(); iProp++)
|
||||
WriteProperty(pStruct->PropertyByIndex(iProp));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void CScriptCooker::WriteLayerMP1(CScriptLayer *pLayer)
|
||||
{
|
||||
u32 LayerStart = mpSCLY->Tell();
|
||||
mpSCLY->WriteByte(0); // Unknown value
|
||||
mpSCLY->WriteLong(pLayer->GetNumObjects());
|
||||
|
||||
for (u32 iInst = 0; iInst < pLayer->GetNumObjects(); iInst++)
|
||||
{
|
||||
CScriptObject *pInstance = pLayer->ObjectByIndex(iInst);
|
||||
WriteInstanceMP1(pInstance);
|
||||
}
|
||||
|
||||
u32 LayerSize = mpSCLY->Tell() - LayerStart;
|
||||
u32 NumPadBytes = 32 - (LayerSize % 32);
|
||||
if (NumPadBytes == 32) NumPadBytes = 0;
|
||||
|
||||
for (u32 iPad = 0; iPad < NumPadBytes; iPad++)
|
||||
mpSCLY->WriteByte(0);
|
||||
}
|
||||
|
||||
void CScriptCooker::WriteInstanceMP1(CScriptObject *pInstance)
|
||||
{
|
||||
mpSCLY->WriteByte((u8) pInstance->ObjectTypeID());
|
||||
|
||||
u32 SizeOffset = mpSCLY->Tell();
|
||||
mpSCLY->WriteLong(0);
|
||||
u32 InstanceStart = mpSCLY->Tell();
|
||||
|
||||
mpSCLY->WriteLong(pInstance->InstanceID());
|
||||
mpSCLY->WriteLong(pInstance->NumOutLinks());
|
||||
|
||||
for (u32 iLink = 0; iLink < pInstance->NumOutLinks(); iLink++)
|
||||
{
|
||||
const SLink& rkLink = pInstance->OutLink(iLink);
|
||||
mpSCLY->WriteLong(rkLink.State);
|
||||
mpSCLY->WriteLong(rkLink.Message);
|
||||
mpSCLY->WriteLong(rkLink.ObjectID);
|
||||
}
|
||||
|
||||
WriteProperty(pInstance->Properties());
|
||||
u32 InstanceEnd = mpSCLY->Tell();
|
||||
u32 InstanceSize = InstanceEnd - InstanceStart;
|
||||
|
||||
mpSCLY->Seek(SizeOffset, SEEK_SET);
|
||||
mpSCLY->WriteLong(InstanceSize);
|
||||
mpSCLY->Seek(InstanceEnd, SEEK_SET);
|
||||
}
|
||||
|
||||
// ************ STATIC ************
|
||||
void CScriptCooker::WriteLayer(EGame Game, CScriptLayer *pLayer, IOutputStream& rOut)
|
||||
{
|
||||
CScriptCooker Cooker;
|
||||
Cooker.mpSCLY = &rOut;
|
||||
Cooker.mVersion = Game;
|
||||
Cooker.WriteLayerMP1(pLayer);
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
#ifndef CSCRIPTCOOKER_H
|
||||
#define CSCRIPTCOOKER_H
|
||||
|
||||
#include "Core/Resource/EGame.h"
|
||||
#include "Core/Resource/Script/CScriptLayer.h"
|
||||
#include "Core/Resource/Script/CScriptObject.h"
|
||||
#include <FileIO/FileIO.h>
|
||||
|
||||
class CScriptCooker
|
||||
{
|
||||
IOutputStream *mpSCLY;
|
||||
EGame mVersion;
|
||||
|
||||
CScriptCooker() {}
|
||||
void WriteProperty(IProperty *pProp);
|
||||
void WriteLayerMP1(CScriptLayer *pLayer);
|
||||
void WriteInstanceMP1(CScriptObject *pInstance);
|
||||
|
||||
public:
|
||||
static void WriteLayer(EGame Game, CScriptLayer *pLayer, IOutputStream& rOut);
|
||||
};
|
||||
|
||||
#endif // CSCRIPTCOOKER_H
|
|
@ -59,26 +59,27 @@ void CAreaLoader::ReadHeaderPrime()
|
|||
mPathBlockNum = mpMREA->ReadLong();
|
||||
mOctreeBlockNum = mpMREA->ReadLong();
|
||||
|
||||
mBlockMgr = new CBlockMgrIn(mNumBlocks, mpMREA);
|
||||
mpSectionMgr = new CSectionMgrIn(mNumBlocks, mpMREA);
|
||||
mpMREA->SeekToBoundary(32);
|
||||
mBlockMgr->Init();
|
||||
mpSectionMgr->Init();
|
||||
LoadSectionDataBuffers();
|
||||
}
|
||||
|
||||
void CAreaLoader::ReadGeometryPrime()
|
||||
{
|
||||
Log::FileWrite(mpMREA->GetSourceString(), "Reading MREA world geometry (MP1/MP2)");
|
||||
mBlockMgr->ToBlock(mGeometryBlockNum);
|
||||
mpSectionMgr->ToSection(mGeometryBlockNum);
|
||||
|
||||
// Materials
|
||||
mpArea->mMaterialSet = CMaterialLoader::LoadMaterialSet(*mpMREA, mVersion);
|
||||
mBlockMgr->ToNextBlock();
|
||||
mpSectionMgr->ToNextSection();
|
||||
|
||||
// Geometry
|
||||
std::vector<CModel*> FileModels;
|
||||
|
||||
for (u32 iMesh = 0; iMesh < mNumMeshes; iMesh++)
|
||||
{
|
||||
CModel *pModel = CModelLoader::LoadWorldModel(*mpMREA, *mBlockMgr, *mpArea->mMaterialSet, mVersion);
|
||||
CModel *pModel = CModelLoader::LoadWorldModel(*mpMREA, *mpSectionMgr, *mpArea->mMaterialSet, mVersion);
|
||||
FileModels.push_back(pModel);
|
||||
|
||||
if (mVersion <= ePrime)
|
||||
|
@ -95,8 +96,8 @@ void CAreaLoader::ReadGeometryPrime()
|
|||
pModel->GetSurface(iSurf)->MeshID = mpMREA->ReadShort();
|
||||
}
|
||||
|
||||
mBlockMgr->ToNextBlock();
|
||||
mBlockMgr->ToNextBlock();
|
||||
mpSectionMgr->ToNextSection();
|
||||
mpSectionMgr->ToNextSection();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,7 +117,7 @@ void CAreaLoader::ReadGeometryPrime()
|
|||
void CAreaLoader::ReadSCLYPrime()
|
||||
{
|
||||
Log::FileWrite(mpMREA->GetSourceString(), "Reading MREA script layers (MP1)");
|
||||
mBlockMgr->ToBlock(mScriptLayerBlockNum);
|
||||
mpSectionMgr->ToSection(mScriptLayerBlockNum);
|
||||
|
||||
CFourCC SCLY(*mpMREA);
|
||||
if (SCLY != "SCLY")
|
||||
|
@ -154,7 +155,7 @@ void CAreaLoader::ReadSCLYPrime()
|
|||
void CAreaLoader::ReadLightsPrime()
|
||||
{
|
||||
Log::FileWrite(mpMREA->GetSourceString(), "Reading MREA dynamic lights (MP1/MP2)");
|
||||
mBlockMgr->ToBlock(mLightsBlockNum);
|
||||
mpSectionMgr->ToSection(mLightsBlockNum);
|
||||
|
||||
u32 babedead = mpMREA->ReadLong();
|
||||
if (babedead != 0xbabedead) return;
|
||||
|
@ -258,7 +259,7 @@ void CAreaLoader::ReadHeaderEchoes()
|
|||
if (mVersion == eEchoes) mClusters.resize(mpMREA->ReadLong());
|
||||
mpMREA->SeekToBoundary(32);
|
||||
|
||||
mBlockMgr = new CBlockMgrIn(numBlocks, mpMREA);
|
||||
mpSectionMgr = new CSectionMgrIn(numBlocks, mpMREA);
|
||||
mpMREA->SeekToBoundary(32);
|
||||
|
||||
if (mVersion == eEchoes)
|
||||
|
@ -267,13 +268,14 @@ void CAreaLoader::ReadHeaderEchoes()
|
|||
Decompress();
|
||||
}
|
||||
|
||||
mBlockMgr->Init();
|
||||
mpSectionMgr->Init();
|
||||
LoadSectionDataBuffers();
|
||||
}
|
||||
|
||||
void CAreaLoader::ReadSCLYEchoes()
|
||||
{
|
||||
Log::FileWrite(mpMREA->GetSourceString(), "Reading MREA script layers (MP2/MP3/DKCR)");
|
||||
mBlockMgr->ToBlock(mScriptLayerBlockNum);
|
||||
mpSectionMgr->ToSection(mScriptLayerBlockNum);
|
||||
|
||||
// SCLY
|
||||
for (u32 l = 0; l < mNumLayers; l++)
|
||||
|
@ -283,11 +285,11 @@ void CAreaLoader::ReadSCLYEchoes()
|
|||
if (pLayer)
|
||||
mpArea->mScriptLayers.push_back(pLayer);
|
||||
|
||||
mBlockMgr->ToNextBlock();
|
||||
mpSectionMgr->ToNextSection();
|
||||
}
|
||||
|
||||
// SCGN
|
||||
mBlockMgr->ToBlock(mScriptGeneratorBlockNum);
|
||||
mpSectionMgr->ToSection(mScriptGeneratorBlockNum);
|
||||
CScriptLayer *pLayer = CScriptLoader::LoadLayer(*mpMREA, mpArea, mVersion);
|
||||
|
||||
if (pLayer)
|
||||
|
@ -309,7 +311,7 @@ void CAreaLoader::ReadHeaderCorruption()
|
|||
u32 SectionNumberCount = mpMREA->ReadLong();
|
||||
mpMREA->SeekToBoundary(32);
|
||||
|
||||
mBlockMgr = new CBlockMgrIn(NumSections, mpMREA);
|
||||
mpSectionMgr = new CSectionMgrIn(NumSections, mpMREA);
|
||||
mpMREA->SeekToBoundary(32);
|
||||
|
||||
ReadCompressedBlocks();
|
||||
|
@ -336,17 +338,18 @@ void CAreaLoader::ReadHeaderCorruption()
|
|||
|
||||
mpMREA->SeekToBoundary(32);
|
||||
Decompress();
|
||||
mBlockMgr->Init();
|
||||
mpSectionMgr->Init();
|
||||
LoadSectionDataBuffers();
|
||||
}
|
||||
|
||||
void CAreaLoader::ReadGeometryCorruption()
|
||||
{
|
||||
Log::FileWrite(mpMREA->GetSourceString(), "Reading MREA world geometry (MP3)");
|
||||
mBlockMgr->ToBlock(mGeometryBlockNum);
|
||||
mpSectionMgr->ToSection(mGeometryBlockNum);
|
||||
|
||||
// Materials
|
||||
mpArea->mMaterialSet = CMaterialLoader::LoadMaterialSet(*mpMREA, mVersion);
|
||||
mBlockMgr->ToNextBlock();
|
||||
mpSectionMgr->ToNextSection();
|
||||
|
||||
// Geometry
|
||||
std::vector<CModel*> FileModels;
|
||||
|
@ -355,14 +358,14 @@ void CAreaLoader::ReadGeometryCorruption()
|
|||
|
||||
for (u32 iMesh = 0; iMesh < mNumMeshes; iMesh++)
|
||||
{
|
||||
CModel *pWorldModel = CModelLoader::LoadCorruptionWorldModel(*mpMREA, *mBlockMgr, *mpArea->mMaterialSet, CurWOBJSection, CurGPUSection, mVersion);
|
||||
CModel *pWorldModel = CModelLoader::LoadCorruptionWorldModel(*mpMREA, *mpSectionMgr, *mpArea->mMaterialSet, CurWOBJSection, CurGPUSection, mVersion);
|
||||
FileModels.push_back(pWorldModel);
|
||||
|
||||
CurWOBJSection += 4;
|
||||
CurGPUSection = mBlockMgr->CurrentBlock();
|
||||
CurGPUSection = mpSectionMgr->CurrentSection();
|
||||
|
||||
// Load surface mesh IDs
|
||||
mBlockMgr->ToBlock(CurWOBJSection - 2);
|
||||
mpSectionMgr->ToSection(CurWOBJSection - 2);
|
||||
u16 NumSurfaces = mpMREA->ReadShort();
|
||||
|
||||
for (u32 iSurf = 0; iSurf < NumSurfaces; iSurf++)
|
||||
|
@ -384,7 +387,7 @@ void CAreaLoader::ReadGeometryCorruption()
|
|||
void CAreaLoader::ReadLightsCorruption()
|
||||
{
|
||||
Log::FileWrite(mpMREA->GetSourceString(), "Reading MREA dynamic lights (MP3)");
|
||||
mBlockMgr->ToBlock(mLightsBlockNum);
|
||||
mpSectionMgr->ToSection(mLightsBlockNum);
|
||||
|
||||
u32 babedead = mpMREA->ReadLong();
|
||||
if (babedead != 0xbabedead) return;
|
||||
|
@ -522,21 +525,35 @@ void CAreaLoader::Decompress()
|
|||
TString Source = mpMREA->GetSourceString();
|
||||
mpMREA = new CMemoryInStream(mDecmpBuffer, mTotalDecmpSize, IOUtil::eBigEndian);
|
||||
mpMREA->SetSourceString(Source.ToStdString());
|
||||
mBlockMgr->SetInputStream(mpMREA);
|
||||
mpSectionMgr->SetInputStream(mpMREA);
|
||||
mHasDecompressedBuffer = true;
|
||||
}
|
||||
|
||||
void CAreaLoader::LoadSectionDataBuffers()
|
||||
{
|
||||
mpArea->mSectionDataBuffers.resize(mpSectionMgr->NumSections());
|
||||
mpSectionMgr->ToSection(0);
|
||||
|
||||
for (u32 iSec = 0; iSec < mpSectionMgr->NumSections(); iSec++)
|
||||
{
|
||||
u32 Size = mpSectionMgr->CurrentSectionSize();
|
||||
mpArea->mSectionDataBuffers[iSec].resize(Size);
|
||||
mpMREA->ReadBytes(mpArea->mSectionDataBuffers[iSec].data(), mpArea->mSectionDataBuffers[iSec].size());
|
||||
mpSectionMgr->ToNextSection();
|
||||
}
|
||||
}
|
||||
|
||||
void CAreaLoader::ReadCollision()
|
||||
{
|
||||
Log::FileWrite(mpMREA->GetSourceString(), "Reading collision (MP1/MP2/MP3)");
|
||||
mBlockMgr->ToBlock(mCollisionBlockNum);
|
||||
mpSectionMgr->ToSection(mCollisionBlockNum);
|
||||
mpArea->mCollision = CCollisionLoader::LoadAreaCollision(*mpMREA);
|
||||
}
|
||||
|
||||
void CAreaLoader::ReadEGMC()
|
||||
{
|
||||
Log::FileWrite(mpMREA->GetSourceString(), "Reading EGMC");
|
||||
mBlockMgr->ToBlock(mEGMCBlockNum);
|
||||
mpSectionMgr->ToSection(mEGMCBlockNum);
|
||||
CUniqueID EGMC(*mpMREA, (mVersion <= eEchoes ? e32Bit : e64Bit));
|
||||
mpArea->mpPoiToWorldMap = gResCache.GetResource(EGMC, "EGMC");
|
||||
}
|
||||
|
@ -665,7 +682,7 @@ CGameArea* CAreaLoader::LoadMREA(IInputStream& MREA)
|
|||
}
|
||||
|
||||
// Cleanup
|
||||
delete Loader.mBlockMgr;
|
||||
delete Loader.mpSectionMgr;
|
||||
return Loader.mpArea;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef CAREALOADER_H
|
||||
#define CAREALOADER_H
|
||||
|
||||
#include "CBlockMgrIn.h"
|
||||
#include "CSectionMgrIn.h"
|
||||
#include "Core/Resource/Script/SConnection.h"
|
||||
#include "Core/Resource/CGameArea.h"
|
||||
#include "Core/Resource/EGame.h"
|
||||
|
@ -16,7 +16,7 @@ class CAreaLoader
|
|||
// Area data
|
||||
TResPtr<CGameArea> mpArea;
|
||||
IInputStream *mpMREA;
|
||||
CBlockMgrIn *mBlockMgr;
|
||||
CSectionMgrIn *mpSectionMgr;
|
||||
EGame mVersion;
|
||||
u32 mNumMeshes;
|
||||
u32 mNumLayers;
|
||||
|
@ -74,6 +74,7 @@ class CAreaLoader
|
|||
// Common
|
||||
void ReadCompressedBlocks();
|
||||
void Decompress();
|
||||
void LoadSectionDataBuffers();
|
||||
void ReadCollision();
|
||||
void ReadEGMC();
|
||||
void SetUpObjects();
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
#include "CBlockMgrIn.h"
|
||||
|
||||
CBlockMgrIn::CBlockMgrIn(unsigned long count, IInputStream* src)
|
||||
{
|
||||
mpInputStream = src;
|
||||
mBlockCount = count;
|
||||
mBlockSizes.resize(count);
|
||||
|
||||
for (unsigned long b = 0; b < count; b++)
|
||||
mBlockSizes[b] = src->ReadLong();
|
||||
}
|
||||
|
||||
void CBlockMgrIn::Init()
|
||||
{
|
||||
// Initialize the block manager; this marks the start of the first block
|
||||
mCurBlock = 0;
|
||||
mCurBlockStart = mpInputStream->Tell();
|
||||
mBlocksStart = mpInputStream->Tell();
|
||||
}
|
||||
|
||||
void CBlockMgrIn::ToBlock(unsigned long block)
|
||||
{
|
||||
unsigned long offset = mBlocksStart;
|
||||
for (unsigned long b = 0; b < block; b++)
|
||||
offset += mBlockSizes[b];
|
||||
|
||||
mpInputStream->Seek(offset, SEEK_SET);
|
||||
|
||||
mCurBlock = block;
|
||||
mCurBlockStart = mpInputStream->Tell();
|
||||
}
|
||||
|
||||
void CBlockMgrIn::ToNextBlock()
|
||||
{
|
||||
mpInputStream->Seek(mCurBlockStart + mBlockSizes[mCurBlock], SEEK_SET);
|
||||
mCurBlock++;
|
||||
mCurBlockStart = mpInputStream->Tell();
|
||||
}
|
||||
|
||||
long CBlockMgrIn::NextOffset()
|
||||
{
|
||||
return mCurBlockStart + mBlockSizes[mCurBlock];
|
||||
}
|
||||
|
||||
long CBlockMgrIn::CurrentBlock()
|
||||
{
|
||||
return mCurBlock;
|
||||
}
|
||||
|
||||
long CBlockMgrIn::CurrentBlockSize()
|
||||
{
|
||||
return mBlockSizes[mCurBlock];
|
||||
}
|
||||
|
||||
void CBlockMgrIn::SetInputStream(IInputStream *in)
|
||||
{
|
||||
mpInputStream = in;
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
#ifndef CBLOCKMGRIN_H
|
||||
#define CBLOCKMGRIN_H
|
||||
|
||||
#include <FileIO/IInputStream.h>
|
||||
#include <vector>
|
||||
|
||||
// The purpose of this class is to keep track of data block navigation - required to read CMDL and MREA files correctly
|
||||
class CBlockMgrIn
|
||||
{
|
||||
IInputStream *mpInputStream;
|
||||
unsigned long mBlockCount;
|
||||
std::vector<unsigned long> mBlockSizes;
|
||||
unsigned long mCurBlock;
|
||||
unsigned long mCurBlockStart;
|
||||
unsigned long mBlocksStart;
|
||||
|
||||
public:
|
||||
CBlockMgrIn(unsigned long count, IInputStream* src);
|
||||
void Init();
|
||||
void ToBlock(unsigned long block);
|
||||
void ToNextBlock();
|
||||
long NextOffset();
|
||||
long CurrentBlock();
|
||||
long CurrentBlockSize();
|
||||
void SetInputStream(IInputStream *in);
|
||||
};
|
||||
|
||||
#endif // CBLOCKMGRIN_H
|
|
@ -18,7 +18,7 @@ void CModelLoader::LoadWorldMeshHeader(IInputStream &Model)
|
|||
// I don't really have any need for most of this data, so
|
||||
Model.Seek(0x34, SEEK_CUR);
|
||||
mAABox = CAABox(Model);
|
||||
mpBlockMgr->ToNextBlock();
|
||||
mpSectionMgr->ToNextSection();
|
||||
}
|
||||
|
||||
void CModelLoader::LoadAttribArrays(IInputStream& Model)
|
||||
|
@ -26,7 +26,7 @@ void CModelLoader::LoadAttribArrays(IInputStream& Model)
|
|||
// Positions
|
||||
if (mFlags & eShortPositions) // Shorts (DKCR only)
|
||||
{
|
||||
mPositions.resize(mpBlockMgr->CurrentBlockSize() / 0x6);
|
||||
mPositions.resize(mpSectionMgr->CurrentSectionSize() / 0x6);
|
||||
float Divisor = 8192.f; // Might be incorrect! Needs verification via size comparison.
|
||||
|
||||
for (u32 iVtx = 0; iVtx < mPositions.size(); iVtx++)
|
||||
|
@ -40,18 +40,18 @@ void CModelLoader::LoadAttribArrays(IInputStream& Model)
|
|||
|
||||
else // Floats
|
||||
{
|
||||
mPositions.resize(mpBlockMgr->CurrentBlockSize() / 0xC);
|
||||
mPositions.resize(mpSectionMgr->CurrentSectionSize() / 0xC);
|
||||
|
||||
for (u32 iVtx = 0; iVtx < mPositions.size(); iVtx++)
|
||||
mPositions[iVtx] = CVector3f(Model);
|
||||
}
|
||||
|
||||
mpBlockMgr->ToNextBlock();
|
||||
mpSectionMgr->ToNextSection();
|
||||
|
||||
// Normals
|
||||
if (mFlags & eShortNormals) // Shorts
|
||||
{
|
||||
mNormals.resize(mpBlockMgr->CurrentBlockSize() / 0x6);
|
||||
mNormals.resize(mpSectionMgr->CurrentSectionSize() / 0x6);
|
||||
float Divisor = (mVersion < eReturns) ? 32768.f : 16384.f;
|
||||
|
||||
for (u32 iVtx = 0; iVtx < mNormals.size(); iVtx++)
|
||||
|
@ -64,35 +64,35 @@ void CModelLoader::LoadAttribArrays(IInputStream& Model)
|
|||
}
|
||||
else // Floats
|
||||
{
|
||||
mNormals.resize(mpBlockMgr->CurrentBlockSize() / 0xC);
|
||||
mNormals.resize(mpSectionMgr->CurrentSectionSize() / 0xC);
|
||||
|
||||
for (u32 iVtx = 0; iVtx < mNormals.size(); iVtx++)
|
||||
mNormals[iVtx] = CVector3f(Model);
|
||||
}
|
||||
|
||||
mpBlockMgr->ToNextBlock();
|
||||
mpSectionMgr->ToNextSection();
|
||||
|
||||
// Colors
|
||||
mColors.resize(mpBlockMgr->CurrentBlockSize() / 4);
|
||||
mColors.resize(mpSectionMgr->CurrentSectionSize() / 4);
|
||||
|
||||
for (u32 iVtx = 0; iVtx < mColors.size(); iVtx++)
|
||||
mColors[iVtx] = CColor(Model);
|
||||
|
||||
mpBlockMgr->ToNextBlock();
|
||||
mpSectionMgr->ToNextSection();
|
||||
|
||||
|
||||
// Float UVs
|
||||
mTex0.resize(mpBlockMgr->CurrentBlockSize() / 0x8);
|
||||
mTex0.resize(mpSectionMgr->CurrentSectionSize() / 0x8);
|
||||
|
||||
for (u32 iVtx = 0; iVtx < mTex0.size(); iVtx++)
|
||||
mTex0[iVtx] = CVector2f(Model);
|
||||
|
||||
mpBlockMgr->ToNextBlock();
|
||||
mpSectionMgr->ToNextSection();
|
||||
|
||||
// Short UVs
|
||||
if (mFlags & eHasTex1)
|
||||
{
|
||||
mTex1.resize(mpBlockMgr->CurrentBlockSize() / 0x4);
|
||||
mTex1.resize(mpSectionMgr->CurrentSectionSize() / 0x4);
|
||||
float Divisor = (mVersion < eReturns) ? 32768.f : 8192.f;
|
||||
|
||||
for (u32 iVtx = 0; iVtx < mTex1.size(); iVtx++)
|
||||
|
@ -102,7 +102,7 @@ void CModelLoader::LoadAttribArrays(IInputStream& Model)
|
|||
mTex1[iVtx] = CVector2f(x, y);
|
||||
}
|
||||
|
||||
mpBlockMgr->ToNextBlock();
|
||||
mpSectionMgr->ToNextSection();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,7 +114,7 @@ void CModelLoader::LoadSurfaceOffsets(IInputStream& Model)
|
|||
for (u32 iSurf = 0; iSurf < mSurfaceCount; iSurf++)
|
||||
mSurfaceOffsets[iSurf] = Model.ReadLong();
|
||||
|
||||
mpBlockMgr->ToNextBlock();
|
||||
mpSectionMgr->ToNextSection();
|
||||
}
|
||||
|
||||
SSurface* CModelLoader::LoadSurface(IInputStream& Model)
|
||||
|
@ -132,7 +132,7 @@ SSurface* CModelLoader::LoadSurface(IInputStream& Model)
|
|||
|
||||
// Primitive table
|
||||
u8 Flag = Model.ReadByte();
|
||||
u32 NextSurface = mpBlockMgr->NextOffset();
|
||||
u32 NextSurface = mpSectionMgr->NextOffset();
|
||||
|
||||
while ((Flag != 0) && ((u32) Model.Tell() < NextSurface))
|
||||
{
|
||||
|
@ -225,7 +225,7 @@ SSurface* CModelLoader::LoadSurface(IInputStream& Model)
|
|||
Flag = Model.ReadByte();
|
||||
} // Primitive table end
|
||||
|
||||
mpBlockMgr->ToNextBlock();
|
||||
mpSectionMgr->ToNextSection();
|
||||
return pSurf;
|
||||
}
|
||||
|
||||
|
@ -451,9 +451,9 @@ CModel* CModelLoader::LoadCMDL(IInputStream& CMDL)
|
|||
|
||||
CModel *pModel = new CModel();
|
||||
Loader.mpModel = pModel;
|
||||
Loader.mpBlockMgr = new CBlockMgrIn(BlockCount, &CMDL);
|
||||
Loader.mpSectionMgr = new CSectionMgrIn(BlockCount, &CMDL);
|
||||
CMDL.SeekToBoundary(32);
|
||||
Loader.mpBlockMgr->Init();
|
||||
Loader.mpSectionMgr->Init();
|
||||
|
||||
// Materials
|
||||
Loader.mMaterials.resize(MatSetCount);
|
||||
|
@ -462,12 +462,12 @@ CModel* CModelLoader::LoadCMDL(IInputStream& CMDL)
|
|||
Loader.mMaterials[iMat] = CMaterialLoader::LoadMaterialSet(CMDL, Loader.mVersion);
|
||||
|
||||
if (Loader.mVersion < eCorruptionProto)
|
||||
Loader.mpBlockMgr->ToNextBlock();
|
||||
Loader.mpSectionMgr->ToNextSection();
|
||||
}
|
||||
|
||||
pModel->mMaterialSets = Loader.mMaterials;
|
||||
pModel->mHasOwnMaterials = true;
|
||||
if (Loader.mVersion >= eCorruptionProto) Loader.mpBlockMgr->ToNextBlock();
|
||||
if (Loader.mVersion >= eCorruptionProto) Loader.mpSectionMgr->ToNextSection();
|
||||
|
||||
// Mesh
|
||||
Loader.LoadAttribArrays(CMDL);
|
||||
|
@ -486,14 +486,14 @@ CModel* CModelLoader::LoadCMDL(IInputStream& CMDL)
|
|||
pModel->mHasOwnSurfaces = true;
|
||||
|
||||
// Cleanup
|
||||
delete Loader.mpBlockMgr;
|
||||
delete Loader.mpSectionMgr;
|
||||
return pModel;
|
||||
}
|
||||
|
||||
CModel* CModelLoader::LoadWorldModel(IInputStream& MREA, CBlockMgrIn& BlockMgr, CMaterialSet& MatSet, EGame Version)
|
||||
CModel* CModelLoader::LoadWorldModel(IInputStream& MREA, CSectionMgrIn& BlockMgr, CMaterialSet& MatSet, EGame Version)
|
||||
{
|
||||
CModelLoader Loader;
|
||||
Loader.mpBlockMgr = &BlockMgr;
|
||||
Loader.mpSectionMgr = &BlockMgr;
|
||||
Loader.mVersion = Version;
|
||||
Loader.mFlags = eShortNormals;
|
||||
if (Version != eCorruptionProto) Loader.mFlags |= eHasTex1;
|
||||
|
@ -523,10 +523,10 @@ CModel* CModelLoader::LoadWorldModel(IInputStream& MREA, CBlockMgrIn& BlockMgr,
|
|||
return pModel;
|
||||
}
|
||||
|
||||
CModel* CModelLoader::LoadCorruptionWorldModel(IInputStream &MREA, CBlockMgrIn &BlockMgr, CMaterialSet &MatSet, u32 HeaderSecNum, u32 GPUSecNum, EGame Version)
|
||||
CModel* CModelLoader::LoadCorruptionWorldModel(IInputStream &MREA, CSectionMgrIn &BlockMgr, CMaterialSet &MatSet, u32 HeaderSecNum, u32 GPUSecNum, EGame Version)
|
||||
{
|
||||
CModelLoader Loader;
|
||||
Loader.mpBlockMgr = &BlockMgr;
|
||||
Loader.mpSectionMgr = &BlockMgr;
|
||||
Loader.mVersion = Version;
|
||||
Loader.mFlags = eShortNormals;
|
||||
Loader.mMaterials.resize(1);
|
||||
|
@ -534,10 +534,10 @@ CModel* CModelLoader::LoadCorruptionWorldModel(IInputStream &MREA, CBlockMgrIn &
|
|||
if (Version == eReturns) Loader.mFlags |= eHasTex1;
|
||||
|
||||
// Corruption/DKCR MREAs split the mesh header and surface offsets away from the actual geometry data so I need two section numbers to read it
|
||||
BlockMgr.ToBlock(HeaderSecNum);
|
||||
BlockMgr.ToSection(HeaderSecNum);
|
||||
Loader.LoadWorldMeshHeader(MREA);
|
||||
Loader.LoadSurfaceOffsets(MREA);
|
||||
BlockMgr.ToBlock(GPUSecNum);
|
||||
BlockMgr.ToSection(GPUSecNum);
|
||||
Loader.LoadAttribArrays(MREA);
|
||||
|
||||
CModel *pModel = new CModel();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef CMODELLOADER_H
|
||||
#define CMODELLOADER_H
|
||||
|
||||
#include "CBlockMgrIn.h"
|
||||
#include "CSectionMgrIn.h"
|
||||
#include "Core/Resource/Model/CBasicModel.h"
|
||||
#include "Core/Resource/Model/CModel.h"
|
||||
#include "Core/Resource/CResCache.h"
|
||||
|
@ -27,7 +27,7 @@ public:
|
|||
private:
|
||||
TResPtr<CModel> mpModel;
|
||||
std::vector<CMaterialSet*> mMaterials;
|
||||
CBlockMgrIn *mpBlockMgr;
|
||||
CSectionMgrIn *mpSectionMgr;
|
||||
CAABox mAABox;
|
||||
EGame mVersion;
|
||||
|
||||
|
@ -57,8 +57,8 @@ private:
|
|||
|
||||
public:
|
||||
static CModel* LoadCMDL(IInputStream& CMDL);
|
||||
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* LoadWorldModel(IInputStream& MREA, CSectionMgrIn& BlockMgr, CMaterialSet& MatSet, EGame Version);
|
||||
static CModel* LoadCorruptionWorldModel(IInputStream& MREA, CSectionMgrIn& 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 EGame GetFormatVersion(u32 Version);
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
#ifndef CSECTIONMGRIN_H
|
||||
#define CSECTIONMGRIN_H
|
||||
|
||||
#include <FileIO/IInputStream.h>
|
||||
#include <Common/types.h>
|
||||
#include <vector>
|
||||
|
||||
// The purpose of this class is to keep track of data block navigation - required to read CMDL and MREA files correctly
|
||||
class CSectionMgrIn
|
||||
{
|
||||
IInputStream *mpInputStream;
|
||||
std::vector<u32> mSectionSizes;
|
||||
u32 mCurSec;
|
||||
u32 mCurSecStart;
|
||||
u32 mSecsStart;
|
||||
|
||||
public:
|
||||
CSectionMgrIn(u32 Count, IInputStream* pSrc)
|
||||
: mpInputStream(pSrc)
|
||||
{
|
||||
mSectionSizes.resize(Count);
|
||||
|
||||
for (u32 iSec = 0; iSec < Count; iSec++)
|
||||
mSectionSizes[iSec] = pSrc->ReadLong();
|
||||
}
|
||||
|
||||
inline void Init()
|
||||
{
|
||||
// Initializes the block manager and marks the start of the first block
|
||||
mCurSec = 0;
|
||||
mCurSecStart = mpInputStream->Tell();
|
||||
mSecsStart = mCurSecStart;
|
||||
}
|
||||
|
||||
void ToSection(u32 SecNum)
|
||||
{
|
||||
u32 Offset = mSecsStart;
|
||||
for (u32 iSec = 0; iSec < SecNum; iSec++)
|
||||
Offset += mSectionSizes[iSec];
|
||||
|
||||
mpInputStream->Seek(Offset, SEEK_SET);
|
||||
mCurSec = SecNum;
|
||||
mCurSecStart = mpInputStream->Tell();
|
||||
}
|
||||
|
||||
inline void ToNextSection()
|
||||
{
|
||||
mCurSecStart += mSectionSizes[mCurSec];
|
||||
mpInputStream->Seek(mCurSecStart, SEEK_SET);
|
||||
mCurSec++;
|
||||
}
|
||||
|
||||
inline u32 NextOffset() { return mCurSecStart + mSectionSizes[mCurSec]; }
|
||||
inline u32 CurrentSection() { return mCurSec; }
|
||||
inline u32 CurrentSectionSize() { return mSectionSizes[mCurSec]; }
|
||||
inline u32 NumSections() { return mSectionSizes.size(); }
|
||||
inline void SetInputStream(IInputStream *pIn) { mpInputStream = pIn; }
|
||||
};
|
||||
|
||||
#endif // CSECTIONMGRIN_H
|
|
@ -11,13 +11,15 @@
|
|||
#include "Editor/UICommon.h"
|
||||
|
||||
#include <Core/Render/CDrawUtil.h>
|
||||
#include <Core/Resource/Cooker/CAreaCooker.h>
|
||||
#include <Core/Scene/CSceneIterator.h>
|
||||
#include <Core/Log.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <QOpenGLContext>
|
||||
#include <QFontMetrics>
|
||||
#include <QComboBox>
|
||||
#include <QFontMetrics>
|
||||
#include <QMessageBox>
|
||||
#include <QOpenGLContext>
|
||||
|
||||
CWorldEditor::CWorldEditor(QWidget *parent) :
|
||||
INodeEditor(parent),
|
||||
|
@ -528,3 +530,11 @@ void CWorldEditor::on_ActionEditPoiToWorldMap_triggered()
|
|||
mpPoiDialog->show();
|
||||
}
|
||||
}
|
||||
|
||||
void CWorldEditor::on_ActionSave_triggered()
|
||||
{
|
||||
TString Out = mpArea->FullSource();
|
||||
CFileOutStream MREA(Out.ToStdString(), IOUtil::eBigEndian);
|
||||
CAreaCooker::WriteCookedArea(mpArea, MREA);
|
||||
QMessageBox::information(this, "Success", "Successfully saved area to " + TO_QSTRING(Out));
|
||||
}
|
||||
|
|
|
@ -85,6 +85,7 @@ private slots:
|
|||
void on_ActionSelectAll_triggered();
|
||||
void on_ActionInvertSelection_triggered();
|
||||
void on_ActionEditPoiToWorldMap_triggered();
|
||||
void on_ActionSave_triggered();
|
||||
};
|
||||
|
||||
#endif // CWORLDEDITOR_H
|
||||
|
|
|
@ -54,6 +54,12 @@ CTransform4f::CTransform4f(CVector3f, CVector3f, CVector3f)
|
|||
{
|
||||
}
|
||||
|
||||
void CTransform4f::Write(IOutputStream& rOut)
|
||||
{
|
||||
for (int iFlt = 0; iFlt < 12; iFlt++)
|
||||
rOut.WriteFloat(_m[iFlt]);
|
||||
}
|
||||
|
||||
// ************ MATH ************
|
||||
void CTransform4f::Translate(CVector3f Translation)
|
||||
{
|
||||
|
|
|
@ -27,6 +27,7 @@ public:
|
|||
float m20, float m21, float m22, float m23);
|
||||
CTransform4f(CVector3f Position, CQuaternion Rotation, CVector3f Scale);
|
||||
CTransform4f(CVector3f Position, CVector3f Rotation, CVector3f Scale);
|
||||
void Write(IOutputStream& rOut);
|
||||
|
||||
// Math
|
||||
void Translate(CVector3f Translation);
|
||||
|
|
Loading…
Reference in New Issue