r5sdk/r5dev/public/studio.h
Rika 10c82e7e64
Model fixup (#91)
* fix header, flags, and add rest of major structs

* minor type swap

* bone flags because there are new ones

* forgor this

* Add compressed vector types.

* fix bitfield sizes

* Fix compilation.

Co-authored-by: Marvin D <41352111+IcePixelx@users.noreply.github.com>
Co-authored-by: rexx <67599507+r-ex@users.noreply.github.com>
2022-12-26 01:42:26 +01:00

1034 lines
28 KiB
C++

#ifndef STUDIO_H
#define STUDIO_H
#include "mathlib/mathlib.h"
#define MAX_NUM_LODS 8
// This flag is set if no hitbox information was specified
#define STUDIOHDR_FLAGS_AUTOGENERATED_HITBOX ( 1 << 0 )
// NOTE: This flag is set at loadtime, not mdl build time so that we don't have to rebuild
// models when we change materials.
#define STUDIOHDR_FLAGS_USES_ENV_CUBEMAP ( 1 << 1 )
// Use this when there are translucent parts to the model but we're not going to sort it
#define STUDIOHDR_FLAGS_FORCE_OPAQUE ( 1 << 2 )
// Use this when we want to render the opaque parts during the opaque pass
// and the translucent parts during the translucent pass
#define STUDIOHDR_FLAGS_TRANSLUCENT_TWOPASS ( 1 << 3 )
// This is set any time the .qc files has $staticprop in it
// Means there's no bones and no transforms
#define STUDIOHDR_FLAGS_STATIC_PROP ( 1 << 4 )
// NOTE: This flag is set at loadtime, not mdl build time so that we don't have to rebuild
// models when we change materials.
#define STUDIOHDR_FLAGS_USES_FB_TEXTURE ( 1 << 5 )
// This flag is set by studiomdl.exe if a separate "$shadowlod" entry was present
// for the .mdl (the shadow lod is the last entry in the lod list if present)
#define STUDIOHDR_FLAGS_HASSHADOWLOD ( 1 << 6 )
// NOTE: This flag is set at loadtime, not mdl build time so that we don't have to rebuild
// models when we change materials.
#define STUDIOHDR_FLAGS_USES_BUMPMAPPING ( 1 << 7 )
// NOTE: This flag is set when we should use the actual materials on the shadow LOD
// instead of overriding them with the default one (necessary for translucent shadows)
#define STUDIOHDR_FLAGS_USE_SHADOWLOD_MATERIALS ( 1 << 8 )
// NOTE: This flag is set when we should use the actual materials on the shadow LOD
// instead of overriding them with the default one (necessary for translucent shadows)
#define STUDIOHDR_FLAGS_OBSOLETE ( 1 << 9 )
// NOTE: This flag is set when we need to draw in the additive stage of the deferred rendering
#define STUDIOHDR_FLAGS_NEEDS_DEFERRED_ADDITIVE ( 1 << 10 )
// NOTE: This flag is set at mdl build time
#define STUDIOHDR_FLAGS_NO_FORCED_FADE ( 1 << 11 )
// NOTE: The npc will lengthen the viseme check to always include two phonemes
#define STUDIOHDR_FLAGS_FORCE_PHONEME_CROSSFADE ( 1 << 12 )
// This flag is set when the .qc has $constantdirectionallight in it
// If set, we use constantdirectionallightdot to calculate light intensity
// rather than the normal directional dot product
// only valid if STUDIOHDR_FLAGS_STATIC_PROP is also set
#define STUDIOHDR_FLAGS_CONSTANT_DIRECTIONAL_LIGHT_DOT ( 1 << 13 )
// This flag indicates that the model has complex weights, which allows it to have 3< weights per bone.
// PREVIOUSLY USED FOR: STUDIOHDR_FLAGS_FLEXES_CONVERTED
#define STUDIOHDR_FLAGS_COMPLEX_WEIGHTS ( 1 << 14 )
// Indicates the studiomdl was built in preview mode
#define STUDIOHDR_FLAGS_BUILT_IN_PREVIEW_MODE ( 1 << 15 )
// Ambient boost (runtime flag)
#define STUDIOHDR_FLAGS_AMBIENT_BOOST ( 1 << 16 )
// Don't cast shadows from this model (useful on first-person models)
#define STUDIOHDR_FLAGS_DO_NOT_CAST_SHADOWS ( 1 << 17 )
// alpha textures should cast shadows in vrad on this model (ONLY prop_static!)
#define STUDIOHDR_FLAGS_CAST_TEXTURE_SHADOWS ( 1 << 18 )
// Model has a quad-only Catmull-Clark SubD cage
#define STUDIOHDR_FLAGS_SUBDIVISION_SURFACE ( 1 << 19 )
// flagged on load to indicate no animation events on this model
#define STUDIOHDR_FLAGS_NO_ANIM_EVENTS ( 1 << 20 )
// If flag is set then studiohdr_t.flVertAnimFixedPointScale contains the
// scale value for fixed point vert anim data, if not set then the
// scale value is the default of 1.0 / 4096.0. Regardless use
// studiohdr_t::VertAnimFixedPointScale() to always retrieve the scale value
#define STUDIOHDR_FLAGS_VERT_ANIM_FIXED_POINT_SCALE ( 1 << 21 )
// unknown purpose but definitely exists
#define STUDIOHDR_FLAGS_RESPAWN_UNK (1 << 23) // 0x800000
// If this flag is present the model has vertex color, and by extension (previously) a VVC (IDVC) file.
#define STUDIOHDR_FLAGS_USES_VERTEX_COLOR (1 << 24) // 0x1000000
// If this flag is present the model has a secondary UV layer, and by extension (previously) a VVC (IDVC) file.
#define STUDIOHDR_FLAGS_USES_UV2 (1 << 25) // 0x2000000
enum
{
STUDIODATA_FLAGS_STUDIOMESH_LOADED = 0x0001,
STUDIODATA_FLAGS_VCOLLISION_LOADED = 0x0002,
STUDIODATA_ERROR_MODEL = 0x0004,
STUDIODATA_FLAGS_NO_STUDIOMESH = 0x0008,
STUDIODATA_FLAGS_NO_VERTEX_DATA = 0x0010,
// = 0x0020, // unused
STUDIODATA_FLAGS_PHYSICS2COLLISION_LOADED = 0x0040,
STUDIODATA_FLAGS_VCOLLISION_SCANNED = 0x0080,
STUDIODATA_FLAGS_COMBINED_PLACEHOLDER = 0x0100,
STUDIODATA_FLAGS_COMBINED = 0x0200,
STUDIODATA_FLAGS_COMBINED_UNAVAILABLE = 0x0400,
STUDIODATA_FLAGS_COMBINED_ASSET = 0x0800,
};
#pragma pack(push, 1)
struct studiohdr_t
{
int id; // 'IDST'
int version; // R5 = '54'
int checksum;
int sznameindex; // This has been moved from studiohdr2 to the front of the main header.
char name[64];
int length; // size of data
Vector3D eyeposition; // ideal eye position
Vector3D illumposition; // illumination center
Vector3D hull_min; // ideal movement hull size
Vector3D hull_max;
Vector3D view_bbmin; // clipping bounding box
Vector3D view_bbmax;
int flags;
int numbones; // bones
int boneindex;
int numbonecontrollers;
int bonecontrollerindex;
int numhitboxsets;
int hitboxsetindex;
int numlocalanim; // animations/poses
int localanimindex; // animation descriptions
int numlocalseq; // sequences
int localseqindex;
int activitylistversion; // initialization flag - have the sequences been indexed ?
int materialtypesindex; // index into an array of byte sized material type enums for each material used by the model
int numtextures;
int textureindex;
int numcdtextures;
int cdtextureindex;
int numskinref; // Total number of references (submeshes)
int numskinfamilies; // Total skins per reference
int skinindex; // Offset to data
int numbodyparts;
int bodypartindex;
int numlocalattachments;
int localattachmentindex;
int numlocalnodes;
int localnodeindex;
int localnodenameindex;
int numunknodes; // ???
int nodedataindexindex; // index into an array of int sized offsets that read into the data for each node
int meshindex; // offset to model meshes
// all flex related model vars and structs are stripped in respawn source
int deprecated_numflexcontrollers;
int deprecated_flexcontrollerindex;
int deprecated_numflexrules;
int deprecated_flexruleindex;
int numikchains;
int ikchainindex;
// mesh panels for using rui on models, primarily for weapons
int numruimeshes;
int ruimeshindex;
int numlocalposeparameters;
int localposeparamindex;
int surfacepropindex;
int keyvalueindex;
int keyvaluesize;
int numlocalikautoplaylocks;
int localikautoplaylockindex;
float mass;
int contents;
// unused for packed models
// technically still functional though I am unsure why you'd want to use it
int numincludemodels;
int includemodelindex;
int virtualModel; // size placeholder
int bonetablebynameindex;
// if STUDIOHDR_FLAGS_CONSTANT_DIRECTIONAL_LIGHT_DOT is set,
// this value is used to calculate directional components of lighting
// on static props
byte constdirectionallightdot;
// set during load of mdl data to track *desired* lod configuration (not actual)
// the *actual* clamped root lod is found in studiohwdata
// this is stored here as a global store to ensure the staged loading matches the rendering
byte rootLOD;
// set in the mdl data to specify that lod configuration should only allow first numAllowRootLODs
// to be set as root LOD:
// numAllowedRootLODs = 0 means no restriction, any lod can be set as root lod.
// numAllowedRootLODs = N means that lod0 - lod(N-1) can be set as root lod, but not lodN or lower.
byte numAllowedRootLODs;
byte unused;
float fadeDist; // fadeDistance
float gatherSize; // gathersize
int deprecated_numflexcontrollerui;
int deprecated_flexcontrolleruiindex;
float flVertAnimFixedPointScale; // to be verified
int surfacepropLookup; // saved in the file
int sourceFilenameOffset; // doesn't actually need to be written pretty sure, only four bytes when not present.
int numsrcbonetransform;
int srcbonetransformindex;
int illumpositionattachmentindex;
int linearboneindex;
// unsure what this is for but it exists for jigglbones
int numprocbones;
int procbonetableindex;
int linearprocboneindex;
// depreciated as they are removed in 12.1
int m_nBoneFlexDriverCount;
int m_nBoneFlexDriverIndex;
int m_nPerTriAABBIndex;
int m_nPerTriAABBNodeCount;
int m_nPerTriAABBLeafCount;
int m_nPerTriAABBVertCount;
// always "" or "Titan"
int unkstringindex;
// this is now used for combined files in rpak, vtx, vvd, and vvc are all combined while vphy is separate.
// the indexes are added to the offset in the rpak mdl_ header.
// vphy isn't vphy, looks like a heavily modified vphy.
int vtxindex; // VTX
int vvdindex; // VVD / IDSV
int vvcindex; // VVC / IDCV
int vphyindex; // VPHY / IVPS
int vtxsize;
int vvdsize;
int vvcsize;
int vphysize; // still used in models using vg
// unused in apex, gets cut in 12.1
int unkmemberindex1;
int numunkmember1;
// only seen on '_animated' suffixed models so far
int unkcount3;
int unkindex3;
// BVH4 size (?)
Vector3D mins;
Vector3D maxs; // seem to be the same as hull size
int unk3_v54[3];
int bvh4index; // bvh4 tree
short unk4_v54[2]; // same as unk3_v54_v121, 2nd might be base for other offsets?
// new in apex vertex weight file for verts that have more than three weights
int vvwindex; // index will come last after other vertex files
int vvwsize;
};
#define BONE_CALCULATE_MASK 0x1F
#define BONE_PHYSICALLY_SIMULATED 0x01 // bone is physically simulated when physics are active
#define BONE_PHYSICS_PROCEDURAL 0x02 // procedural when physics is active
#define BONE_ALWAYS_PROCEDURAL 0x04 // bone is always procedurally animated
#define BONE_SCREEN_ALIGN_SPHERE 0x08 // bone aligns to the screen, not constrained in motion.
#define BONE_SCREEN_ALIGN_CYLINDER 0x10 // bone aligns to the screen, constrained by it's own axis.
#define BONE_USED_BY_IKCHAIN 0x20 // bone is influenced by IK chains, added in V52 (Titanfall 1)
#define BONE_USED_MASK 0x0007FF00
#define BONE_USED_BY_ANYTHING 0x0007FF00
#define BONE_USED_BY_HITBOX 0x00000100 // bone (or child) is used by a hit box
#define BONE_USED_BY_ATTACHMENT 0x00000200 // bone (or child) is used by an attachment point
#define BONE_USED_BY_VERTEX_MASK 0x0003FC00
#define BONE_USED_BY_VERTEX_LOD0 0x00000400 // bone (or child) is used by the toplevel model via skinned vertex
#define BONE_USED_BY_VERTEX_LOD1 0x00000800
#define BONE_USED_BY_VERTEX_LOD2 0x00001000
#define BONE_USED_BY_VERTEX_LOD3 0x00002000
#define BONE_USED_BY_VERTEX_LOD4 0x00004000
#define BONE_USED_BY_VERTEX_LOD5 0x00008000
#define BONE_USED_BY_VERTEX_LOD6 0x00010000
#define BONE_USED_BY_VERTEX_LOD7 0x00020000
// no longer used in apex from what I can tell
//#define BONE_USED_BY_BONE_MERGE 0x00040000 // bone is available for bone merge to occur against it
#define BONE_FLAG_UNK 0x00080000 // respawn flag
#define BONE_USED_BY_VERTEX_AT_LOD(lod) ( BONE_USED_BY_VERTEX_LOD0 << (lod) )
#define BONE_USED_BY_ANYTHING_AT_LOD(lod) ( ( BONE_USED_BY_ANYTHING & ~BONE_USED_BY_VERTEX_MASK ) | BONE_USED_BY_VERTEX_AT_LOD(lod) )
#define BONE_TYPE_MASK 0x00F00000
#define BONE_FIXED_ALIGNMENT 0x00100000 // bone can't spin 360 degrees, all interpolation is normalized around a fixed orientation
#define BONE_HAS_SAVEFRAME_POS 0x00200000 // Vector48
// v48 -> v49 : BONE_HAS_SAVEFRAME_ROT -> BONE_HAS_SAVEFRAME_ROT64
#define BONE_HAS_SAVEFRAME_ROT64 0x00400000 // Quaternion64
#define BONE_HAS_SAVEFRAME_ROT32 0x00800000 // Quaternion32
struct mstudiobone_t
{
int sznameindex;
int parent; // parent bone
int bonecontroller[6]; // bone controller index, -1 == none
// default values
Vector3D pos;
Quaternion quat;
RadianEuler rot;
Vector3D scale; // bone scale(?)
matrix3x4_t poseToBone;
Quaternion qAlignment;
int flags;
int proctype;
int procindex; // procedural rule
int physicsbone; // index into physically simulated bone
int surfacepropidx; // index into string tablefor property name
int contents; // See BSPFlags.h for the contents flags
int surfacepropLookup; // written on compile in v54
int unk;
int unkid; // physics index (?)
};
struct mstudiojigglebone_t
{
byte flags; // looks to be.
unsigned char bone; // id of bone, might be single byte
short pad; // possibly unused
// general params
float length; // how far from bone base, along bone, is tip
float tipMass;
float unkfloat; // v54 adds an extra value here but otherwise the same
// observed values are between 0-1
// flexible params
float yawStiffness;
float yawDamping;
float pitchStiffness;
float pitchDamping;
float alongStiffness;
float alongDamping;
// angle constraint
float angleLimit; // maximum deflection of tip in radians
// yaw constraint
float minYaw; // in radians
float maxYaw; // in radians
float yawFriction;
float yawBounce;
// pitch constraint
float minPitch; // in radians
float maxPitch; // in radians
float pitchFriction;
float pitchBounce;
// base spring
float baseMass;
float baseStiffness;
float baseDamping;
float baseMinLeft;
float baseMaxLeft;
float baseLeftFriction;
float baseMinUp;
float baseMaxUp;
float baseUpFriction;
float baseMinForward;
float baseMaxForward;
float baseForwardFriction;
};
struct mstudioattachment_t
{
int sznameindex;
int flags;
int localbone; // parent bone
matrix3x4_t localmatrix; // attachment point
};
struct mstudiohitboxset_t
{
int sznameindex;
int numhitboxes;
int hitboxindex;
};
struct mstudiobbox_t
{
int bone;
int group; // intersection group
Vector3D bbmin; // bounding box
Vector3D bbmax;
int szhitboxnameindex; // offset to the name of the hitbox.
int critoverride; // overrides the group to be a crit, 0 or 1. might be group override since group 1 is head.
int keyvalueindex; // used for keyvalues, most for titans.
};
// sequence and autolayer flags
#define STUDIO_LOOPING 0x0001 // ending frame should be the same as the starting frame
#define STUDIO_SNAP 0x0002 // do not interpolate between previous animation and this one
#define STUDIO_DELTA 0x0004 // this sequence "adds" to the base sequences, not slerp blends
#define STUDIO_AUTOPLAY 0x0008 // temporary flag that forces the sequence to always play
#define STUDIO_POST 0x0010 //
#define STUDIO_ALLZEROS 0x0020 // this animation/sequence has no real animation data
#define STUDIO_CYCLEPOSE 0x0080 // cycle index is taken from a pose parameter index
#define STUDIO_REALTIME 0x0100 // cycle index is taken from a real-time clock, not the animations cycle index
#define STUDIO_LOCAL 0x0200 // sequence has a local context sequence
#define STUDIO_HIDDEN 0x0400 // don't show in default selection views
#define STUDIO_OVERRIDE 0x0800 // a forward declared sequence (empty)
#define STUDIO_ACTIVITY 0x1000 // Has been updated at runtime to activity index
#define STUDIO_EVENT 0x2000 // Has been updated at runtime to event index on server
#define STUDIO_WORLD 0x4000 // sequence blends in worldspace
#define STUDIO_NOFORCELOOP 0x8000 // do not force the animation loop
#define STUDIO_EVENT_CLIENT 0x10000 // Has been updated at runtime to event index on client
// new in respawn models
// PREVIOUSLY: STUDIO_FRAMEANIM
#define STUDIO_ANIM_UNK3 0x0040 // used on something that is clearly not a frame anim in v54
// animseq/humans/class/heavy/mp_pilot_heavy_core/mp_pt_crypto_base_execution_heavy_victim.rseq
#define STUDIO_ANIM_UNK 0x20000
#define STUDIO_ANIM_UNK1 0x40000
#define STUDIO_ANIM_UNK2 0x80000 // cherry blossom v53, levi in v54
struct mstudioanimdesc_t
{
int baseptr;
int sznameindex;
float fps; // frames per second
int flags; // looping/non-looping flags
int numframes;
// piecewise movement
int nummovements;
int movementindex;
int framemovementindex; // new in v52
int animindex; // non-zero when anim data isn't in sections
int numikrules;
int ikruleindex; // non-zero when IK data is stored in the mdl
int sectionindex;
int sectionframes; // number of frames used in each fast lookup section, zero if not used
};
struct mstudioanimsections_t
{
int animindex;
};
// flags for the per bone array, in 4 bit sections (two sets of flags per byte)
#define STUDIO_ANIM_POS 0x1 // animation has pos values
#define STUDIO_ANIM_ROT 0x2 // animation has rot values
#define STUDIO_ANIM_SCALE 0x4 // animation has scale values
// the actual animation values
union mstudioanimvalue_t
{
struct
{
byte valid; // number of valid frames, or how many frames of data this value has
byte total; // total number of frames, aka "values"
} num;
short value; // actual value, value*posscale
};
struct mstudioanim_valueptr_t
{
char packedoffsets[4]; // packing unknown
};
// flags for the actually per bone animation headers
// "mstudioanim_valueptr_t" indicates it has a set of offsets into anim tracks
#define STUDIO_ANIM_DELTA 0x01 // unverified, animation is additive
#define STUDIO_ANIM_ANIMSCALE 0x01 // mstudioanim_valueptr_t
#define STUDIO_ANIM_ANIMROT 0x02 // mstudioanim_valueptr_t
#define STUDIO_ANIM_ANIMPOS 0x04 // mstudioanim_valueptr_t
struct mstudio_rle_anim_t_v54
{
short size : 13; // total size of all animation data, not nextoffset because even the last one has it
short flags : 3;
// if flag 'STUDIO_ANIM_ANIMPOS' then these two
float posscale;
mstudioanim_valueptr_t pPosV;
// else (static value, no actual animation)
//Vector48 pPos; // type does not exist in R5SDK
// if flag 'STUDIO_ANIM_ANIMROT' then
mstudioanim_valueptr_t pRotV;
// else (static value, no actual animation)
//Quaternion64 pRot; // type does not exist in R5SDK
// if flag 'STUDIO_ANIM_ANIMSCALE' then
mstudioanim_valueptr_t pScaleV;
// else (static value, no actual animation)
//Vector48 pScale; // type does not exist in R5SDK
};
// apex ikerrors do the same thing as apex framemovements
struct mstudiocompressedikerror_t
{
float scale[6]; // these values are the same as what posscale (if it was used) and rotscale are.
int sectionframes; // frames per section, may not match animdesc
};
struct mstudioikrule_t
{
int index;
int type;
int chain;
int bone; // gets it from ikchain now pretty sure
int slot; // iktarget slot. Usually same as chain.
float height;
float radius;
float floor;
Vector3D pos;
Quaternion q;
// apex does this oddly
mstudiocompressedikerror_t compressedikerror;
int compressedikerrorindex;
int iStart;
int ikerrorindex;
float start; // beginning of influence
float peak; // start of full influence
float tail; // end of full influence
float end; // end of all influence
float contact; // frame footstep makes ground concact
float drop; // how far down the foot should drop when reaching for IK
float top; // top of the foot box
int szattachmentindex; // name of world attachment
float endHeight; // new in v52
};
// basically compressedikerrors and frame movements will have an array of offsets that leads into the traditional 'short offset' array, allowing it to have per section (if the anim uses sections) data
struct mstudioframemovement_t
{
float scale[4]; // first three values are the same as what posscale (if it was used) is, fourth is similar to unkvector1.
int sectionframes; // frames per section, may not match animdesc
// may have more than one, even when not section anim
};
struct mstudioseqdesc_t
{
int baseptr;
int szlabelindex;
int szactivitynameindex;
int flags; // looping/non-looping flags
int activity; // initialized at loadtime to game DLL values
int actweight;
int numevents;
int eventindex;
Vector3D bbmin; // per sequence bounding box
Vector3D bbmax;
int numblends;
// Index into array of shorts which is groupsize[0] x groupsize[1] in length
int animindexindex;
int movementindex; // [blend] float array for blended movement
int groupsize[2];
int paramindex[2]; // X, Y, Z, XR, YR, ZR
float paramstart[2]; // local (0..1) starting value
float paramend[2]; // local (0..1) ending value
int paramparent;
float fadeintime; // ideal cross fate in time (0.2 default)
float fadeouttime; // ideal cross fade out time (0.2 default)
int localentrynode; // transition node at entry
int localexitnode; // transition node at exit
int nodeflags; // transition rules
float entryphase; // used to match entry gait
float exitphase; // used to match exit gait
float lastframe; // frame that should generation EndOfSequence
int nextseq; // auto advancing sequences
int pose; // index of delta animation between end and nextseq
int numikrules;
int numautolayers;
int autolayerindex;
int weightlistindex;
int posekeyindex;
int numiklocks;
int iklockindex;
// Key values
int keyvalueindex;
int keyvaluesize;
int cycleposeindex; // index of pose parameter to use as cycle index
int activitymodifierindex;
int numactivitymodifiers;
int ikResetMask; // new in v52
int unk1;
// offset unkindex amount into an array of unkcount 'unkseqdata_t'
int unkindex;
int unkcount;
};
struct mstudioautolayer_t
{
// this needs to have a guid descriptor in rpak
__int64 guidSequence; // hashed aseq guid asset
short iSequence; // only used within an rmdl I would imagine
short iPose;
int flags;
float start; // beginning of influence
float peak; // start of full influence
float tail; // end of full influence
float end; // end of all influence
};
#define NEW_EVENT_STYLE ( 1 << 10 )
struct mstudioevent_t
{
float cycle;
int event;
int type; // this will be 0 if old style
char options[256];
int szeventindex;
};
// will align to four, so takes up eight bytes
struct mstudioactivitymodifier_t_v52
{
int sznameindex;
bool negate; // negate all other activity modifiers when this one is active?
};
struct unkseqdata_t
{
// generally 0-1
float unkfloat;
int unk;
// quaternion mayhaps
float unkfloat1;
float unkfloat2;
float unkfloat3;
float unkfloat4;
};
struct mstudiobodyparts_t
{
int sznameindex;
int nummodels;
int base;
int modelindex; // index into models array
};
struct mstudiomodel_t
{
char name[64];
int unkindex2; // goes to bones sometimes, string index
int type;
float boundingradius;
int nummeshes;
int meshindex;
// cache purposes
int numvertices; // number of unique vertices/normals/texcoords
int vertexindex; // vertex Vector
int tangentsindex; // tangents Vector
int numattachments;
int attachmentindex;
int deprecated_numeyeballs;
int deprecated_eyeballindex;
int pad[4];
int colorindex; // vertex color
// offset by colorindex number of bytes into vvc vertex colors
int uv2index; // vertex second uv map
// offset by uv2index number of bytes into vvc secondary uv map
};
struct mstudio_meshvertexloddata_t
{
int modelvertexdataUnusedPad; // likely has none of the funny stuff because unused
int numLODVertexes[MAX_NUM_LODS]; // depreciated starting with rmdl v14(?)
};
struct mstudiomesh_t
{
int material;
int modelindex;
int numvertices; // number of unique vertices/normals/texcoords
int vertexoffset; // vertex mstudiovertex_t
// Access thin/fat mesh vertex data (only one will return a non-NULL result)
int deprecated_numflexes; // vertex animation
int deprecated_flexindex;
// special codes for material operations
int deprecated_materialtype;
int deprecated_materialparam;
// a unique ordinal for this mesh
int meshid;
Vector3D center;
mstudio_meshvertexloddata_t vertexloddata;
char unk[8]; // these are suposed to be filled on load, however this isn't true??
};
struct mstudioposeparamdesc_t
{
int sznameindex;
int flags; // ????
float start; // starting value
float end; // ending value
float loop; // looping range, 0 for no looping, 360 for rotations, etc.
};
struct mstudioikchain_t
{
int sznameindex;
int linktype;
int numlinks;
int linkindex;
float unk; // no clue what this does tbh, tweaking it does nothing
// default value: 0.707f
};
struct mstudioiklink_t
{
int bone;
Vector3D kneeDir; // no kneeDir in apex I think
};
struct mstudiotexturedir_t
{
int sznameindex; // file name
};
struct mstudiotexture_t
{
int sznameindex;
__int64 guid; // guid of the material it references
};
struct mstudiorruiheader_t
{
int unk; // unsure, it doesn't line up
int ruimeshindex; // offset to the actual rui mesh
};
// vertex map for a face
struct mstudioruivertmap_t
{
// order of vertices for triangles:
// 1st tri: 1-3-2
// 2nd tri: 4-2-3
// sometimes these are for a triangle instead of a quad, if that's the case then:
// tri: 1-4-2
// in this case the vert map will only cover 3 verts.
// in v53 the first two are an array like such:
// 1-3
// while the third is the fourth vert.
short vertid[3];
};
struct mstudioruivert_t
{
int parent; // relative to global mesh parent, assumed
Vector3D vertexpos; // position of vertex relative to bone
};
struct mstudioruimeshface_t
{
// this might be the same as the RPak UIMG UV struct.
// these values are for the two vertices that are not shared
// for the other do as such:
// vertex 2: take x from vextex 1 and y from vextex 4
// vertex 2: take x from vextex 4 and y from vextex 1
// normal smd uv, seems to calculate for other values
Vector2D faceuvmin; // vertex 1
Vector2D faceuvmax; // vertex 4
// these could likely be calculated by doing math with a height/width scale
// scale of the ui element
Vector2D facescalemin; // vertex 1
Vector2D facescalemax; // vertex 4
};
struct mstudioruimesh_t
{
short numparents; // apparently you can have meshes parented to more than one bone(?)
short numvertices; // number of verts
short numfaces; // number of faces (quads)
short unk; // num uvs? or this is num faces and current num faces is num uvs
int parentindex; // this gets padding out front of it to even off the struct
int vertexindex; // offset into smd style vertex data
// not actually fourth vert wtf??
int fourthvertmapindex; // they now fully map the vertices for each quad
int vertmapindex; // offsets into a vertex map for each quad
int facedataindex; // offset into uv section
};
struct mstudiosrcbonetransform_t
{
int sznameindex;
matrix3x4_t pretransform;
matrix3x4_t posttransform;
};
struct mstudiolinearbone_t
{
// they cut pos and rot scale, understandable since posscale was never used it tf|2 and they do anims different in apex
int numbones;
int flagsindex;
int parentindex;
int posindex;
int quatindex;
int rotindex;
int posetoboneindex;
};
struct BVH4Axis_t
{
short minChild0;
short maxChild0;
short minChild1;
short maxChild1;
short minChild2;
short maxChild2;
short minChild3;
short maxChild3;
};
struct BVH4Node_t
{
BVH4Axis_t x;
BVH4Axis_t y;
BVH4Axis_t z;
int pad : 8;
int index0 : 24;
int collision_mask : 8;
int index1 : 24;
int child0_type : 4;
int child1_type : 4;
int index2 : 24;
int child2_type : 4;
int child3_type : 4;
int index3 : 24;
};
#pragma pack(pop)
// studio model data
struct studiomeshdata_t
{
int m_NumGroup;
void* m_pMeshGroup; // studiomeshgroup_t
};
struct studioloddata_t
{
studiomeshdata_t* m_pMeshData;
// !TODO:
};
struct studiohwdata_t
{
int m_RootLOD; // calced and clamped, nonzero for lod culling
int m_NumLODs;
studioloddata_t* m_pLODs;
int m_NumStudioMeshes;
// !TODO:
};
class CStudioHdr
{
public:
static int LookupSequence(CStudioHdr* pStudio, const char* pszName);
int64_t m_nUnk0;
studiohdr_t* m_pStudioHdr;
uint8_t m_Pad[0x85A]; // Compatible between S0 - S3.
void* m_pMdlCacheVTable;
};
class CStudioHWDataRef
{
public:
bool IsDataRef(void) const { return true; }
CStudioHWDataRef* m_pVTable;
uint8_t pad0[0x8];
studiohwdata_t m_HardwareData;
};
#endif // STUDIO_H