mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2026-09-08 15:07:06 +00:00
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:
@@ -167,7 +167,7 @@ using `Linker`):
|
|||||||
| PhysConstraints | ✅ | ❌ | |
|
| PhysConstraints | ✅ | ❌ | |
|
||||||
| DestructibleDef | ❌ | ❌ | |
|
| DestructibleDef | ❌ | ❌ | |
|
||||||
| XAnimParts | ✅ | ✅ | |
|
| XAnimParts | ✅ | ✅ | |
|
||||||
| XModel | ✅ | ❌ | Model data can be exported to `XMODEL_EXPORT/XMODEL_BIN`, `OBJ`, `GLB/GLTF`. |
|
| XModel | ✅ | ✅ | Model data can be exported to `XMODEL_EXPORT/XMODEL_BIN`, `OBJ`, `GLB/GLTF`. |
|
||||||
| Material | ✅ | ✅ | |
|
| Material | ✅ | ✅ | |
|
||||||
| MaterialTechniqueSet | ❌ | ❌ | |
|
| MaterialTechniqueSet | ❌ | ❌ | |
|
||||||
| GfxImage | ✅ | ✅ | A few special image encodings are not yet supported. |
|
| GfxImage | ✅ | ✅ | A few special image encodings are not yet supported. |
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
J_Hip_RI,right_leg_upper
|
||||||
|
J_Hip_LE,left_leg_upper
|
||||||
|
J_Knee_RI,right_leg_lower
|
||||||
|
J_SpineUpper,torso_upper
|
||||||
|
J_Knee_LE,left_leg_lower
|
||||||
|
J_Ankle_RI,right_foot
|
||||||
|
J_Ankle_LE,left_foot
|
||||||
|
J_Clavicle_RI,torso_upper
|
||||||
|
J_Clavicle_LE,torso_upper
|
||||||
|
J_Shoulder_RI,right_arm_upper
|
||||||
|
J_Shoulder_LE,left_arm_upper
|
||||||
|
J_Neck,neck
|
||||||
|
J_Head,head
|
||||||
|
J_Elbow_RI,right_arm_lower
|
||||||
|
J_Elbow_LE,left_arm_lower
|
||||||
|
J_Wrist_RI,right_hand
|
||||||
|
J_Wrist_LE,left_hand
|
||||||
|
J_MainRoot,torso_lower
|
||||||
|
TAG_WEAPON_LEFT,gun
|
||||||
|
TAG_WEAPON_RIGHT,gun
|
||||||
|
J_Helmet,helmet
|
||||||
|
@@ -0,0 +1,19 @@
|
|||||||
|
J_Hip_RI,right_leg_upper
|
||||||
|
J_Hip_LE,left_leg_upper
|
||||||
|
J_Knee_RI,right_leg_lower
|
||||||
|
J_SpineUpper,torso_lower
|
||||||
|
J_SpineLower,torso_lower
|
||||||
|
J_MainRoot,torso_lower
|
||||||
|
J_Knee_LE,left_leg_lower
|
||||||
|
J_Ankle_RI,right_foot
|
||||||
|
J_Ankle_LE,left_foot
|
||||||
|
J_Clavicle_RI,torso_upper
|
||||||
|
J_Clavicle_LE,torso_upper
|
||||||
|
J_Shoulder_RI,right_arm_upper
|
||||||
|
J_Shoulder_LE,left_arm_upper
|
||||||
|
J_Neck,neck
|
||||||
|
J_Head,head
|
||||||
|
J_Elbow_RI,right_arm_lower
|
||||||
|
J_Elbow_LE,left_arm_lower
|
||||||
|
J_Wrist_RI,right_hand
|
||||||
|
J_Wrist_LE,left_hand
|
||||||
|
@@ -376,8 +376,8 @@ namespace T4
|
|||||||
|
|
||||||
struct XSurfaceCollisionTree
|
struct XSurfaceCollisionTree
|
||||||
{
|
{
|
||||||
float trans[3];
|
vec3_t trans;
|
||||||
float scale[3];
|
vec3_t scale;
|
||||||
unsigned int nodeCount;
|
unsigned int nodeCount;
|
||||||
XSurfaceCollisionNode* nodes;
|
XSurfaceCollisionNode* nodes;
|
||||||
unsigned int leafCount;
|
unsigned int leafCount;
|
||||||
@@ -591,12 +591,6 @@ namespace T4
|
|||||||
XMODEL_LOD_RAMP_COUNT
|
XMODEL_LOD_RAMP_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
struct XModelHighMipBounds
|
|
||||||
{
|
|
||||||
float mins[3];
|
|
||||||
float maxs[3];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct XModelStreamInfo
|
struct XModelStreamInfo
|
||||||
{
|
{
|
||||||
char pad;
|
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"
|
#filename "Game/" + GAME + "/XModel/XModelConstants" + GAME + ".h"
|
||||||
|
|
||||||
@@ -10,6 +10,8 @@
|
|||||||
#define FEATURE_IW4
|
#define FEATURE_IW4
|
||||||
#elif GAME == "IW5"
|
#elif GAME == "IW5"
|
||||||
#define FEATURE_IW5
|
#define FEATURE_IW5
|
||||||
|
#elif GAME == "T4"
|
||||||
|
#define FEATURE_T4
|
||||||
#elif GAME == "T5"
|
#elif GAME == "T5"
|
||||||
#define FEATURE_T5
|
#define FEATURE_T5
|
||||||
#elif GAME == "T6"
|
#elif GAME == "T6"
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "Game/T4/T4.h"
|
#include "Game/T4/T4.h"
|
||||||
#include "Game/T4/Weapon/AccuracyGraphLoaderT4.h"
|
#include "Game/T4/Weapon/AccuracyGraphLoaderT4.h"
|
||||||
#include "Game/T4/XAnim/XAnimLoaderT4.h"
|
#include "Game/T4/XAnim/XAnimLoaderT4.h"
|
||||||
|
#include "Game/T4/XModel/LoaderXModelT4.h"
|
||||||
#include "Localize/AssetLoaderLocalizeT4.h"
|
#include "Localize/AssetLoaderLocalizeT4.h"
|
||||||
#include "Maps/MapEntsLoaderT4.h"
|
#include "Maps/MapEntsLoaderT4.h"
|
||||||
#include "Material/LoaderMaterialT4.h"
|
#include "Material/LoaderMaterialT4.h"
|
||||||
@@ -101,6 +102,7 @@ namespace
|
|||||||
auto& memory = zone.Memory();
|
auto& memory = zone.Memory();
|
||||||
|
|
||||||
collection.AddAssetCreator(xanim::CreateLoaderT4(memory, searchPath, zone));
|
collection.AddAssetCreator(xanim::CreateLoaderT4(memory, searchPath, zone));
|
||||||
|
collection.AddAssetCreator(xmodel::CreateLoaderT4(memory, searchPath, zone));
|
||||||
collection.AddAssetCreator(image::CreateLoaderEmbeddedT4(memory, searchPath));
|
collection.AddAssetCreator(image::CreateLoaderEmbeddedT4(memory, searchPath));
|
||||||
collection.AddAssetCreator(image::CreateLoaderExternalT4(memory, searchPath));
|
collection.AddAssetCreator(image::CreateLoaderExternalT4(memory, searchPath));
|
||||||
collection.AddAssetCreator(material::CreateLoaderT4(memory, searchPath));
|
collection.AddAssetCreator(material::CreateLoaderT4(memory, searchPath));
|
||||||
|
|||||||
@@ -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"
|
#filename "Game/" + GAME + "/XModel/LoaderXModel" + GAME + ".cpp"
|
||||||
|
|
||||||
@@ -16,6 +16,9 @@
|
|||||||
#elif GAME == "IW5"
|
#elif GAME == "IW5"
|
||||||
#define FEATURE_IW5
|
#define FEATURE_IW5
|
||||||
#define EVEN_TRI_COUNT
|
#define EVEN_TRI_COUNT
|
||||||
|
#elif GAME == "T4"
|
||||||
|
#define FEATURE_T4
|
||||||
|
#define EVEN_TRI_COUNT
|
||||||
#elif GAME == "T5"
|
#elif GAME == "T5"
|
||||||
#define FEATURE_T5
|
#define FEATURE_T5
|
||||||
#define EVEN_TRI_COUNT
|
#define EVEN_TRI_COUNT
|
||||||
@@ -375,7 +378,7 @@ namespace
|
|||||||
{
|
{
|
||||||
xmodel.parentList = m_memory.Alloc<unsigned char>(xmodel.numBones - xmodel.numRootBones);
|
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?
|
// 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);
|
xmodel.trans = m_memory.Alloc<float>((xmodel.numBones - xmodel.numRootBones) * 4u);
|
||||||
#else
|
#else
|
||||||
@@ -429,7 +432,7 @@ namespace
|
|||||||
// Viewhands seem to have nulled trans for some reason?
|
// Viewhands seem to have nulled trans for some reason?
|
||||||
if (jXModel.type.value_or(JsonXModelType::RIGID) == JsonXModelType::VIEWHANDS)
|
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));
|
memset(xmodel.trans, 0, sizeof(float) * 4 * (xmodel.numBones - xmodel.numRootBones));
|
||||||
#else
|
#else
|
||||||
memset(xmodel.trans, 0, sizeof(float) * 3 * (xmodel.numBones - xmodel.numRootBones));
|
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 maxWeightCount = common.m_vertex_bone_weights[xmodelToCommonVertexIndexLookup[xmodelToCommonVertexIndexLookup.size() - 1]].weightCount;
|
||||||
const auto surfaceIsRigid = maxWeightCount <= 1;
|
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;
|
surface.deformed = !surfaceIsRigid;
|
||||||
#else
|
#else
|
||||||
if (!surfaceIsRigid)
|
if (!surfaceIsRigid)
|
||||||
@@ -1114,16 +1117,20 @@ namespace
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(FEATURE_T5) || defined(FEATURE_T6)
|
#if defined(FEATURE_T4) || defined(FEATURE_T5) || defined(FEATURE_T6)
|
||||||
static bool HasAnySkinnedSurfs(const XModel& xmodel)
|
static bool HasAnySkinnedSurfs(const XModel& xmodel)
|
||||||
{
|
{
|
||||||
for (auto lodIndex = 0u; lodIndex < xmodel.numLods; lodIndex++)
|
for (auto lodIndex = 0u; lodIndex < xmodel.numLods; lodIndex++)
|
||||||
{
|
{
|
||||||
const auto& lod = xmodel.lodInfo[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)
|
if (surf.flags & XSURFACE_FLAG_DEFORMED)
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1158,7 +1165,7 @@ namespace
|
|||||||
|
|
||||||
xmodel.numsurfs = static_cast<decltype(XModel::numsurfs)>(m_surfaces.size());
|
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);
|
xmodel.surfs = m_memory.Alloc<XSurface>(xmodel.numsurfs);
|
||||||
memcpy(xmodel.surfs, m_surfaces.data(), sizeof(XSurface) * xmodel.numsurfs);
|
memcpy(xmodel.surfs, m_surfaces.data(), sizeof(XSurface) * xmodel.numsurfs);
|
||||||
#endif
|
#endif
|
||||||
@@ -1180,7 +1187,7 @@ namespace
|
|||||||
else
|
else
|
||||||
xmodel.collLod = -1;
|
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;
|
xmodel.lodRampType = HasAnySkinnedSurfs(xmodel) ? XMODEL_LOD_RAMP_SKINNED : XMODEL_LOD_RAMP_RIGID;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1218,7 +1225,7 @@ namespace
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(FEATURE_T5) || defined(FEATURE_T6)
|
#if defined(FEATURE_T4) || defined(FEATURE_T5) || defined(FEATURE_T6)
|
||||||
if (jXModel.physConstraints)
|
if (jXModel.physConstraints)
|
||||||
{
|
{
|
||||||
auto* physConstraints = context.LoadDependency<AssetPhysConstraints>(jXModel.physConstraints.value());
|
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"
|
#filename "Game/" + GAME + "/XModel/LoaderXModel" + GAME + ".h"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user