|
|
//===== Copyright � 1996-2008, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//
//===========================================================================//
#ifndef STUDIOMDL_H
#define STUDIOMDL_H
#ifdef _WIN32
#pragma once
#endif
#include <stdio.h>
#include "basetypes.h"
#include "tier1/utlvector.h"
#include "tier1/utlsymbol.h"
#include "tier1/utlstring.h"
#include "mathlib/vector.h"
#include "studio.h"
#include "datamodel/dmelementhandle.h"
struct LodScriptData_t; struct s_flexkey_t; struct s_flexcontroller_t; struct s_flexcontrollerremap_t; struct s_combinationrule_t; struct s_combinationcontrol_t; class CDmeVertexDeltaData; class CDmeCombinationOperator;
#ifdef MDLCOMPILE
#define SRC_FILE_EXT ".mc"
#define MC_CURRENT_VERSION 1
#else
#define SRC_FILE_EXT ".qc"
#define MC_CURRENT_VERSION 0
#endif
#define IDSTUDIOHEADER (('T'<<24)+('S'<<16)+('D'<<8)+'I')
// little-endian "IDST"
#define IDSTUDIOANIMGROUPHEADER (('G'<<24)+('A'<<16)+('D'<<8)+'I')
// little-endian "IDAG"
#define STUDIO_QUADRATIC_MOTION 0x00002000
#define MAXSTUDIOANIMFRAMES 5000 // max frames per animation
// [mlowrance] updated total number of animations to give more headroom for new weapons
// bumped up from 2k to 3k
#define MAXSTUDIOANIMS 3000 // total animations
#define MAXSTUDIOSEQUENCES 1524 // total sequences
#define MAXSTUDIOSRCBONES 1024 // bones allowed at source movement
#define MAXSTUDIOTEXCOORDS 8
#define MAXSTUDIOMESHES 256
#define MAXSTUDIOEVENTS 1024
#define MAXSTUDIOFLEXKEYS 512
#define MAXSTUDIOFLEXRULES 1024
#define MAXSTUDIOBONEWEIGHTS 3
#define MAXSTUDIOCMDS 64
#define MAXSTUDIOMOVEKEYS 64
#define MAXSTUDIOIKRULES 64
#define MAXSTUDIONAME 128
#define MAXSTUDIOACTIVITYMODIFIERS 128
#define MAXSTUDIOTAGS 1024
#define MAXSTUDIOSRCVERTS (8*65536)
#ifndef EXTERN
#define EXTERN extern
#endif
EXTERN char g_outname[MAX_PATH]; EXTERN char g_szInternalName[MAX_PATH]; EXTERN qboolean cdset; EXTERN int numdirs; EXTERN char cddir[32][MAX_PATH]; EXTERN int numcdtextures; EXTERN char * cdtextures[16]; EXTERN char g_fullpath[MAX_PATH];
EXTERN char rootname[MAXSTUDIONAME]; // name of the root bone
EXTERN float g_defaultscale; EXTERN float g_currentscale; EXTERN RadianEuler g_defaultrotation;
EXTERN char defaulttexture[16][MAX_PATH]; EXTERN char sourcetexture[16][MAX_PATH];
EXTERN int numrep;
EXTERN int tag_reversed; EXTERN int tag_normals; EXTERN float normal_blend; EXTERN int dump_hboxes; EXTERN int ignore_warnings;
EXTERN Vector eyeposition; EXTERN float g_flMaxEyeDeflection; EXTERN int g_illumpositionattachment; EXTERN Vector illumposition; EXTERN int illumpositionset; EXTERN int gflags; EXTERN Vector bbox[2]; EXTERN Vector cbox[2]; EXTERN bool g_wrotebbox; EXTERN bool g_wrotecbox; EXTERN bool g_bboxonlyverts;
EXTERN int clip_texcoords; EXTERN bool g_staticprop; EXTERN bool g_centerstaticprop;
EXTERN bool g_realignbones; EXTERN bool g_definebones; EXTERN bool g_bSkinnedLODs;
EXTERN byte g_constdirectionalightdot;
// Methods associated with the key value text block
extern CUtlVector< char > g_KeyValueText; int KeyValueTextSize( CUtlVector< char > *pKeyValue ); const char *KeyValueText( CUtlVector< char > *pKeyValue );
extern vec_t Q_rint (vec_t in);
extern void WriteModelFiles(void);
// --------------------------------------------------------------------
template< class T > class CUtlVectorAuto : public CUtlVector< T > { // typedef CUtlVectorAuto< T, CUtlVector<T > > BaseClass;
public: T& operator[]( int i ); };
template< typename T > inline T& CUtlVectorAuto<T>::operator[]( int i ) { EnsureCount( i + 1 ); Assert( IsValidIndex(i) ); return Base()[i]; }
//////////////////////////////////////////////////////////////////////////
// Purpose: contains settings specified in gameinfo.txt
//////////////////////////////////////////////////////////////////////////
struct GameInfo_t { bool bSupportsXBox360; bool bSupportsDX8; }; extern struct GameInfo_t g_gameinfo;
// --------------------------------------------------------------------
struct s_trianglevert_t { int vertindex; int normindex; // index into normal array
int s,t; float u,v; };
struct s_boneweight_t { int numbones;
int bone[MAXSTUDIOBONEWEIGHTS]; float weight[MAXSTUDIOBONEWEIGHTS]; };
struct s_tmpface_t { int material; unsigned long a, b, c, d; //
unsigned long na, nb, nc, nd; //
unsigned long ta[MAXSTUDIOTEXCOORDS]; unsigned long tb[MAXSTUDIOTEXCOORDS]; unsigned long tc[MAXSTUDIOTEXCOORDS]; unsigned long td[MAXSTUDIOTEXCOORDS]; // d used by subd quads, otherwise 0xFFFFFFFF
s_tmpface_t(){ a = b = c = d = 0xFFFFFFFF; na = nb = nc = nd = 0xFFFFFFFF; for ( int i = 0; i < MAXSTUDIOTEXCOORDS; ++i ) { ta[i] = tb[i] = tc[i] = td[i] = 0xFFFFFFFF; } } };
struct s_face_t { s_face_t(){ a = b = c = d = 0xFFFFFFFF; } unsigned long a, b, c, d; // d used by subd quads
};
struct s_vertexinfo_t { int material; int mesh; Vector position; Vector normal; Vector4D tangentS; int numTexcoord; Vector2D texcoord[MAXSTUDIOTEXCOORDS]; s_boneweight_t boneweight; };
//============================================================================
// dstudiobone_t bone[MAXSTUDIOBONES];
struct s_bonefixup_t { matrix3x4_t m; };
EXTERN int g_numbones; struct s_bonetable_t { char name[MAXSTUDIONAME]; // bone name for symbolic links
int parent; // parent bone
bool split; int bonecontroller; // -1 == 0
Vector pos; // default pos
Vector posscale; // pos values scale
RadianEuler rot; // default pos
Vector rotscale; // rotation values scale
int group; // hitgroup
Vector bmin, bmax; // bounding box
bool bPreDefined; matrix3x4_t rawLocalOriginal; // original transform of preDefined bone
matrix3x4_t rawLocal; matrix3x4_t srcRealign; bool bPreAligned; matrix3x4_t boneToPose; int flags; int proceduralindex; int physicsBoneIndex; int surfacePropIndex; Quaternion qAlignment; bool bDontCollapse; Vector posrange; }; EXTERN s_bonetable_t g_bonetable[MAXSTUDIOSRCBONES]; extern int findGlobalBone( const char *name ); // finds a named bone in the global bone table
EXTERN int g_numrenamedbones; struct s_renamebone_t { char from[MAXSTUDIONAME]; char to[MAXSTUDIONAME]; }; EXTERN s_renamebone_t g_renamedbone[MAXSTUDIOSRCBONES]; const char *RenameBone( const char *pName ); // returns new name if available, else return pName.
EXTERN char g_szStripBonePrefix[MAXSTUDIOSRCBONES][MAXSTUDIONAME]; EXTERN int g_numStripBonePrefixes;
EXTERN s_renamebone_t g_szRenameBoneSubstr[MAXSTUDIOSRCBONES]; EXTERN int g_numRenameBoneSubstr;
EXTERN int g_numimportbones; struct s_importbone_t { char name[MAXSTUDIONAME]; char parent[MAXSTUDIONAME]; matrix3x4_t rawLocal; bool bPreAligned; matrix3x4_t srcRealign; bool bUnlocked; }; EXTERN s_importbone_t g_importbone[MAXSTUDIOSRCBONES];
EXTERN int g_numincludemodels; struct s_includemodel_t { char name[MAXSTUDIONAME]; }; EXTERN s_includemodel_t g_includemodel[128];
struct s_bbox_t { char name[MAXSTUDIONAME]; // bone name
char hitboxname[MAXSTUDIONAME]; // hitbox name
int bone; int group; // hitgroup
int model; Vector bmin, bmax; // bounding box
QAngle angOffsetOrientation; float flCapsuleRadius; };
#define MAXSTUDIOHITBOXSETNAME 64
struct s_hitboxset { char hitboxsetname[ MAXSTUDIOHITBOXSETNAME ]; int numhitboxes;
s_bbox_t hitbox[MAXSTUDIOSRCBONES]; };
extern CUtlVector< s_hitboxset > g_hitboxsets;
EXTERN int g_numhitgroups; struct s_hitgroup_t { int models; int group; char name[MAXSTUDIONAME]; // bone name
}; EXTERN s_hitgroup_t g_hitgroup[MAXSTUDIOSRCBONES];
struct s_bonecontroller_t { char name[MAXSTUDIONAME]; int bone; int type; int inputfield; float start; float end; };
EXTERN s_bonecontroller_t g_bonecontroller[MAXSTUDIOSRCBONES]; EXTERN int g_numbonecontrollers;
struct s_screenalignedbone_t { char name[MAXSTUDIONAME]; int flags; };
EXTERN s_screenalignedbone_t g_screenalignedbone[MAXSTUDIOSRCBONES]; EXTERN int g_numscreenalignedbones;
struct s_worldalignedbone_t { char name[MAXSTUDIONAME]; int flags; };
EXTERN s_worldalignedbone_t g_worldalignedbone[MAXSTUDIOSRCBONES]; EXTERN int g_numworldalignedbones;
struct s_attachment_t { char name[MAXSTUDIONAME]; char bonename[MAXSTUDIONAME]; int bone; int type; int flags; matrix3x4_t local;
bool operator==( const s_attachment_t &rhs ) const; };
#define IS_ABSOLUTE 0x0001
#define IS_RIGID 0x0002
EXTERN s_attachment_t g_attachment[MAXSTUDIOSRCBONES]; EXTERN int g_numattachments;
struct s_bonemerge_t { char bonename[MAXSTUDIONAME]; };
EXTERN CUtlVector< s_bonemerge_t > g_BoneMerge;
struct s_alwayssetup_t { char bonename[MAXSTUDIONAME]; };
EXTERN CUtlVector< s_alwayssetup_t > g_BoneAlwaysSetup;
struct s_mouth_t { char bonename[MAXSTUDIONAME]; int bone; Vector forward; int flexdesc; };
EXTERN s_mouth_t g_mouth[MAXSTUDIOSRCBONES]; // ?? skins?
EXTERN int g_nummouths;
struct s_node_t { char name[MAXSTUDIONAME]; int parent; };
struct s_bone_t { Vector pos; RadianEuler rot; };
struct s_linearmove_t { int endframe; // frame when pos, rot is valid.
int flags; // type of motion. Only linear, linear accel, and linear decel is allowed
float v0; float v1; Vector vector; // movement vector
Vector pos; // final position
RadianEuler rot; // final rotation
};
#define CMD_WEIGHTS 1
#define CMD_SUBTRACT 2
#define CMD_AO 3
#define CMD_MATCH 4
#define CMD_FIXUP 5
#define CMD_ANGLE 6
#define CMD_IKFIXUP 7
#define CMD_IKRULE 8
#define CMD_MOTION 9
#define CMD_REFMOTION 10
#define CMD_DERIVATIVE 11
#define CMD_NOANIMATION 12
#define CMD_LINEARDELTA 13
#define CMD_SPLINEDELTA 14
#define CMD_COMPRESS 15
#define CMD_NUMFRAMES 16
#define CMD_COUNTERROTATE 17
#define CMD_SETBONE 18
#define CMD_WORLDSPACEBLEND 19
#define CMD_MATCHBLEND 20
#define CMD_LOCALHIERARCHY 21
#define CMD_FORCEBONEPOSROT 22
#define CMD_REVERSE 23
#define CMD_APPENDANIM 24
#define CMD_BONEDRIVER 25
#define CMD_NOANIM_KEEPDURATION 26
struct s_animation_t; struct s_ikrule_t;
struct s_motion_t { int motiontype; int iStartFrame;// starting frame to apply motion over
int iEndFrame; // end frame to apply motion over
int iSrcFrame; // frame that matches the "reference" animation
s_animation_t *pRefAnim; // animation to match
int iRefFrame; // reference animation's frame to match
};
struct s_animcmd_t { int cmd; union { struct { int index; } weightlist;
struct { s_animation_t *ref; int frame; int flags; } subtract;
struct { s_animation_t *ref; int motiontype; int srcframe; int destframe; char *pBonename; } ao;
struct { s_animation_t *ref; int srcframe; int destframe; int destpre; int destpost; } match;
struct { s_animation_t *ref; int startframe; int loops; } world;
struct { int start; int end; } fixuploop;
struct { float angle; } angle;
struct { s_ikrule_t *pRule; } ikfixup;
struct { s_ikrule_t *pRule; } ikrule;
struct { float scale; } derivative;
struct { int flags; } linear;
struct { int frames; } compress;
struct { int frames; } numframes;
struct { char *pBonename; bool bHasTarget; float targetAngle[3]; } counterrotate;
struct { char *pBonename; char *pParentname; int start; int peak; int tail; int end; } localhierarchy;
struct { char *pBonename; bool bDoPos; float pos[3]; bool bDoRot; float rot[3]; bool bRotIsLocal; } forceboneposrot;
struct { char *pBonename; int iAxis; float value; int start; int peak; int tail; int end; bool all; } bonedriver;
struct { s_animation_t *ref; } appendanim;
struct s_motion_t motion; } u; };
struct s_streamdata_t { Vector pos; Quaternion q; };
struct s_animationstream_t { // source animations
int numerror; s_streamdata_t *pError; // compressed animations
float scale[6]; int numanim[6]; mstudioanimvalue_t *anim[6]; };
struct s_ikrule_t { int chain;
int index; int type; int slot; char bonename[MAXSTUDIONAME]; char attachment[MAXSTUDIONAME]; int bone; Vector pos; Quaternion q; float height; float floor; float radius;
int start; int peak; int tail; int end;
int contact;
bool usesequence; bool usesource;
int flags;
s_animationstream_t errorData; };
struct s_localhierarchy_t { int bone; int newparent;
int start; int peak; int tail; int end;
s_animationstream_t localData; };
struct s_source_t; EXTERN int g_numani; struct s_compressed_t { int num[6]; mstudioanimvalue_t *data[6]; };
struct s_animation_t { bool isImplied; bool isOverride; bool doesOverride; int index; char name[MAXSTUDIONAME]; char filename[MAX_PATH];
/*
int animsubindex;
// For sharing outside of current .mdl file
bool shared_group_checkvalidity; bool shared_group_valid; char shared_animgroup_file[ MAX_PATH ]; // share file name
char shared_animgroup_name[ MAXSTUDIONAME ]; // group name in share file
int shared_group_subindex; studioanimhdr_t *shared_group_header; */
float fps; int startframe; int endframe; int flags; // animations processed (time shifted, linearized, and bone adjusted ) from source animations
CUtlVectorAuto< s_bone_t * > sanim; // [MAXSTUDIOANIMFRAMES]; // [frame][bones];
int motiontype;
int fudgeloop; int looprestart; // new starting frame for looping animations
float looprestartpercent;
// piecewise linear motion
int numpiecewisekeys; s_linearmove_t piecewisemove[MAXSTUDIOMOVEKEYS];
// default adjustments
Vector adjust; float scale; // ????
RadianEuler rotation;
s_source_t *source; char animationname[MAX_PATH];
Vector bmin; Vector bmax;
int numframes;
// compressed animation data
int numsections; int sectionframes; CUtlVectorAuto< CUtlVectorAuto< s_compressed_t > > anim;
// int weightlist;
float weight[MAXSTUDIOSRCBONES]; float posweight[MAXSTUDIOSRCBONES];
int numcmds; s_animcmd_t cmds[MAXSTUDIOCMDS];
int numikrules; s_ikrule_t ikrule[MAXSTUDIOIKRULES]; bool noAutoIK;
int numlocalhierarchy; s_localhierarchy_t localhierarchy[MAXSTUDIOIKRULES];
float motionrollback;
bool disableAnimblocks; // no demand loading
bool isFirstSectionLocal; // first block of a section isn't demand loaded
int numNostallFrames; // number of frames to keep in memory (modulo segement size)
int rootDriverIndex; }; EXTERN s_animation_t *g_panimation[MAXSTUDIOANIMS];
EXTERN int g_numcmdlists; struct s_cmdlist_t { char name[MAXSTUDIONAME]; int numcmds; s_animcmd_t cmds[MAXSTUDIOCMDS]; }; EXTERN s_cmdlist_t g_cmdlist[MAXSTUDIOANIMS];
struct s_iklock_t { char name[MAXSTUDIONAME]; int chain; float flPosWeight; float flLocalQWeight; };
EXTERN int g_numikautoplaylocks; EXTERN s_iklock_t g_ikautoplaylock[16];
struct s_animtag_t { int tag; float cycle; char tagname[MAXSTUDIONAME]; };
struct s_event_t { int event; int frame; char options[64]; char eventname[MAXSTUDIONAME]; };
struct s_autolayer_t { char name[MAXSTUDIONAME]; int sequence; int flags; int pose; float start; float peak; float tail; float end; };
struct s_activitymodifier_t { int id; char name[64]; };
class s_sequence_t { public: char name[MAXSTUDIONAME]; char activityname[MAXSTUDIONAME]; // index into the string table, the name of this activity.
int flags; // float fps;
// int numframes;
int activity; int actweight;
int numanimtags; s_animtag_t animtags[MAXSTUDIOTAGS];
int numevents; s_event_t event[MAXSTUDIOEVENTS];
int numblends; int groupsize[2]; CUtlVectorAuto< CUtlVectorAuto< s_animation_t * > > panim; // [MAXSTUDIOBLENDS][MAXSTUDIOBLENDS];
int paramindex[2]; float paramstart[2]; float paramend[2]; int paramattachment[2]; int paramcontrol[2]; CUtlVectorAuto< float >param0; // [MAXSTUDIOBLENDS];
CUtlVectorAuto< float >param1; // [MAXSTUDIOBLENDS];
s_animation_t *paramanim; s_animation_t *paramcompanim; s_animation_t *paramcenter;
// Vector automovepos[MAXSTUDIOANIMATIONS];
// Vector automoveangle[MAXSTUDIOANIMATIONS];
int animindex;
Vector bmin; Vector bmax;
float fadeintime; float fadeouttime;
int entrynode; int exitnode; int nodeflags; float entryphase; float exitphase;
int numikrules;
int numautolayers; s_autolayer_t autolayer[64];
float weight[MAXSTUDIOSRCBONES];
s_iklock_t iklock[64]; int numiklocks;
int cycleposeindex;
CUtlVector< char > KeyValue;
int numactivitymodifiers; s_activitymodifier_t activitymodifier[MAXSTUDIOACTIVITYMODIFIERS];
int rootDriverIndex; char rootDriverBoneName[MAXSTUDIONAME]; }; EXTERN CUtlVector< s_sequence_t > g_sequence; //EXTERN int g_numseq;
EXTERN int g_numanimblocks; struct s_animblock_t { int iStartAnim; int iEndAnim; byte *start; byte *end; }; EXTERN s_animblock_t g_animblock[MAXSTUDIOANIMBLOCKS]; EXTERN int g_animblocksize; EXTERN char g_animblockname[260]; EXTERN int g_animblockmaxframes;
EXTERN int g_numposeparameters; struct s_poseparameter_t { char name[MAXSTUDIONAME]; float min; float max; int flags; float loop; }; EXTERN s_poseparameter_t g_pose[32]; // FIXME: this shouldn't be hard coded
EXTERN int g_numxnodes; EXTERN char *g_xnodename[100]; EXTERN int g_xnode[100][100]; EXTERN int g_numxnodeskips; EXTERN int g_xnodeskip[10000][2];
struct rgb_t { byte r, g, b; }; struct rgb2_t { float r, g, b, a; };
// FIXME: what about texture overrides inline with loading models
enum TextureFlags_t { RELATIVE_TEXTURE_PATH_SPECIFIED = 0x1 };
struct s_texture_t { char name[MAX_PATH]; int flags; int parent; int material; float width; float height; float dPdu; float dPdv; }; EXTERN s_texture_t g_texture[MAXSTUDIOSKINS]; EXTERN int g_numtextures; EXTERN int g_material[MAXSTUDIOSKINS]; // link into texture array
EXTERN int g_nummaterials;
EXTERN float g_gamma; EXTERN int g_numskinref; EXTERN int g_numskinfamilies; EXTERN int g_skinref[256][MAXSTUDIOSKINS]; // [skin][skinref], returns texture index
EXTERN int g_numtexturegroups; EXTERN int g_numtexturelayers[32]; EXTERN int g_numtexturereps[32]; EXTERN int g_texturegroup[32][32][32];
struct s_mesh_t { int numvertices; int vertexoffset;
int numfaces; int faceoffset; };
struct s_vertanim_t { int vertex; float speed; float side; Vector pos; Vector normal; float wrinkle; };
struct s_lodvertexinfo_t : public s_vertexinfo_t { int lodFlag; };
// processed aggregate lod pools
struct s_loddata_t { int numvertices; s_lodvertexinfo_t *vertex;
int numfaces; s_face_t *face;
s_mesh_t mesh[MAXSTUDIOSKINS];
// remaps verts from an lod's source mesh to this all-lod processed aggregate pool
int *pMeshVertIndexMaps[MAX_NUM_LODS]; };
// Animations stored in raw off-disk source files. Raw data should be not processed.
class s_sourceanim_t { public: char animationname[MAX_PATH]; int numframes; int startframe; int endframe; CUtlVectorAuto< s_bone_t * >rawanim;
// vertex animation
bool newStyleVertexAnimations; // new style doesn't store a base pose in vertex anim[0]
int *vanim_mapcount; // local verts map to N target verts
int **vanim_map; // local vertices to target vertices mapping list
int *vanim_flag; // local vert does animate
int numvanims[MAXSTUDIOANIMFRAMES]; s_vertanim_t *vanim[MAXSTUDIOANIMFRAMES]; // [frame][vertex]
};
// raw off-disk source files. Raw data should be not processed.
struct s_source_t { char filename[MAX_PATH]; int version; // Version number from SMD file, otherwise 0
bool isActiveModel;
// local skeleton hierarchy
int numbones; s_node_t localBone[MAXSTUDIOSRCBONES]; matrix3x4_t boneToPose[MAXSTUDIOSRCBONES]; // converts bone local data into initial pose data
// bone remapping
int boneflags[MAXSTUDIOSRCBONES]; // attachment, vertex, etc flags for this bone
int boneref[MAXSTUDIOSRCBONES]; // flags for this and child bones
int boneLocalToGlobal[MAXSTUDIOSRCBONES]; // bonemap : local bone to world bone mapping
int boneGlobalToLocal[MAXSTUDIOSRCBONES]; // boneimap : world bone to local bone mapping
int texmap[MAXSTUDIOSKINS*4]; // map local MAX materials to unique textures
// per material mesh
int nummeshes; int meshindex[MAXSTUDIOSKINS]; // mesh to skin index
s_mesh_t mesh[MAXSTUDIOSKINS];
// vertices defined in "local" space (not remapped to global bones)
int numvertices; s_vertexinfo_t *vertex;
// vertices defined in "global" space (remapped to global bones)
CUtlVector< s_vertexinfo_t > m_GlobalVertices;
int numfaces; s_face_t *face; // vertex indexs per face
// raw skeletal animation
CUtlVector< s_sourceanim_t > m_Animations;
// default adjustments
Vector adjust; float scale; // ????
RadianEuler rotation;
// Flex keys stored in the source data
bool bNoAutoDMXRules; CUtlVector< s_flexkey_t > m_FlexKeys;
// Combination controls stored in the source data
CUtlVector< s_combinationcontrol_t > m_CombinationControls;
// Combination rules stored in the source data
CUtlVector< s_combinationrule_t > m_CombinationRules;
// Flexcontroller remaps
CUtlVector< s_flexcontrollerremap_t > m_FlexControllerRemaps;
// Attachment points stored in the SMD/DMX/etc. file
CUtlVector< s_attachment_t > m_Attachments;
// Information about how flex controller remaps map into flex rules
int m_nKeyStartIndex; // The index at which the flex keys for this model start in the global list
CUtlVector< int > m_rawIndexToRemapSourceIndex; CUtlVector< int > m_rawIndexToRemapLocalIndex; CUtlVector< int > m_leftRemapIndexToGlobalFlexControllIndex; CUtlVector< int > m_rightRemapIndexToGlobalFlexControllIndex; };
EXTERN int g_numsources; EXTERN s_source_t *g_source[MAXSTUDIOSEQUENCES];
struct s_eyeball_t { char name[MAXSTUDIONAME]; int index; int bone; Vector org; float zoffset; float radius; Vector up; Vector forward;
int mesh; float iris_scale;
int upperlidflexdesc; int upperflexdesc[3]; float uppertarget[3];
int lowerlidflexdesc; int lowerflexdesc[3]; float lowertarget[3]; };
struct s_model_t { char name[MAXSTUDIONAME]; char filename[MAX_PATH];
// needs local scaling and rotation paramaters
s_source_t *source; // index into source table
float scale; // UNUSED
float boundingradius;
Vector boundingbox[MAXSTUDIOSRCBONES][2];
int numattachments; s_attachment_t attachment[32];
int numeyeballs; s_eyeball_t eyeball[4]; // References to sources which are the LODs for this model
CUtlVector< s_source_t* > m_LodSources;
// processed aggregate lod data
s_loddata_t *m_pLodData; };
EXTERN int g_nummodels; EXTERN int g_nummodelsbeforeLOD; EXTERN CUtlVectorAuto< s_model_t *> g_model;
struct s_flexdesc_t { char FACS[MAXSTUDIONAME]; // FACS identifier
}; EXTERN int g_numflexdesc; EXTERN s_flexdesc_t g_flexdesc[MAXSTUDIOFLEXDESC]; int Add_Flexdesc( const char *name );
struct s_flexcontroller_t { char name[MAXSTUDIONAME]; char type[MAXSTUDIONAME]; float min; float max; }; EXTERN int g_numflexcontrollers; EXTERN s_flexcontroller_t g_flexcontroller[MAXSTUDIOFLEXCTRL];
struct s_flexcontrollerremap_t { CUtlString m_Name; FlexControllerRemapType_t m_RemapType; bool m_bIsStereo; CUtlVector< CUtlString > m_RawControls; int m_Index; ///< The model relative index of the slider control for value for this if it's not split, -1 otherwise
int m_LeftIndex; ///< The model relative index of the left slider control for this if it's split, -1 otherwise
int m_RightIndex; ///< The model relative index of the right slider control for this if it's split, -1 otherwise
int m_MultiIndex; ///< The model relative index of the value slider control for this if it's multi, -1 otherwise
CUtlString m_EyesUpDownFlexName; // The name of the eyes up/down flex controller
int m_EyesUpDownFlexController; // The global index of the Eyes Up/Down Flex Controller
int m_BlinkController; // The global index of the Blink Up/Down Flex Controller
};
extern CUtlVector<s_flexcontrollerremap_t> g_FlexControllerRemap;
struct s_flexkey_t { int flexdesc; int flexpair; s_source_t *source; // index into source table
char animationname[MAX_PATH];
int imodel; int frame;
float target0; float target1; float target2; float target3;
float split; float decay;
// extracted and remapped vertex animations
int numvanims; s_vertanim_t *vanim; int vanimtype; int weighttable; }; EXTERN int g_numflexkeys; EXTERN s_flexkey_t g_flexkey[MAXSTUDIOFLEXKEYS]; EXTERN s_flexkey_t *g_defaultflexkey;
#define MAX_OPS 512
struct s_flexop_t { int op; union { int index; float value; } d; };
struct s_flexrule_t { int flex; int numops; s_flexop_t op[MAX_OPS]; };
EXTERN int g_numflexrules; EXTERN s_flexrule_t g_flexrule[MAXSTUDIOFLEXRULES];
struct s_combinationcontrol_t { char name[MAX_PATH]; };
struct s_combinationrule_t { // The 'ints' here are indices into the m_Controls array
CUtlVector< int > m_Combination; CUtlVector< CUtlVector< int > > m_Dominators;
// The index into the flexkeys to put the result in
// (should affect both left + right if the key is sided)
int m_nFlex; };
EXTERN Vector g_defaultadjust;
struct s_bodypart_t { char name[MAXSTUDIONAME]; int nummodels; int base; CUtlVectorAuto< s_model_t * > pmodel;
s_bodypart_t() { memset( this, 0, sizeof( s_bodypart_t ) ); } };
EXTERN int g_numbodyparts; EXTERN CUtlVectorAuto< s_bodypart_t > g_bodypart;
struct s_bodygrouppreset_t { char name[MAXSTUDIONAME]; int iValue; int iMask;
s_bodygrouppreset_t() { memset( this, 0, sizeof( s_bodygrouppreset_t ) ); } };
EXTERN int g_numbodygrouppresets; EXTERN CUtlVectorAuto< s_bodygrouppreset_t > g_bodygrouppresets;
#define MAXWEIGHTLISTS 128
#define MAXWEIGHTSPERLIST (MAXSTUDIOBONES)
struct s_weightlist_t { // weights, indexed by numbones per weightlist
char name[MAXSTUDIONAME]; int numbones; char *bonename[MAXWEIGHTSPERLIST]; float boneweight[MAXWEIGHTSPERLIST]; float boneposweight[MAXWEIGHTSPERLIST];
// weights, indexed by global bone index
float weight[MAXSTUDIOBONES]; float posweight[MAXSTUDIOBONES]; };
EXTERN int g_numweightlist; EXTERN s_weightlist_t g_weightlist[MAXWEIGHTLISTS];
struct s_iklink_t { int bone; Vector kneeDir; };
struct s_ikchain_t { char name[MAXSTUDIONAME]; char bonename[MAXSTUDIONAME]; int axis; float value; int numlinks; s_iklink_t link[10]; // hip, knee, ankle, toes...
float height; float radius; float floor; Vector center; };
EXTERN int g_numikchains; EXTERN s_ikchain_t g_ikchain[16];
struct s_jigglebone_t { int flags; char bonename[MAXSTUDIONAME]; int bone;
mstudiojigglebone_t data; // the actual jiggle properties
};
EXTERN int g_numjigglebones; EXTERN s_jigglebone_t g_jigglebones[MAXSTUDIOBONES]; EXTERN int g_jigglebonemap[MAXSTUDIOBONES]; // map used jigglebone's to source jigglebonebone's
struct s_axisinterpbone_t { int flags; char bonename[MAXSTUDIONAME]; int bone; char controlname[MAXSTUDIONAME]; int control; int axis; Vector pos[6]; Quaternion quat[6]; };
EXTERN int g_numaxisinterpbones; EXTERN s_axisinterpbone_t g_axisinterpbones[MAXSTUDIOBONES]; EXTERN int g_axisinterpbonemap[MAXSTUDIOBONES]; // map used axisinterpbone's to source axisinterpbone's
struct s_quatinterpbone_t { int flags; char bonename[MAXSTUDIONAME]; int bone; char parentname[MAXSTUDIONAME]; // int parent;
char controlparentname[MAXSTUDIONAME]; // int controlparent;
char controlname[MAXSTUDIONAME]; int control; int numtriggers; Vector size; Vector basepos; float percentage; float tolerance[32]; Quaternion trigger[32]; Vector pos[32]; Quaternion quat[32]; };
EXTERN int g_numquatinterpbones; EXTERN s_quatinterpbone_t g_quatinterpbones[MAXSTUDIOBONES]; EXTERN int g_quatinterpbonemap[MAXSTUDIOBONES]; // map used quatinterpbone's to source axisinterpbone's
struct s_aimatbone_t { char bonename[MAXSTUDIONAME]; int bone; char parentname[MAXSTUDIONAME]; int parent; char aimname[MAXSTUDIONAME]; int aimAttach; int aimBone; Vector aimvector; Vector upvector; Vector basepos; };
EXTERN int g_numaimatbones; EXTERN s_aimatbone_t g_aimatbones[MAXSTUDIOBONES]; EXTERN int g_aimatbonemap[MAXSTUDIOBONES]; // map used aimatpbone's to source aimatpbone's (may be optimized out)
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
struct s_constraintbonetarget_t { char m_szBoneName[MAXSTUDIONAME]; int m_nBone; float m_flWeight; Vector m_vOffset; Quaternion m_qOffset;
bool operator==( const s_constraintbonetarget_t &rhs ) const; bool operator!=( const s_constraintbonetarget_t &rhs ) const { return !( *this == rhs ); } };
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
struct s_constraintboneslave_t { char m_szBoneName[MAXSTUDIONAME]; int m_nBone; Vector m_vBaseTranslate; Quaternion m_qBaseRotation;
bool operator==( const s_constraintboneslave_t &rhs ) const; bool operator!=( const s_constraintboneslave_t &rhs ) const { return !( *this == rhs ); } };
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
class CTwistBone { public: bool m_bInverse; Vector m_vUpVector; char m_szParentBoneName[MAXSTUDIONAME]; int m_nParentBone; Quaternion m_qBaseRotation; char m_szChildBoneName[MAXSTUDIONAME]; int m_nChildBone;
CUtlVector< s_constraintbonetarget_t > m_twistBoneTargets;
CTwistBone() { m_bInverse = false; m_vUpVector.Init(); m_szParentBoneName[0] = '\0'; m_nParentBone = -1; m_qBaseRotation.Init(); m_szChildBoneName[0] = '\0'; m_nChildBone = -1; } };
EXTERN CUtlVector< CTwistBone > g_twistbones;
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
class CConstraintBoneBase { public: virtual ~CConstraintBoneBase() {}
CUtlVector< s_constraintbonetarget_t > m_targets; s_constraintboneslave_t m_slave;
bool operator==( const CConstraintBoneBase &rhs ) const; bool operator!=( const CConstraintBoneBase &rhs ) const { return !( *this == rhs ); } };
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
EXTERN CUtlVector< CConstraintBoneBase * > g_constraintBones;
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
class CPointConstraint : public CConstraintBoneBase { public: };
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
class COrientConstraint : public CConstraintBoneBase { public: };
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
class CAimConstraint : public CConstraintBoneBase { public: CAimConstraint() { m_nUpSpaceTargetBone = -1; }
Quaternion m_qAimOffset; Vector m_vUpVector; char m_szUpSpaceTargetBone[MAXSTUDIONAME]; int m_nUpSpaceTargetBone; int m_nUpType; // CConstraintBones::AimConstraintUpType_t
};
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
class CParentConstraint : public CConstraintBoneBase { public: };
struct s_forcedhierarchy_t { char parentname[MAXSTUDIONAME]; char childname[MAXSTUDIONAME]; char subparentname[MAXSTUDIONAME]; };
EXTERN int g_numforcedhierarchy; EXTERN s_forcedhierarchy_t g_forcedhierarchy[MAXSTUDIOBONES];
struct s_forcedrealign_t { char name[MAXSTUDIONAME]; RadianEuler rot; }; EXTERN int g_numforcedrealign; EXTERN s_forcedrealign_t g_forcedrealign[MAXSTUDIOBONES];
struct s_limitrotation_t { char name[MAXSTUDIONAME]; int numseq; char *sequencename[64]; };
EXTERN int g_numlimitrotation; EXTERN s_limitrotation_t g_limitrotation[MAXSTUDIOBONES];
extern int BuildTris (s_trianglevert_t (*x)[3], s_mesh_t *y, byte **ppdata );
struct s_bonesaveframe_t { char name[ MAXSTUDIOHITBOXSETNAME ]; bool bSavePos; bool bSaveRot; bool bSaveRot64; };
EXTERN CUtlVector< s_bonesaveframe_t > g_bonesaveframe;
int OpenGlobalFile( char *src ); bool GetGlobalFilePath( const char *pSrc, char *pFullPath, int nMaxLen ); s_source_t *Load_Source( const char *filename, const char *ext, bool reverse = false, bool isActiveModel = false, bool bUseCache = true ); void ApplyOffsetToSrcVerts( s_source_t *pModel, matrix3x4_t matOffset ); void AddSrcToSrc( s_source_t *pOrigSource, s_source_t *pAppendSource, matrix3x4_t matOffset ); void AddSrcToSrc( s_source_t *pOrigSource, s_source_t *pAppendSource ); int Load_VRM( s_source_t *psource ); int Load_SMD( s_source_t *psource ); int Load_VTA( s_source_t *psource ); int Load_OBJ( s_source_t *psource ); int Load_DMX( s_source_t *psource ); int Load_FBX( s_source_t *psource ); bool LoadPreprocessedFile( const char *pFileName, float flScale ); int AppendVTAtoOBJ( s_source_t *psource, char *filename, int frame ); void Build_Reference( s_source_t *psource, const char *pAnimName ); int Grab_Nodes( s_node_t *pnodes ); void Grab_Animation( s_source_t *psource, const char *pAnimName );
// Processes source comment line and extracts information about the data file
void ProcessSourceComment( s_source_t *psource, const char *pCommentString );
// Processes original content file "szOriginalContentFile" that was used to generate
// data file "szDataFile"
void ProcessOriginalContentFile( const char *szDataFile, const char *szOriginalContentFile );
//-----------------------------------------------------------------------------
// Utility methods to get or add animation data from sources
//-----------------------------------------------------------------------------
s_sourceanim_t *FindSourceAnim( s_source_t *pSource, const char *pAnimName ); const s_sourceanim_t *FindSourceAnim( const s_source_t *pSource, const char *pAnimName ); s_sourceanim_t *FindOrAddSourceAnim( s_source_t *pSource, const char *pAnimName );
// Adds flexkey data to a particular source
void AddFlexKey( s_source_t *pSource, CDmeCombinationOperator *pComboOp, const char *pFlexKeyName );
// Adds combination data to the source
void AddCombination( s_source_t *pSource, CDmeCombinationOperator *pCombination );
int LookupTexture( const char *pTextureName, bool bRelativePath = false ); int UseTextureAsMaterial( int textureindex ); int MaterialToTexture( int material );
int LookupAttachment( const char *name );
void ClearModel (void); void SimplifyModel (void); void CollapseBones (void);
void adjust_vertex( float *org ); void scale_vertex( Vector &org ); void clip_rotations( RadianEuler& rot ); void clip_rotations( Vector& rot );
char *stristr( const char *string, const char *string2 ); #define strcpyn( a, b ) strncpy( a, b, sizeof( a ) )
void CalcBoneTransforms( s_animation_t *panimation, int frame, matrix3x4_t* pBoneToWorld ); void CalcBoneTransforms( s_animation_t *panimation, s_animation_t *pbaseanimation, int frame, matrix3x4_t* pBoneToWorld ); void CalcBoneTransformsCycle( s_animation_t *panimation, s_animation_t *pbaseanimation, float flCycle, matrix3x4_t* pBoneToWorld );
void BuildRawTransforms( const s_source_t *psource, const char *pAnimationName, int frame, float scale, Vector const &shift, RadianEuler const &rotate, int flags, matrix3x4_t* boneToWorld ); void BuildRawTransforms( const s_source_t *psource, const char *pAnimationName, int frame, matrix3x4_t* boneToWorld );
void TranslateAnimations( const s_source_t *pSource, const matrix3x4_t *pSrcBoneToWorld, matrix3x4_t *pDestBoneToWorld );
// Returns surface property for a given joint
char* GetSurfaceProp ( const char* pJointName ); int GetContents ( const char* pJointName ); char* GetDefaultSurfaceProp ( ); int GetDefaultContents( );
// Did we read 'end'
bool IsEnd( const char* pLine );
// Parses an LOD command
void Cmd_LOD( const char *cmdname ); void Cmd_ShadowLOD( void );
// Fixes up the LOD source files
void FixupLODSources();
// Get model LOD source
s_source_t* GetModelLODSource( const char *pModelName, const LodScriptData_t& scriptLOD, bool* pFound );
void LoadLODSources( void ); void ConvertBoneTreeCollapsesToReplaceBones( void ); void FixupReplacedBones( void ); void UnifyLODs( void ); void SpewBoneUsageStats( void ); void MarkParentBoneLODs( void ); //void CheckAutoShareAnimationGroup( const char *animation_name );
/*
================= ================= */
extern bool GetLineInput(void); extern char g_szFilename[1024]; extern FILE *g_fpInput; extern char g_szLine[4096]; extern int g_iLinecount;
extern int g_min_faces, g_max_faces; extern float g_min_resolution, g_max_resolution;
EXTERN int g_numverts; EXTERN CUtlVectorAuto< Vector > g_vertex; EXTERN CUtlVectorAuto< s_boneweight_t > g_bone;
EXTERN int g_numnormals; EXTERN CUtlVectorAuto< Vector > g_normal;
extern int g_numtexcoords[MAXSTUDIOTEXCOORDS]; extern CUtlVectorAuto< Vector2D > g_texcoord[MAXSTUDIOTEXCOORDS];
EXTERN int g_numfaces; EXTERN CUtlVectorAuto< s_tmpface_t > g_face; EXTERN CUtlVectorAuto< s_face_t > g_src_uface; // max res unified faces
struct v_unify_t { int refcount; int lastref; int firstref; int v; int m; int n; int t[MAXSTUDIOTEXCOORDS]; v_unify_t *next; // pointer to next entry with same v
};
EXTERN v_unify_t *v_list[MAXSTUDIOSRCVERTS]; EXTERN v_unify_t v_listdata[MAXSTUDIOSRCVERTS]; EXTERN int g_numvlist;
int SortAndBalanceBones( int iCount, int iMaxCount, int bones[], float weights[] ); void Grab_Vertexanimation( s_source_t *psource, const char *pAnimationName ); extern void BuildIndividualMeshes( s_source_t *psource );
//-----------------------------------------------------------------------------
// A little class used to deal with replacement commands
//-----------------------------------------------------------------------------
class CLodScriptReplacement_t { public: void SetSrcName( const char *pSrcName ) { if( m_pSrcName ) { delete [] m_pSrcName; } m_pSrcName = new char[strlen( pSrcName ) + 1]; strcpy( m_pSrcName, pSrcName ); } void SetDstName( const char *pDstName ) { if( m_pDstName ) { delete [] m_pDstName; } m_pDstName = new char[strlen( pDstName ) + 1]; strcpy( m_pDstName, pDstName ); }
const char *GetSrcName( void ) const { return m_pSrcName; } const char *GetDstName( void ) const { return m_pDstName; } CLodScriptReplacement_t() { m_pSrcName = NULL; m_pDstName = NULL; m_pSource = 0; } ~CLodScriptReplacement_t() { delete [] m_pSrcName; delete [] m_pDstName; }
s_source_t* m_pSource;
private: char *m_pSrcName; char *m_pDstName; };
struct LodScriptData_t { public: float switchValue; CUtlVector<CLodScriptReplacement_t> modelReplacements; CUtlVector<CLodScriptReplacement_t> boneReplacements; CUtlVector<CLodScriptReplacement_t> boneTreeCollapses; CUtlVector<CLodScriptReplacement_t> materialReplacements; CUtlVector<CLodScriptReplacement_t> meshRemovals;
void EnableFacialAnimation( bool val ) { m_bFacialAnimation = val; } bool GetFacialAnimationEnabled() const { return m_bFacialAnimation; }
void StripFromModel( bool val ) { m_bStrippedFromModel = val; } bool IsStrippedFromModel() const { return m_bStrippedFromModel; } LodScriptData_t() { m_bFacialAnimation = true; m_bStrippedFromModel = false; }
private: bool m_bFacialAnimation; bool m_bStrippedFromModel; };
EXTERN CUtlVector<LodScriptData_t> g_ScriptLODs;
extern bool g_parseable_completion_output; extern bool g_collapse_bones_message; extern bool g_collapse_bones; extern bool g_collapse_bones_aggressive; extern bool g_quiet; extern bool g_verbose; extern bool g_bCheckLengths; extern bool g_bPrintBones; extern bool g_bPerf; extern bool g_bFast; extern bool g_bDumpGraph; extern bool g_bMultistageGraph; extern bool g_bCreateMakefile; extern bool g_bZBrush; extern bool g_bVerifyOnly; extern bool g_bUseBoneInBBox; extern bool g_bLockBoneLengths; extern bool g_bDefineBonesLockedByDefault; extern bool g_bX360; extern int g_minLod; extern bool g_bFastBuild; extern int g_numAllowedRootLODs; extern bool g_bBuildPreview; extern bool g_bPreserveTriangleOrder; extern bool g_bCenterBonesOnVerts; extern float g_flDefaultMotionRollback; extern int g_minSectionFrameLimit; extern int g_sectionFrames; extern bool g_bNoAnimblockStall; extern float g_flPreloadTime; extern bool g_bStripLods; extern bool g_bAnimblockHighRes; extern bool g_bAnimblockLowRes; extern int g_nMaxZeroFrames; extern bool g_bZeroFramesHighres; extern float g_flMinZeroFramePosDelta;
extern Vector g_vecMinWorldspace; extern Vector g_vecMaxWorldspace;
extern bool g_bLCaseAllSequences;
extern bool g_bErrorOnSeqRemapFail; extern bool g_bModelIntentionallyHasZeroSequences;
extern float g_flDefaultFadeInTime; extern float g_flDefaultFadeOutTime;
extern float g_flCollisionPrecision;
EXTERN CUtlVector< char * >g_collapse;
extern float GetCollisionModelMass();
// List of defined bone flex drivers
extern DmElementHandle_t g_hDmeBoneFlexDriverList;
// the first time these are called, the name of the model/QC file is printed so that when
// running in batch mode, no echo, when dumping to a file, it can be determined which file is broke.
void MdlError( const char *pMsg, ... ); void MdlWarning( const char *pMsg, ... );
void CreateMakefile_AddDependency( const char *pFileName ); void EnsureDependencyFileCheckedIn( const char *pFileName );
void AddSurfaceProp( const char *pBoneName, const char *pSurfaceProperty ); char* FindSurfaceProp( const char* pBoneName );
bool ComparePath( const char *a, const char *b );
void SetDefaultSurfaceProp( const char *pSurfaceProperty ); void PostProcessSource( s_source_t *pSource, int imodel );
byte IsByte( int val ); char IsChar( int val ); int IsInt24( int val ); short IsShort( int val ); unsigned short IsUShort( int val );
struct MDLCommand_t { char *m_pName; void (*m_pCmd)(); int m_nLastValidVersion; };
//-----------------------------------------------------------------------------
// Assigns a default contents to the entire model
//-----------------------------------------------------------------------------
struct ContentsName_t { char m_pJointName[128]; int m_nContents; };
extern int s_nDefaultContents; // in studiomdl.cpp
extern CUtlVector<ContentsName_t> s_JointContents; // in studiomdl.cpp
#ifdef MDLCOMPILE
void ConvertToCurrentVersion( int nSrcVersion, const char *pFullPath ); extern int g_nMDLCommandCount; extern MDLCommand_t *g_pMDLCommands; void ProcessStaticProp(); s_sequence_t *ProcessCmdSequence( const char *pSequenceName ); s_animation_t *ProcessImpliedAnimation( s_sequence_t *psequence, const char *filename ); void ProcessSequence( s_sequence_t *pseq, int numblends, s_animation_t **animations, bool isAppend ); s_animation_t *LookupAnimation( const char *name ); int LookupXNode( const char *name ); int LookupPoseParameter( const char *name ); void AddBodyAttachments( s_source_t *pSource ); #endif
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
enum EyelidType_t { kLowerer = 0, kNeutral = 1, kRaiser = 2, kEyelidTypeCount = 3 };
//-----------------------------------------------------------------------------
// Used to point to the current s_model_t when loading QcModelElements from DMX
//-----------------------------------------------------------------------------
extern s_model_t *g_pCurrentModel;
#endif // STUDIOMDL_H
|