mirror of
https://github.com/0TheSpy/Seaside.git
synced 2025-01-11 11:33:01 +08:00
2781 lines
79 KiB
C
2781 lines
79 KiB
C
|
#ifndef STUDIO_H
|
||
|
#define STUDIO_H
|
||
|
|
||
|
#ifdef _WIN32
|
||
|
#pragma once
|
||
|
#endif
|
||
|
|
||
|
#include "basetypes.h"
|
||
|
#include "vector2d.h"
|
||
|
#include "vector.h"
|
||
|
#include "vector4d.h"
|
||
|
#include "compressed_vector.h"
|
||
|
#include "dbg.h"
|
||
|
#include "threadtools.h"
|
||
|
#include "mathlib.h"
|
||
|
#include "utlvector.h"
|
||
|
#include "utlhash.h"
|
||
|
#include "datamap.h"
|
||
|
#include "generichash.h"
|
||
|
#include "localflexcontroller.h"
|
||
|
#include "utlsymbol.h"
|
||
|
|
||
|
#define STUDIO_ENABLE_PERF_COUNTERS
|
||
|
|
||
|
#define STUDIO_SEQUENCE_ACTIVITY_LOOKUPS_ARE_SLOW 0
|
||
|
#define STUDIO_SEQUENCE_ACTIVITY_LAZY_INITIALIZE 1
|
||
|
|
||
|
class IMaterial;
|
||
|
class IMesh;
|
||
|
class IMorph;
|
||
|
struct virtualmodel_t;
|
||
|
struct vertexFileHeader_t;
|
||
|
struct thinModelVertices_t;
|
||
|
|
||
|
namespace OptimizedModel
|
||
|
{
|
||
|
struct StripHeader_t;
|
||
|
}
|
||
|
|
||
|
|
||
|
#define STUDIO_VERSION 48
|
||
|
|
||
|
#ifndef _XBOX
|
||
|
#define MAXSTUDIOTRIANGLES 65536
|
||
|
#define MAXSTUDIOVERTS 65536
|
||
|
#define MAXSTUDIOFLEXVERTS 10000
|
||
|
#else
|
||
|
#define MAXSTUDIOTRIANGLES 25000
|
||
|
#define MAXSTUDIOVERTS 10000
|
||
|
#define MAXSTUDIOFLEXVERTS 1000
|
||
|
#endif
|
||
|
#define MAXSTUDIOSKINS 32
|
||
|
#define MAXSTUDIOBONES 128
|
||
|
#define MAXSTUDIOFLEXDESC 1024
|
||
|
#define MAXSTUDIOFLEXCTRL 96
|
||
|
#define MAXSTUDIOPOSEPARAM 24
|
||
|
#define MAXSTUDIOBONECTRLS 4
|
||
|
#define MAXSTUDIOANIMBLOCKS 256
|
||
|
|
||
|
#define MAXSTUDIOBONEBITS 7
|
||
|
|
||
|
#define MAX_NUM_BONES_PER_VERT 3
|
||
|
|
||
|
#define NEW_EVENT_STYLE ( 1 << 10 )
|
||
|
|
||
|
struct mstudiodata_t
|
||
|
{
|
||
|
int count;
|
||
|
int offset;
|
||
|
};
|
||
|
|
||
|
#define STUDIO_PROC_AXISINTERP 1
|
||
|
#define STUDIO_PROC_QUATINTERP 2
|
||
|
#define STUDIO_PROC_AIMATBONE 3
|
||
|
#define STUDIO_PROC_AIMATATTACH 4
|
||
|
#define STUDIO_PROC_JIGGLE 5
|
||
|
|
||
|
struct mstudioaxisinterpbone_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
int control;
|
||
|
int axis;
|
||
|
Vector pos[6];
|
||
|
Quaternion quat[6];
|
||
|
|
||
|
mstudioaxisinterpbone_t() {}
|
||
|
private:
|
||
|
mstudioaxisinterpbone_t(const mstudioaxisinterpbone_t& vOther);
|
||
|
};
|
||
|
|
||
|
|
||
|
struct mstudioquatinterpinfo_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
float inv_tolerance;
|
||
|
Quaternion trigger;
|
||
|
Vector pos;
|
||
|
Quaternion quat;
|
||
|
|
||
|
mstudioquatinterpinfo_t() {}
|
||
|
private:
|
||
|
mstudioquatinterpinfo_t(const mstudioquatinterpinfo_t& vOther);
|
||
|
};
|
||
|
|
||
|
struct mstudioquatinterpbone_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
int control;
|
||
|
int numtriggers;
|
||
|
int triggerindex;
|
||
|
inline mstudioquatinterpinfo_t* pTrigger(int i) const { return (mstudioquatinterpinfo_t*)(((byte*)this) + triggerindex) + i; };
|
||
|
|
||
|
mstudioquatinterpbone_t() {}
|
||
|
private:
|
||
|
mstudioquatinterpbone_t(const mstudioquatinterpbone_t& vOther);
|
||
|
};
|
||
|
|
||
|
|
||
|
#define JIGGLE_IS_FLEXIBLE 0x01
|
||
|
#define JIGGLE_IS_RIGID 0x02
|
||
|
#define JIGGLE_HAS_YAW_CONSTRAINT 0x04
|
||
|
#define JIGGLE_HAS_PITCH_CONSTRAINT 0x08
|
||
|
#define JIGGLE_HAS_ANGLE_CONSTRAINT 0x10
|
||
|
#define JIGGLE_HAS_LENGTH_CONSTRAINT 0x20
|
||
|
#define JIGGLE_HAS_BASE_SPRING 0x40
|
||
|
#define JIGGLE_IS_BOING 0x80
|
||
|
|
||
|
struct mstudiojigglebone_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
|
||
|
int flags;
|
||
|
|
||
|
float length;
|
||
|
float tipMass;
|
||
|
|
||
|
float yawStiffness;
|
||
|
float yawDamping;
|
||
|
float pitchStiffness;
|
||
|
float pitchDamping;
|
||
|
float alongStiffness;
|
||
|
float alongDamping;
|
||
|
|
||
|
float angleLimit;
|
||
|
|
||
|
float minYaw;
|
||
|
float maxYaw;
|
||
|
float yawFriction;
|
||
|
float yawBounce;
|
||
|
|
||
|
float minPitch;
|
||
|
float maxPitch;
|
||
|
float pitchFriction;
|
||
|
float pitchBounce;
|
||
|
|
||
|
float baseMass;
|
||
|
float baseStiffness;
|
||
|
float baseDamping;
|
||
|
float baseMinLeft;
|
||
|
float baseMaxLeft;
|
||
|
float baseLeftFriction;
|
||
|
float baseMinUp;
|
||
|
float baseMaxUp;
|
||
|
float baseUpFriction;
|
||
|
float baseMinForward;
|
||
|
float baseMaxForward;
|
||
|
float baseForwardFriction;
|
||
|
|
||
|
float boingImpactSpeed;
|
||
|
float boingImpactAngle;
|
||
|
float boingDampingRate;
|
||
|
float boingFrequency;
|
||
|
float boingAmplitude;
|
||
|
|
||
|
private:
|
||
|
};
|
||
|
|
||
|
struct mstudioaimatbone_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
|
||
|
int parent;
|
||
|
int aim;
|
||
|
Vector aimvector;
|
||
|
Vector upvector;
|
||
|
Vector basepos;
|
||
|
|
||
|
mstudioaimatbone_t() {}
|
||
|
private:
|
||
|
mstudioaimatbone_t(const mstudioaimatbone_t& vOther);
|
||
|
};
|
||
|
|
||
|
struct mstudiobone_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
int sznameindex;
|
||
|
inline char* const pszName(void) const { return ((char*)this) + sznameindex; }
|
||
|
int parent;
|
||
|
int bonecontroller[6];
|
||
|
|
||
|
Vector pos;
|
||
|
Quaternion quat;
|
||
|
RadianEuler rot;
|
||
|
Vector posscale;
|
||
|
Vector rotscale;
|
||
|
|
||
|
matrix3x4_t poseToBone;
|
||
|
Quaternion qAlignment;
|
||
|
int flags;
|
||
|
int proctype;
|
||
|
int procindex;
|
||
|
mutable int physicsbone;
|
||
|
inline void* pProcedure() const { if (procindex == 0) return NULL; else return (void*)(((byte*)this) + procindex); };
|
||
|
int surfacepropidx;
|
||
|
inline char* const pszSurfaceProp(void) const { return ((char*)this) + surfacepropidx; }
|
||
|
int contents;
|
||
|
|
||
|
int unused[8];
|
||
|
|
||
|
mstudiobone_t() {}
|
||
|
private:
|
||
|
mstudiobone_t(const mstudiobone_t& vOther);
|
||
|
};
|
||
|
|
||
|
struct mstudiolinearbone_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
|
||
|
int numbones;
|
||
|
|
||
|
int flagsindex;
|
||
|
inline int flags(int i) const { Assert(i >= 0 && i < numbones); return *((int*)(((byte*)this) + flagsindex) + i); };
|
||
|
inline int* pflags(int i) { Assert(i >= 0 && i < numbones); return ((int*)(((byte*)this) + flagsindex) + i); };
|
||
|
|
||
|
int parentindex;
|
||
|
inline int parent(int i) const { Assert(i >= 0 && i < numbones); return *((int*)(((byte*)this) + parentindex) + i); };
|
||
|
|
||
|
int posindex;
|
||
|
inline Vector pos(int i) const { Assert(i >= 0 && i < numbones); return *((Vector*)(((byte*)this) + posindex) + i); };
|
||
|
|
||
|
int quatindex;
|
||
|
inline Quaternion quat(int i) const { Assert(i >= 0 && i < numbones); return *((Quaternion*)(((byte*)this) + quatindex) + i); };
|
||
|
|
||
|
int rotindex;
|
||
|
inline RadianEuler rot(int i) const { Assert(i >= 0 && i < numbones); return *((RadianEuler*)(((byte*)this) + rotindex) + i); };
|
||
|
|
||
|
int posetoboneindex;
|
||
|
inline matrix3x4_t poseToBone(int i) const { Assert(i >= 0 && i < numbones); return *((matrix3x4_t*)(((byte*)this) + posetoboneindex) + i); };
|
||
|
|
||
|
int posscaleindex;
|
||
|
inline Vector posscale(int i) const { Assert(i >= 0 && i < numbones); return *((Vector*)(((byte*)this) + posscaleindex) + i); };
|
||
|
|
||
|
int rotscaleindex;
|
||
|
inline Vector rotscale(int i) const { Assert(i >= 0 && i < numbones); return *((Vector*)(((byte*)this) + rotscaleindex) + i); };
|
||
|
|
||
|
int qalignmentindex;
|
||
|
inline Quaternion qalignment(int i) const { Assert(i >= 0 && i < numbones); return *((Quaternion*)(((byte*)this) + qalignmentindex) + i); };
|
||
|
|
||
|
int unused[6];
|
||
|
|
||
|
mstudiolinearbone_t() {}
|
||
|
private:
|
||
|
mstudiolinearbone_t(const mstudiolinearbone_t& vOther);
|
||
|
};
|
||
|
|
||
|
|
||
|
enum StudioBoneFlexComponent_t
|
||
|
{
|
||
|
STUDIO_BONE_FLEX_INVALID = -1,
|
||
|
STUDIO_BONE_FLEX_TX = 0,
|
||
|
STUDIO_BONE_FLEX_TY = 1,
|
||
|
STUDIO_BONE_FLEX_TZ = 2
|
||
|
};
|
||
|
|
||
|
|
||
|
struct mstudioboneflexdrivercontrol_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
|
||
|
int m_nBoneComponent;
|
||
|
int m_nFlexControllerIndex;
|
||
|
float m_flMin;
|
||
|
float m_flMax;
|
||
|
|
||
|
mstudioboneflexdrivercontrol_t() {}
|
||
|
private:
|
||
|
mstudioboneflexdrivercontrol_t(const mstudioboneflexdrivercontrol_t& vOther);
|
||
|
};
|
||
|
|
||
|
|
||
|
struct mstudioboneflexdriver_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
|
||
|
int m_nBoneIndex;
|
||
|
int m_nControlCount;
|
||
|
int m_nControlIndex;
|
||
|
|
||
|
inline mstudioboneflexdrivercontrol_t* pBoneFlexDriverControl(int i) const
|
||
|
{
|
||
|
Assert(i >= 0 && i < m_nControlCount);
|
||
|
return (mstudioboneflexdrivercontrol_t*)(((byte*)this) + m_nControlIndex) + i;
|
||
|
}
|
||
|
|
||
|
int unused[3];
|
||
|
|
||
|
mstudioboneflexdriver_t() {}
|
||
|
private:
|
||
|
mstudioboneflexdriver_t(const mstudioboneflexdriver_t& vOther);
|
||
|
};
|
||
|
|
||
|
|
||
|
#define BONE_CALCULATE_MASK 0x1F
|
||
|
#define BONE_PHYSICALLY_SIMULATED 0x01
|
||
|
#define BONE_PHYSICS_PROCEDURAL 0x02
|
||
|
#define BONE_ALWAYS_PROCEDURAL 0x04
|
||
|
#define BONE_SCREEN_ALIGN_SPHERE 0x08
|
||
|
#define BONE_SCREEN_ALIGN_CYLINDER 0x10
|
||
|
|
||
|
#define BONE_USED_MASK 0x0007FF00
|
||
|
#define BONE_USED_BY_ANYTHING 0x0007FF00
|
||
|
#define BONE_USED_BY_HITBOX 0x00000100
|
||
|
#define BONE_USED_BY_ATTACHMENT 0x00000200
|
||
|
#define BONE_USED_BY_VERTEX_MASK 0x0003FC00
|
||
|
#define BONE_USED_BY_VERTEX_LOD0 0x00000400
|
||
|
#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
|
||
|
#define BONE_USED_BY_BONE_MERGE 0x00040000
|
||
|
|
||
|
#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 MAX_NUM_LODS 8
|
||
|
|
||
|
#define BONE_TYPE_MASK 0x00F00000
|
||
|
#define BONE_FIXED_ALIGNMENT 0x00100000
|
||
|
|
||
|
#define BONE_HAS_SAVEFRAME_POS 0x00200000
|
||
|
#define BONE_HAS_SAVEFRAME_ROT 0x00400000
|
||
|
|
||
|
struct mstudiobonecontroller_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
int bone;
|
||
|
int type;
|
||
|
float start;
|
||
|
float end;
|
||
|
int rest;
|
||
|
int inputfield;
|
||
|
int unused[8];
|
||
|
};
|
||
|
|
||
|
struct mstudiobbox_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
int bone;
|
||
|
int group;
|
||
|
Vector bbmin;
|
||
|
Vector bbmax;
|
||
|
int szhitboxnameindex;
|
||
|
int unused[8];
|
||
|
|
||
|
const char* pszHitboxName()
|
||
|
{
|
||
|
if (szhitboxnameindex == 0)
|
||
|
return "";
|
||
|
|
||
|
return ((const char*)this) + szhitboxnameindex;
|
||
|
}
|
||
|
|
||
|
mstudiobbox_t() {}
|
||
|
|
||
|
private:
|
||
|
mstudiobbox_t(const mstudiobbox_t& vOther);
|
||
|
};
|
||
|
|
||
|
struct mstudiomodelgroup_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
int szlabelindex;
|
||
|
inline char* const pszLabel(void) const { return ((char*)this) + szlabelindex; }
|
||
|
int sznameindex;
|
||
|
inline char* const pszName(void) const { return ((char*)this) + sznameindex; }
|
||
|
};
|
||
|
|
||
|
struct mstudiomodelgrouplookup_t
|
||
|
{
|
||
|
int modelgroup;
|
||
|
int indexwithingroup;
|
||
|
};
|
||
|
|
||
|
struct mstudioevent_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
float cycle;
|
||
|
int event;
|
||
|
int type;
|
||
|
inline const char* pszOptions(void) const { return options; }
|
||
|
char options[64];
|
||
|
|
||
|
int szeventindex;
|
||
|
inline char* const pszEventName(void) const { return ((char*)this) + szeventindex; }
|
||
|
};
|
||
|
|
||
|
#define ATTACHMENT_FLAG_WORLD_ALIGN 0x10000
|
||
|
|
||
|
struct mstudioattachment_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
int sznameindex;
|
||
|
inline char* const pszName(void) const { return ((char*)this) + sznameindex; }
|
||
|
unsigned int flags;
|
||
|
int localbone;
|
||
|
matrix3x4_t local;
|
||
|
int unused[8];
|
||
|
};
|
||
|
|
||
|
#define IK_SELF 1
|
||
|
#define IK_WORLD 2
|
||
|
#define IK_GROUND 3
|
||
|
#define IK_RELEASE 4
|
||
|
#define IK_ATTACHMENT 5
|
||
|
#define IK_UNLATCH 6
|
||
|
|
||
|
struct mstudioikerror_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
Vector pos;
|
||
|
Quaternion q;
|
||
|
|
||
|
mstudioikerror_t() {}
|
||
|
|
||
|
private:
|
||
|
mstudioikerror_t(const mstudioikerror_t& vOther);
|
||
|
};
|
||
|
|
||
|
union mstudioanimvalue_t;
|
||
|
|
||
|
struct mstudiocompressedikerror_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
float scale[6];
|
||
|
short offset[6];
|
||
|
inline mstudioanimvalue_t* pAnimvalue(int i) const { if (offset[i] > 0) return (mstudioanimvalue_t*)(((byte*)this) + offset[i]); else return NULL; };
|
||
|
mstudiocompressedikerror_t() {}
|
||
|
|
||
|
private:
|
||
|
mstudiocompressedikerror_t(const mstudiocompressedikerror_t& vOther);
|
||
|
};
|
||
|
|
||
|
struct mstudioikrule_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
int index;
|
||
|
|
||
|
int type;
|
||
|
int chain;
|
||
|
|
||
|
int bone;
|
||
|
|
||
|
int slot;
|
||
|
float height;
|
||
|
float radius;
|
||
|
float floor;
|
||
|
Vector pos;
|
||
|
Quaternion q;
|
||
|
|
||
|
int compressedikerrorindex;
|
||
|
inline mstudiocompressedikerror_t* pCompressedError() const { return (mstudiocompressedikerror_t*)(((byte*)this) + compressedikerrorindex); };
|
||
|
int unused2;
|
||
|
|
||
|
int iStart;
|
||
|
int ikerrorindex;
|
||
|
inline mstudioikerror_t* pError(int i) const { return (ikerrorindex) ? (mstudioikerror_t*)(((byte*)this) + ikerrorindex) + (i - iStart) : NULL; };
|
||
|
|
||
|
float start;
|
||
|
float peak;
|
||
|
float tail;
|
||
|
float end;
|
||
|
|
||
|
float unused3;
|
||
|
float contact;
|
||
|
float drop;
|
||
|
float top;
|
||
|
|
||
|
int unused6;
|
||
|
int unused7;
|
||
|
int unused8;
|
||
|
|
||
|
int szattachmentindex;
|
||
|
inline char* const pszAttachment(void) const { return ((char*)this) + szattachmentindex; }
|
||
|
|
||
|
int unused[7];
|
||
|
|
||
|
mstudioikrule_t() {}
|
||
|
|
||
|
private:
|
||
|
mstudioikrule_t(const mstudioikrule_t& vOther);
|
||
|
};
|
||
|
|
||
|
|
||
|
struct mstudioiklock_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
int chain;
|
||
|
float flPosWeight;
|
||
|
float flLocalQWeight;
|
||
|
int flags;
|
||
|
|
||
|
int unused[4];
|
||
|
};
|
||
|
|
||
|
|
||
|
struct mstudiolocalhierarchy_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
int iBone;
|
||
|
int iNewParent;
|
||
|
|
||
|
float start;
|
||
|
float peak;
|
||
|
float tail;
|
||
|
float end;
|
||
|
|
||
|
int iStart;
|
||
|
|
||
|
int localanimindex;
|
||
|
inline mstudiocompressedikerror_t* pLocalAnim() const { return (mstudiocompressedikerror_t*)(((byte*)this) + localanimindex); };
|
||
|
|
||
|
int unused[4];
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
union mstudioanimvalue_t
|
||
|
{
|
||
|
struct
|
||
|
{
|
||
|
byte valid;
|
||
|
byte total;
|
||
|
} num;
|
||
|
short value;
|
||
|
};
|
||
|
|
||
|
struct mstudioanim_valueptr_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
short offset[3];
|
||
|
inline mstudioanimvalue_t* pAnimvalue(int i) const { if (offset[i] > 0) return (mstudioanimvalue_t*)(((byte*)this) + offset[i]); else return NULL; };
|
||
|
};
|
||
|
|
||
|
#define STUDIO_ANIM_RAWPOS 0x01
|
||
|
#define STUDIO_ANIM_RAWROT 0x02
|
||
|
#define STUDIO_ANIM_ANIMPOS 0x04
|
||
|
#define STUDIO_ANIM_ANIMROT 0x08
|
||
|
#define STUDIO_ANIM_DELTA 0x10
|
||
|
#define STUDIO_ANIM_RAWROT2 0x20
|
||
|
|
||
|
|
||
|
struct mstudioanim_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
byte bone;
|
||
|
byte flags;
|
||
|
|
||
|
inline byte* pData(void) const { return (((byte*)this) + sizeof(struct mstudioanim_t)); };
|
||
|
inline mstudioanim_valueptr_t* pRotV(void) const { return (mstudioanim_valueptr_t*)(pData()); };
|
||
|
inline mstudioanim_valueptr_t* pPosV(void) const { return (mstudioanim_valueptr_t*)(pData()) + ((flags & STUDIO_ANIM_ANIMROT) != 0); };
|
||
|
|
||
|
inline Quaternion48* pQuat48(void) const { return (Quaternion48*)(pData()); };
|
||
|
inline Quaternion64* pQuat64(void) const { return (Quaternion64*)(pData()); };
|
||
|
inline Vector48* pPos(void) const { return (Vector48*)(pData() + ((flags & STUDIO_ANIM_RAWROT) != 0) * sizeof(*pQuat48()) + ((flags & STUDIO_ANIM_RAWROT2) != 0) * sizeof(*pQuat64())); };
|
||
|
|
||
|
short nextoffset;
|
||
|
inline mstudioanim_t* pNext(void) const { if (nextoffset != 0) return (mstudioanim_t*)(((byte*)this) + nextoffset); else return NULL; };
|
||
|
};
|
||
|
|
||
|
struct mstudiomovement_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
int endframe;
|
||
|
int motionflags;
|
||
|
float v0;
|
||
|
float v1;
|
||
|
float angle;
|
||
|
Vector vector;
|
||
|
Vector position;
|
||
|
|
||
|
mstudiomovement_t() {}
|
||
|
private:
|
||
|
mstudiomovement_t(const mstudiomovement_t& vOther);
|
||
|
};
|
||
|
|
||
|
struct studiohdr_t;
|
||
|
|
||
|
struct mstudioanimblock_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
int datastart;
|
||
|
int dataend;
|
||
|
};
|
||
|
|
||
|
struct mstudioanimsections_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
int animblock;
|
||
|
int animindex;
|
||
|
};
|
||
|
|
||
|
struct mstudioanimdesc_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
int baseptr;
|
||
|
inline studiohdr_t* pStudiohdr(void) const { return (studiohdr_t*)(((byte*)this) + baseptr); }
|
||
|
|
||
|
int sznameindex;
|
||
|
inline char* const pszName(void) const { return ((char*)this) + sznameindex; }
|
||
|
|
||
|
float fps;
|
||
|
int flags;
|
||
|
|
||
|
int numframes;
|
||
|
|
||
|
int nummovements;
|
||
|
int movementindex;
|
||
|
inline mstudiomovement_t* const pMovement(int i) const { return (mstudiomovement_t*)(((byte*)this) + movementindex) + i; };
|
||
|
|
||
|
int unused1[6];
|
||
|
|
||
|
int animblock;
|
||
|
int animindex;
|
||
|
mstudioanim_t* pAnimBlock(int block, int index) const;
|
||
|
mstudioanim_t* pAnim(int* piFrame, float& flStall) const;
|
||
|
mstudioanim_t* pAnim(int* piFrame) const;
|
||
|
|
||
|
int numikrules;
|
||
|
int ikruleindex;
|
||
|
int animblockikruleindex;
|
||
|
mstudioikrule_t* pIKRule(int i) const;
|
||
|
|
||
|
int numlocalhierarchy;
|
||
|
int localhierarchyindex;
|
||
|
mstudiolocalhierarchy_t* pHierarchy(int i) const;
|
||
|
|
||
|
int sectionindex;
|
||
|
int sectionframes;
|
||
|
inline mstudioanimsections_t* const pSection(int i) const { return (mstudioanimsections_t*)(((byte*)this) + sectionindex) + i; }
|
||
|
|
||
|
short zeroframespan;
|
||
|
short zeroframecount;
|
||
|
int zeroframeindex;
|
||
|
byte* pZeroFrameData() const { if (zeroframeindex) return (((byte*)this) + zeroframeindex); else return NULL; };
|
||
|
mutable float zeroframestalltime;
|
||
|
|
||
|
mstudioanimdesc_t() {}
|
||
|
private:
|
||
|
mstudioanimdesc_t(const mstudioanimdesc_t& vOther);
|
||
|
};
|
||
|
|
||
|
struct mstudioikrule_t;
|
||
|
|
||
|
struct mstudioautolayer_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
short iSequence;
|
||
|
short iPose;
|
||
|
int flags;
|
||
|
float start;
|
||
|
float peak;
|
||
|
float tail;
|
||
|
float end;
|
||
|
};
|
||
|
|
||
|
struct mstudioactivitymodifier_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
|
||
|
int sznameindex;
|
||
|
inline char* pszName() { return (sznameindex) ? (char*)(((byte*)this) + sznameindex) : NULL; }
|
||
|
};
|
||
|
|
||
|
struct mstudioseqdesc_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
int baseptr;
|
||
|
inline studiohdr_t* pStudiohdr(void) const { return (studiohdr_t*)(((byte*)this) + baseptr); }
|
||
|
|
||
|
int szlabelindex;
|
||
|
inline char* const pszLabel(void) const { return ((char*)this) + szlabelindex; }
|
||
|
|
||
|
int szactivitynameindex;
|
||
|
inline char* const pszActivityName(void) const { return ((char*)this) + szactivitynameindex; }
|
||
|
|
||
|
int flags;
|
||
|
|
||
|
int activity;
|
||
|
int actweight;
|
||
|
|
||
|
int numevents;
|
||
|
int eventindex;
|
||
|
inline mstudioevent_t* pEvent(int i) const { Assert(i >= 0 && i < numevents); return (mstudioevent_t*)(((byte*)this) + eventindex) + i; };
|
||
|
|
||
|
Vector bbmin;
|
||
|
Vector bbmax;
|
||
|
|
||
|
int numblends;
|
||
|
|
||
|
int animindexindex;
|
||
|
|
||
|
inline int anim(int x, int y) const
|
||
|
{
|
||
|
if (x >= groupsize[0])
|
||
|
{
|
||
|
x = groupsize[0] - 1;
|
||
|
}
|
||
|
|
||
|
if (y >= groupsize[1])
|
||
|
{
|
||
|
y = groupsize[1] - 1;
|
||
|
}
|
||
|
|
||
|
int offset = y * groupsize[0] + x;
|
||
|
short* blends = (short*)(((byte*)this) + animindexindex);
|
||
|
int value = (int)blends[offset];
|
||
|
return value;
|
||
|
}
|
||
|
|
||
|
int movementindex;
|
||
|
int groupsize[2];
|
||
|
int paramindex[2];
|
||
|
float paramstart[2];
|
||
|
float paramend[2];
|
||
|
int paramparent;
|
||
|
|
||
|
float fadeintime;
|
||
|
float fadeouttime;
|
||
|
|
||
|
int localentrynode;
|
||
|
int localexitnode;
|
||
|
int nodeflags;
|
||
|
|
||
|
float entryphase;
|
||
|
float exitphase;
|
||
|
|
||
|
float lastframe;
|
||
|
|
||
|
int nextseq;
|
||
|
int pose;
|
||
|
|
||
|
int numikrules;
|
||
|
|
||
|
int numautolayers;
|
||
|
int autolayerindex;
|
||
|
inline mstudioautolayer_t* pAutolayer(int i) const { Assert(i >= 0 && i < numautolayers); return (mstudioautolayer_t*)(((byte*)this) + autolayerindex) + i; };
|
||
|
|
||
|
int weightlistindex;
|
||
|
inline float* pBoneweight(int i) const { return ((float*)(((byte*)this) + weightlistindex) + i); };
|
||
|
inline float weight(int i) const { return *(pBoneweight(i)); };
|
||
|
|
||
|
int posekeyindex;
|
||
|
float* pPoseKey(int iParam, int iAnim) const { return (float*)(((byte*)this) + posekeyindex) + iParam * groupsize[0] + iAnim; }
|
||
|
float poseKey(int iParam, int iAnim) const { return *(pPoseKey(iParam, iAnim)); }
|
||
|
|
||
|
int numiklocks;
|
||
|
int iklockindex;
|
||
|
inline mstudioiklock_t* pIKLock(int i) const { Assert(i >= 0 && i < numiklocks); return (mstudioiklock_t*)(((byte*)this) + iklockindex) + i; };
|
||
|
|
||
|
int keyvalueindex;
|
||
|
int keyvaluesize;
|
||
|
inline const char* KeyValueText(void) const { return keyvaluesize != 0 ? ((char*)this) + keyvalueindex : NULL; }
|
||
|
|
||
|
int cycleposeindex;
|
||
|
|
||
|
int activitymodifierindex;
|
||
|
int numactivitymodifiers;
|
||
|
inline mstudioactivitymodifier_t* pActivityModifier(int i) const { Assert(i >= 0 && i < numactivitymodifiers); return activitymodifierindex != 0 ? (mstudioactivitymodifier_t*)(((byte*)this) + activitymodifierindex) + i : NULL; };
|
||
|
|
||
|
int unused[5];
|
||
|
|
||
|
mstudioseqdesc_t() {}
|
||
|
private:
|
||
|
mstudioseqdesc_t(const mstudioseqdesc_t& vOther);
|
||
|
};
|
||
|
|
||
|
|
||
|
struct mstudioposeparamdesc_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
int sznameindex;
|
||
|
inline char* const pszName(void) const { return ((char*)this) + sznameindex; }
|
||
|
int flags;
|
||
|
float start;
|
||
|
float end;
|
||
|
float loop;
|
||
|
};
|
||
|
|
||
|
struct mstudioflexdesc_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
int szFACSindex;
|
||
|
inline char* const pszFACS(void) const { return ((char*)this) + szFACSindex; }
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
struct mstudioflexcontroller_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
int sztypeindex;
|
||
|
inline char* const pszType(void) const { return ((char*)this) + sztypeindex; }
|
||
|
int sznameindex;
|
||
|
inline char* const pszName(void) const { return ((char*)this) + sznameindex; }
|
||
|
mutable int localToGlobal;
|
||
|
float min;
|
||
|
float max;
|
||
|
};
|
||
|
|
||
|
|
||
|
enum FlexControllerRemapType_t
|
||
|
{
|
||
|
FLEXCONTROLLER_REMAP_PASSTHRU = 0,
|
||
|
FLEXCONTROLLER_REMAP_2WAY,
|
||
|
FLEXCONTROLLER_REMAP_NWAY,
|
||
|
FLEXCONTROLLER_REMAP_EYELID
|
||
|
};
|
||
|
|
||
|
|
||
|
class CStudioHdr;
|
||
|
struct mstudioflexcontrollerui_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
int sznameindex;
|
||
|
inline char* const pszName(void) const { return ((char*)this) + sznameindex; }
|
||
|
|
||
|
int szindex0;
|
||
|
int szindex1;
|
||
|
int szindex2;
|
||
|
|
||
|
inline const mstudioflexcontroller_t* pController(void) const
|
||
|
{
|
||
|
return !stereo ? (mstudioflexcontroller_t*)((char*)this + szindex0) : NULL;
|
||
|
}
|
||
|
inline char* const pszControllerName(void) const { return !stereo ? pController()->pszName() : NULL; }
|
||
|
inline int controllerIndex(const CStudioHdr& cStudioHdr) const;
|
||
|
|
||
|
inline const mstudioflexcontroller_t* pLeftController(void) const
|
||
|
{
|
||
|
return stereo ? (mstudioflexcontroller_t*)((char*)this + szindex0) : NULL;
|
||
|
}
|
||
|
inline char* const pszLeftName(void) const { return stereo ? pLeftController()->pszName() : NULL; }
|
||
|
inline int leftIndex(const CStudioHdr& cStudioHdr) const;
|
||
|
|
||
|
inline const mstudioflexcontroller_t* pRightController(void) const
|
||
|
{
|
||
|
return stereo ? (mstudioflexcontroller_t*)((char*)this + szindex1) : NULL;
|
||
|
}
|
||
|
inline char* const pszRightName(void) const { return stereo ? pRightController()->pszName() : NULL; }
|
||
|
inline int rightIndex(const CStudioHdr& cStudioHdr) const;
|
||
|
|
||
|
inline const mstudioflexcontroller_t* pNWayValueController(void) const
|
||
|
{
|
||
|
return remaptype == FLEXCONTROLLER_REMAP_NWAY ? (mstudioflexcontroller_t*)((char*)this + szindex2) : NULL;
|
||
|
}
|
||
|
inline char* const pszNWayValueName(void) const { return remaptype == FLEXCONTROLLER_REMAP_NWAY ? pNWayValueController()->pszName() : NULL; }
|
||
|
inline int nWayValueIndex(const CStudioHdr& cStudioHdr) const;
|
||
|
|
||
|
inline int Count() const { return (stereo ? 2 : 1) + (remaptype == FLEXCONTROLLER_REMAP_NWAY ? 1 : 0); }
|
||
|
inline const mstudioflexcontroller_t* pController(int index) const;
|
||
|
|
||
|
unsigned char remaptype;
|
||
|
bool stereo;
|
||
|
byte unused[2];
|
||
|
};
|
||
|
|
||
|
|
||
|
struct mstudiovertanim_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
unsigned short index;
|
||
|
byte speed;
|
||
|
byte side;
|
||
|
|
||
|
protected:
|
||
|
union
|
||
|
{
|
||
|
short delta[3];
|
||
|
float16 flDelta[3];
|
||
|
};
|
||
|
|
||
|
union
|
||
|
{
|
||
|
short ndelta[3];
|
||
|
float16 flNDelta[3];
|
||
|
};
|
||
|
|
||
|
public:
|
||
|
inline void ConvertToFixed(float flVertAnimFixedPointScale)
|
||
|
{
|
||
|
delta[0] = flDelta[0].GetFloat() / flVertAnimFixedPointScale;
|
||
|
delta[1] = flDelta[1].GetFloat() / flVertAnimFixedPointScale;
|
||
|
delta[2] = flDelta[2].GetFloat() / flVertAnimFixedPointScale;
|
||
|
ndelta[0] = flNDelta[0].GetFloat() / flVertAnimFixedPointScale;
|
||
|
ndelta[1] = flNDelta[1].GetFloat() / flVertAnimFixedPointScale;
|
||
|
ndelta[2] = flNDelta[2].GetFloat() / flVertAnimFixedPointScale;
|
||
|
}
|
||
|
|
||
|
inline Vector GetDeltaFixed(float flVertAnimFixedPointScale)
|
||
|
{
|
||
|
return Vector(delta[0] * flVertAnimFixedPointScale, delta[1] * flVertAnimFixedPointScale, delta[2] * flVertAnimFixedPointScale);
|
||
|
}
|
||
|
inline Vector GetNDeltaFixed(float flVertAnimFixedPointScale)
|
||
|
{
|
||
|
return Vector(ndelta[0] * flVertAnimFixedPointScale, ndelta[1] * flVertAnimFixedPointScale, ndelta[2] * flVertAnimFixedPointScale);
|
||
|
}
|
||
|
inline void GetDeltaFixed4DAligned(Vector4DAligned* vFillIn, float flVertAnimFixedPointScale)
|
||
|
{
|
||
|
vFillIn->Set(delta[0] * flVertAnimFixedPointScale, delta[1] * flVertAnimFixedPointScale, delta[2] * flVertAnimFixedPointScale, 0.0f);
|
||
|
}
|
||
|
inline void GetNDeltaFixed4DAligned(Vector4DAligned* vFillIn, float flVertAnimFixedPointScale)
|
||
|
{
|
||
|
vFillIn->Set(ndelta[0] * flVertAnimFixedPointScale, ndelta[1] * flVertAnimFixedPointScale, ndelta[2] * flVertAnimFixedPointScale, 0.0f);
|
||
|
}
|
||
|
inline Vector GetDeltaFloat()
|
||
|
{
|
||
|
return Vector(flDelta[0].GetFloat(), flDelta[1].GetFloat(), flDelta[2].GetFloat());
|
||
|
}
|
||
|
inline Vector GetNDeltaFloat()
|
||
|
{
|
||
|
return Vector(flNDelta[0].GetFloat(), flNDelta[1].GetFloat(), flNDelta[2].GetFloat());
|
||
|
}
|
||
|
inline void SetDeltaFixed(const Vector& vInput, float flVertAnimFixedPointScale)
|
||
|
{
|
||
|
delta[0] = vInput.x / flVertAnimFixedPointScale;
|
||
|
delta[1] = vInput.y / flVertAnimFixedPointScale;
|
||
|
delta[2] = vInput.z / flVertAnimFixedPointScale;
|
||
|
}
|
||
|
inline void SetNDeltaFixed(const Vector& vInputNormal, float flVertAnimFixedPointScale)
|
||
|
{
|
||
|
ndelta[0] = vInputNormal.x / flVertAnimFixedPointScale;
|
||
|
ndelta[1] = vInputNormal.y / flVertAnimFixedPointScale;
|
||
|
ndelta[2] = vInputNormal.z / flVertAnimFixedPointScale;
|
||
|
}
|
||
|
|
||
|
inline void SetDeltaFloat(const Vector& vInput)
|
||
|
{
|
||
|
flDelta[0].SetFloat(vInput.x);
|
||
|
flDelta[1].SetFloat(vInput.y);
|
||
|
flDelta[2].SetFloat(vInput.z);
|
||
|
}
|
||
|
inline void SetNDeltaFloat(const Vector& vInputNormal)
|
||
|
{
|
||
|
flNDelta[0].SetFloat(vInputNormal.x);
|
||
|
flNDelta[1].SetFloat(vInputNormal.y);
|
||
|
flNDelta[2].SetFloat(vInputNormal.z);
|
||
|
}
|
||
|
|
||
|
class CSortByIndex
|
||
|
{
|
||
|
public:
|
||
|
bool operator()(const mstudiovertanim_t& left, const mstudiovertanim_t& right)const
|
||
|
{
|
||
|
return left.index < right.index;
|
||
|
}
|
||
|
};
|
||
|
friend class CSortByIndex;
|
||
|
|
||
|
mstudiovertanim_t() {}
|
||
|
};
|
||
|
|
||
|
|
||
|
struct mstudiovertanim_wrinkle_t : public mstudiovertanim_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
|
||
|
short wrinkledelta;
|
||
|
|
||
|
inline void SetWrinkleFixed(float flWrinkle, float flVertAnimFixedPointScale)
|
||
|
{
|
||
|
int nWrinkleDeltaInt = flWrinkle / flVertAnimFixedPointScale;
|
||
|
wrinkledelta = clamp(nWrinkleDeltaInt, -32767, 32767);
|
||
|
}
|
||
|
|
||
|
inline Vector4D GetDeltaFixed(float flVertAnimFixedPointScale)
|
||
|
{
|
||
|
return Vector4D(delta[0] * flVertAnimFixedPointScale, delta[1] * flVertAnimFixedPointScale, delta[2] * flVertAnimFixedPointScale, wrinkledelta * flVertAnimFixedPointScale);
|
||
|
}
|
||
|
|
||
|
inline void GetDeltaFixed4DAligned(Vector4DAligned* vFillIn, float flVertAnimFixedPointScale)
|
||
|
{
|
||
|
vFillIn->Set(delta[0] * flVertAnimFixedPointScale, delta[1] * flVertAnimFixedPointScale, delta[2] * flVertAnimFixedPointScale, wrinkledelta * flVertAnimFixedPointScale);
|
||
|
}
|
||
|
|
||
|
inline float GetWrinkleDeltaFixed(float flVertAnimFixedPointScale)
|
||
|
{
|
||
|
return wrinkledelta * flVertAnimFixedPointScale;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
enum StudioVertAnimType_t
|
||
|
{
|
||
|
STUDIO_VERT_ANIM_NORMAL = 0,
|
||
|
STUDIO_VERT_ANIM_WRINKLE,
|
||
|
};
|
||
|
|
||
|
struct mstudioflex_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
int flexdesc;
|
||
|
|
||
|
float target0;
|
||
|
float target1;
|
||
|
float target2;
|
||
|
float target3;
|
||
|
|
||
|
int numverts;
|
||
|
int vertindex;
|
||
|
|
||
|
inline mstudiovertanim_t* pVertanim(int i) const { Assert(vertanimtype == STUDIO_VERT_ANIM_NORMAL); return (mstudiovertanim_t*)(((byte*)this) + vertindex) + i; };
|
||
|
inline mstudiovertanim_wrinkle_t* pVertanimWrinkle(int i) const { Assert(vertanimtype == STUDIO_VERT_ANIM_WRINKLE); return (mstudiovertanim_wrinkle_t*)(((byte*)this) + vertindex) + i; };
|
||
|
|
||
|
inline byte* pBaseVertanim() const { return ((byte*)this) + vertindex; };
|
||
|
inline int VertAnimSizeBytes() const { return (vertanimtype == STUDIO_VERT_ANIM_NORMAL) ? sizeof(mstudiovertanim_t) : sizeof(mstudiovertanim_wrinkle_t); }
|
||
|
|
||
|
int flexpair;
|
||
|
unsigned char vertanimtype;
|
||
|
unsigned char unusedchar[3];
|
||
|
int unused[6];
|
||
|
};
|
||
|
|
||
|
|
||
|
struct mstudioflexop_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
int op;
|
||
|
union
|
||
|
{
|
||
|
int index;
|
||
|
float value;
|
||
|
} d;
|
||
|
};
|
||
|
|
||
|
struct mstudioflexrule_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
int flex;
|
||
|
int numops;
|
||
|
int opindex;
|
||
|
inline mstudioflexop_t* iFlexOp(int i) const { return (mstudioflexop_t*)(((byte*)this) + opindex) + i; };
|
||
|
};
|
||
|
|
||
|
struct mstudioboneweight_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
float weight[MAX_NUM_BONES_PER_VERT];
|
||
|
char bone[MAX_NUM_BONES_PER_VERT];
|
||
|
byte numbones;
|
||
|
|
||
|
};
|
||
|
|
||
|
struct mstudiovertex_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
mstudioboneweight_t m_BoneWeights;
|
||
|
Vector m_vecPosition;
|
||
|
Vector m_vecNormal;
|
||
|
Vector2D m_vecTexCoord;
|
||
|
|
||
|
mstudiovertex_t() {}
|
||
|
|
||
|
private:
|
||
|
mstudiovertex_t(const mstudiovertex_t& vOther);
|
||
|
};
|
||
|
|
||
|
struct mstudiotexture_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
int sznameindex;
|
||
|
inline char* const pszName(void) const { return ((char*)this) + sznameindex; }
|
||
|
int flags;
|
||
|
int used;
|
||
|
int unused1;
|
||
|
mutable IMaterial* material;
|
||
|
mutable void* clientmaterial;
|
||
|
|
||
|
int unused[10];
|
||
|
};
|
||
|
|
||
|
struct mstudioeyeball_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
int sznameindex;
|
||
|
inline char* const pszName(void) const { return ((char*)this) + sznameindex; }
|
||
|
int bone;
|
||
|
Vector org;
|
||
|
float zoffset;
|
||
|
float radius;
|
||
|
Vector up;
|
||
|
Vector forward;
|
||
|
int texture;
|
||
|
|
||
|
int unused1;
|
||
|
float iris_scale;
|
||
|
int unused2;
|
||
|
|
||
|
int upperflexdesc[3];
|
||
|
int lowerflexdesc[3];
|
||
|
float uppertarget[3];
|
||
|
float lowertarget[3];
|
||
|
|
||
|
int upperlidflexdesc;
|
||
|
int lowerlidflexdesc;
|
||
|
int unused[4];
|
||
|
bool m_bNonFACS;
|
||
|
char unused3[3];
|
||
|
int unused4[7];
|
||
|
|
||
|
mstudioeyeball_t() {}
|
||
|
private:
|
||
|
mstudioeyeball_t(const mstudioeyeball_t& vOther);
|
||
|
};
|
||
|
|
||
|
|
||
|
struct mstudioiklink_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
int bone;
|
||
|
Vector kneeDir;
|
||
|
Vector unused0;
|
||
|
|
||
|
mstudioiklink_t() {}
|
||
|
private:
|
||
|
mstudioiklink_t(const mstudioiklink_t& vOther);
|
||
|
};
|
||
|
|
||
|
struct mstudioikchain_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
int sznameindex;
|
||
|
inline char* const pszName(void) const { return ((char*)this) + sznameindex; }
|
||
|
int linktype;
|
||
|
int numlinks;
|
||
|
int linkindex;
|
||
|
inline mstudioiklink_t* pLink(int i) const { return (mstudioiklink_t*)(((byte*)this) + linkindex) + i; };
|
||
|
};
|
||
|
|
||
|
|
||
|
struct mstudioiface_t
|
||
|
{
|
||
|
unsigned short a, b, c;
|
||
|
};
|
||
|
|
||
|
|
||
|
struct mstudiomodel_t;
|
||
|
|
||
|
struct mstudio_modelvertexdata_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
Vector* Position(int i) const;
|
||
|
Vector* Normal(int i) const;
|
||
|
Vector4D* TangentS(int i) const;
|
||
|
Vector2D* Texcoord(int i) const;
|
||
|
mstudioboneweight_t* BoneWeights(int i) const;
|
||
|
mstudiovertex_t* Vertex(int i) const;
|
||
|
bool HasTangentData(void) const;
|
||
|
int GetGlobalVertexIndex(int i) const;
|
||
|
int GetGlobalTangentIndex(int i) const;
|
||
|
|
||
|
const void* pVertexData;
|
||
|
const void* pTangentData;
|
||
|
};
|
||
|
|
||
|
struct mstudio_meshvertexdata_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
Vector* Position(int i) const;
|
||
|
Vector* Normal(int i) const;
|
||
|
Vector4D* TangentS(int i) const;
|
||
|
Vector2D* Texcoord(int i) const;
|
||
|
mstudioboneweight_t* BoneWeights(int i) const;
|
||
|
mstudiovertex_t* Vertex(int i) const;
|
||
|
bool HasTangentData(void) const;
|
||
|
int GetModelVertexIndex(int i) const;
|
||
|
int GetGlobalVertexIndex(int i) const;
|
||
|
|
||
|
const mstudio_modelvertexdata_t* modelvertexdata;
|
||
|
|
||
|
int numLODVertexes[MAX_NUM_LODS];
|
||
|
};
|
||
|
|
||
|
struct mstudiomesh_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
int material;
|
||
|
|
||
|
int modelindex;
|
||
|
mstudiomodel_t* pModel() const;
|
||
|
|
||
|
int numvertices;
|
||
|
int vertexoffset;
|
||
|
|
||
|
const mstudio_meshvertexdata_t* GetVertexData(void* pModelData = NULL);
|
||
|
const thinModelVertices_t* GetThinVertexData(void* pModelData = NULL);
|
||
|
|
||
|
int numflexes;
|
||
|
int flexindex;
|
||
|
inline mstudioflex_t* pFlex(int i) const { return (mstudioflex_t*)(((byte*)this) + flexindex) + i; };
|
||
|
|
||
|
int materialtype;
|
||
|
int materialparam;
|
||
|
|
||
|
int meshid;
|
||
|
|
||
|
Vector center;
|
||
|
|
||
|
mstudio_meshvertexdata_t vertexdata;
|
||
|
|
||
|
int unused[8];
|
||
|
|
||
|
mstudiomesh_t() {}
|
||
|
private:
|
||
|
mstudiomesh_t(const mstudiomesh_t& vOther);
|
||
|
};
|
||
|
|
||
|
struct mstudiomodel_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
inline const char* pszName(void) const { return name; }
|
||
|
char name[64];
|
||
|
|
||
|
int type;
|
||
|
|
||
|
float boundingradius;
|
||
|
|
||
|
int nummeshes;
|
||
|
int meshindex;
|
||
|
inline mstudiomesh_t* pMesh(int i) const { return (mstudiomesh_t*)(((byte*)this) + meshindex) + i; };
|
||
|
|
||
|
int numvertices;
|
||
|
int vertexindex;
|
||
|
int tangentsindex;
|
||
|
|
||
|
const vertexFileHeader_t* CacheVertexData(void* pModelData);
|
||
|
|
||
|
const mstudio_modelvertexdata_t* GetVertexData(void* pModelData = NULL);
|
||
|
const thinModelVertices_t* GetThinVertexData(void* pModelData = NULL);
|
||
|
|
||
|
int numattachments;
|
||
|
int attachmentindex;
|
||
|
|
||
|
int numeyeballs;
|
||
|
int eyeballindex;
|
||
|
inline mstudioeyeball_t* pEyeball(int i) { return (mstudioeyeball_t*)(((byte*)this) + eyeballindex) + i; };
|
||
|
|
||
|
mstudio_modelvertexdata_t vertexdata;
|
||
|
|
||
|
int unused[8];
|
||
|
};
|
||
|
|
||
|
inline bool mstudio_modelvertexdata_t::HasTangentData(void) const
|
||
|
{
|
||
|
return (pTangentData != NULL);
|
||
|
}
|
||
|
|
||
|
inline int mstudio_modelvertexdata_t::GetGlobalVertexIndex(int i) const
|
||
|
{
|
||
|
mstudiomodel_t* modelptr = (mstudiomodel_t*)((byte*)this - offsetof(mstudiomodel_t, vertexdata));
|
||
|
Assert((modelptr->vertexindex % sizeof(mstudiovertex_t)) == 0);
|
||
|
return (i + (modelptr->vertexindex / sizeof(mstudiovertex_t)));
|
||
|
}
|
||
|
|
||
|
inline int mstudio_modelvertexdata_t::GetGlobalTangentIndex(int i) const
|
||
|
{
|
||
|
mstudiomodel_t* modelptr = (mstudiomodel_t*)((byte*)this - offsetof(mstudiomodel_t, vertexdata));
|
||
|
Assert((modelptr->tangentsindex % sizeof(Vector4D)) == 0);
|
||
|
return (i + (modelptr->tangentsindex / sizeof(Vector4D)));
|
||
|
}
|
||
|
|
||
|
inline mstudiovertex_t* mstudio_modelvertexdata_t::Vertex(int i) const
|
||
|
{
|
||
|
return (mstudiovertex_t*)pVertexData + GetGlobalVertexIndex(i);
|
||
|
}
|
||
|
|
||
|
inline Vector* mstudio_modelvertexdata_t::Position(int i) const
|
||
|
{
|
||
|
return &Vertex(i)->m_vecPosition;
|
||
|
}
|
||
|
|
||
|
inline Vector* mstudio_modelvertexdata_t::Normal(int i) const
|
||
|
{
|
||
|
return &Vertex(i)->m_vecNormal;
|
||
|
}
|
||
|
|
||
|
inline Vector4D* mstudio_modelvertexdata_t::TangentS(int i) const
|
||
|
{
|
||
|
return (Vector4D*)pTangentData + GetGlobalTangentIndex(i);
|
||
|
}
|
||
|
|
||
|
inline Vector2D* mstudio_modelvertexdata_t::Texcoord(int i) const
|
||
|
{
|
||
|
return &Vertex(i)->m_vecTexCoord;
|
||
|
}
|
||
|
|
||
|
inline mstudioboneweight_t* mstudio_modelvertexdata_t::BoneWeights(int i) const
|
||
|
{
|
||
|
return &Vertex(i)->m_BoneWeights;
|
||
|
}
|
||
|
|
||
|
inline mstudiomodel_t* mstudiomesh_t::pModel() const
|
||
|
{
|
||
|
return (mstudiomodel_t*)(((byte*)this) + modelindex);
|
||
|
}
|
||
|
|
||
|
inline bool mstudio_meshvertexdata_t::HasTangentData(void) const
|
||
|
{
|
||
|
return modelvertexdata->HasTangentData();
|
||
|
}
|
||
|
|
||
|
inline const mstudio_meshvertexdata_t* mstudiomesh_t::GetVertexData(void* pModelData)
|
||
|
{
|
||
|
this->pModel()->GetVertexData(pModelData);
|
||
|
vertexdata.modelvertexdata = &(this->pModel()->vertexdata);
|
||
|
|
||
|
if (!vertexdata.modelvertexdata->pVertexData)
|
||
|
return NULL;
|
||
|
|
||
|
return &vertexdata;
|
||
|
}
|
||
|
|
||
|
inline const thinModelVertices_t* mstudiomesh_t::GetThinVertexData(void* pModelData)
|
||
|
{
|
||
|
return this->pModel()->GetThinVertexData(pModelData);
|
||
|
}
|
||
|
|
||
|
inline int mstudio_meshvertexdata_t::GetModelVertexIndex(int i) const
|
||
|
{
|
||
|
mstudiomesh_t* meshptr = (mstudiomesh_t*)((byte*)this - offsetof(mstudiomesh_t, vertexdata));
|
||
|
return meshptr->vertexoffset + i;
|
||
|
}
|
||
|
|
||
|
inline int mstudio_meshvertexdata_t::GetGlobalVertexIndex(int i) const
|
||
|
{
|
||
|
return modelvertexdata->GetGlobalVertexIndex(GetModelVertexIndex(i));
|
||
|
}
|
||
|
|
||
|
inline Vector* mstudio_meshvertexdata_t::Position(int i) const
|
||
|
{
|
||
|
return modelvertexdata->Position(GetModelVertexIndex(i));
|
||
|
};
|
||
|
|
||
|
inline Vector* mstudio_meshvertexdata_t::Normal(int i) const
|
||
|
{
|
||
|
return modelvertexdata->Normal(GetModelVertexIndex(i));
|
||
|
};
|
||
|
|
||
|
inline Vector4D* mstudio_meshvertexdata_t::TangentS(int i) const
|
||
|
{
|
||
|
return modelvertexdata->TangentS(GetModelVertexIndex(i));
|
||
|
}
|
||
|
|
||
|
inline Vector2D* mstudio_meshvertexdata_t::Texcoord(int i) const
|
||
|
{
|
||
|
return modelvertexdata->Texcoord(GetModelVertexIndex(i));
|
||
|
};
|
||
|
|
||
|
inline mstudioboneweight_t* mstudio_meshvertexdata_t::BoneWeights(int i) const
|
||
|
{
|
||
|
return modelvertexdata->BoneWeights(GetModelVertexIndex(i));
|
||
|
};
|
||
|
|
||
|
inline mstudiovertex_t* mstudio_meshvertexdata_t::Vertex(int i) const
|
||
|
{
|
||
|
return modelvertexdata->Vertex(GetModelVertexIndex(i));
|
||
|
}
|
||
|
|
||
|
enum studiomeshgroupflags_t
|
||
|
{
|
||
|
MESHGROUP_IS_FLEXED = 0x1,
|
||
|
MESHGROUP_IS_HWSKINNED = 0x2,
|
||
|
MESHGROUP_IS_DELTA_FLEXED = 0x4
|
||
|
};
|
||
|
|
||
|
|
||
|
struct studiomeshgroup_t
|
||
|
{
|
||
|
IMesh* m_pMesh;
|
||
|
int m_NumStrips;
|
||
|
int m_Flags;
|
||
|
OptimizedModel::StripHeader_t* m_pStripData;
|
||
|
unsigned short* m_pGroupIndexToMeshIndex;
|
||
|
int m_NumVertices;
|
||
|
int* m_pUniqueTris;
|
||
|
unsigned short* m_pIndices;
|
||
|
bool m_MeshNeedsRestore;
|
||
|
short m_ColorMeshID;
|
||
|
IMorph* m_pMorph;
|
||
|
|
||
|
inline unsigned short MeshIndex(int i) const { return m_pGroupIndexToMeshIndex[m_pIndices[i]]; }
|
||
|
};
|
||
|
|
||
|
|
||
|
struct studiomeshdata_t
|
||
|
{
|
||
|
int m_NumGroup;
|
||
|
studiomeshgroup_t* m_pMeshGroup;
|
||
|
};
|
||
|
|
||
|
struct studioloddata_t
|
||
|
{
|
||
|
studiomeshdata_t* m_pMeshData;
|
||
|
float m_SwitchPoint;
|
||
|
int numMaterials;
|
||
|
IMaterial** ppMaterials;
|
||
|
int* pMaterialFlags;
|
||
|
|
||
|
int* m_pHWMorphDecalBoneRemap;
|
||
|
int m_nDecalBoneCount;
|
||
|
};
|
||
|
|
||
|
struct studiohwdata_t
|
||
|
{
|
||
|
int m_RootLOD;
|
||
|
int m_NumLODs;
|
||
|
studioloddata_t* m_pLODs;
|
||
|
int m_NumStudioMeshes;
|
||
|
|
||
|
inline float LODMetric(float unitSphereSize) const { return (unitSphereSize != 0.0f) ? (100.0f / unitSphereSize) : 0.0f; }
|
||
|
inline int GetLODForMetric(float lodMetric) const
|
||
|
{
|
||
|
if (!m_NumLODs)
|
||
|
return 0;
|
||
|
|
||
|
int numLODs = (m_pLODs[m_NumLODs - 1].m_SwitchPoint < 0.0f) ? m_NumLODs - 1 : m_NumLODs;
|
||
|
|
||
|
for (int i = m_RootLOD; i < numLODs - 1; i++)
|
||
|
{
|
||
|
if (m_pLODs[i + 1].m_SwitchPoint > lodMetric)
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
return numLODs - 1;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
struct mstudiobodyparts_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
int sznameindex;
|
||
|
inline char* const pszName(void) const { return ((char*)this) + sznameindex; }
|
||
|
int nummodels;
|
||
|
int base;
|
||
|
int modelindex;
|
||
|
inline mstudiomodel_t* pModel(int i) const { return (mstudiomodel_t*)(((byte*)this) + modelindex) + i; };
|
||
|
};
|
||
|
|
||
|
|
||
|
struct mstudiomouth_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
int bone;
|
||
|
Vector forward;
|
||
|
int flexdesc;
|
||
|
|
||
|
mstudiomouth_t() {}
|
||
|
private:
|
||
|
mstudiomouth_t(const mstudiomouth_t& vOther);
|
||
|
};
|
||
|
|
||
|
struct mstudiohitboxset_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
int sznameindex;
|
||
|
inline char* const pszName(void) const { return ((char*)this) + sznameindex; }
|
||
|
int numhitboxes;
|
||
|
int hitboxindex;
|
||
|
inline mstudiobbox_t* pHitbox(int i) const { return (mstudiobbox_t*)(((byte*)this) + hitboxindex) + i; };
|
||
|
};
|
||
|
|
||
|
|
||
|
struct mstudiosrcbonetransform_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
|
||
|
int sznameindex;
|
||
|
inline const char* pszName(void) const { return ((char*)this) + sznameindex; }
|
||
|
matrix3x4_t pretransform;
|
||
|
matrix3x4_t posttransform;
|
||
|
};
|
||
|
|
||
|
|
||
|
class virtualgroup_t
|
||
|
{
|
||
|
public:
|
||
|
virtualgroup_t(void) { cache = NULL; };
|
||
|
void* cache;
|
||
|
const studiohdr_t* GetStudioHdr(void) const;
|
||
|
|
||
|
CUtlVector< int > boneMap;
|
||
|
CUtlVector< int > masterBone;
|
||
|
CUtlVector< int > masterSeq;
|
||
|
CUtlVector< int > masterAnim;
|
||
|
CUtlVector< int > masterAttachment;
|
||
|
CUtlVector< int > masterPose;
|
||
|
CUtlVector< int > masterNode;
|
||
|
};
|
||
|
|
||
|
struct virtualsequence_t
|
||
|
{
|
||
|
#ifdef _XBOX
|
||
|
short flags;
|
||
|
short activity;
|
||
|
short group;
|
||
|
short index;
|
||
|
#else
|
||
|
int flags;
|
||
|
int activity;
|
||
|
int group;
|
||
|
int index;
|
||
|
#endif
|
||
|
};
|
||
|
|
||
|
struct virtualgeneric_t
|
||
|
{
|
||
|
#ifdef _XBOX
|
||
|
short group;
|
||
|
short index;
|
||
|
#else
|
||
|
int group;
|
||
|
int index;
|
||
|
#endif
|
||
|
};
|
||
|
|
||
|
|
||
|
struct virtualmodel_t
|
||
|
{
|
||
|
void AppendSequences(int group, const studiohdr_t* pStudioHdr);
|
||
|
void AppendAnimations(int group, const studiohdr_t* pStudioHdr);
|
||
|
void AppendAttachments(int ground, const studiohdr_t* pStudioHdr);
|
||
|
void AppendPoseParameters(int group, const studiohdr_t* pStudioHdr);
|
||
|
void AppendBonemap(int group, const studiohdr_t* pStudioHdr);
|
||
|
void AppendNodes(int group, const studiohdr_t* pStudioHdr);
|
||
|
void AppendTransitions(int group, const studiohdr_t* pStudioHdr);
|
||
|
void AppendIKLocks(int group, const studiohdr_t* pStudioHdr);
|
||
|
void AppendModels(int group, const studiohdr_t* pStudioHdr);
|
||
|
void UpdateAutoplaySequences(const studiohdr_t* pStudioHdr);
|
||
|
|
||
|
virtualgroup_t* pAnimGroup(int animation) { return &m_group[m_anim[animation].group]; }
|
||
|
virtualgroup_t* pSeqGroup(int sequence)
|
||
|
{
|
||
|
if ((unsigned)sequence >= (unsigned)m_seq.Count())
|
||
|
{
|
||
|
Assert(0);
|
||
|
return 0;
|
||
|
}
|
||
|
return &m_group[m_seq[sequence].group];
|
||
|
}
|
||
|
|
||
|
CThreadFastMutex m_Lock;
|
||
|
|
||
|
CUtlVector< virtualsequence_t > m_seq;
|
||
|
CUtlVector< virtualgeneric_t > m_anim;
|
||
|
CUtlVector< virtualgeneric_t > m_attachment;
|
||
|
CUtlVector< virtualgeneric_t > m_pose;
|
||
|
CUtlVector< virtualgroup_t > m_group;
|
||
|
CUtlVector< virtualgeneric_t > m_node;
|
||
|
CUtlVector< virtualgeneric_t > m_iklock;
|
||
|
CUtlVector< unsigned short > m_autoplaySequences;
|
||
|
};
|
||
|
|
||
|
struct thinModelVertices_t
|
||
|
{
|
||
|
void Init(int numBoneInfluences, Vector* positions, unsigned short* normals, float* boneWeights, char* boneIndices)
|
||
|
{
|
||
|
Assert(positions != NULL);
|
||
|
Assert(normals != NULL);
|
||
|
Assert((numBoneInfluences >= 0) && (numBoneInfluences <= 3));
|
||
|
Assert(numBoneInfluences > 0 ? !!boneIndices : !boneIndices);
|
||
|
Assert(numBoneInfluences > 1 ? !!boneWeights : !boneWeights);
|
||
|
m_numBoneInfluences = numBoneInfluences;
|
||
|
m_vecPositions = positions;
|
||
|
m_vecNormals = normals;
|
||
|
m_boneWeights = boneWeights;
|
||
|
m_boneIndices = boneIndices;
|
||
|
}
|
||
|
|
||
|
void SetPosition(int vertIndex, const Vector& position)
|
||
|
{
|
||
|
Assert(m_vecPositions);
|
||
|
m_vecPositions[vertIndex] = position;
|
||
|
}
|
||
|
|
||
|
void SetNormal(int vertIndex, const Vector& normal)
|
||
|
{
|
||
|
Assert(m_vecNormals);
|
||
|
unsigned int packedNormal;
|
||
|
PackNormal_UBYTE4(normal.x, normal.y, normal.z, &packedNormal);
|
||
|
m_vecNormals[vertIndex] = (unsigned short)(0x0000FFFF & packedNormal);
|
||
|
}
|
||
|
|
||
|
void SetBoneWeights(int vertIndex, const mstudioboneweight_t& boneWeights)
|
||
|
{
|
||
|
Assert((m_numBoneInfluences >= 1) && (m_numBoneInfluences <= 3));
|
||
|
Assert((boneWeights.numbones >= 1) && (boneWeights.numbones <= m_numBoneInfluences));
|
||
|
int numStoredWeights = max(0, (m_numBoneInfluences - 1));
|
||
|
float* pBaseWeight = m_boneWeights + vertIndex * numStoredWeights;
|
||
|
char* pBaseIndex = m_boneIndices + vertIndex * m_numBoneInfluences;
|
||
|
for (int i = 0; i < m_numBoneInfluences; i++)
|
||
|
{
|
||
|
pBaseIndex[i] = boneWeights.bone[i];
|
||
|
}
|
||
|
for (int i = 0; i < numStoredWeights; i++)
|
||
|
{
|
||
|
pBaseWeight[i] = boneWeights.weight[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void GetMeshPosition(mstudiomesh_t* pMesh, int meshIndex, Vector* pPosition) const
|
||
|
{
|
||
|
Assert(pMesh);
|
||
|
GetPosition(pMesh->vertexdata.GetGlobalVertexIndex(meshIndex), pPosition);
|
||
|
}
|
||
|
|
||
|
void GetMeshNormal(mstudiomesh_t* pMesh, int meshIndex, Vector* pNormal) const
|
||
|
{
|
||
|
Assert(pMesh);
|
||
|
GetNormal(pMesh->vertexdata.GetGlobalVertexIndex(meshIndex), pNormal);
|
||
|
}
|
||
|
|
||
|
void GetMeshBoneWeights(mstudiomesh_t* pMesh, int meshIndex, mstudioboneweight_t* pBoneWeights) const
|
||
|
{
|
||
|
Assert(pMesh);
|
||
|
GetBoneWeights(pMesh->vertexdata.GetGlobalVertexIndex(meshIndex), pBoneWeights);
|
||
|
}
|
||
|
|
||
|
void GetModelPosition(mstudiomodel_t* pModel, int modelIndex, Vector* pPosition) const
|
||
|
{
|
||
|
Assert(pModel);
|
||
|
GetPosition(pModel->vertexdata.GetGlobalVertexIndex(modelIndex), pPosition);
|
||
|
}
|
||
|
|
||
|
void GetModelNormal(mstudiomodel_t* pModel, int modelIndex, Vector* pNormal) const
|
||
|
{
|
||
|
Assert(pModel);
|
||
|
GetNormal(pModel->vertexdata.GetGlobalVertexIndex(modelIndex), pNormal);
|
||
|
}
|
||
|
|
||
|
void GetModelBoneWeights(mstudiomodel_t* pModel, int modelIndex, mstudioboneweight_t* pBoneWeights) const
|
||
|
{
|
||
|
Assert(pModel);
|
||
|
GetBoneWeights(pModel->vertexdata.GetGlobalVertexIndex(modelIndex), pBoneWeights);
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
void GetPosition(int vertIndex, Vector* pPosition) const
|
||
|
{
|
||
|
Assert(pPosition);
|
||
|
Assert(m_vecPositions);
|
||
|
*pPosition = m_vecPositions[vertIndex];
|
||
|
}
|
||
|
|
||
|
void GetNormal(int vertIndex, Vector* pNormal) const
|
||
|
{
|
||
|
Assert(pNormal);
|
||
|
Assert(m_vecNormals);
|
||
|
unsigned int packedNormal = 0x0000FFFF & m_vecNormals[vertIndex];
|
||
|
UnpackNormal_UBYTE4(&packedNormal, pNormal->Base());
|
||
|
}
|
||
|
|
||
|
void GetBoneWeights(int vertIndex, mstudioboneweight_t* pBoneWeights) const
|
||
|
{
|
||
|
Assert(pBoneWeights);
|
||
|
Assert((m_numBoneInfluences <= 1) || (m_boneWeights != NULL));
|
||
|
Assert((m_numBoneInfluences <= 0) || (m_boneIndices != NULL));
|
||
|
int numStoredWeights = max(0, (m_numBoneInfluences - 1));
|
||
|
float* pBaseWeight = m_boneWeights + vertIndex * numStoredWeights;
|
||
|
char* pBaseIndex = m_boneIndices + vertIndex * m_numBoneInfluences;
|
||
|
float sum = 0.0f;
|
||
|
for (int i = 0; i < MAX_NUM_BONES_PER_VERT; i++)
|
||
|
{
|
||
|
if (i < (m_numBoneInfluences - 1))
|
||
|
pBoneWeights->weight[i] = pBaseWeight[i];
|
||
|
else
|
||
|
pBoneWeights->weight[i] = 1.0f - sum;
|
||
|
sum += pBoneWeights->weight[i];
|
||
|
|
||
|
pBoneWeights->bone[i] = (i < m_numBoneInfluences) ? pBaseIndex[i] : 0;
|
||
|
}
|
||
|
|
||
|
pBoneWeights->numbones = m_numBoneInfluences ? m_numBoneInfluences : 1;
|
||
|
}
|
||
|
|
||
|
int m_numBoneInfluences;
|
||
|
float* m_boneWeights;
|
||
|
char* m_boneIndices;
|
||
|
Vector* m_vecPositions;
|
||
|
unsigned short* m_vecNormals;
|
||
|
};
|
||
|
|
||
|
#define MODEL_VERTEX_FILE_ID (('V'<<24)+('S'<<16)+('D'<<8)+'I')
|
||
|
#define MODEL_VERTEX_FILE_VERSION 4
|
||
|
#define MODEL_VERTEX_FILE_THIN_ID (('V'<<24)+('C'<<16)+('D'<<8)+'I')
|
||
|
|
||
|
struct vertexFileHeader_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
int id;
|
||
|
int version;
|
||
|
int checksum;
|
||
|
int numLODs;
|
||
|
int numLODVertexes[MAX_NUM_LODS];
|
||
|
int numFixups;
|
||
|
int fixupTableStart;
|
||
|
int vertexDataStart;
|
||
|
int tangentDataStart;
|
||
|
|
||
|
public:
|
||
|
|
||
|
const mstudiovertex_t* GetVertexData() const
|
||
|
{
|
||
|
if ((id == MODEL_VERTEX_FILE_ID) && (vertexDataStart != 0))
|
||
|
return (mstudiovertex_t*)(vertexDataStart + (byte*)this);
|
||
|
else
|
||
|
return NULL;
|
||
|
}
|
||
|
const Vector4D* GetTangentData() const
|
||
|
{
|
||
|
if ((id == MODEL_VERTEX_FILE_ID) && (tangentDataStart != 0))
|
||
|
return (Vector4D*)(tangentDataStart + (byte*)this);
|
||
|
else
|
||
|
return NULL;
|
||
|
}
|
||
|
const thinModelVertices_t* GetThinVertexData() const
|
||
|
{
|
||
|
if ((id == MODEL_VERTEX_FILE_THIN_ID) && (vertexDataStart != 0))
|
||
|
return (thinModelVertices_t*)(vertexDataStart + (byte*)this);
|
||
|
else
|
||
|
return NULL;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
inline const mstudio_modelvertexdata_t* mstudiomodel_t::GetVertexData(void* pModelData)
|
||
|
{
|
||
|
const vertexFileHeader_t* pVertexHdr = CacheVertexData(pModelData);
|
||
|
if (!pVertexHdr)
|
||
|
{
|
||
|
vertexdata.pVertexData = NULL;
|
||
|
vertexdata.pTangentData = NULL;
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
vertexdata.pVertexData = pVertexHdr->GetVertexData();
|
||
|
vertexdata.pTangentData = pVertexHdr->GetTangentData();
|
||
|
|
||
|
if (!vertexdata.pVertexData)
|
||
|
return NULL;
|
||
|
|
||
|
return &vertexdata;
|
||
|
}
|
||
|
|
||
|
inline const thinModelVertices_t* mstudiomodel_t::GetThinVertexData(void* pModelData)
|
||
|
{
|
||
|
const vertexFileHeader_t* pVertexHdr = CacheVertexData(pModelData);
|
||
|
if (!pVertexHdr)
|
||
|
return NULL;
|
||
|
|
||
|
return pVertexHdr->GetThinVertexData();
|
||
|
}
|
||
|
|
||
|
struct vertexFileFixup_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
int lod;
|
||
|
int sourceVertexID;
|
||
|
int numVertexes;
|
||
|
};
|
||
|
|
||
|
#define STUDIOHDR_FLAGS_AUTOGENERATED_HITBOX 0x00000001
|
||
|
|
||
|
#define STUDIOHDR_FLAGS_USES_ENV_CUBEMAP 0x00000002
|
||
|
|
||
|
#define STUDIOHDR_FLAGS_FORCE_OPAQUE 0x00000004
|
||
|
|
||
|
#define STUDIOHDR_FLAGS_TRANSLUCENT_TWOPASS 0x00000008
|
||
|
|
||
|
#define STUDIOHDR_FLAGS_STATIC_PROP 0x00000010
|
||
|
|
||
|
#define STUDIOHDR_FLAGS_USES_FB_TEXTURE 0x00000020
|
||
|
|
||
|
#define STUDIOHDR_FLAGS_HASSHADOWLOD 0x00000040
|
||
|
|
||
|
#define STUDIOHDR_FLAGS_USES_BUMPMAPPING 0x00000080
|
||
|
|
||
|
#define STUDIOHDR_FLAGS_USE_SHADOWLOD_MATERIALS 0x00000100
|
||
|
|
||
|
#define STUDIOHDR_FLAGS_OBSOLETE 0x00000200
|
||
|
|
||
|
#define STUDIOHDR_FLAGS_UNUSED 0x00000400
|
||
|
|
||
|
#define STUDIOHDR_FLAGS_NO_FORCED_FADE 0x00000800
|
||
|
|
||
|
#define STUDIOHDR_FLAGS_FORCE_PHONEME_CROSSFADE 0x00001000
|
||
|
|
||
|
#define STUDIOHDR_FLAGS_CONSTANT_DIRECTIONAL_LIGHT_DOT 0x00002000
|
||
|
|
||
|
#define STUDIOHDR_FLAGS_FLEXES_CONVERTED 0x00004000
|
||
|
|
||
|
#define STUDIOHDR_FLAGS_BUILT_IN_PREVIEW_MODE 0x00008000
|
||
|
|
||
|
#define STUDIOHDR_FLAGS_AMBIENT_BOOST 0x00010000
|
||
|
|
||
|
#define STUDIOHDR_FLAGS_DO_NOT_CAST_SHADOWS 0x00020000
|
||
|
|
||
|
#define STUDIOHDR_FLAGS_CAST_TEXTURE_SHADOWS 0x00040000
|
||
|
|
||
|
|
||
|
#define STUDIOHDR_FLAGS_VERT_ANIM_FIXED_POINT_SCALE 0x00200000
|
||
|
|
||
|
struct studiohdr2_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
int numsrcbonetransform;
|
||
|
int srcbonetransformindex;
|
||
|
|
||
|
int illumpositionattachmentindex;
|
||
|
inline int IllumPositionAttachmentIndex() const { return illumpositionattachmentindex; }
|
||
|
|
||
|
float flMaxEyeDeflection;
|
||
|
inline float MaxEyeDeflection() const { return flMaxEyeDeflection != 0.0f ? flMaxEyeDeflection : 0.866f; }
|
||
|
|
||
|
int linearboneindex;
|
||
|
inline mstudiolinearbone_t* pLinearBones() const { return (linearboneindex) ? (mstudiolinearbone_t*)(((byte*)this) + linearboneindex) : NULL; }
|
||
|
|
||
|
int sznameindex;
|
||
|
inline char* pszName() { return (sznameindex) ? (char*)(((byte*)this) + sznameindex) : NULL; }
|
||
|
|
||
|
int m_nBoneFlexDriverCount;
|
||
|
int m_nBoneFlexDriverIndex;
|
||
|
inline mstudioboneflexdriver_t* pBoneFlexDriver(int i) const { Assert(i >= 0 && i < m_nBoneFlexDriverCount); return (mstudioboneflexdriver_t*)(((byte*)this) + m_nBoneFlexDriverIndex) + i; }
|
||
|
|
||
|
int reserved[56];
|
||
|
};
|
||
|
|
||
|
struct studiohdr_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
int id;
|
||
|
int version;
|
||
|
int checksum;
|
||
|
inline const char* pszName(void) const { if (studiohdr2index && pStudioHdr2()->pszName()) return pStudioHdr2()->pszName(); else return name; }
|
||
|
char name[64];
|
||
|
int length;
|
||
|
Vector eyeposition;
|
||
|
Vector illumposition;
|
||
|
Vector hull_min;
|
||
|
Vector hull_max;
|
||
|
Vector view_bbmin;
|
||
|
Vector view_bbmax;
|
||
|
int flags;
|
||
|
int numbones;
|
||
|
int boneindex;
|
||
|
inline mstudiobone_t* pBone(int i) const { Assert(i >= 0 && i < numbones); return (mstudiobone_t*)(((byte*)this) + boneindex) + i; };
|
||
|
int RemapSeqBone(int iSequence, int iLocalBone) const;
|
||
|
int RemapAnimBone(int iAnim, int iLocalBone) const;
|
||
|
int numbonecontrollers;
|
||
|
int bonecontrollerindex;
|
||
|
inline mstudiobonecontroller_t* pBonecontroller(int i) const { Assert(i >= 0 && i < numbonecontrollers); return (mstudiobonecontroller_t*)(((byte*)this) + bonecontrollerindex) + i; };
|
||
|
int numhitboxsets;
|
||
|
int hitboxsetindex;
|
||
|
|
||
|
mstudiohitboxset_t* pHitboxSet(int i) const
|
||
|
{
|
||
|
Assert(i >= 0 && i < numhitboxsets);
|
||
|
return (mstudiohitboxset_t*)(((byte*)this) + hitboxsetindex) + i;
|
||
|
};
|
||
|
|
||
|
inline mstudiobbox_t* pHitbox(int i, int set) const
|
||
|
{
|
||
|
mstudiohitboxset_t const* s = pHitboxSet(set);
|
||
|
if (!s)
|
||
|
return NULL;
|
||
|
|
||
|
return s->pHitbox(i);
|
||
|
};
|
||
|
|
||
|
inline int iHitboxCount(int set) const
|
||
|
{
|
||
|
mstudiohitboxset_t const* s = pHitboxSet(set);
|
||
|
if (!s)
|
||
|
return 0;
|
||
|
|
||
|
return s->numhitboxes;
|
||
|
};
|
||
|
|
||
|
|
||
|
int numlocalanim;
|
||
|
int localanimindex;
|
||
|
inline mstudioanimdesc_t* pLocalAnimdesc(int i) const { if (i < 0 || i >= numlocalanim) i = 0; return (mstudioanimdesc_t*)(((byte*)this) + localanimindex) + i; };
|
||
|
|
||
|
int numlocalseq;
|
||
|
int localseqindex;
|
||
|
inline mstudioseqdesc_t* pLocalSeqdesc(int i) const { if (i < 0 || i >= numlocalseq) i = 0; return (mstudioseqdesc_t*)(((byte*)this) + localseqindex) + i; };
|
||
|
|
||
|
bool SequencesAvailable() const;
|
||
|
int GetNumSeq() const;
|
||
|
mstudioanimdesc_t& pAnimdesc(int i) const;
|
||
|
mstudioseqdesc_t& pSeqdesc(int i) const;
|
||
|
int iRelativeAnim(int baseseq, int relanim) const;
|
||
|
int iRelativeSeq(int baseseq, int relseq) const;
|
||
|
|
||
|
mutable int activitylistversion;
|
||
|
mutable int eventsindexed;
|
||
|
int GetSequenceActivity(int iSequence);
|
||
|
void SetSequenceActivity(int iSequence, int iActivity);
|
||
|
int GetActivityListVersion(void);
|
||
|
void SetActivityListVersion(int version) const;
|
||
|
int GetEventListVersion(void);
|
||
|
void SetEventListVersion(int version);
|
||
|
|
||
|
int numtextures;
|
||
|
int textureindex;
|
||
|
inline mstudiotexture_t* pTexture(int i) const { Assert(i >= 0 && i < numtextures); return (mstudiotexture_t*)(((byte*)this) + textureindex) + i; };
|
||
|
|
||
|
|
||
|
int numcdtextures;
|
||
|
int cdtextureindex;
|
||
|
inline char* pCdtexture(int i) const { return (((char*)this) + *((int*)(((byte*)this) + cdtextureindex) + i)); };
|
||
|
|
||
|
int numskinref;
|
||
|
int numskinfamilies;
|
||
|
int skinindex;
|
||
|
inline short* pSkinref(int i) const { return (short*)(((byte*)this) + skinindex) + i; };
|
||
|
|
||
|
int numbodyparts;
|
||
|
int bodypartindex;
|
||
|
inline mstudiobodyparts_t* pBodypart(int i) const { return (mstudiobodyparts_t*)(((byte*)this) + bodypartindex) + i; };
|
||
|
|
||
|
int numlocalattachments;
|
||
|
int localattachmentindex;
|
||
|
inline mstudioattachment_t* pLocalAttachment(int i) const { Assert(i >= 0 && i < numlocalattachments); return (mstudioattachment_t*)(((byte*)this) + localattachmentindex) + i; };
|
||
|
int GetNumAttachments(void) const;
|
||
|
const mstudioattachment_t& pAttachment(int i) const;
|
||
|
int GetAttachmentBone(int i);
|
||
|
void SetAttachmentBone(int iAttachment, int iBone);
|
||
|
|
||
|
int numlocalnodes;
|
||
|
int localnodeindex;
|
||
|
int localnodenameindex;
|
||
|
inline char* pszLocalNodeName(int iNode) const { Assert(iNode >= 0 && iNode < numlocalnodes); return (((char*)this) + *((int*)(((byte*)this) + localnodenameindex) + iNode)); }
|
||
|
inline byte* pLocalTransition(int i) const { Assert(i >= 0 && i < (numlocalnodes* numlocalnodes)); return (byte*)(((byte*)this) + localnodeindex) + i; };
|
||
|
|
||
|
int EntryNode(int iSequence);
|
||
|
int ExitNode(int iSequence);
|
||
|
char* pszNodeName(int iNode);
|
||
|
int GetTransition(int iFrom, int iTo) const;
|
||
|
|
||
|
int numflexdesc;
|
||
|
int flexdescindex;
|
||
|
inline mstudioflexdesc_t* pFlexdesc(int i) const { Assert(i >= 0 && i < numflexdesc); return (mstudioflexdesc_t*)(((byte*)this) + flexdescindex) + i; };
|
||
|
|
||
|
int numflexcontrollers;
|
||
|
int flexcontrollerindex;
|
||
|
inline mstudioflexcontroller_t* pFlexcontroller(LocalFlexController_t i) const { Assert(numflexcontrollers == 0 || (i >= 0 && i < numflexcontrollers)); return (mstudioflexcontroller_t*)(((byte*)this) + flexcontrollerindex) + i; };
|
||
|
|
||
|
int numflexrules;
|
||
|
int flexruleindex;
|
||
|
inline mstudioflexrule_t* pFlexRule(int i) const { Assert(i >= 0 && i < numflexrules); return (mstudioflexrule_t*)(((byte*)this) + flexruleindex) + i; };
|
||
|
|
||
|
int numikchains;
|
||
|
int ikchainindex;
|
||
|
inline mstudioikchain_t* pIKChain(int i) const { Assert(i >= 0 && i < numikchains); return (mstudioikchain_t*)(((byte*)this) + ikchainindex) + i; };
|
||
|
|
||
|
int nummouths;
|
||
|
int mouthindex;
|
||
|
inline mstudiomouth_t* pMouth(int i) const { Assert(i >= 0 && i < nummouths); return (mstudiomouth_t*)(((byte*)this) + mouthindex) + i; };
|
||
|
|
||
|
int numlocalposeparameters;
|
||
|
int localposeparamindex;
|
||
|
inline mstudioposeparamdesc_t* pLocalPoseParameter(int i) const { Assert(i >= 0 && i < numlocalposeparameters); return (mstudioposeparamdesc_t*)(((byte*)this) + localposeparamindex) + i; };
|
||
|
int GetNumPoseParameters(void) const;
|
||
|
const mstudioposeparamdesc_t& pPoseParameter(int i);
|
||
|
int GetSharedPoseParameter(int iSequence, int iLocalPose) const;
|
||
|
|
||
|
int surfacepropindex;
|
||
|
inline char* const pszSurfaceProp(void) const { return ((char*)this) + surfacepropindex; }
|
||
|
|
||
|
int keyvalueindex;
|
||
|
int keyvaluesize;
|
||
|
inline const char* KeyValueText(void) const { return keyvaluesize != 0 ? ((char*)this) + keyvalueindex : NULL; }
|
||
|
|
||
|
int numlocalikautoplaylocks;
|
||
|
int localikautoplaylockindex;
|
||
|
inline mstudioiklock_t* pLocalIKAutoplayLock(int i) const { Assert(i >= 0 && i < numlocalikautoplaylocks); return (mstudioiklock_t*)(((byte*)this) + localikautoplaylockindex) + i; };
|
||
|
|
||
|
int GetNumIKAutoplayLocks(void) const;
|
||
|
const mstudioiklock_t& pIKAutoplayLock(int i);
|
||
|
int CountAutoplaySequences() const;
|
||
|
int CopyAutoplaySequences(unsigned short* pOut, int outCount) const;
|
||
|
int GetAutoplayList(unsigned short** pOut) const;
|
||
|
|
||
|
float mass;
|
||
|
int contents;
|
||
|
|
||
|
int numincludemodels;
|
||
|
int includemodelindex;
|
||
|
inline mstudiomodelgroup_t* pModelGroup(int i) const { Assert(i >= 0 && i < numincludemodels); return (mstudiomodelgroup_t*)(((byte*)this) + includemodelindex) + i; };
|
||
|
const studiohdr_t* FindModel(void** cache, char const* modelname) const;
|
||
|
|
||
|
mutable void* virtualModel;
|
||
|
virtualmodel_t* GetVirtualModel(void) const;
|
||
|
|
||
|
int szanimblocknameindex;
|
||
|
inline char* const pszAnimBlockName(void) const { return ((char*)this) + szanimblocknameindex; }
|
||
|
int numanimblocks;
|
||
|
int animblockindex;
|
||
|
inline mstudioanimblock_t* pAnimBlock(int i) const { Assert(i > 0 && i < numanimblocks); return (mstudioanimblock_t*)(((byte*)this) + animblockindex) + i; };
|
||
|
mutable void* animblockModel;
|
||
|
byte* GetAnimBlock(int i) const;
|
||
|
|
||
|
int bonetablebynameindex;
|
||
|
inline const byte* GetBoneTableSortedByName() const { return (byte*)this + bonetablebynameindex; }
|
||
|
|
||
|
void* pVertexBase;
|
||
|
void* pIndexBase;
|
||
|
|
||
|
byte constdirectionallightdot;
|
||
|
|
||
|
byte rootLOD;
|
||
|
|
||
|
byte numAllowedRootLODs;
|
||
|
|
||
|
byte unused[1];
|
||
|
|
||
|
int unused4;
|
||
|
|
||
|
int numflexcontrollerui;
|
||
|
int flexcontrolleruiindex;
|
||
|
mstudioflexcontrollerui_t* pFlexControllerUI(int i) const { Assert(i >= 0 && i < numflexcontrollerui); return (mstudioflexcontrollerui_t*)(((byte*)this) + flexcontrolleruiindex) + i; }
|
||
|
|
||
|
float flVertAnimFixedPointScale;
|
||
|
inline float VertAnimFixedPointScale() const { return (flags & STUDIOHDR_FLAGS_VERT_ANIM_FIXED_POINT_SCALE) ? flVertAnimFixedPointScale : 1.0f / 4096.0f; }
|
||
|
|
||
|
int unused3[1];
|
||
|
|
||
|
int studiohdr2index;
|
||
|
studiohdr2_t* pStudioHdr2() const { return (studiohdr2_t*)(((byte*)this) + studiohdr2index); }
|
||
|
|
||
|
int NumSrcBoneTransforms() const { return studiohdr2index ? pStudioHdr2()->numsrcbonetransform : 0; }
|
||
|
const mstudiosrcbonetransform_t* SrcBoneTransform(int i) const { Assert(i >= 0 && i < NumSrcBoneTransforms()); return (mstudiosrcbonetransform_t*)(((byte*)this) + pStudioHdr2()->srcbonetransformindex) + i; }
|
||
|
|
||
|
inline int IllumPositionAttachmentIndex() const { return studiohdr2index ? pStudioHdr2()->IllumPositionAttachmentIndex() : 0; }
|
||
|
|
||
|
inline float MaxEyeDeflection() const { return studiohdr2index ? pStudioHdr2()->MaxEyeDeflection() : 0.866f; }
|
||
|
|
||
|
inline mstudiolinearbone_t* pLinearBones() const { return studiohdr2index ? pStudioHdr2()->pLinearBones() : NULL; }
|
||
|
|
||
|
inline int BoneFlexDriverCount() const { return studiohdr2index ? pStudioHdr2()->m_nBoneFlexDriverCount : 0; }
|
||
|
inline const mstudioboneflexdriver_t* BoneFlexDriver(int i) const { Assert(i >= 0 && i < BoneFlexDriverCount()); return studiohdr2index ? pStudioHdr2()->pBoneFlexDriver(i) : NULL; }
|
||
|
|
||
|
int unused2[1];
|
||
|
|
||
|
studiohdr_t() {}
|
||
|
|
||
|
private:
|
||
|
studiohdr_t(const studiohdr_t& vOther);
|
||
|
|
||
|
friend struct virtualmodel_t;
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
class IDataCache;
|
||
|
class IMDLCache;
|
||
|
|
||
|
class CStudioHdr
|
||
|
{
|
||
|
public:
|
||
|
CStudioHdr(void);
|
||
|
CStudioHdr(const studiohdr_t* pStudioHdr, IMDLCache* mdlcache = NULL);
|
||
|
~CStudioHdr() { Term(); }
|
||
|
|
||
|
void Init(const studiohdr_t* pStudioHdr, IMDLCache* mdlcache = NULL);
|
||
|
void Term();
|
||
|
|
||
|
public:
|
||
|
inline bool IsVirtual(void) { return (m_pVModel != NULL); };
|
||
|
inline bool IsValid(void) { return (m_pStudioHdr != NULL); };
|
||
|
inline bool IsReadyForAccess(void) const { return (m_pStudioHdr != NULL); };
|
||
|
inline virtualmodel_t* GetVirtualModel(void) const { return m_pVModel; };
|
||
|
inline const studiohdr_t* GetRenderHdr(void) const { return m_pStudioHdr; };
|
||
|
const studiohdr_t* pSeqStudioHdr(int sequence);
|
||
|
const studiohdr_t* pAnimStudioHdr(int animation);
|
||
|
|
||
|
private:
|
||
|
mutable const studiohdr_t* m_pStudioHdr;
|
||
|
mutable virtualmodel_t* m_pVModel;
|
||
|
|
||
|
const virtualmodel_t* ResetVModel(const virtualmodel_t* pVModel) const;
|
||
|
const studiohdr_t* GroupStudioHdr(int group);
|
||
|
mutable CUtlVector< const studiohdr_t* > m_pStudioHdrCache;
|
||
|
|
||
|
mutable int m_nFrameUnlockCounter;
|
||
|
int* m_pFrameUnlockCounter;
|
||
|
CThreadFastMutex m_FrameUnlockCounterMutex;
|
||
|
|
||
|
public:
|
||
|
inline int numbones(void) const { return m_pStudioHdr->numbones; };
|
||
|
inline mstudiobone_t* pBone(int i) const { return m_pStudioHdr->pBone(i); };
|
||
|
int RemapAnimBone(int iAnim, int iLocalBone) const;
|
||
|
int RemapSeqBone(int iSequence, int iLocalBone) const;
|
||
|
|
||
|
bool SequencesAvailable() const;
|
||
|
int GetNumSeq(void) const;
|
||
|
mstudioanimdesc_t& pAnimdesc(int i);
|
||
|
mstudioseqdesc_t& pSeqdesc(int iSequence);
|
||
|
int iRelativeAnim(int baseseq, int relanim) const;
|
||
|
int iRelativeSeq(int baseseq, int relseq) const;
|
||
|
|
||
|
int GetSequenceActivity(int iSequence);
|
||
|
void SetSequenceActivity(int iSequence, int iActivity);
|
||
|
int GetActivityListVersion(void);
|
||
|
void SetActivityListVersion(int version);
|
||
|
int GetEventListVersion(void);
|
||
|
void SetEventListVersion(int version);
|
||
|
|
||
|
int GetNumAttachments(void) const;
|
||
|
const mstudioattachment_t& pAttachment(int i);
|
||
|
int GetAttachmentBone(int i);
|
||
|
void SetAttachmentBone(int iAttachment, int iBone);
|
||
|
|
||
|
int EntryNode(int iSequence);
|
||
|
int ExitNode(int iSequence);
|
||
|
char* pszNodeName(int iNode);
|
||
|
int GetTransition(int iFrom, int iTo) const;
|
||
|
|
||
|
int GetNumPoseParameters(void) const;
|
||
|
const mstudioposeparamdesc_t& pPoseParameter(int i);
|
||
|
int GetSharedPoseParameter(int iSequence, int iLocalPose) const;
|
||
|
|
||
|
int GetNumIKAutoplayLocks(void) const;
|
||
|
const mstudioiklock_t& pIKAutoplayLock(int i);
|
||
|
|
||
|
inline int CountAutoplaySequences() const { return m_pStudioHdr->CountAutoplaySequences(); };
|
||
|
inline int CopyAutoplaySequences(unsigned short* pOut, int outCount) const { return m_pStudioHdr->CopyAutoplaySequences(pOut, outCount); };
|
||
|
inline int GetAutoplayList(unsigned short** pOut) const { return m_pStudioHdr->GetAutoplayList(pOut); };
|
||
|
|
||
|
inline int GetNumBoneControllers(void) const { return m_pStudioHdr->numbonecontrollers; };
|
||
|
inline mstudiobonecontroller_t* pBonecontroller(int i) const { return m_pStudioHdr->pBonecontroller(i); };
|
||
|
|
||
|
inline int numikchains() const { return m_pStudioHdr->numikchains; };
|
||
|
inline int GetNumIKChains(void) const { return m_pStudioHdr->numikchains; };
|
||
|
inline mstudioikchain_t* pIKChain(int i) const { return m_pStudioHdr->pIKChain(i); };
|
||
|
|
||
|
inline int numflexrules() const { return m_pStudioHdr->numflexrules; };
|
||
|
inline mstudioflexrule_t* pFlexRule(int i) const { return m_pStudioHdr->pFlexRule(i); };
|
||
|
|
||
|
inline int numflexdesc() const { return m_pStudioHdr->numflexdesc; };
|
||
|
inline mstudioflexdesc_t* pFlexdesc(int i) const { return m_pStudioHdr->pFlexdesc(i); };
|
||
|
|
||
|
inline LocalFlexController_t numflexcontrollers() const { return (LocalFlexController_t)m_pStudioHdr->numflexcontrollers; };
|
||
|
inline mstudioflexcontroller_t* pFlexcontroller(LocalFlexController_t i) const { return m_pStudioHdr->pFlexcontroller(i); };
|
||
|
|
||
|
inline int numflexcontrollerui() const { return m_pStudioHdr->numflexcontrollerui; };
|
||
|
inline mstudioflexcontrollerui_t* pFlexcontrollerUI(int i) const { return m_pStudioHdr->pFlexControllerUI(i); };
|
||
|
|
||
|
inline const char* pszName() const { return m_pStudioHdr->pszName(); };
|
||
|
|
||
|
inline int numbonecontrollers() const { return m_pStudioHdr->numbonecontrollers; };
|
||
|
|
||
|
inline int numhitboxsets() const { return m_pStudioHdr->numhitboxsets; };
|
||
|
inline mstudiohitboxset_t* pHitboxSet(int i) const { return m_pStudioHdr->pHitboxSet(i); };
|
||
|
|
||
|
inline mstudiobbox_t* pHitbox(int i, int set) const { return m_pStudioHdr->pHitbox(i, set); };
|
||
|
inline int iHitboxCount(int set) const { return m_pStudioHdr->iHitboxCount(set); };
|
||
|
|
||
|
inline int numbodyparts() const { return m_pStudioHdr->numbodyparts; };
|
||
|
inline mstudiobodyparts_t* pBodypart(int i) const { return m_pStudioHdr->pBodypart(i); };
|
||
|
|
||
|
inline int numskinfamilies() const { return m_pStudioHdr->numskinfamilies; }
|
||
|
|
||
|
inline Vector eyeposition() const { return m_pStudioHdr->eyeposition; };
|
||
|
|
||
|
inline int flags() const { return m_pStudioHdr->flags; };
|
||
|
|
||
|
inline char* const pszSurfaceProp(void) const { return m_pStudioHdr->pszSurfaceProp(); };
|
||
|
|
||
|
inline float mass() const { return m_pStudioHdr->mass; };
|
||
|
inline int contents() const { return m_pStudioHdr->contents; }
|
||
|
|
||
|
inline const byte* GetBoneTableSortedByName() const { return m_pStudioHdr->GetBoneTableSortedByName(); };
|
||
|
|
||
|
inline Vector illumposition() const { return m_pStudioHdr->illumposition; };
|
||
|
|
||
|
inline Vector hull_min() const { return m_pStudioHdr->hull_min; };
|
||
|
inline Vector hull_max() const { return m_pStudioHdr->hull_max; };
|
||
|
|
||
|
inline Vector view_bbmin() const { return m_pStudioHdr->view_bbmin; };
|
||
|
inline Vector view_bbmax() const { return m_pStudioHdr->view_bbmax; };
|
||
|
|
||
|
inline int numtextures() const { return m_pStudioHdr->numtextures; };
|
||
|
|
||
|
inline int IllumPositionAttachmentIndex() const { return m_pStudioHdr->IllumPositionAttachmentIndex(); }
|
||
|
|
||
|
inline float MaxEyeDeflection() const { return m_pStudioHdr->MaxEyeDeflection(); }
|
||
|
|
||
|
inline mstudiolinearbone_t* pLinearBones() const { return m_pStudioHdr->pLinearBones(); }
|
||
|
|
||
|
inline int BoneFlexDriverCount() const { return m_pStudioHdr->BoneFlexDriverCount(); }
|
||
|
inline const mstudioboneflexdriver_t* BoneFlexDriver(int i) const { return m_pStudioHdr->BoneFlexDriver(i); }
|
||
|
|
||
|
inline float VertAnimFixedPointScale() const { return m_pStudioHdr->VertAnimFixedPointScale(); }
|
||
|
|
||
|
public:
|
||
|
int IsSequenceLooping(int iSequence);
|
||
|
float GetSequenceCycleRate(int iSequence);
|
||
|
|
||
|
void RunFlexRules(const float* src, float* dest);
|
||
|
|
||
|
|
||
|
public:
|
||
|
inline int boneFlags(int iBone) const { return m_boneFlags[iBone]; }
|
||
|
inline int boneParent(int iBone) const { return m_boneParent[iBone]; }
|
||
|
|
||
|
private:
|
||
|
CUtlVector< int > m_boneFlags;
|
||
|
CUtlVector< int > m_boneParent;
|
||
|
|
||
|
public:
|
||
|
|
||
|
class CActivityToSequenceMapping
|
||
|
{
|
||
|
public:
|
||
|
struct SequenceTuple
|
||
|
{
|
||
|
short seqnum;
|
||
|
short weight;
|
||
|
CUtlSymbol* pActivityModifiers;
|
||
|
int iNumActivityModifiers;
|
||
|
};
|
||
|
|
||
|
struct HashValueType
|
||
|
{
|
||
|
int activityIdx;
|
||
|
|
||
|
int startingIdx;
|
||
|
int count;
|
||
|
int totalWeight;
|
||
|
|
||
|
HashValueType(int _actIdx, int _stIdx, int _ct, int _tW) :
|
||
|
activityIdx(_actIdx), startingIdx(_stIdx), count(_ct), totalWeight(_tW) {}
|
||
|
|
||
|
HashValueType() : activityIdx(-1), startingIdx(-1), count(-1), totalWeight(-1)
|
||
|
{
|
||
|
AssertMsg(false, "Don't use default HashValueType()!");
|
||
|
}
|
||
|
|
||
|
|
||
|
class HashFuncs
|
||
|
{
|
||
|
public:
|
||
|
HashFuncs(int) {}
|
||
|
|
||
|
bool operator()(const HashValueType& lhs, const HashValueType& rhs) const
|
||
|
{
|
||
|
return lhs.activityIdx == rhs.activityIdx;
|
||
|
}
|
||
|
|
||
|
unsigned int operator()(const HashValueType& item) const
|
||
|
{
|
||
|
return HashInt(item.activityIdx);
|
||
|
}
|
||
|
};
|
||
|
};
|
||
|
|
||
|
typedef CUtlHash<HashValueType, HashValueType::HashFuncs, HashValueType::HashFuncs> ActivityToValueIdxHash;
|
||
|
|
||
|
CActivityToSequenceMapping(void)
|
||
|
: m_pSequenceTuples(NULL), m_iSequenceTuplesCount(0), m_ActToSeqHash(8, 0, 0), m_expectedPStudioHdr(NULL), m_expectedVModel(NULL)
|
||
|
#if STUDIO_SEQUENCE_ACTIVITY_LAZY_INITIALIZE
|
||
|
, m_bIsInitialized(false)
|
||
|
#endif
|
||
|
{};
|
||
|
|
||
|
~CActivityToSequenceMapping()
|
||
|
{
|
||
|
if (m_pSequenceTuples != NULL)
|
||
|
{
|
||
|
if (m_pSequenceTuples->pActivityModifiers != NULL)
|
||
|
{
|
||
|
delete[] m_pSequenceTuples->pActivityModifiers;
|
||
|
}
|
||
|
delete[] m_pSequenceTuples;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const SequenceTuple* GetSequences(int forActivity, int* outSequenceCount, int* outTotalWeight);
|
||
|
|
||
|
int NumSequencesForActivity(int forActivity);
|
||
|
|
||
|
#if STUDIO_SEQUENCE_ACTIVITY_LAZY_INITIALIZE
|
||
|
inline bool IsInitialized(void) { return m_bIsInitialized; }
|
||
|
#endif
|
||
|
|
||
|
private:
|
||
|
|
||
|
void Initialize(CStudioHdr* pstudiohdr);
|
||
|
|
||
|
void Reinitialize(CStudioHdr* pstudiohdr);
|
||
|
|
||
|
int SelectWeightedSequence(CStudioHdr* pstudiohdr, int activity, int curSequence);
|
||
|
|
||
|
int SelectWeightedSequenceFromModifiers(CStudioHdr* pstudiohdr, int activity, CUtlSymbol* pActivityModifiers, int iModifierCount);
|
||
|
|
||
|
SequenceTuple* m_pSequenceTuples;
|
||
|
unsigned int m_iSequenceTuplesCount;
|
||
|
#if STUDIO_SEQUENCE_ACTIVITY_LAZY_INITIALIZE
|
||
|
bool m_bIsInitialized;
|
||
|
#endif
|
||
|
|
||
|
ActivityToValueIdxHash m_ActToSeqHash;
|
||
|
|
||
|
const void* m_expectedPStudioHdr;
|
||
|
const void* m_expectedVModel;
|
||
|
|
||
|
bool ValidateAgainst(const CStudioHdr* RESTRICT pstudiohdr);
|
||
|
void SetValidationPair(const CStudioHdr* RESTRICT pstudiohdr);
|
||
|
|
||
|
friend class CStudioHdr;
|
||
|
};
|
||
|
|
||
|
CActivityToSequenceMapping m_ActivityToSequence;
|
||
|
|
||
|
inline int SelectWeightedSequence(int activity, int curSequence)
|
||
|
{
|
||
|
#if STUDIO_SEQUENCE_ACTIVITY_LAZY_INITIALIZE
|
||
|
if (!m_ActivityToSequence.IsInitialized())
|
||
|
{
|
||
|
m_ActivityToSequence.Initialize(this);
|
||
|
}
|
||
|
#endif
|
||
|
return m_ActivityToSequence.SelectWeightedSequence(this, activity, curSequence);
|
||
|
}
|
||
|
|
||
|
inline int SelectWeightedSequenceFromModifiers(int activity, CUtlSymbol* pActivityModifiers, int iModifierCount)
|
||
|
{
|
||
|
#if STUDIO_SEQUENCE_ACTIVITY_LAZY_INITIALIZE
|
||
|
if (!m_ActivityToSequence.IsInitialized())
|
||
|
{
|
||
|
m_ActivityToSequence.Initialize(this);
|
||
|
}
|
||
|
#endif
|
||
|
return m_ActivityToSequence.SelectWeightedSequenceFromModifiers(this, activity, pActivityModifiers, iModifierCount);
|
||
|
}
|
||
|
|
||
|
inline bool HaveSequenceForActivity(int activity)
|
||
|
{
|
||
|
#if STUDIO_SEQUENCE_ACTIVITY_LAZY_INITIALIZE
|
||
|
if (!m_ActivityToSequence.IsInitialized())
|
||
|
{
|
||
|
m_ActivityToSequence.Initialize(this);
|
||
|
}
|
||
|
#endif
|
||
|
return (m_ActivityToSequence.NumSequencesForActivity(activity) > 0);
|
||
|
}
|
||
|
|
||
|
inline void ReinitializeSequenceMapping(void)
|
||
|
{
|
||
|
m_ActivityToSequence.Reinitialize(this);
|
||
|
}
|
||
|
|
||
|
#ifdef STUDIO_ENABLE_PERF_COUNTERS
|
||
|
public:
|
||
|
inline void ClearPerfCounters(void)
|
||
|
{
|
||
|
m_nPerfAnimatedBones = 0;
|
||
|
m_nPerfUsedBones = 0;
|
||
|
m_nPerfAnimationLayers = 0;
|
||
|
};
|
||
|
|
||
|
mutable int m_nPerfAnimatedBones;
|
||
|
mutable int m_nPerfUsedBones;
|
||
|
mutable int m_nPerfAnimationLayers;
|
||
|
#endif
|
||
|
|
||
|
|
||
|
};
|
||
|
|
||
|
struct flexweight_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
int key;
|
||
|
float weight;
|
||
|
float influence;
|
||
|
};
|
||
|
|
||
|
struct flexsetting_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
int nameindex;
|
||
|
|
||
|
inline char* pszName(void) const
|
||
|
{
|
||
|
return (char*)(((byte*)this) + nameindex);
|
||
|
}
|
||
|
|
||
|
int obsolete1;
|
||
|
|
||
|
int numsettings;
|
||
|
int index;
|
||
|
|
||
|
int obsolete2;
|
||
|
|
||
|
int settingindex;
|
||
|
|
||
|
inline int psetting(byte* base, int i, flexweight_t** weights) const;
|
||
|
};
|
||
|
|
||
|
|
||
|
struct flexsettinghdr_t
|
||
|
{
|
||
|
DECLARE_BYTESWAP_DATADESC();
|
||
|
int id;
|
||
|
int version;
|
||
|
|
||
|
inline const char* pszName(void) const { return name; }
|
||
|
char name[64];
|
||
|
int length;
|
||
|
|
||
|
int numflexsettings;
|
||
|
int flexsettingindex;
|
||
|
inline flexsetting_t* pSetting(int i) const { return (flexsetting_t*)(((byte*)this) + flexsettingindex) + i; };
|
||
|
int nameindex;
|
||
|
|
||
|
int numindexes;
|
||
|
int indexindex;
|
||
|
|
||
|
inline flexsetting_t* pIndexedSetting(int index) const
|
||
|
{
|
||
|
if (index < 0 || index >= numindexes)
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
int i = *((int*)(((byte*)this) + indexindex) + index);
|
||
|
|
||
|
if (i == -1)
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
return pSetting(i);
|
||
|
}
|
||
|
|
||
|
int numkeys;
|
||
|
int keynameindex;
|
||
|
inline char* pLocalName(int i) const { return (char*)(((byte*)this) + *((int*)(((byte*)this) + keynameindex) + i)); };
|
||
|
|
||
|
int keymappingindex;
|
||
|
inline int* pLocalToGlobal(int i) const { return (int*)(((byte*)this) + keymappingindex) + i; };
|
||
|
inline int LocalToGlobal(int i) const { return *pLocalToGlobal(i); };
|
||
|
};
|
||
|
|
||
|
inline int flexsetting_t::psetting(byte* base, int i, flexweight_t** weights) const
|
||
|
{
|
||
|
*weights = (flexweight_t*)(((byte*)this) + settingindex) + i;
|
||
|
return numsettings;
|
||
|
};
|
||
|
|
||
|
|
||
|
inline int mstudioflexcontrollerui_t::controllerIndex(const CStudioHdr& cStudioHdr) const
|
||
|
{
|
||
|
return !stereo ? pController() - cStudioHdr.pFlexcontroller((LocalFlexController_t)0) : -1;
|
||
|
}
|
||
|
|
||
|
|
||
|
inline int mstudioflexcontrollerui_t::rightIndex(const CStudioHdr& cStudioHdr) const
|
||
|
{
|
||
|
return stereo ? pRightController() - cStudioHdr.pFlexcontroller((LocalFlexController_t)0) : -1;
|
||
|
}
|
||
|
|
||
|
|
||
|
inline int mstudioflexcontrollerui_t::leftIndex(const CStudioHdr& cStudioHdr) const
|
||
|
{
|
||
|
return stereo ? pLeftController() - cStudioHdr.pFlexcontroller((LocalFlexController_t)0) : -1;
|
||
|
}
|
||
|
|
||
|
|
||
|
inline int mstudioflexcontrollerui_t::nWayValueIndex(const CStudioHdr& cStudioHdr) const
|
||
|
{
|
||
|
return remaptype == FLEXCONTROLLER_REMAP_NWAY ? pNWayValueController() - cStudioHdr.pFlexcontroller((LocalFlexController_t)0) : -1;
|
||
|
}
|
||
|
|
||
|
|
||
|
inline const mstudioflexcontroller_t* mstudioflexcontrollerui_t::pController(int index) const
|
||
|
{
|
||
|
if (index < 0 || index > Count())
|
||
|
return NULL;
|
||
|
|
||
|
if (remaptype == FLEXCONTROLLER_REMAP_NWAY)
|
||
|
{
|
||
|
if (stereo)
|
||
|
return (mstudioflexcontroller_t*)((char*)this) + *(&szindex0 + index);
|
||
|
|
||
|
if (index == 0)
|
||
|
return pController();
|
||
|
|
||
|
if (index == 1)
|
||
|
return pNWayValueController();
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
if (index > 1)
|
||
|
return NULL;
|
||
|
|
||
|
if (stereo)
|
||
|
return (mstudioflexcontroller_t*)((char*)this) + *(&szindex0 + index);
|
||
|
|
||
|
if (index > 0)
|
||
|
return NULL;
|
||
|
|
||
|
return pController();
|
||
|
}
|
||
|
|
||
|
|
||
|
#define STUDIO_CONST 1
|
||
|
#define STUDIO_FETCH1 2
|
||
|
#define STUDIO_FETCH2 3
|
||
|
#define STUDIO_ADD 4
|
||
|
#define STUDIO_SUB 5
|
||
|
#define STUDIO_MUL 6
|
||
|
#define STUDIO_DIV 7
|
||
|
#define STUDIO_NEG 8
|
||
|
#define STUDIO_EXP 9
|
||
|
#define STUDIO_OPEN 10
|
||
|
#define STUDIO_CLOSE 11
|
||
|
#define STUDIO_COMMA 12
|
||
|
#define STUDIO_MAX 13
|
||
|
#define STUDIO_MIN 14
|
||
|
#define STUDIO_2WAY_0 15
|
||
|
#define STUDIO_2WAY_1 16
|
||
|
#define STUDIO_NWAY 17
|
||
|
#define STUDIO_COMBO 18
|
||
|
#define STUDIO_DOMINATE 19
|
||
|
#define STUDIO_DME_LOWER_EYELID 20
|
||
|
#define STUDIO_DME_UPPER_EYELID 21
|
||
|
|
||
|
#define STUDIO_X 0x00000001
|
||
|
#define STUDIO_Y 0x00000002
|
||
|
#define STUDIO_Z 0x00000004
|
||
|
#define STUDIO_XR 0x00000008
|
||
|
#define STUDIO_YR 0x00000010
|
||
|
#define STUDIO_ZR 0x00000020
|
||
|
|
||
|
#define STUDIO_LX 0x00000040
|
||
|
#define STUDIO_LY 0x00000080
|
||
|
#define STUDIO_LZ 0x00000100
|
||
|
#define STUDIO_LXR 0x00000200
|
||
|
#define STUDIO_LYR 0x00000400
|
||
|
#define STUDIO_LZR 0x00000800
|
||
|
|
||
|
#define STUDIO_LINEAR 0x00001000
|
||
|
|
||
|
#define STUDIO_TYPES 0x0003FFFF
|
||
|
#define STUDIO_RLOOP 0x00040000
|
||
|
|
||
|
#define STUDIO_LOOPING 0x0001
|
||
|
#define STUDIO_SNAP 0x0002
|
||
|
#define STUDIO_DELTA 0x0004
|
||
|
#define STUDIO_AUTOPLAY 0x0008
|
||
|
#define STUDIO_POST 0x0010
|
||
|
#define STUDIO_ALLZEROS 0x0020
|
||
|
#define STUDIO_CYCLEPOSE 0x0080
|
||
|
#define STUDIO_REALTIME 0x0100
|
||
|
#define STUDIO_LOCAL 0x0200
|
||
|
#define STUDIO_HIDDEN 0x0400
|
||
|
#define STUDIO_OVERRIDE 0x0800
|
||
|
#define STUDIO_ACTIVITY 0x1000
|
||
|
#define STUDIO_EVENT 0x2000
|
||
|
#define STUDIO_WORLD 0x4000
|
||
|
#define STUDIO_AL_POST 0x0010
|
||
|
#define STUDIO_AL_SPLINE 0x0040
|
||
|
#define STUDIO_AL_XFADE 0x0080
|
||
|
#define STUDIO_AL_NOBLEND 0x0200
|
||
|
#define STUDIO_AL_LOCAL 0x1000
|
||
|
#define STUDIO_AL_POSE 0x4000
|
||
|
|
||
|
|
||
|
inline bool Studio_ConvertStudioHdrToNewVersion(studiohdr_t* pStudioHdr)
|
||
|
{
|
||
|
COMPILE_TIME_ASSERT(STUDIO_VERSION == 48);
|
||
|
|
||
|
int version = pStudioHdr->version;
|
||
|
if (version == STUDIO_VERSION)
|
||
|
return true;
|
||
|
|
||
|
bool bResult = true;
|
||
|
if (version < 46)
|
||
|
{
|
||
|
for (int i = 0; i < pStudioHdr->numlocalanim; i++)
|
||
|
{
|
||
|
mstudioanimdesc_t* pAnim = (mstudioanimdesc_t*)pStudioHdr->pLocalAnimdesc(i);
|
||
|
|
||
|
if (pAnim->sectionframes != 0)
|
||
|
{
|
||
|
memset(&(pAnim->numframes), 0, (byte*)(pAnim + 1) - (byte*)&(pAnim->numframes));
|
||
|
|
||
|
pAnim->numframes = 1;
|
||
|
pAnim->animblock = -1;
|
||
|
bResult = false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (version < 47)
|
||
|
{
|
||
|
if (pStudioHdr->unused4 != 0)
|
||
|
{
|
||
|
pStudioHdr->unused4 = 0;
|
||
|
bResult = false;
|
||
|
}
|
||
|
for (int i = 0; i < pStudioHdr->numlocalanim; i++)
|
||
|
{
|
||
|
mstudioanimdesc_t* pAnim = (mstudioanimdesc_t*)pStudioHdr->pLocalAnimdesc(i);
|
||
|
pAnim->zeroframeindex = 0;
|
||
|
pAnim->zeroframespan = 0;
|
||
|
}
|
||
|
}
|
||
|
else if (version == 47)
|
||
|
{
|
||
|
for (int i = 0; i < pStudioHdr->numlocalanim; i++)
|
||
|
{
|
||
|
mstudioanimdesc_t* pAnim = (mstudioanimdesc_t*)pStudioHdr->pLocalAnimdesc(i);
|
||
|
if (pAnim->zeroframeindex != 0)
|
||
|
{
|
||
|
pAnim->zeroframeindex = 0;
|
||
|
pAnim->zeroframespan = 0;
|
||
|
bResult = false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pStudioHdr->version = STUDIO_VERSION;
|
||
|
|
||
|
return bResult;
|
||
|
}
|
||
|
|
||
|
inline void Studio_SetRootLOD(studiohdr_t* pStudioHdr, int rootLOD)
|
||
|
{
|
||
|
if (pStudioHdr->numAllowedRootLODs > 0 &&
|
||
|
rootLOD >= pStudioHdr->numAllowedRootLODs)
|
||
|
{
|
||
|
rootLOD = pStudioHdr->numAllowedRootLODs - 1;
|
||
|
}
|
||
|
|
||
|
Assert(rootLOD >= 0 && rootLOD < MAX_NUM_LODS);
|
||
|
Clamp(rootLOD, 0, MAX_NUM_LODS - 1);
|
||
|
|
||
|
int vertexindex = 0;
|
||
|
int tangentsindex = 0;
|
||
|
int bodyPartID;
|
||
|
for (bodyPartID = 0; bodyPartID < pStudioHdr->numbodyparts; bodyPartID++)
|
||
|
{
|
||
|
mstudiobodyparts_t* pBodyPart = pStudioHdr->pBodypart(bodyPartID);
|
||
|
int modelID;
|
||
|
for (modelID = 0; modelID < pBodyPart->nummodels; modelID++)
|
||
|
{
|
||
|
mstudiomodel_t* pModel = pBodyPart->pModel(modelID);
|
||
|
int totalMeshVertexes = 0;
|
||
|
int meshID;
|
||
|
for (meshID = 0; meshID < pModel->nummeshes; meshID++)
|
||
|
{
|
||
|
mstudiomesh_t* pMesh = pModel->pMesh(meshID);
|
||
|
|
||
|
pMesh->numvertices = pMesh->vertexdata.numLODVertexes[rootLOD];
|
||
|
pMesh->vertexoffset = totalMeshVertexes;
|
||
|
totalMeshVertexes += pMesh->numvertices;
|
||
|
}
|
||
|
|
||
|
pModel->numvertices = totalMeshVertexes;
|
||
|
pModel->vertexindex = vertexindex;
|
||
|
pModel->tangentsindex = tangentsindex;
|
||
|
|
||
|
vertexindex += totalMeshVertexes * sizeof(mstudiovertex_t);
|
||
|
tangentsindex += totalMeshVertexes * sizeof(Vector4D);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pStudioHdr->rootLOD = rootLOD;
|
||
|
}
|
||
|
|
||
|
inline int Studio_VertexDataSize(const vertexFileHeader_t* pVvdHdr, int rootLOD, bool bNeedsTangentS)
|
||
|
{
|
||
|
int numVertexes = pVvdHdr->numLODVertexes[rootLOD] + 1;
|
||
|
int dataLength = pVvdHdr->vertexDataStart + numVertexes * sizeof(mstudiovertex_t);
|
||
|
if (bNeedsTangentS)
|
||
|
{
|
||
|
dataLength += numVertexes * sizeof(Vector4D);
|
||
|
}
|
||
|
|
||
|
return dataLength;
|
||
|
}
|
||
|
|
||
|
inline int Studio_LoadVertexes(const vertexFileHeader_t* pTempVvdHdr, vertexFileHeader_t* pNewVvdHdr, int rootLOD, bool bNeedsTangentS)
|
||
|
{
|
||
|
int i;
|
||
|
int target;
|
||
|
int numVertexes;
|
||
|
vertexFileFixup_t* pFixupTable;
|
||
|
|
||
|
numVertexes = pTempVvdHdr->numLODVertexes[rootLOD];
|
||
|
|
||
|
memcpy((void*)pNewVvdHdr, (void*)pTempVvdHdr, pTempVvdHdr->vertexDataStart);
|
||
|
|
||
|
for (i = 0; i < rootLOD; i++)
|
||
|
{
|
||
|
pNewVvdHdr->numLODVertexes[i] = pNewVvdHdr->numLODVertexes[rootLOD];
|
||
|
}
|
||
|
|
||
|
if (bNeedsTangentS)
|
||
|
{
|
||
|
pNewVvdHdr->tangentDataStart = pNewVvdHdr->vertexDataStart + numVertexes * sizeof(mstudiovertex_t);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pNewVvdHdr->tangentDataStart = 0;
|
||
|
}
|
||
|
|
||
|
if (!pNewVvdHdr->numFixups)
|
||
|
{
|
||
|
memcpy(
|
||
|
(byte*)pNewVvdHdr + pNewVvdHdr->vertexDataStart,
|
||
|
(byte*)pTempVvdHdr + pTempVvdHdr->vertexDataStart,
|
||
|
numVertexes * sizeof(mstudiovertex_t));
|
||
|
|
||
|
if (bNeedsTangentS)
|
||
|
{
|
||
|
memcpy(
|
||
|
(byte*)pNewVvdHdr + pNewVvdHdr->tangentDataStart,
|
||
|
(byte*)pTempVvdHdr + pTempVvdHdr->tangentDataStart,
|
||
|
numVertexes * sizeof(Vector4D));
|
||
|
}
|
||
|
|
||
|
return numVertexes;
|
||
|
}
|
||
|
|
||
|
target = 0;
|
||
|
pFixupTable = (vertexFileFixup_t*)((byte*)pTempVvdHdr + pTempVvdHdr->fixupTableStart);
|
||
|
for (i = 0; i < pTempVvdHdr->numFixups; i++)
|
||
|
{
|
||
|
if (pFixupTable[i].lod < rootLOD)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
memcpy(
|
||
|
(mstudiovertex_t*)((byte*)pNewVvdHdr + pNewVvdHdr->vertexDataStart) + target,
|
||
|
(mstudiovertex_t*)((byte*)pTempVvdHdr + pTempVvdHdr->vertexDataStart) + pFixupTable[i].sourceVertexID,
|
||
|
pFixupTable[i].numVertexes * sizeof(mstudiovertex_t));
|
||
|
|
||
|
if (bNeedsTangentS)
|
||
|
{
|
||
|
memcpy(
|
||
|
(Vector4D*)((byte*)pNewVvdHdr + pNewVvdHdr->tangentDataStart) + target,
|
||
|
(Vector4D*)((byte*)pTempVvdHdr + pTempVvdHdr->tangentDataStart) + pFixupTable[i].sourceVertexID,
|
||
|
pFixupTable[i].numVertexes * sizeof(Vector4D));
|
||
|
}
|
||
|
|
||
|
target += pFixupTable[i].numVertexes;
|
||
|
}
|
||
|
|
||
|
pNewVvdHdr->numFixups = 0;
|
||
|
|
||
|
return target;
|
||
|
}
|
||
|
|
||
|
#endif
|