[IXModel] Correct model loading
This commit is contained in:
parent
75158227fb
commit
2c7b7f6d87
@ -1,6 +1,6 @@
|
||||
#include <STDInclude.hpp>
|
||||
|
||||
#define IW4X_MODEL_VERSION 2
|
||||
#define IW4X_MODEL_VERSION 3
|
||||
|
||||
namespace Assets
|
||||
{
|
||||
@ -34,6 +34,8 @@ namespace Assets
|
||||
model->numRootBones = reader.readByte();
|
||||
model->numSurfaces = reader.read<unsigned char>();
|
||||
model->numColSurfs = reader.read<int>();
|
||||
model->numLods = static_cast<char>(reader.read<short>());
|
||||
model->collLod = reader.read<short>();
|
||||
|
||||
// Read bone names
|
||||
model->boneNames = builder->getAllocator()->allocateArray<short>(model->numBones);
|
||||
@ -53,41 +55,32 @@ namespace Assets
|
||||
model->animMatrix = reader.readArray<Game::DObjAnimMat>(boneCount);
|
||||
|
||||
// Prepare surfaces
|
||||
Game::XSurface* baseSurface = &baseModel->lods[0].surfaces[0].surfaces[0];
|
||||
Game::XModelSurfs* surf = builder->getAllocator()->allocate<Game::XModelSurfs>();
|
||||
Game::XModelSurfs surf;
|
||||
Utils::Memory::Allocator allocator;
|
||||
Game::XSurface* baseSurface = &baseModel->lods[0].modelSurfs[0].surfaces[0];
|
||||
|
||||
std::memcpy(surf, baseModel->lods[0].surfaces, sizeof(Game::XModelSurfs));
|
||||
surf->name = builder->getAllocator()->duplicateString(fmt::sprintf("%s_lod1", model->name));
|
||||
surf->surfaces = builder->getAllocator()->allocateArray<Game::XSurface>(model->numSurfaces);
|
||||
surf->numSurfaces = model->numSurfaces;
|
||||
std::memcpy(&surf, baseModel->lods[0].modelSurfs, sizeof(Game::XModelSurfs));
|
||||
surf.surfaces = allocator.allocateArray<Game::XSurface>(model->numSurfaces);
|
||||
surf.numSurfaces = model->numSurfaces;
|
||||
|
||||
// Store surfs for later writing
|
||||
Components::AssetHandler::StoreTemporaryAsset(Game::XAssetType::ASSET_TYPE_XMODELSURFS, { surf });
|
||||
|
||||
// Reset surfaces in remaining lods
|
||||
for (unsigned int i = 1; i < 4; ++i)
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
ZeroMemory(&model->lods[i], sizeof(Game::XModelLodInfo));
|
||||
model->lods[i].dist = reader.read<float>();
|
||||
model->lods[i].numsurfs = reader.read<unsigned short>();
|
||||
model->lods[i].surfIndex = reader.read<unsigned short>();
|
||||
|
||||
model->lods[i].partBits[0] = reader.read<int>();
|
||||
model->lods[i].partBits[1] = reader.read<int>();
|
||||
model->lods[i].partBits[2] = reader.read<int>();
|
||||
model->lods[i].partBits[3] = reader.read<int>();
|
||||
model->lods[i].partBits[4] = 0;
|
||||
model->lods[i].partBits[5] = 0;
|
||||
}
|
||||
|
||||
model->lods[0].dist = reader.read<float>();
|
||||
model->lods[0].numSurfs = reader.read<short>();
|
||||
model->lods[0].maxSurfs = reader.read<short>();
|
||||
|
||||
model->lods[0].partBits[0] = reader.read<int>();
|
||||
model->lods[0].partBits[1] = reader.read<int>();
|
||||
model->lods[0].partBits[2] = reader.read<int>();
|
||||
model->lods[0].partBits[3] = reader.read<int>();
|
||||
|
||||
model->lods[0].numSurfs = model->numSurfaces; // This is needed in case we have more than 1 LOD
|
||||
model->lods[0].surfaces = surf;
|
||||
model->lods[0].surfs = surf->surfaces;
|
||||
model->numLods = 1;
|
||||
|
||||
// Read surfaces
|
||||
for (int i = 0; i < surf->numSurfaces; ++i)
|
||||
for (int i = 0; i < surf.numSurfaces; ++i)
|
||||
{
|
||||
Game::XSurface* surface = &surf->surfaces[i];
|
||||
Game::XSurface* surface = &surf.surfaces[i];
|
||||
std::memcpy(surface, baseSurface, sizeof(Game::XSurface));
|
||||
|
||||
surface->tileMode = reader.read<char>();
|
||||
@ -98,6 +91,8 @@ namespace Assets
|
||||
surface->partBits[1] = reader.read<int>();
|
||||
surface->partBits[2] = reader.read<int>();
|
||||
surface->partBits[3] = reader.read<int>();
|
||||
surface->partBits[4] = 0;
|
||||
surface->partBits[5] = 0;
|
||||
|
||||
surface->baseTriIndex = reader.read<unsigned __int16>();
|
||||
surface->baseVertIndex = reader.read<unsigned __int16>();
|
||||
@ -136,6 +131,27 @@ namespace Assets
|
||||
}
|
||||
}
|
||||
|
||||
// When all surfaces are loaded, split them up.
|
||||
for (char i = 0; i < model->numLods; ++i)
|
||||
{
|
||||
Game::XModelSurfs* realSurf = builder->getAllocator()->allocate<Game::XModelSurfs>();
|
||||
|
||||
// Usually, a binary representation is used for the index, but meh.
|
||||
realSurf->name = builder->getAllocator()->duplicateString(fmt::sprintf("%s_lod%d", model->name, i & 0xFF));
|
||||
|
||||
realSurf->numSurfaces = model->lods[i].numsurfs;
|
||||
realSurf->surfaces = builder->getAllocator()->allocateArray<Game::XSurface>(realSurf->numSurfaces);
|
||||
|
||||
std::memcpy(realSurf->surfaces, &surf.surfaces[model->lods[i].surfIndex], sizeof(Game::XSurface) * realSurf->numSurfaces);
|
||||
std::memcpy(realSurf->partBits, model->lods[i].partBits, sizeof(realSurf->partBits));
|
||||
|
||||
model->lods[i].modelSurfs = realSurf;
|
||||
model->lods[i].surfs = realSurf->surfaces;
|
||||
|
||||
// Store surfs for later writing
|
||||
Components::AssetHandler::StoreTemporaryAsset(Game::XAssetType::ASSET_TYPE_XMODELSURFS, { realSurf });
|
||||
}
|
||||
|
||||
// Read materials
|
||||
model->materials = builder->getAllocator()->allocateArray<Game::Material*>(model->numSurfaces);
|
||||
for (unsigned char i = 0; i < model->numSurfaces; ++i)
|
||||
@ -205,9 +221,9 @@ namespace Assets
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
if (asset->lods[i].surfaces)
|
||||
if (asset->lods[i].modelSurfs)
|
||||
{
|
||||
builder->loadAsset(Game::XAssetType::ASSET_TYPE_XMODELSURFS, asset->lods[i].surfaces);
|
||||
builder->loadAsset(Game::XAssetType::ASSET_TYPE_XMODELSURFS, asset->lods[i].modelSurfs);
|
||||
}
|
||||
}
|
||||
|
||||
@ -317,9 +333,9 @@ namespace Assets
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
if (asset->lods[i].surfaces)
|
||||
if (asset->lods[i].modelSurfs)
|
||||
{
|
||||
dest->lods[i].surfaces = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_XMODELSURFS, asset->lods[i].surfaces).surfaces;
|
||||
dest->lods[i].modelSurfs = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_XMODELSURFS, asset->lods[i].modelSurfs).surfaces;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -152,7 +152,7 @@ namespace Components
|
||||
|
||||
for (char i = 0; i < model->numLods; ++i)
|
||||
{
|
||||
Game::XModelSurfs* surfs = model->lods[i].surfaces;
|
||||
Game::XModelSurfs* surfs = model->lods[i].modelSurfs;
|
||||
|
||||
if (!surfs->surfaces)
|
||||
{
|
||||
@ -164,12 +164,11 @@ namespace Components
|
||||
surfs->numSurfaces = newSurfs->numSurfaces;
|
||||
|
||||
model->lods[i].surfs = newSurfs->surfaces;
|
||||
std::memcpy(&model->lods[i].partBits, &newSurfs->partBits, 16);
|
||||
std::memcpy(&model->lods[i].pad3, &newSurfs->pad, 8);
|
||||
std::memcpy(&model->lods[i].partBits, &newSurfs->partBits, 24);
|
||||
|
||||
short numSurfs = static_cast<short>(newSurfs->numSurfaces);
|
||||
model->lods[i].numSurfs = numSurfs;
|
||||
model->lods[i].maxSurfs = surfCount;
|
||||
model->lods[i].numsurfs = numSurfs;
|
||||
model->lods[i].surfIndex = surfCount;
|
||||
surfCount += numSurfs;
|
||||
|
||||
changed = true;
|
||||
|
@ -1586,10 +1586,7 @@ namespace Game
|
||||
GfxPackedVertex* vertexBuffer; // +28
|
||||
int numCT; // +32
|
||||
XRigidVertList* ct; // +36
|
||||
int partBits[4];
|
||||
char pad5[8]; // +40
|
||||
// pad5 matches XModelSurfaces pad
|
||||
// total size, 64
|
||||
int partBits[6];
|
||||
};
|
||||
|
||||
struct XModelSurfs
|
||||
@ -1597,19 +1594,17 @@ namespace Game
|
||||
const char* name;
|
||||
XSurface* surfaces;
|
||||
int numSurfaces;
|
||||
int partBits[4];
|
||||
char pad[8];
|
||||
int partBits[6];
|
||||
};
|
||||
|
||||
struct XModelLodInfo
|
||||
{
|
||||
float dist;
|
||||
short numSurfs; // +4
|
||||
short maxSurfs;// +6
|
||||
XModelSurfs* surfaces; // +8
|
||||
int partBits[4]; // +12
|
||||
char pad3[8];
|
||||
XSurface* surfs;
|
||||
unsigned __int16 numsurfs;
|
||||
unsigned __int16 surfIndex;
|
||||
XModelSurfs *modelSurfs;
|
||||
int partBits[6];
|
||||
XSurface *surfs;
|
||||
char pad4[4];
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user