diff --git a/docs/SupportedAssetTypes.md b/docs/SupportedAssetTypes.md index 1c57aa57..6597f121 100644 --- a/docs/SupportedAssetTypes.md +++ b/docs/SupportedAssetTypes.md @@ -167,7 +167,7 @@ using `Linker`): | PhysConstraints | ✅ | ❌ | | | DestructibleDef | ❌ | ❌ | | | 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 | ✅ | ✅ | | | MaterialTechniqueSet | ❌ | ❌ | | | GfxImage | ✅ | ✅ | A few special image encodings are not yet supported. | diff --git a/raw/t4/partclassification.csv b/raw/t4/partclassification.csv new file mode 100644 index 00000000..66ac687f --- /dev/null +++ b/raw/t4/partclassification.csv @@ -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 diff --git a/raw/t4/partclassification_mp.csv b/raw/t4/partclassification_mp.csv new file mode 100644 index 00000000..87ee201f --- /dev/null +++ b/raw/t4/partclassification_mp.csv @@ -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 diff --git a/src/Common/Game/T4/T4_Assets.h b/src/Common/Game/T4/T4_Assets.h index 115a4439..efaf5c5c 100644 --- a/src/Common/Game/T4/T4_Assets.h +++ b/src/Common/Game/T4/T4_Assets.h @@ -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; diff --git a/src/ObjCommon/XModel/XModelConstants.h.template b/src/ObjCommon/XModel/XModelConstants.h.template index d075a60b..ee31997e 100644 --- a/src/ObjCommon/XModel/XModelConstants.h.template +++ b/src/ObjCommon/XModel/XModelConstants.h.template @@ -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" diff --git a/src/ObjLoading/Game/T4/ObjLoaderT4.cpp b/src/ObjLoading/Game/T4/ObjLoaderT4.cpp index b0e166aa..ea42584d 100644 --- a/src/ObjLoading/Game/T4/ObjLoaderT4.cpp +++ b/src/ObjLoading/Game/T4/ObjLoaderT4.cpp @@ -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)); diff --git a/src/ObjLoading/XModel/LoaderXModel.cpp.template b/src/ObjLoading/XModel/LoaderXModel.cpp.template index 4d03f301..c07106a5 100644 --- a/src/ObjLoading/XModel/LoaderXModel.cpp.template +++ b/src/ObjLoading/XModel/LoaderXModel.cpp.template @@ -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(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((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(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(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(jXModel.physConstraints.value()); diff --git a/src/ObjLoading/XModel/LoaderXModel.h.template b/src/ObjLoading/XModel/LoaderXModel.h.template index f6668ca2..d343a725 100644 --- a/src/ObjLoading/XModel/LoaderXModel.h.template +++ b/src/ObjLoading/XModel/LoaderXModel.h.template @@ -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"