[IXModel] Use correct XModel structure

This commit is contained in:
momo5502 2017-01-02 22:35:55 +01:00
parent 85c9488c2a
commit 7d9c588e0e
4 changed files with 112 additions and 122 deletions

View File

@ -29,16 +29,18 @@ namespace Assets
Components::Logger::Error(0, "Reading model '%s' failed, expected version is %d, but it was %d!", name.data(), IW4X_MODEL_VERSION, version); Components::Logger::Error(0, "Reading model '%s' failed, expected version is %d, but it was %d!", name.data(), IW4X_MODEL_VERSION, version);
} }
ZeroMemory(model->noScalePartBits, sizeof model->noScalePartBits);
model->name = reader.readCString(); model->name = reader.readCString();
model->numBones = reader.readByte(); model->numBones = reader.readByte();
model->numRootBones = reader.readByte(); model->numRootBones = reader.readByte();
model->numSurfaces = reader.read<unsigned char>(); model->numsurfs = reader.read<unsigned char>();
model->numColSurfs = reader.read<int>(); model->numCollSurfs = reader.read<int>();
model->numLods = static_cast<char>(reader.read<short>()); model->numLods = static_cast<char>(reader.read<short>());
model->collLod = reader.read<short>(); model->collLod = static_cast<char>(reader.read<short>());
// Read bone names // Read bone names
model->boneNames = builder->getAllocator()->allocateArray<short>(model->numBones); model->boneNames = builder->getAllocator()->allocateArray<unsigned short>(model->numBones);
for (int i = 0; i < model->numBones; ++i) for (int i = 0; i < model->numBones; ++i)
{ {
model->boneNames[i] = Game::SL_GetString(reader.readCString(), 0); model->boneNames[i] = Game::SL_GetString(reader.readCString(), 0);
@ -49,32 +51,32 @@ namespace Assets
// Read bone data // Read bone data
model->parentList = reader.readArray<char>(boneCount); model->parentList = reader.readArray<char>(boneCount);
model->tagAngles = reader.readArray<Game::XModelAngle>(boneCount); model->quats = reader.readArray<short>(boneCount * 4);
model->tagPositions = reader.readArray<Game::XModelTagPos>(boneCount); model->trans = reader.readArray<float>(boneCount * 3);
model->partClassification = reader.readArray<char>(boneCount); model->partClassification = reader.readArray<char>(boneCount);
model->animMatrix = reader.readArray<Game::DObjAnimMat>(boneCount); model->baseMat = reader.readArray<Game::DObjAnimMat>(boneCount);
// Prepare surfaces // Prepare surfaces
Game::XModelSurfs surf; Game::XModelSurfs surf;
Utils::Memory::Allocator allocator; Utils::Memory::Allocator allocator;
Game::XSurface* baseSurface = &baseModel->lods[0].modelSurfs[0].surfaces[0]; Game::XSurface* baseSurface = &baseModel->lodInfo[0].modelSurfs[0].surfaces[0];
std::memcpy(&surf, baseModel->lods[0].modelSurfs, sizeof(Game::XModelSurfs)); std::memcpy(&surf, baseModel->lodInfo[0].modelSurfs, sizeof(Game::XModelSurfs));
surf.surfaces = allocator.allocateArray<Game::XSurface>(model->numSurfaces); surf.surfaces = allocator.allocateArray<Game::XSurface>(model->numsurfs);
surf.numSurfaces = model->numSurfaces; surf.numSurfaces = model->numsurfs;
for (int i = 0; i < 4; ++i) for (int i = 0; i < 4; ++i)
{ {
model->lods[i].dist = reader.read<float>(); model->lodInfo[i].dist = reader.read<float>();
model->lods[i].numsurfs = reader.read<unsigned short>(); model->lodInfo[i].numsurfs = reader.read<unsigned short>();
model->lods[i].surfIndex = reader.read<unsigned short>(); model->lodInfo[i].surfIndex = reader.read<unsigned short>();
model->lods[i].partBits[0] = reader.read<int>(); model->lodInfo[i].partBits[0] = reader.read<int>();
model->lods[i].partBits[1] = reader.read<int>(); model->lodInfo[i].partBits[1] = reader.read<int>();
model->lods[i].partBits[2] = reader.read<int>(); model->lodInfo[i].partBits[2] = reader.read<int>();
model->lods[i].partBits[3] = reader.read<int>(); model->lodInfo[i].partBits[3] = reader.read<int>();
model->lods[i].partBits[4] = 0; model->lodInfo[i].partBits[4] = 0;
model->lods[i].partBits[5] = 0; model->lodInfo[i].partBits[5] = 0;
} }
// Read surfaces // Read surfaces
@ -139,42 +141,42 @@ namespace Assets
// Usually, a binary representation is used for the index, but meh. // 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->name = builder->getAllocator()->duplicateString(fmt::sprintf("%s_lod%d", model->name, i & 0xFF));
realSurf->numSurfaces = model->lods[i].numsurfs; realSurf->numSurfaces = model->lodInfo[i].numsurfs;
realSurf->surfaces = builder->getAllocator()->allocateArray<Game::XSurface>(realSurf->numSurfaces); 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->surfaces, &surf.surfaces[model->lodInfo[i].surfIndex], sizeof(Game::XSurface) * realSurf->numSurfaces);
std::memcpy(realSurf->partBits, model->lods[i].partBits, sizeof(realSurf->partBits)); std::memcpy(realSurf->partBits, model->lodInfo[i].partBits, sizeof(realSurf->partBits));
model->lods[i].modelSurfs = realSurf; model->lodInfo[i].modelSurfs = realSurf;
model->lods[i].surfs = realSurf->surfaces; model->lodInfo[i].surfs = realSurf->surfaces;
// Store surfs for later writing // Store surfs for later writing
Components::AssetHandler::StoreTemporaryAsset(Game::XAssetType::ASSET_TYPE_XMODELSURFS, { realSurf }); Components::AssetHandler::StoreTemporaryAsset(Game::XAssetType::ASSET_TYPE_XMODELSURFS, { realSurf });
} }
// Read materials // Read materials
model->materials = builder->getAllocator()->allocateArray<Game::Material*>(model->numSurfaces); model->materialHandles = builder->getAllocator()->allocateArray<Game::Material*>(model->numsurfs);
for (unsigned char i = 0; i < model->numSurfaces; ++i) for (char i = 0; i < model->numsurfs; ++i)
{ {
model->materials[i] = Components::AssetHandler::FindAssetForZone(Game::XAssetType::ASSET_TYPE_MATERIAL, reader.readString(), builder).material; model->materialHandles[i] = Components::AssetHandler::FindAssetForZone(Game::XAssetType::ASSET_TYPE_MATERIAL, reader.readString(), builder).material;
} }
// Read collision surfaces // Read collision surfaces
if (reader.readByte()) if (reader.readByte())
{ {
model->colSurf = reader.readArray<Game::XModelCollSurf>(model->numColSurfs); model->collSurfs = reader.readArray<Game::XModelCollSurf_s>(model->numCollSurfs);
for (int i = 0; i < model->numColSurfs; ++i) for (int i = 0; i < model->numCollSurfs; ++i)
{ {
if (model->colSurf[i].collTris) if (model->collSurfs[i].collTris)
{ {
model->colSurf[i].collTris = reader.readArray<Game::XModelCollTri_s>(model->colSurf[i].numCollTris); model->collSurfs[i].collTris = reader.readArray<Game::XModelCollTri_s>(model->collSurfs[i].numCollTris);
} }
} }
} }
else else
{ {
model->colSurf = nullptr; model->collSurfs = nullptr;
} }
// Read bone info // Read bone info
@ -208,22 +210,22 @@ namespace Assets
} }
} }
if (asset->materials) if (asset->materialHandles)
{ {
for (unsigned char i = 0; i < asset->numSurfaces; ++i) for (unsigned char i = 0; i < asset->numsurfs; ++i)
{ {
if (asset->materials[i]) if (asset->materialHandles[i])
{ {
builder->loadAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, asset->materials[i]); builder->loadAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, asset->materialHandles[i]);
} }
} }
} }
for (int i = 0; i < 4; ++i) for (int i = 0; i < 4; ++i)
{ {
if (asset->lods[i].modelSurfs) if (asset->lodInfo[i].modelSurfs)
{ {
builder->loadAsset(Game::XAssetType::ASSET_TYPE_XMODELSURFS, asset->lods[i].modelSurfs); builder->loadAsset(Game::XAssetType::ASSET_TYPE_XMODELSURFS, asset->lodInfo[i].modelSurfs);
} }
} }
@ -276,22 +278,18 @@ namespace Assets
Utils::Stream::ClearPointer(&dest->parentList); Utils::Stream::ClearPointer(&dest->parentList);
} }
if (asset->tagAngles) if (asset->quats)
{ {
AssertSize(Game::XModelAngle, 8);
buffer->align(Utils::Stream::ALIGN_2); buffer->align(Utils::Stream::ALIGN_2);
buffer->saveArray(asset->tagAngles, asset->numBones - asset->numRootBones); buffer->saveArray(asset->quats, (asset->numBones - asset->numRootBones) * 4);
Utils::Stream::ClearPointer(&dest->tagAngles); Utils::Stream::ClearPointer(&dest->quats);
} }
if (asset->tagPositions) if (asset->trans)
{ {
AssertSize(Game::XModelTagPos, 12);
buffer->align(Utils::Stream::ALIGN_4); buffer->align(Utils::Stream::ALIGN_4);
buffer->saveArray(asset->tagPositions, asset->numBones - asset->numRootBones); buffer->saveArray(asset->trans, (asset->numBones - asset->numRootBones) * 3);
Utils::Stream::ClearPointer(&dest->tagPositions); Utils::Stream::ClearPointer(&dest->trans);
} }
if (asset->partClassification) if (asset->partClassification)
@ -300,31 +298,31 @@ namespace Assets
Utils::Stream::ClearPointer(&dest->partClassification); Utils::Stream::ClearPointer(&dest->partClassification);
} }
if (asset->animMatrix) if (asset->baseMat)
{ {
AssertSize(Game::DObjAnimMat, 32); AssertSize(Game::DObjAnimMat, 32);
buffer->align(Utils::Stream::ALIGN_4); buffer->align(Utils::Stream::ALIGN_4);
buffer->saveArray(asset->animMatrix, asset->numBones); buffer->saveArray(asset->baseMat, asset->numBones);
Utils::Stream::ClearPointer(&dest->animMatrix); Utils::Stream::ClearPointer(&dest->baseMat);
} }
if (asset->materials) if (asset->materialHandles)
{ {
buffer->align(Utils::Stream::ALIGN_4); buffer->align(Utils::Stream::ALIGN_4);
Game::Material** destMaterials = buffer->dest<Game::Material*>(); Game::Material** destMaterials = buffer->dest<Game::Material*>();
buffer->saveArray(asset->materials, asset->numSurfaces); buffer->saveArray(asset->materialHandles, asset->numsurfs);
for (unsigned char i = 0; i < asset->numSurfaces; ++i) for (unsigned char i = 0; i < asset->numsurfs; ++i)
{ {
if (asset->materials[i]) if (asset->materialHandles[i])
{ {
destMaterials[i] = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, asset->materials[i]).material; destMaterials[i] = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_MATERIAL, asset->materialHandles[i]).material;
} }
} }
Utils::Stream::ClearPointer(&dest->materials); Utils::Stream::ClearPointer(&dest->materialHandles);
} }
// Save_XModelLodInfoArray // Save_XModelLodInfoArray
@ -333,38 +331,38 @@ namespace Assets
for (int i = 0; i < 4; ++i) for (int i = 0; i < 4; ++i)
{ {
if (asset->lods[i].modelSurfs) if (asset->lodInfo[i].modelSurfs)
{ {
dest->lods[i].modelSurfs = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_XMODELSURFS, asset->lods[i].modelSurfs).surfaces; dest->lodInfo[i].modelSurfs = builder->saveSubAsset(Game::XAssetType::ASSET_TYPE_XMODELSURFS, asset->lodInfo[i].modelSurfs).surfaces;
} }
} }
} }
// Save_XModelCollSurfArray // Save_XModelCollSurfArray
if (asset->colSurf) if (asset->collSurfs)
{ {
AssertSize(Game::XModelCollSurf, 44); AssertSize(Game::XModelCollSurf_s, 44);
buffer->align(Utils::Stream::ALIGN_4); buffer->align(Utils::Stream::ALIGN_4);
Game::XModelCollSurf* destColSurfs = buffer->dest<Game::XModelCollSurf>(); Game::XModelCollSurf_s* destColSurfs = buffer->dest<Game::XModelCollSurf_s>();
buffer->saveArray(asset->colSurf, asset->numColSurfs); buffer->saveArray(asset->collSurfs, asset->numCollSurfs);
for (int i = 0; i < asset->numColSurfs; ++i) for (int i = 0; i < asset->numCollSurfs; ++i)
{ {
Game::XModelCollSurf* destColSurf = &destColSurfs[i]; Game::XModelCollSurf_s* destCollSurf = &destColSurfs[i];
Game::XModelCollSurf* colSurf = &asset->colSurf[i]; Game::XModelCollSurf_s* collSurf = &asset->collSurfs[i];
if (colSurf->collTris) if (collSurf->collTris)
{ {
buffer->align(Utils::Stream::ALIGN_4); buffer->align(Utils::Stream::ALIGN_4);
buffer->save(colSurf->collTris, 48, colSurf->numCollTris); buffer->save(collSurf->collTris, 48, collSurf->numCollTris);
Utils::Stream::ClearPointer(&destColSurf->collTris); Utils::Stream::ClearPointer(&destCollSurf->collTris);
} }
} }
Utils::Stream::ClearPointer(&dest->colSurf); Utils::Stream::ClearPointer(&dest->collSurfs);
} }
if (asset->boneInfo) if (asset->boneInfo)

View File

@ -152,7 +152,7 @@ namespace Components
for (char i = 0; i < model->numLods; ++i) for (char i = 0; i < model->numLods; ++i)
{ {
Game::XModelSurfs* surfs = model->lods[i].modelSurfs; Game::XModelSurfs* surfs = model->lodInfo[i].modelSurfs;
if (!surfs->surfaces) if (!surfs->surfaces)
{ {
@ -163,12 +163,12 @@ namespace Components
surfs->surfaces = newSurfs->surfaces; surfs->surfaces = newSurfs->surfaces;
surfs->numSurfaces = newSurfs->numSurfaces; surfs->numSurfaces = newSurfs->numSurfaces;
model->lods[i].surfs = newSurfs->surfaces; model->lodInfo[i].surfs = newSurfs->surfaces;
std::memcpy(&model->lods[i].partBits, &newSurfs->partBits, 24); std::memcpy(&model->lodInfo[i].partBits, &newSurfs->partBits, 24);
short numSurfs = static_cast<short>(newSurfs->numSurfaces); short numSurfs = static_cast<short>(newSurfs->numSurfaces);
model->lods[i].numsurfs = numSurfs; model->lodInfo[i].numsurfs = numSurfs;
model->lods[i].surfIndex = surfCount; model->lodInfo[i].surfIndex = surfCount;
surfCount += numSurfs; surfCount += numSurfs;
changed = true; changed = true;

View File

@ -89,19 +89,19 @@ namespace Components
Game::XModel model[2]; // Allocate 2 models, as we exceed the buffer Game::XModel model[2]; // Allocate 2 models, as we exceed the buffer
std::memcpy(model, xmodel, 36); std::memcpy(model, xmodel, 36);
std::memcpy(&model->pad3[0x1C], &xmodel[44], 28); std::memcpy(&model->boneNames, &xmodel[44], 28);
for (int i = 0; i < 4; ++i) for (int i = 0; i < 4; ++i)
{ {
AssertOffset(Game::XModelLodInfo, partBits, 12); AssertOffset(Game::XModelLodInfo, partBits, 12);
std::memcpy(&model->lods[i], &xmodel[72 + (i * 56)], 12); std::memcpy(&model->lodInfo[i], &xmodel[72 + (i * 56)], 12);
std::memcpy(&model->lods[i].partBits, &xmodel[72 + (i * 56) + 16], 32); std::memcpy(&model->lodInfo[i].partBits, &xmodel[72 + (i * 56) + 16], 32);
std::memcpy(reinterpret_cast<char*>(&model) + (size - 4) - (i * 4), &xmodel[72 + (i * 56) + 12], 4); std::memcpy(reinterpret_cast<char*>(&model) + (size - 4) - (i * 4), &xmodel[72 + (i * 56) + 12], 4);
} }
std::memcpy(&model->lods[3].pad4[0], &xmodel[292], (size - 292 - 4)/*68*/); std::memcpy(&model->lodInfo[3].lod, &xmodel[292], (size - 292 - 4)/*68*/);
std::memcpy(&model->physPreset, &xmodel[(size - 8)], 8); std::memcpy(&model->physPreset, &xmodel[(size - 8)], 8);
model[1].name = reinterpret_cast<char*>(0xDEADC0DE); model[1].name = reinterpret_cast<char*>(0xDEADC0DE);

View File

@ -1517,21 +1517,6 @@ namespace Game
int error; int error;
} structuredDataFindState_t; } structuredDataFindState_t;
struct XModelAngle
{
short x;
short y;
short z;
short base; // defines the 90-degree point for the shorts
};
struct XModelTagPos
{
float x;
float y;
float z;
};
struct XSurfaceCollisionTree struct XSurfaceCollisionTree
{ {
float trans[3]; float trans[3];
@ -1605,7 +1590,10 @@ namespace Game
XModelSurfs *modelSurfs; XModelSurfs *modelSurfs;
int partBits[6]; int partBits[6];
XSurface *surfs; XSurface *surfs;
char pad4[4]; char lod;
char smcBaseIndexPlusOne;
char smcSubIndexMask;
char smcBucket;
}; };
struct cplane_t struct cplane_t
@ -1683,12 +1671,11 @@ namespace Game
float tvec[4]; float tvec[4];
}; };
struct XModelCollSurf struct XModelCollSurf_s
{ {
XModelCollTri_s *collTris; XModelCollTri_s *collTris;
int numCollTris; int numCollTris;
float mins[3]; Bounds bounds;
float maxs[3];
int boneIdx; int boneIdx;
int contents; int contents;
int surfFlags; int surfFlags;
@ -1718,31 +1705,36 @@ namespace Game
struct XModel struct XModel
{ {
const char* name; // +0 const char *name;
char numBones; // +4 char numBones;
char numRootBones; // +5 char numRootBones;
unsigned char numSurfaces; // +6 char numsurfs;
char pad2; // +7 char lodRampType;
char pad3[28]; // +8 float scale;
short* boneNames; // +36 unsigned int noScalePartBits[6];
char* parentList; // +40 unsigned __int16 *boneNames;
XModelAngle* tagAngles; // +44, element size 8 char *parentList;
XModelTagPos* tagPositions; // +48, element size 12 __int16 *quats;
char* partClassification; // +52 float *trans;
DObjAnimMat* animMatrix; // +56, element size 32 char *partClassification;
Material** materials; // +60 DObjAnimMat *baseMat;
XModelLodInfo lods[4]; // +64 Material **materialHandles;
char pad4; XModelLodInfo lodInfo[4];
char maxLoadedLod;
char numLods; char numLods;
short collLod; char collLod;
XModelCollSurf* colSurf; // +244 char flags;
int numColSurfs; // +248 XModelCollSurf_s *collSurfs;
int numCollSurfs;
int contents; int contents;
XBoneInfo* boneInfo; // bone count, +256, element size 28 XBoneInfo *boneInfo;
char pad7[36]; float radius;
Bounds bounds;
int memUsage;
bool bad;
PhysPreset *physPreset; PhysPreset *physPreset;
PhysCollmap *physCollmap; PhysCollmap *physCollmap;
}; // total size 304 };
struct CModelAllocData struct CModelAllocData
{ {