diff --git a/src/Components/Modules/AssetInterfaces/IXModel.cpp b/src/Components/Modules/AssetInterfaces/IXModel.cpp index b1ebc945..5249cb7d 100644 --- a/src/Components/Modules/AssetInterfaces/IXModel.cpp +++ b/src/Components/Modules/AssetInterfaces/IXModel.cpp @@ -1,6 +1,6 @@ #include -#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(); model->numColSurfs = reader.read(); + model->numLods = static_cast(reader.read()); + model->collLod = reader.read(); // Read bone names model->boneNames = builder->getAllocator()->allocateArray(model->numBones); @@ -53,41 +55,32 @@ namespace Assets model->animMatrix = reader.readArray(boneCount); // Prepare surfaces - Game::XSurface* baseSurface = &baseModel->lods[0].surfaces[0].surfaces[0]; - Game::XModelSurfs* surf = builder->getAllocator()->allocate(); + 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(model->numSurfaces); - surf->numSurfaces = model->numSurfaces; + std::memcpy(&surf, baseModel->lods[0].modelSurfs, sizeof(Game::XModelSurfs)); + surf.surfaces = allocator.allocateArray(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(); + model->lods[i].numsurfs = reader.read(); + model->lods[i].surfIndex = reader.read(); + + model->lods[i].partBits[0] = reader.read(); + model->lods[i].partBits[1] = reader.read(); + model->lods[i].partBits[2] = reader.read(); + model->lods[i].partBits[3] = reader.read(); + model->lods[i].partBits[4] = 0; + model->lods[i].partBits[5] = 0; } - model->lods[0].dist = reader.read(); - model->lods[0].numSurfs = reader.read(); - model->lods[0].maxSurfs = reader.read(); - - model->lods[0].partBits[0] = reader.read(); - model->lods[0].partBits[1] = reader.read(); - model->lods[0].partBits[2] = reader.read(); - model->lods[0].partBits[3] = reader.read(); - - 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(); @@ -98,6 +91,8 @@ namespace Assets surface->partBits[1] = reader.read(); surface->partBits[2] = reader.read(); surface->partBits[3] = reader.read(); + surface->partBits[4] = 0; + surface->partBits[5] = 0; surface->baseTriIndex = reader.read(); surface->baseVertIndex = reader.read(); @@ -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(); + + // 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(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(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; } } } diff --git a/src/Components/Modules/ModelSurfs.cpp b/src/Components/Modules/ModelSurfs.cpp index 12c2b9b1..cff3f685 100644 --- a/src/Components/Modules/ModelSurfs.cpp +++ b/src/Components/Modules/ModelSurfs.cpp @@ -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(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; diff --git a/src/Game/Structs.hpp b/src/Game/Structs.hpp index 06a1ceff..2f2ade64 100644 --- a/src/Game/Structs.hpp +++ b/src/Game/Structs.hpp @@ -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]; };