feat: T4 add xmodel loader (#989)

* feat: T4 add xmodel loader

* chore: remove unused xmodel related struct from T4

* fix: allocating too little trans for t4

---------

Co-authored-by: Jan Laupetin <[email protected]>
This commit is contained in:
mo
2026-09-04 19:37:24 +02:00
committed by GitHub
co-authored by Jan Laupetin
parent 2569303de4
commit 61fd267b2b
8 changed files with 66 additions and 21 deletions
+2 -8
View File
@@ -376,8 +376,8 @@ namespace T4
struct XSurfaceCollisionTree
{
float trans[3];
float scale[3];
vec3_t trans;
vec3_t scale;
unsigned int nodeCount;
XSurfaceCollisionNode* nodes;
unsigned int leafCount;
@@ -591,12 +591,6 @@ namespace T4
XMODEL_LOD_RAMP_COUNT
};
struct XModelHighMipBounds
{
float mins[3];
float maxs[3];
};
struct XModelStreamInfo
{
char pad;
@@ -1,4 +1,4 @@
#options GAME (IW3, IW4, IW5, T5, T6)
#options GAME (IW3, IW4, IW5, T4, T5, T6)
#filename "Game/" + GAME + "/XModel/XModelConstants" + GAME + ".h"
@@ -10,6 +10,8 @@
#define FEATURE_IW4
#elif GAME == "IW5"
#define FEATURE_IW5
#elif GAME == "T4"
#define FEATURE_T4
#elif GAME == "T5"
#define FEATURE_T5
#elif GAME == "T6"
+2
View File
@@ -9,6 +9,7 @@
#include "Game/T4/T4.h"
#include "Game/T4/Weapon/AccuracyGraphLoaderT4.h"
#include "Game/T4/XAnim/XAnimLoaderT4.h"
#include "Game/T4/XModel/LoaderXModelT4.h"
#include "Localize/AssetLoaderLocalizeT4.h"
#include "Maps/MapEntsLoaderT4.h"
#include "Material/LoaderMaterialT4.h"
@@ -101,6 +102,7 @@ namespace
auto& memory = zone.Memory();
collection.AddAssetCreator(xanim::CreateLoaderT4(memory, searchPath, zone));
collection.AddAssetCreator(xmodel::CreateLoaderT4(memory, searchPath, zone));
collection.AddAssetCreator(image::CreateLoaderEmbeddedT4(memory, searchPath));
collection.AddAssetCreator(image::CreateLoaderExternalT4(memory, searchPath));
collection.AddAssetCreator(material::CreateLoaderT4(memory, searchPath));
+17 -10
View File
@@ -1,4 +1,4 @@
#options GAME(IW3, IW4, IW5, T5, T6)
#options GAME(IW3, IW4, IW5, T4, T5, T6)
#filename "Game/" + GAME + "/XModel/LoaderXModel" + GAME + ".cpp"
@@ -16,6 +16,9 @@
#elif GAME == "IW5"
#define FEATURE_IW5
#define EVEN_TRI_COUNT
#elif GAME == "T4"
#define FEATURE_T4
#define EVEN_TRI_COUNT
#elif GAME == "T5"
#define FEATURE_T5
#define EVEN_TRI_COUNT
@@ -375,7 +378,7 @@ namespace
{
xmodel.parentList = m_memory.Alloc<unsigned char>(xmodel.numBones - xmodel.numRootBones);
#if defined(FEATURE_IW3) || defined(FEATURE_T5) || defined(FEATURE_T6)
#if defined(FEATURE_IW3) || defined(FEATURE_T4) || defined(FEATURE_T5) || defined(FEATURE_T6)
// For some reason some games allocate for a vec4 here. it is treated as a vec3 though?
xmodel.trans = m_memory.Alloc<float>((xmodel.numBones - xmodel.numRootBones) * 4u);
#else
@@ -429,7 +432,7 @@ namespace
// Viewhands seem to have nulled trans for some reason?
if (jXModel.type.value_or(JsonXModelType::RIGID) == JsonXModelType::VIEWHANDS)
{
#if defined(FEATURE_IW3) || defined(FEATURE_T5) || defined(FEATURE_T6)
#if defined(FEATURE_IW3) || defined(FEATURE_T4) || defined(FEATURE_T5) || defined(FEATURE_T6)
memset(xmodel.trans, 0, sizeof(float) * 4 * (xmodel.numBones - xmodel.numRootBones));
#else
memset(xmodel.trans, 0, sizeof(float) * 3 * (xmodel.numBones - xmodel.numRootBones));
@@ -859,7 +862,7 @@ namespace
const auto maxWeightCount = common.m_vertex_bone_weights[xmodelToCommonVertexIndexLookup[xmodelToCommonVertexIndexLookup.size() - 1]].weightCount;
const auto surfaceIsRigid = maxWeightCount <= 1;
#if defined(FEATURE_IW3) || defined(FEATURE_IW4)
#if defined(FEATURE_IW3) || defined(FEATURE_IW4) || defined(FEATURE_T4)
surface.deformed = !surfaceIsRigid;
#else
if (!surfaceIsRigid)
@@ -1114,16 +1117,20 @@ namespace
#endif
}
#if defined(FEATURE_T5) || defined(FEATURE_T6)
#if defined(FEATURE_T4) || defined(FEATURE_T5) || defined(FEATURE_T6)
static bool HasAnySkinnedSurfs(const XModel& xmodel)
{
for (auto lodIndex = 0u; lodIndex < xmodel.numLods; lodIndex++)
{
const auto& lod = xmodel.lodInfo[lodIndex];
for (auto surfIndex = lod.surfIndex; surfIndex < lod.numsurfs; surfIndex++)
for (auto surfaceOffset = 0u; surfaceOffset < lod.numsurfs; surfaceOffset++)
{
const auto& surf = xmodel.surfs[lod.surfIndex + surfIndex];
const auto& surf = xmodel.surfs[lod.surfIndex + surfaceOffset];
#ifdef FEATURE_T4
if (surf.deformed)
#else
if (surf.flags & XSURFACE_FLAG_DEFORMED)
#endif
return true;
}
}
@@ -1158,7 +1165,7 @@ namespace
xmodel.numsurfs = static_cast<decltype(XModel::numsurfs)>(m_surfaces.size());
#if defined(FEATURE_IW3) || defined(FEATURE_T5) || defined(FEATURE_T6)
#if defined(FEATURE_IW3) || defined(FEATURE_T4) || defined(FEATURE_T5) || defined(FEATURE_T6)
xmodel.surfs = m_memory.Alloc<XSurface>(xmodel.numsurfs);
memcpy(xmodel.surfs, m_surfaces.data(), sizeof(XSurface) * xmodel.numsurfs);
#endif
@@ -1180,7 +1187,7 @@ namespace
else
xmodel.collLod = -1;
#if defined(FEATURE_T5) || defined(FEATURE_T6)
#if defined(FEATURE_T4) || defined(FEATURE_T5) || defined(FEATURE_T6)
xmodel.lodRampType = HasAnySkinnedSurfs(xmodel) ? XMODEL_LOD_RAMP_SKINNED : XMODEL_LOD_RAMP_RIGID;
#endif
@@ -1218,7 +1225,7 @@ namespace
}
#endif
#if defined(FEATURE_T5) || defined(FEATURE_T6)
#if defined(FEATURE_T4) || defined(FEATURE_T5) || defined(FEATURE_T6)
if (jXModel.physConstraints)
{
auto* physConstraints = context.LoadDependency<AssetPhysConstraints>(jXModel.physConstraints.value());
@@ -1,4 +1,4 @@
#options GAME (IW3, IW4, IW5, T5, T6)
#options GAME (IW3, IW4, IW5, T4, T5, T6)
#filename "Game/" + GAME + "/XModel/LoaderXModel" + GAME + ".h"