XModel import tests

This commit is contained in:
momo5502 2016-06-09 01:26:33 +02:00
parent 276e35e2d2
commit 5a4ddb27d3
6 changed files with 216 additions and 14 deletions

2
deps/protobuf vendored

@ -1 +1 @@
Subproject commit 401e07d3726e91659228dff8ed9f7cb02026c47e
Subproject commit fba7976f5d6f1be69d4219a7c485c93b8b28bf65

View File

@ -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;

View File

@ -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)

View File

@ -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;
};
}

View File

@ -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];

View File

@ -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);