[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);
}
ZeroMemory(model->noScalePartBits, sizeof model->noScalePartBits);
model->name = reader.readCString();
model->numBones = reader.readByte();
model->numRootBones = reader.readByte();
model->numSurfaces = reader.read<unsigned char>();
model->numColSurfs = reader.read<int>();
model->numsurfs = reader.read<unsigned char>();
model->numCollSurfs = reader.read<int>();
model->numLods = static_cast<char>(reader.read<short>());
model->collLod = reader.read<short>();
model->collLod = static_cast<char>(reader.read<short>());
// 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)
{
model->boneNames[i] = Game::SL_GetString(reader.readCString(), 0);
@ -49,32 +51,32 @@ namespace Assets
// Read bone data
model->parentList = reader.readArray<char>(boneCount);
model->tagAngles = reader.readArray<Game::XModelAngle>(boneCount);
model->tagPositions = reader.readArray<Game::XModelTagPos>(boneCount);
model->quats = reader.readArray<short>(boneCount * 4);
model->trans = reader.readArray<float>(boneCount * 3);
model->partClassification = reader.readArray<char>(boneCount);
model->animMatrix = reader.readArray<Game::DObjAnimMat>(boneCount);
model->baseMat = reader.readArray<Game::DObjAnimMat>(boneCount);
// Prepare surfaces
Game::XModelSurfs surf;
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));
surf.surfaces = allocator.allocateArray<Game::XSurface>(model->numSurfaces);
surf.numSurfaces = model->numSurfaces;
std::memcpy(&surf, baseModel->lodInfo[0].modelSurfs, sizeof(Game::XModelSurfs));
surf.surfaces = allocator.allocateArray<Game::XSurface>(model->numsurfs);
surf.numSurfaces = model->numsurfs;
for (int i = 0; i < 4; ++i)
{
model->lods[i].dist = reader.read<float>();
model->lods[i].numsurfs = reader.read<unsigned short>();
model->lods[i].surfIndex = reader.read<unsigned short>();
model->lodInfo[i].dist = reader.read<float>();
model->lodInfo[i].numsurfs = reader.read<unsigned short>();
model->lodInfo[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->lodInfo[i].partBits[0] = reader.read<int>();
model->lodInfo[i].partBits[1] = reader.read<int>();
model->lodInfo[i].partBits[2] = reader.read<int>();
model->lodInfo[i].partBits[3] = reader.read<int>();
model->lodInfo[i].partBits[4] = 0;
model->lodInfo[i].partBits[5] = 0;
}
// Read surfaces
@ -139,42 +141,42 @@ namespace Assets
// 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->numSurfaces = model->lodInfo[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));
std::memcpy(realSurf->surfaces, &surf.surfaces[model->lodInfo[i].surfIndex], sizeof(Game::XSurface) * realSurf->numSurfaces);
std::memcpy(realSurf->partBits, model->lodInfo[i].partBits, sizeof(realSurf->partBits));
model->lods[i].modelSurfs = realSurf;
model->lods[i].surfs = realSurf->surfaces;
model->lodInfo[i].modelSurfs = realSurf;
model->lodInfo[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)
model->materialHandles = builder->getAllocator()->allocateArray<Game::Material*>(model->numsurfs);
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
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
{
model->colSurf = nullptr;
model->collSurfs = nullptr;
}
// 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)
{
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);
}
if (asset->tagAngles)
if (asset->quats)
{
AssertSize(Game::XModelAngle, 8);
buffer->align(Utils::Stream::ALIGN_2);
buffer->saveArray(asset->tagAngles, asset->numBones - asset->numRootBones);
Utils::Stream::ClearPointer(&dest->tagAngles);
buffer->saveArray(asset->quats, (asset->numBones - asset->numRootBones) * 4);
Utils::Stream::ClearPointer(&dest->quats);
}
if (asset->tagPositions)
if (asset->trans)
{
AssertSize(Game::XModelTagPos, 12);
buffer->align(Utils::Stream::ALIGN_4);
buffer->saveArray(asset->tagPositions, asset->numBones - asset->numRootBones);
Utils::Stream::ClearPointer(&dest->tagPositions);
buffer->saveArray(asset->trans, (asset->numBones - asset->numRootBones) * 3);
Utils::Stream::ClearPointer(&dest->trans);
}
if (asset->partClassification)
@ -300,31 +298,31 @@ namespace Assets
Utils::Stream::ClearPointer(&dest->partClassification);
}
if (asset->animMatrix)
if (asset->baseMat)
{
AssertSize(Game::DObjAnimMat, 32);
buffer->align(Utils::Stream::ALIGN_4);
buffer->saveArray(asset->animMatrix, asset->numBones);
Utils::Stream::ClearPointer(&dest->animMatrix);
buffer->saveArray(asset->baseMat, asset->numBones);
Utils::Stream::ClearPointer(&dest->baseMat);
}
if (asset->materials)
if (asset->materialHandles)
{
buffer->align(Utils::Stream::ALIGN_4);
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
@ -333,38 +331,38 @@ namespace Assets
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
if (asset->colSurf)
if (asset->collSurfs)
{
AssertSize(Game::XModelCollSurf, 44);
AssertSize(Game::XModelCollSurf_s, 44);
buffer->align(Utils::Stream::ALIGN_4);
Game::XModelCollSurf* destColSurfs = buffer->dest<Game::XModelCollSurf>();
buffer->saveArray(asset->colSurf, asset->numColSurfs);
Game::XModelCollSurf_s* destColSurfs = buffer->dest<Game::XModelCollSurf_s>();
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* colSurf = &asset->colSurf[i];
Game::XModelCollSurf_s* destCollSurf = &destColSurfs[i];
Game::XModelCollSurf_s* collSurf = &asset->collSurfs[i];
if (colSurf->collTris)
if (collSurf->collTris)
{
buffer->align(Utils::Stream::ALIGN_4);
buffer->save(colSurf->collTris, 48, colSurf->numCollTris);
Utils::Stream::ClearPointer(&destColSurf->collTris);
buffer->save(collSurf->collTris, 48, collSurf->numCollTris);
Utils::Stream::ClearPointer(&destCollSurf->collTris);
}
}
Utils::Stream::ClearPointer(&dest->colSurf);
Utils::Stream::ClearPointer(&dest->collSurfs);
}
if (asset->boneInfo)

View File

@ -152,7 +152,7 @@ namespace Components
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)
{
@ -163,12 +163,12 @@ namespace Components
surfs->surfaces = newSurfs->surfaces;
surfs->numSurfaces = newSurfs->numSurfaces;
model->lods[i].surfs = newSurfs->surfaces;
std::memcpy(&model->lods[i].partBits, &newSurfs->partBits, 24);
model->lodInfo[i].surfs = newSurfs->surfaces;
std::memcpy(&model->lodInfo[i].partBits, &newSurfs->partBits, 24);
short numSurfs = static_cast<short>(newSurfs->numSurfaces);
model->lods[i].numsurfs = numSurfs;
model->lods[i].surfIndex = surfCount;
model->lodInfo[i].numsurfs = numSurfs;
model->lodInfo[i].surfIndex = surfCount;
surfCount += numSurfs;
changed = true;

View File

@ -89,19 +89,19 @@ namespace Components
Game::XModel model[2]; // Allocate 2 models, as we exceed the buffer
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)
{
AssertOffset(Game::XModelLodInfo, partBits, 12);
std::memcpy(&model->lods[i], &xmodel[72 + (i * 56)], 12);
std::memcpy(&model->lods[i].partBits, &xmodel[72 + (i * 56) + 16], 32);
std::memcpy(&model->lodInfo[i], &xmodel[72 + (i * 56)], 12);
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(&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);
model[1].name = reinterpret_cast<char*>(0xDEADC0DE);

View File

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