XModel import tests
This commit is contained in:
parent
276e35e2d2
commit
5a4ddb27d3
2
deps/protobuf
vendored
2
deps/protobuf
vendored
@ -1 +1 @@
|
||||
Subproject commit 401e07d3726e91659228dff8ed9f7cb02026c47e
|
||||
Subproject commit fba7976f5d6f1be69d4219a7c485c93b8b28bf65
|
@ -93,8 +93,8 @@ namespace Assets
|
||||
|
||||
textureDef.semantic = 0; // No water image
|
||||
textureDef.sampleState = -30;
|
||||
textureDef.nameEnd = map.string_value().data()[map.string_value().size() - 1];
|
||||
textureDef.nameStart = map.string_value().data()[0];
|
||||
textureDef.nameEnd = map.string_value().back();
|
||||
textureDef.nameStart = map.string_value().front();
|
||||
textureDef.nameHash = Game::R_HashString(map.string_value().data());
|
||||
|
||||
textureDef.info.image = Components::AssetHandler::FindAssetForZone(Game::XAssetType::ASSET_TYPE_IMAGE, image.string_value(), builder).image;
|
||||
|
@ -2,6 +2,147 @@
|
||||
|
||||
namespace Assets
|
||||
{
|
||||
void IXModel::Load(Game::XAssetHeader* header, std::string name, Components::ZoneBuilder::Zone* builder)
|
||||
{
|
||||
Components::FileSystem::File modelFile(Utils::VA("xmodel/%s.iw4xModel", name.data()));
|
||||
|
||||
if (modelFile.Exists())
|
||||
{
|
||||
Game::XModel* baseModel = Components::AssetHandler::FindOriginalAsset(Game::XAssetType::ASSET_TYPE_XMODEL, "viewmodel_mp5k").model;
|
||||
|
||||
// Allocate new model and copy the base data to it
|
||||
Game::XModel* model = builder->GetAllocator()->AllocateArray<Game::XModel>();
|
||||
memcpy(model, baseModel, sizeof(Game::XModel));
|
||||
|
||||
Utils::Stream::Reader reader(builder->GetAllocator(), modelFile.GetBuffer());
|
||||
|
||||
model->name = reader.ReadCString();
|
||||
model->numBones = reader.ReadByte();
|
||||
model->numRootBones = reader.ReadByte();
|
||||
model->numSurfaces = reader.ReadByte();
|
||||
model->numColSurfs = reader.Read<int>();
|
||||
|
||||
// Read bone names
|
||||
model->boneNames = builder->GetAllocator()->AllocateArray<short>(model->numBones);
|
||||
for (int i = 0; i < model->numBones; ++i)
|
||||
{
|
||||
model->boneNames[i] = Game::SL_GetString(reader.ReadCString(), 0);
|
||||
}
|
||||
|
||||
// Bone count
|
||||
int boneCount = (model->numBones - model->numRootBones);
|
||||
|
||||
// Read bone data
|
||||
model->parentList = reader.ReadArray<char>(boneCount);
|
||||
model->tagAngles = reader.ReadArray<Game::XModelAngle>(boneCount);
|
||||
model->tagPositions = reader.ReadArray<Game::XModelTagPos>(boneCount);
|
||||
model->partClassification = reader.ReadArray<char>(boneCount);
|
||||
model->animMatrix = reader.ReadArray<Game::DObjAnimMat>(boneCount);
|
||||
|
||||
// Prepare surfaces
|
||||
Game::XSurface* baseSurface = &baseModel->lods[0].surfaces[0].surfaces[0];
|
||||
Game::XModelSurfs* surf = builder->GetAllocator()->AllocateArray<Game::XModelSurfs>();
|
||||
|
||||
memcpy(surf, baseModel->lods[0].surfaces, sizeof(Game::XModelSurfs));
|
||||
surf->name = builder->GetAllocator()->DuplicateString(Utils::VA("%s1", model->name));
|
||||
surf->surfaces = builder->GetAllocator()->AllocateArray<Game::XSurface>(model->numSurfaces);
|
||||
surf->numSurfaces = model->numSurfaces;
|
||||
|
||||
model->lods[0].numSurfs = model->numSurfaces;
|
||||
model->lods[0].surfaces = surf;
|
||||
|
||||
// Reset surfaces in remaining lods
|
||||
for (unsigned int i = 1; i < 4; ++i)
|
||||
{
|
||||
model->lods[i].numSurfs = 0;
|
||||
model->lods[i].surfaces = nullptr;
|
||||
}
|
||||
|
||||
// Read surfaces
|
||||
for (int i = 0; i < surf->numSurfaces; ++i)
|
||||
{
|
||||
Game::XSurface* surface = &surf->surfaces[i];
|
||||
memcpy(surface, baseSurface, sizeof(Game::XSurface));
|
||||
|
||||
surface->numVertices = reader.Read<unsigned short>();
|
||||
surface->numPrimitives = reader.Read<unsigned short>();
|
||||
surface->numCT = reader.Read<int>();
|
||||
|
||||
surface->blendNum1 = reader.Read<short>();
|
||||
surface->blendNum2 = reader.Read<short>();
|
||||
surface->blendNum3 = reader.Read<short>();
|
||||
surface->blendNum4 = reader.Read<short>();
|
||||
|
||||
surface->blendInfo = reinterpret_cast<char*>(reader.Read(2, surface->blendNum1 + (3 * surface->blendNum2) + (5 * surface->blendNum3) + (7 * surface->blendNum4)));
|
||||
|
||||
surface->vertexBuffer = reader.ReadArray<Game::GfxPackedVertex>(surface->numVertices);
|
||||
surface->indexBuffer = reader.ReadArray<Game::Face>(surface->numPrimitives);
|
||||
|
||||
// Read vert list
|
||||
if (reader.ReadByte())
|
||||
{
|
||||
surface->ct = reader.ReadArray<Game::XRigidVertList>(surface->numCT);
|
||||
|
||||
for (int j = 0; j < surface->numCT; ++j)
|
||||
{
|
||||
Game::XRigidVertList* vertList = &surface->ct[j];
|
||||
|
||||
vertList->entry = reader.ReadArray<Game::XSurfaceCollisionTree>();
|
||||
vertList->entry->node = reinterpret_cast<char*>(reader.Read(16, vertList->entry->numNode));
|
||||
vertList->entry->leaf = reader.ReadArray<short>(vertList->entry->numLeaf);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
surface->ct = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Read materials
|
||||
model->materials = builder->GetAllocator()->AllocateArray<Game::Material*>(model->numSurfaces);
|
||||
for (char i = 0; i < model->numSurfaces; ++i)
|
||||
{
|
||||
model->materials[i] = Components::AssetHandler::FindAssetForZone(Game::XAssetType::ASSET_TYPE_MATERIAL, reader.ReadString(), builder).material;
|
||||
model->materials[i] = baseModel->materials[0];
|
||||
}
|
||||
|
||||
// Read collision surfaces
|
||||
if (reader.ReadByte())
|
||||
{
|
||||
model->colSurf = reader.ReadArray<Game::XModelCollSurf>(model->numColSurfs);
|
||||
|
||||
for (int i = 0; i < model->numColSurfs; ++i)
|
||||
{
|
||||
if (model->colSurf[i].tris)
|
||||
{
|
||||
model->colSurf[i].tris = reader.Read(48, model->colSurf[i].count);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
model->colSurf = nullptr;
|
||||
}
|
||||
|
||||
// Read bone info
|
||||
if (reader.ReadByte())
|
||||
{
|
||||
model->boneInfo = reader.ReadArray<Game::XBoneInfo>(model->numBones);
|
||||
}
|
||||
else
|
||||
{
|
||||
model->boneInfo = nullptr;
|
||||
}
|
||||
|
||||
if (!reader.End())
|
||||
{
|
||||
Components::Logger::Error(0, "Reading model '%s' failed, remaining raw data found!", name.data());
|
||||
}
|
||||
|
||||
header->model = model;
|
||||
}
|
||||
}
|
||||
|
||||
void IXModel::Mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder)
|
||||
{
|
||||
Game::XModel* asset = header.model;
|
||||
@ -186,10 +327,12 @@ namespace Assets
|
||||
|
||||
if (asset->boneInfo)
|
||||
{
|
||||
Assert_Size(Game::XBoneInfo, 28);
|
||||
|
||||
buffer->Align(Utils::Stream::ALIGN_4);
|
||||
|
||||
buffer->Save(asset->boneInfo, 28, asset->numBones);
|
||||
dest->boneInfo = reinterpret_cast<char*>(-1);
|
||||
buffer->SaveArray(asset->boneInfo, asset->numBones);
|
||||
dest->boneInfo = reinterpret_cast<Game::XBoneInfo*>(-1);
|
||||
}
|
||||
|
||||
if (asset->physPreset)
|
||||
|
@ -7,5 +7,6 @@ namespace Assets
|
||||
|
||||
virtual void Save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override;
|
||||
virtual void Mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override;
|
||||
virtual void Load(Game::XAssetHeader* header, std::string name, Components::ZoneBuilder::Zone* builder) override;
|
||||
};
|
||||
}
|
||||
|
@ -1304,7 +1304,8 @@ namespace Game
|
||||
|
||||
struct XSurfaceCollisionTree
|
||||
{
|
||||
char pad[24];
|
||||
float trans[3];
|
||||
float scale[3];
|
||||
int numNode;
|
||||
char* node; // el size 16
|
||||
int numLeaf;
|
||||
@ -1313,8 +1314,10 @@ namespace Game
|
||||
|
||||
struct XRigidVertList
|
||||
{
|
||||
int pad;
|
||||
int pad2;
|
||||
unsigned short boneOffset;
|
||||
unsigned short vertCount;
|
||||
unsigned short triOffset;
|
||||
unsigned short triCount;
|
||||
XSurfaceCollisionTree* entry;
|
||||
};
|
||||
|
||||
@ -1371,7 +1374,9 @@ namespace Game
|
||||
short numSurfs; // +4
|
||||
short pad2;// +6
|
||||
XModelSurfs* surfaces; // +8
|
||||
char pad3[32]; // +12
|
||||
char pad3[24];
|
||||
XSurface* surfs;
|
||||
char pad4[4]; // +12
|
||||
};
|
||||
|
||||
struct cplane_t
|
||||
@ -1461,9 +1466,15 @@ namespace Game
|
||||
bool tempDefaultToCylinder;
|
||||
};
|
||||
|
||||
struct XBoneInfo
|
||||
{
|
||||
float bounds[2][3];
|
||||
float radiusSquared;
|
||||
};
|
||||
|
||||
struct XModel
|
||||
{
|
||||
char* name; // +0
|
||||
const char* name; // +0
|
||||
char numBones; // +4
|
||||
char numRootBones; // +5
|
||||
char numSurfaces; // +6
|
||||
@ -1477,16 +1488,52 @@ namespace Game
|
||||
DObjAnimMat* animMatrix; // +56, element size 32
|
||||
Material** materials; // +60
|
||||
XModelLodInfo lods[4]; // +64
|
||||
int pad4; // +240
|
||||
char pad4;
|
||||
char numLods;
|
||||
short collLod;
|
||||
XModelCollSurf* colSurf; // +244
|
||||
int numColSurfs; // +248
|
||||
int pad6;
|
||||
char* boneInfo; // bone count, +256, element size 28
|
||||
char pad5[36];
|
||||
int contents;
|
||||
XBoneInfo* boneInfo; // bone count, +256, element size 28
|
||||
char pad7[36];
|
||||
PhysPreset* physPreset;
|
||||
PhysCollmap* physCollmap;
|
||||
}; // total size 304
|
||||
|
||||
struct DSkelPartBits
|
||||
{
|
||||
int anim[4];
|
||||
int control[4];
|
||||
int skel[4];
|
||||
};
|
||||
|
||||
struct DSkel
|
||||
{
|
||||
DSkelPartBits partBits;
|
||||
int timeStamp;
|
||||
DObjAnimMat *mat;
|
||||
};
|
||||
|
||||
#pragma pack(push, 2)
|
||||
struct DObj
|
||||
{
|
||||
/*XAnimTree_s*/void *tree;
|
||||
unsigned __int16 duplicateParts;
|
||||
unsigned __int16 entnum;
|
||||
char duplicatePartsSize;
|
||||
char numModels;
|
||||
char numBones;
|
||||
char pad;
|
||||
unsigned int ignoreCollision;
|
||||
volatile int locked;
|
||||
DSkel skel;
|
||||
float radius;
|
||||
int hidePartBits[4];
|
||||
char pad2[56];
|
||||
XModel **models;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
union XAnimDynamicIndices
|
||||
{
|
||||
char _1[1];
|
||||
|
@ -24,6 +24,17 @@ namespace Utils
|
||||
{
|
||||
return reinterpret_cast<T*>(Read(sizeof(T), count));
|
||||
}
|
||||
template <typename T> T Read()
|
||||
{
|
||||
T obj;
|
||||
|
||||
for (unsigned int i = 0; i < sizeof(T); ++i)
|
||||
{
|
||||
reinterpret_cast<char*>(&obj)[i] = ReadByte();
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
bool End();
|
||||
void Seek(unsigned int position);
|
||||
|
Loading…
Reference in New Issue
Block a user