Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3229 lines
106 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //===========================================================================//
  8. #ifndef STUDIO_H
  9. #define STUDIO_H
  10. #ifdef _WIN32
  11. #pragma once
  12. #endif
  13. #include "basetypes.h"
  14. #include "mathlib/vector2d.h"
  15. #include "mathlib/vector.h"
  16. #include "mathlib/vector4d.h"
  17. #include "mathlib/compressed_vector.h"
  18. #include "tier0/dbg.h"
  19. #include "tier0/threadtools.h"
  20. #include "mathlib/mathlib.h"
  21. #include "utlvector.h"
  22. #include "utlhash.h"
  23. #include "datamap.h"
  24. #include "generichash.h"
  25. #include "localflexcontroller.h"
  26. #include "utlsymbol.h"
  27. #define STUDIO_ENABLE_PERF_COUNTERS
  28. #define STUDIO_SEQUENCE_ACTIVITY_LOOKUPS_ARE_SLOW 0
  29. // If this is set to 1, then the activity->sequence mapping inside
  30. // the CStudioHdr will not be initialized until the first call to
  31. // SelectWeightedSequence() or HaveSequenceForActivity(). If set
  32. // to zero, the mapping will be initialized from CStudioHdr::Init()
  33. // (itself called from the constructor).
  34. // As of June 4 2007, this was set to 1 because physics, among other
  35. // systems, extemporaneously declares CStudioHdrs inside local function
  36. // scopes without querying their activity/sequence mapping at all.
  37. #define STUDIO_SEQUENCE_ACTIVITY_LAZY_INITIALIZE 1
  38. //-----------------------------------------------------------------------------
  39. // forward declarations
  40. //-----------------------------------------------------------------------------
  41. class IMaterial;
  42. class IMesh;
  43. class IMorph;
  44. struct virtualmodel_t;
  45. struct vertexFileHeader_t;
  46. struct thinModelVertices_t;
  47. namespace OptimizedModel
  48. {
  49. struct StripHeader_t;
  50. }
  51. /*
  52. ==============================================================================
  53. STUDIO MODELS
  54. Studio models are position independent, so the cache manager can move them.
  55. ==============================================================================
  56. */
  57. #define STUDIO_VERSION 48
  58. #ifndef _XBOX
  59. #define MAXSTUDIOTRIANGLES 65536 // TODO: tune this
  60. #define MAXSTUDIOVERTS 65536 // TODO: tune this
  61. #define MAXSTUDIOFLEXVERTS 10000 // max number of verts that can be flexed per mesh. TODO: tune this
  62. #else
  63. #define MAXSTUDIOTRIANGLES 25000
  64. #define MAXSTUDIOVERTS 10000
  65. #define MAXSTUDIOFLEXVERTS 1000
  66. #endif
  67. #define MAXSTUDIOSKINS 32 // total textures
  68. #define MAXSTUDIOBONES 128 // total bones actually used
  69. #define MAXSTUDIOFLEXDESC 1024 // maximum number of low level flexes (actual morph targets)
  70. #define MAXSTUDIOFLEXCTRL 96 // maximum number of flexcontrollers (input sliders)
  71. #define MAXSTUDIOPOSEPARAM 24
  72. #define MAXSTUDIOBONECTRLS 4
  73. #define MAXSTUDIOANIMBLOCKS 256
  74. #define MAXSTUDIOBONEBITS 7 // NOTE: MUST MATCH MAXSTUDIOBONES
  75. // NOTE!!! : Changing this number also changes the vtx file format!!!!!
  76. #define MAX_NUM_BONES_PER_VERT 3
  77. //Adrian - Remove this when we completely phase out the old event system.
  78. #define NEW_EVENT_STYLE ( 1 << 10 )
  79. struct mstudiodata_t
  80. {
  81. int count;
  82. int offset;
  83. };
  84. #define STUDIO_PROC_AXISINTERP 1
  85. #define STUDIO_PROC_QUATINTERP 2
  86. #define STUDIO_PROC_AIMATBONE 3
  87. #define STUDIO_PROC_AIMATATTACH 4
  88. #define STUDIO_PROC_JIGGLE 5
  89. struct mstudioaxisinterpbone_t
  90. {
  91. DECLARE_BYTESWAP_DATADESC();
  92. int control;// local transformation of this bone used to calc 3 point blend
  93. int axis; // axis to check
  94. Vector pos[6]; // X+, X-, Y+, Y-, Z+, Z-
  95. Quaternion quat[6];// X+, X-, Y+, Y-, Z+, Z-
  96. mstudioaxisinterpbone_t(){}
  97. private:
  98. // No copy constructors allowed
  99. mstudioaxisinterpbone_t(const mstudioaxisinterpbone_t& vOther);
  100. };
  101. struct mstudioquatinterpinfo_t
  102. {
  103. DECLARE_BYTESWAP_DATADESC();
  104. float inv_tolerance; // 1 / radian angle of trigger influence
  105. Quaternion trigger; // angle to match
  106. Vector pos; // new position
  107. Quaternion quat; // new angle
  108. mstudioquatinterpinfo_t(){}
  109. private:
  110. // No copy constructors allowed
  111. mstudioquatinterpinfo_t(const mstudioquatinterpinfo_t& vOther);
  112. };
  113. struct mstudioquatinterpbone_t
  114. {
  115. DECLARE_BYTESWAP_DATADESC();
  116. int control;// local transformation to check
  117. int numtriggers;
  118. int triggerindex;
  119. inline mstudioquatinterpinfo_t *pTrigger( int i ) const { return (mstudioquatinterpinfo_t *)(((byte *)this) + triggerindex) + i; };
  120. mstudioquatinterpbone_t(){}
  121. private:
  122. // No copy constructors allowed
  123. mstudioquatinterpbone_t(const mstudioquatinterpbone_t& vOther);
  124. };
  125. #define JIGGLE_IS_FLEXIBLE 0x01
  126. #define JIGGLE_IS_RIGID 0x02
  127. #define JIGGLE_HAS_YAW_CONSTRAINT 0x04
  128. #define JIGGLE_HAS_PITCH_CONSTRAINT 0x08
  129. #define JIGGLE_HAS_ANGLE_CONSTRAINT 0x10
  130. #define JIGGLE_HAS_LENGTH_CONSTRAINT 0x20
  131. #define JIGGLE_HAS_BASE_SPRING 0x40
  132. #define JIGGLE_IS_BOING 0x80 // simple squash and stretch sinusoid "boing"
  133. struct mstudiojigglebone_t
  134. {
  135. DECLARE_BYTESWAP_DATADESC();
  136. int flags;
  137. // general params
  138. float length; // how from from bone base, along bone, is tip
  139. float tipMass;
  140. // flexible params
  141. float yawStiffness;
  142. float yawDamping;
  143. float pitchStiffness;
  144. float pitchDamping;
  145. float alongStiffness;
  146. float alongDamping;
  147. // angle constraint
  148. float angleLimit; // maximum deflection of tip in radians
  149. // yaw constraint
  150. float minYaw; // in radians
  151. float maxYaw; // in radians
  152. float yawFriction;
  153. float yawBounce;
  154. // pitch constraint
  155. float minPitch; // in radians
  156. float maxPitch; // in radians
  157. float pitchFriction;
  158. float pitchBounce;
  159. // base spring
  160. float baseMass;
  161. float baseStiffness;
  162. float baseDamping;
  163. float baseMinLeft;
  164. float baseMaxLeft;
  165. float baseLeftFriction;
  166. float baseMinUp;
  167. float baseMaxUp;
  168. float baseUpFriction;
  169. float baseMinForward;
  170. float baseMaxForward;
  171. float baseForwardFriction;
  172. // boing
  173. float boingImpactSpeed;
  174. float boingImpactAngle;
  175. float boingDampingRate;
  176. float boingFrequency;
  177. float boingAmplitude;
  178. private:
  179. // No copy constructors allowed
  180. //mstudiojigglebone_t(const mstudiojigglebone_t& vOther);
  181. };
  182. struct mstudioaimatbone_t
  183. {
  184. DECLARE_BYTESWAP_DATADESC();
  185. int parent;
  186. int aim; // Might be bone or attach
  187. Vector aimvector;
  188. Vector upvector;
  189. Vector basepos;
  190. mstudioaimatbone_t() {}
  191. private:
  192. // No copy constructors allowed
  193. mstudioaimatbone_t(const mstudioaimatbone_t& vOther);
  194. };
  195. // bones
  196. struct mstudiobone_t
  197. {
  198. DECLARE_BYTESWAP_DATADESC();
  199. int sznameindex;
  200. inline char * const pszName( void ) const { return ((char *)this) + sznameindex; }
  201. int parent; // parent bone
  202. int bonecontroller[6]; // bone controller index, -1 == none
  203. // default values
  204. Vector pos;
  205. Quaternion quat;
  206. RadianEuler rot;
  207. // compression scale
  208. Vector posscale;
  209. Vector rotscale;
  210. matrix3x4_t poseToBone;
  211. Quaternion qAlignment;
  212. int flags;
  213. int proctype;
  214. int procindex; // procedural rule
  215. mutable int physicsbone; // index into physically simulated bone
  216. inline void *pProcedure( ) const { if (procindex == 0) return NULL; else return (void *)(((byte *)this) + procindex); };
  217. int surfacepropidx; // index into string tablefor property name
  218. inline char * const pszSurfaceProp( void ) const { return ((char *)this) + surfacepropidx; }
  219. int contents; // See BSPFlags.h for the contents flags
  220. int unused[8]; // remove as appropriate
  221. mstudiobone_t(){}
  222. private:
  223. // No copy constructors allowed
  224. mstudiobone_t(const mstudiobone_t& vOther);
  225. };
  226. struct mstudiolinearbone_t
  227. {
  228. DECLARE_BYTESWAP_DATADESC();
  229. int numbones;
  230. int flagsindex;
  231. inline int flags( int i ) const { Assert( i >= 0 && i < numbones); return *((int *)(((byte *)this) + flagsindex) + i); };
  232. inline int *pflags( int i ) { Assert( i >= 0 && i < numbones); return ((int *)(((byte *)this) + flagsindex) + i); };
  233. int parentindex;
  234. inline int parent( int i ) const { Assert( i >= 0 && i < numbones); return *((int *)(((byte *)this) + parentindex) + i); };
  235. int posindex;
  236. inline Vector pos( int i ) const { Assert( i >= 0 && i < numbones); return *((Vector *)(((byte *)this) + posindex) + i); };
  237. int quatindex;
  238. inline Quaternion quat( int i ) const { Assert( i >= 0 && i < numbones); return *((Quaternion *)(((byte *)this) + quatindex) + i); };
  239. int rotindex;
  240. inline RadianEuler rot( int i ) const { Assert( i >= 0 && i < numbones); return *((RadianEuler *)(((byte *)this) + rotindex) + i); };
  241. int posetoboneindex;
  242. inline matrix3x4_t poseToBone( int i ) const { Assert( i >= 0 && i < numbones); return *((matrix3x4_t *)(((byte *)this) + posetoboneindex) + i); };
  243. int posscaleindex;
  244. inline Vector posscale( int i ) const { Assert( i >= 0 && i < numbones); return *((Vector *)(((byte *)this) + posscaleindex) + i); };
  245. int rotscaleindex;
  246. inline Vector rotscale( int i ) const { Assert( i >= 0 && i < numbones); return *((Vector *)(((byte *)this) + rotscaleindex) + i); };
  247. int qalignmentindex;
  248. inline Quaternion qalignment( int i ) const { Assert( i >= 0 && i < numbones); return *((Quaternion *)(((byte *)this) + qalignmentindex) + i); };
  249. int unused[6];
  250. mstudiolinearbone_t(){}
  251. private:
  252. // No copy constructors allowed
  253. mstudiolinearbone_t(const mstudiolinearbone_t& vOther);
  254. };
  255. //-----------------------------------------------------------------------------
  256. // The component of the bone used by mstudioboneflexdriver_t
  257. //-----------------------------------------------------------------------------
  258. enum StudioBoneFlexComponent_t
  259. {
  260. STUDIO_BONE_FLEX_INVALID = -1, // Invalid
  261. STUDIO_BONE_FLEX_TX = 0, // Translate X
  262. STUDIO_BONE_FLEX_TY = 1, // Translate Y
  263. STUDIO_BONE_FLEX_TZ = 2 // Translate Z
  264. };
  265. //-----------------------------------------------------------------------------
  266. // Component is one of Translate X, Y or Z [0,2] (StudioBoneFlexComponent_t)
  267. //-----------------------------------------------------------------------------
  268. struct mstudioboneflexdrivercontrol_t
  269. {
  270. DECLARE_BYTESWAP_DATADESC();
  271. int m_nBoneComponent; // Bone component that drives flex, StudioBoneFlexComponent_t
  272. int m_nFlexControllerIndex; // Flex controller to drive
  273. float m_flMin; // Min value of bone component mapped to 0 on flex controller
  274. float m_flMax; // Max value of bone component mapped to 1 on flex controller
  275. mstudioboneflexdrivercontrol_t(){}
  276. private:
  277. // No copy constructors allowed
  278. mstudioboneflexdrivercontrol_t( const mstudioboneflexdrivercontrol_t &vOther );
  279. };
  280. //-----------------------------------------------------------------------------
  281. // Drive flex controllers from bone components
  282. //-----------------------------------------------------------------------------
  283. struct mstudioboneflexdriver_t
  284. {
  285. DECLARE_BYTESWAP_DATADESC();
  286. int m_nBoneIndex; // Bone to drive flex controller
  287. int m_nControlCount; // Number of flex controllers being driven
  288. int m_nControlIndex; // Index into data where controllers are (relative to this)
  289. inline mstudioboneflexdrivercontrol_t *pBoneFlexDriverControl( int i ) const
  290. {
  291. Assert( i >= 0 && i < m_nControlCount );
  292. return (mstudioboneflexdrivercontrol_t *)(((byte *)this) + m_nControlIndex) + i;
  293. }
  294. int unused[3];
  295. mstudioboneflexdriver_t(){}
  296. private:
  297. // No copy constructors allowed
  298. mstudioboneflexdriver_t( const mstudioboneflexdriver_t &vOther );
  299. };
  300. #define BONE_CALCULATE_MASK 0x1F
  301. #define BONE_PHYSICALLY_SIMULATED 0x01 // bone is physically simulated when physics are active
  302. #define BONE_PHYSICS_PROCEDURAL 0x02 // procedural when physics is active
  303. #define BONE_ALWAYS_PROCEDURAL 0x04 // bone is always procedurally animated
  304. #define BONE_SCREEN_ALIGN_SPHERE 0x08 // bone aligns to the screen, not constrained in motion.
  305. #define BONE_SCREEN_ALIGN_CYLINDER 0x10 // bone aligns to the screen, constrained by it's own axis.
  306. #define BONE_USED_MASK 0x0007FF00
  307. #define BONE_USED_BY_ANYTHING 0x0007FF00
  308. #define BONE_USED_BY_HITBOX 0x00000100 // bone (or child) is used by a hit box
  309. #define BONE_USED_BY_ATTACHMENT 0x00000200 // bone (or child) is used by an attachment point
  310. #define BONE_USED_BY_VERTEX_MASK 0x0003FC00
  311. #define BONE_USED_BY_VERTEX_LOD0 0x00000400 // bone (or child) is used by the toplevel model via skinned vertex
  312. #define BONE_USED_BY_VERTEX_LOD1 0x00000800
  313. #define BONE_USED_BY_VERTEX_LOD2 0x00001000
  314. #define BONE_USED_BY_VERTEX_LOD3 0x00002000
  315. #define BONE_USED_BY_VERTEX_LOD4 0x00004000
  316. #define BONE_USED_BY_VERTEX_LOD5 0x00008000
  317. #define BONE_USED_BY_VERTEX_LOD6 0x00010000
  318. #define BONE_USED_BY_VERTEX_LOD7 0x00020000
  319. #define BONE_USED_BY_BONE_MERGE 0x00040000 // bone is available for bone merge to occur against it
  320. #define BONE_USED_BY_VERTEX_AT_LOD(lod) ( BONE_USED_BY_VERTEX_LOD0 << (lod) )
  321. #define BONE_USED_BY_ANYTHING_AT_LOD(lod) ( ( BONE_USED_BY_ANYTHING & ~BONE_USED_BY_VERTEX_MASK ) | BONE_USED_BY_VERTEX_AT_LOD(lod) )
  322. #define MAX_NUM_LODS 8
  323. #define BONE_TYPE_MASK 0x00F00000
  324. #define BONE_FIXED_ALIGNMENT 0x00100000 // bone can't spin 360 degrees, all interpolation is normalized around a fixed orientation
  325. #define BONE_HAS_SAVEFRAME_POS 0x00200000 // Vector48
  326. #define BONE_HAS_SAVEFRAME_ROT 0x00400000 // Quaternion64
  327. // bone controllers
  328. struct mstudiobonecontroller_t
  329. {
  330. DECLARE_BYTESWAP_DATADESC();
  331. int bone; // -1 == 0
  332. int type; // X, Y, Z, XR, YR, ZR, M
  333. float start;
  334. float end;
  335. int rest; // byte index value at rest
  336. int inputfield; // 0-3 user set controller, 4 mouth
  337. int unused[8];
  338. };
  339. // intersection boxes
  340. struct mstudiobbox_t
  341. {
  342. DECLARE_BYTESWAP_DATADESC();
  343. int bone;
  344. int group; // intersection group
  345. Vector bbmin; // bounding box
  346. Vector bbmax;
  347. int szhitboxnameindex; // offset to the name of the hitbox.
  348. int unused[8];
  349. const char* pszHitboxName()
  350. {
  351. if( szhitboxnameindex == 0 )
  352. return "";
  353. return ((const char*)this) + szhitboxnameindex;
  354. }
  355. mstudiobbox_t() {}
  356. private:
  357. // No copy constructors allowed
  358. mstudiobbox_t(const mstudiobbox_t& vOther);
  359. };
  360. // demand loaded sequence groups
  361. struct mstudiomodelgroup_t
  362. {
  363. DECLARE_BYTESWAP_DATADESC();
  364. int szlabelindex; // textual name
  365. inline char * const pszLabel( void ) const { return ((char *)this) + szlabelindex; }
  366. int sznameindex; // file name
  367. inline char * const pszName( void ) const { return ((char *)this) + sznameindex; }
  368. };
  369. struct mstudiomodelgrouplookup_t
  370. {
  371. int modelgroup;
  372. int indexwithingroup;
  373. };
  374. // events
  375. struct mstudioevent_t
  376. {
  377. DECLARE_BYTESWAP_DATADESC();
  378. float cycle;
  379. int event;
  380. int type;
  381. inline const char * pszOptions( void ) const { return options; }
  382. char options[64];
  383. int szeventindex;
  384. inline char * const pszEventName( void ) const { return ((char *)this) + szeventindex; }
  385. };
  386. #define ATTACHMENT_FLAG_WORLD_ALIGN 0x10000
  387. // attachment
  388. struct mstudioattachment_t
  389. {
  390. DECLARE_BYTESWAP_DATADESC();
  391. int sznameindex;
  392. inline char * const pszName( void ) const { return ((char *)this) + sznameindex; }
  393. unsigned int flags;
  394. int localbone;
  395. matrix3x4_t local; // attachment point
  396. int unused[8];
  397. };
  398. #define IK_SELF 1
  399. #define IK_WORLD 2
  400. #define IK_GROUND 3
  401. #define IK_RELEASE 4
  402. #define IK_ATTACHMENT 5
  403. #define IK_UNLATCH 6
  404. struct mstudioikerror_t
  405. {
  406. DECLARE_BYTESWAP_DATADESC();
  407. Vector pos;
  408. Quaternion q;
  409. mstudioikerror_t() {}
  410. private:
  411. // No copy constructors allowed
  412. mstudioikerror_t(const mstudioikerror_t& vOther);
  413. };
  414. union mstudioanimvalue_t;
  415. struct mstudiocompressedikerror_t
  416. {
  417. DECLARE_BYTESWAP_DATADESC();
  418. float scale[6];
  419. short offset[6];
  420. inline mstudioanimvalue_t *pAnimvalue( int i ) const { if (offset[i] > 0) return (mstudioanimvalue_t *)(((byte *)this) + offset[i]); else return NULL; };
  421. mstudiocompressedikerror_t(){}
  422. private:
  423. // No copy constructors allowed
  424. mstudiocompressedikerror_t(const mstudiocompressedikerror_t& vOther);
  425. };
  426. struct mstudioikrule_t
  427. {
  428. DECLARE_BYTESWAP_DATADESC();
  429. int index;
  430. int type;
  431. int chain;
  432. int bone;
  433. int slot; // iktarget slot. Usually same as chain.
  434. float height;
  435. float radius;
  436. float floor;
  437. Vector pos;
  438. Quaternion q;
  439. int compressedikerrorindex;
  440. inline mstudiocompressedikerror_t *pCompressedError() const { return (mstudiocompressedikerror_t *)(((byte *)this) + compressedikerrorindex); };
  441. int unused2;
  442. int iStart;
  443. int ikerrorindex;
  444. inline mstudioikerror_t *pError( int i ) const { return (ikerrorindex) ? (mstudioikerror_t *)(((byte *)this) + ikerrorindex) + (i - iStart) : NULL; };
  445. float start; // beginning of influence
  446. float peak; // start of full influence
  447. float tail; // end of full influence
  448. float end; // end of all influence
  449. float unused3; //
  450. float contact; // frame footstep makes ground concact
  451. float drop; // how far down the foot should drop when reaching for IK
  452. float top; // top of the foot box
  453. int unused6;
  454. int unused7;
  455. int unused8;
  456. int szattachmentindex; // name of world attachment
  457. inline char * const pszAttachment( void ) const { return ((char *)this) + szattachmentindex; }
  458. int unused[7];
  459. mstudioikrule_t() {}
  460. private:
  461. // No copy constructors allowed
  462. mstudioikrule_t(const mstudioikrule_t& vOther);
  463. };
  464. struct mstudioiklock_t
  465. {
  466. DECLARE_BYTESWAP_DATADESC();
  467. int chain;
  468. float flPosWeight;
  469. float flLocalQWeight;
  470. int flags;
  471. int unused[4];
  472. };
  473. struct mstudiolocalhierarchy_t
  474. {
  475. DECLARE_BYTESWAP_DATADESC();
  476. int iBone; // bone being adjusted
  477. int iNewParent; // the bones new parent
  478. float start; // beginning of influence
  479. float peak; // start of full influence
  480. float tail; // end of full influence
  481. float end; // end of all influence
  482. int iStart; // first frame
  483. int localanimindex;
  484. inline mstudiocompressedikerror_t *pLocalAnim() const { return (mstudiocompressedikerror_t *)(((byte *)this) + localanimindex); };
  485. int unused[4];
  486. };
  487. // animation frames
  488. union mstudioanimvalue_t
  489. {
  490. struct
  491. {
  492. byte valid;
  493. byte total;
  494. } num;
  495. short value;
  496. };
  497. struct mstudioanim_valueptr_t
  498. {
  499. DECLARE_BYTESWAP_DATADESC();
  500. short offset[3];
  501. inline mstudioanimvalue_t *pAnimvalue( int i ) const { if (offset[i] > 0) return (mstudioanimvalue_t *)(((byte *)this) + offset[i]); else return NULL; };
  502. };
  503. #define STUDIO_ANIM_RAWPOS 0x01 // Vector48
  504. #define STUDIO_ANIM_RAWROT 0x02 // Quaternion48
  505. #define STUDIO_ANIM_ANIMPOS 0x04 // mstudioanim_valueptr_t
  506. #define STUDIO_ANIM_ANIMROT 0x08 // mstudioanim_valueptr_t
  507. #define STUDIO_ANIM_DELTA 0x10
  508. #define STUDIO_ANIM_RAWROT2 0x20 // Quaternion64
  509. // per bone per animation DOF and weight pointers
  510. struct mstudioanim_t
  511. {
  512. DECLARE_BYTESWAP_DATADESC();
  513. byte bone;
  514. byte flags; // weighing options
  515. // valid for animating data only
  516. inline byte *pData( void ) const { return (((byte *)this) + sizeof( struct mstudioanim_t )); };
  517. inline mstudioanim_valueptr_t *pRotV( void ) const { return (mstudioanim_valueptr_t *)(pData()); };
  518. inline mstudioanim_valueptr_t *pPosV( void ) const { return (mstudioanim_valueptr_t *)(pData()) + ((flags & STUDIO_ANIM_ANIMROT) != 0); };
  519. // valid if animation unvaring over timeline
  520. inline Quaternion48 *pQuat48( void ) const { return (Quaternion48 *)(pData()); };
  521. inline Quaternion64 *pQuat64( void ) const { return (Quaternion64 *)(pData()); };
  522. inline Vector48 *pPos( void ) const { return (Vector48 *)(pData() + ((flags & STUDIO_ANIM_RAWROT) != 0) * sizeof( *pQuat48() ) + ((flags & STUDIO_ANIM_RAWROT2) != 0) * sizeof( *pQuat64() ) ); };
  523. short nextoffset;
  524. inline mstudioanim_t *pNext( void ) const { if (nextoffset != 0) return (mstudioanim_t *)(((byte *)this) + nextoffset); else return NULL; };
  525. };
  526. struct mstudiomovement_t
  527. {
  528. DECLARE_BYTESWAP_DATADESC();
  529. int endframe;
  530. int motionflags;
  531. float v0; // velocity at start of block
  532. float v1; // velocity at end of block
  533. float angle; // YAW rotation at end of this blocks movement
  534. Vector vector; // movement vector relative to this blocks initial angle
  535. Vector position; // relative to start of animation???
  536. mstudiomovement_t(){}
  537. private:
  538. // No copy constructors allowed
  539. mstudiomovement_t(const mstudiomovement_t& vOther);
  540. };
  541. struct studiohdr_t;
  542. // used for piecewise loading of animation data
  543. struct mstudioanimblock_t
  544. {
  545. DECLARE_BYTESWAP_DATADESC();
  546. int datastart;
  547. int dataend;
  548. };
  549. struct mstudioanimsections_t
  550. {
  551. DECLARE_BYTESWAP_DATADESC();
  552. int animblock;
  553. int animindex;
  554. };
  555. struct mstudioanimdesc_t
  556. {
  557. DECLARE_BYTESWAP_DATADESC();
  558. int baseptr;
  559. inline studiohdr_t *pStudiohdr( void ) const { return (studiohdr_t *)(((byte *)this) + baseptr); }
  560. int sznameindex;
  561. inline char * const pszName( void ) const { return ((char *)this) + sznameindex; }
  562. float fps; // frames per second
  563. int flags; // looping/non-looping flags
  564. int numframes;
  565. // piecewise movement
  566. int nummovements;
  567. int movementindex;
  568. inline mstudiomovement_t * const pMovement( int i ) const { return (mstudiomovement_t *)(((byte *)this) + movementindex) + i; };
  569. int unused1[6]; // remove as appropriate (and zero if loading older versions)
  570. int animblock;
  571. int animindex; // non-zero when anim data isn't in sections
  572. mstudioanim_t *pAnimBlock( int block, int index ) const; // returns pointer to a specific anim block (local or external)
  573. mstudioanim_t *pAnim( int *piFrame, float &flStall ) const; // returns pointer to data and new frame index
  574. mstudioanim_t *pAnim( int *piFrame ) const; // returns pointer to data and new frame index
  575. int numikrules;
  576. int ikruleindex; // non-zero when IK data is stored in the mdl
  577. int animblockikruleindex; // non-zero when IK data is stored in animblock file
  578. mstudioikrule_t *pIKRule( int i ) const;
  579. int numlocalhierarchy;
  580. int localhierarchyindex;
  581. mstudiolocalhierarchy_t *pHierarchy( int i ) const;
  582. int sectionindex;
  583. int sectionframes; // number of frames used in each fast lookup section, zero if not used
  584. inline mstudioanimsections_t * const pSection( int i ) const { return (mstudioanimsections_t *)(((byte *)this) + sectionindex) + i; }
  585. short zeroframespan; // frames per span
  586. short zeroframecount; // number of spans
  587. int zeroframeindex;
  588. byte *pZeroFrameData( ) const { if (zeroframeindex) return (((byte *)this) + zeroframeindex); else return NULL; };
  589. mutable float zeroframestalltime; // saved during read stalls
  590. mstudioanimdesc_t(){}
  591. private:
  592. // No copy constructors allowed
  593. mstudioanimdesc_t(const mstudioanimdesc_t& vOther);
  594. };
  595. struct mstudioikrule_t;
  596. struct mstudioautolayer_t
  597. {
  598. DECLARE_BYTESWAP_DATADESC();
  599. //private:
  600. short iSequence;
  601. short iPose;
  602. //public:
  603. int flags;
  604. float start; // beginning of influence
  605. float peak; // start of full influence
  606. float tail; // end of full influence
  607. float end; // end of all influence
  608. };
  609. struct mstudioactivitymodifier_t
  610. {
  611. DECLARE_BYTESWAP_DATADESC();
  612. int sznameindex;
  613. inline char *pszName() { return (sznameindex) ? (char *)(((byte *)this) + sznameindex ) : NULL; }
  614. };
  615. // sequence descriptions
  616. struct mstudioseqdesc_t
  617. {
  618. DECLARE_BYTESWAP_DATADESC();
  619. int baseptr;
  620. inline studiohdr_t *pStudiohdr( void ) const { return (studiohdr_t *)(((byte *)this) + baseptr); }
  621. int szlabelindex;
  622. inline char * const pszLabel( void ) const { return ((char *)this) + szlabelindex; }
  623. int szactivitynameindex;
  624. inline char * const pszActivityName( void ) const { return ((char *)this) + szactivitynameindex; }
  625. int flags; // looping/non-looping flags
  626. int activity; // initialized at loadtime to game DLL values
  627. int actweight;
  628. int numevents;
  629. int eventindex;
  630. inline mstudioevent_t *pEvent( int i ) const { Assert( i >= 0 && i < numevents); return (mstudioevent_t *)(((byte *)this) + eventindex) + i; };
  631. Vector bbmin; // per sequence bounding box
  632. Vector bbmax;
  633. int numblends;
  634. // Index into array of shorts which is groupsize[0] x groupsize[1] in length
  635. int animindexindex;
  636. inline int anim( int x, int y ) const
  637. {
  638. if ( x >= groupsize[0] )
  639. {
  640. x = groupsize[0] - 1;
  641. }
  642. if ( y >= groupsize[1] )
  643. {
  644. y = groupsize[ 1 ] - 1;
  645. }
  646. int offset = y * groupsize[0] + x;
  647. short *blends = (short *)(((byte *)this) + animindexindex);
  648. int value = (int)blends[ offset ];
  649. return value;
  650. }
  651. int movementindex; // [blend] float array for blended movement
  652. int groupsize[2];
  653. int paramindex[2]; // X, Y, Z, XR, YR, ZR
  654. float paramstart[2]; // local (0..1) starting value
  655. float paramend[2]; // local (0..1) ending value
  656. int paramparent;
  657. float fadeintime; // ideal cross fate in time (0.2 default)
  658. float fadeouttime; // ideal cross fade out time (0.2 default)
  659. int localentrynode; // transition node at entry
  660. int localexitnode; // transition node at exit
  661. int nodeflags; // transition rules
  662. float entryphase; // used to match entry gait
  663. float exitphase; // used to match exit gait
  664. float lastframe; // frame that should generation EndOfSequence
  665. int nextseq; // auto advancing sequences
  666. int pose; // index of delta animation between end and nextseq
  667. int numikrules;
  668. int numautolayers; //
  669. int autolayerindex;
  670. inline mstudioautolayer_t *pAutolayer( int i ) const { Assert( i >= 0 && i < numautolayers); return (mstudioautolayer_t *)(((byte *)this) + autolayerindex) + i; };
  671. int weightlistindex;
  672. inline float *pBoneweight( int i ) const { return ((float *)(((byte *)this) + weightlistindex) + i); };
  673. inline float weight( int i ) const { return *(pBoneweight( i)); };
  674. // FIXME: make this 2D instead of 2x1D arrays
  675. int posekeyindex;
  676. float *pPoseKey( int iParam, int iAnim ) const { return (float *)(((byte *)this) + posekeyindex) + iParam * groupsize[0] + iAnim; }
  677. float poseKey( int iParam, int iAnim ) const { return *(pPoseKey( iParam, iAnim )); }
  678. int numiklocks;
  679. int iklockindex;
  680. inline mstudioiklock_t *pIKLock( int i ) const { Assert( i >= 0 && i < numiklocks); return (mstudioiklock_t *)(((byte *)this) + iklockindex) + i; };
  681. // Key values
  682. int keyvalueindex;
  683. int keyvaluesize;
  684. inline const char * KeyValueText( void ) const { return keyvaluesize != 0 ? ((char *)this) + keyvalueindex : NULL; }
  685. int cycleposeindex; // index of pose parameter to use as cycle index
  686. int activitymodifierindex;
  687. int numactivitymodifiers;
  688. inline mstudioactivitymodifier_t *pActivityModifier( int i ) const { Assert( i >= 0 && i < numactivitymodifiers); return activitymodifierindex != 0 ? (mstudioactivitymodifier_t *)(((byte *)this) + activitymodifierindex) + i : NULL; };
  689. int unused[5]; // remove/add as appropriate (grow back to 8 ints on version change!)
  690. mstudioseqdesc_t(){}
  691. private:
  692. // No copy constructors allowed
  693. mstudioseqdesc_t(const mstudioseqdesc_t& vOther);
  694. };
  695. struct mstudioposeparamdesc_t
  696. {
  697. DECLARE_BYTESWAP_DATADESC();
  698. int sznameindex;
  699. inline char * const pszName( void ) const { return ((char *)this) + sznameindex; }
  700. int flags; // ????
  701. float start; // starting value
  702. float end; // ending value
  703. float loop; // looping range, 0 for no looping, 360 for rotations, etc.
  704. };
  705. struct mstudioflexdesc_t
  706. {
  707. DECLARE_BYTESWAP_DATADESC();
  708. int szFACSindex;
  709. inline char * const pszFACS( void ) const { return ((char *)this) + szFACSindex; }
  710. };
  711. struct mstudioflexcontroller_t
  712. {
  713. DECLARE_BYTESWAP_DATADESC();
  714. int sztypeindex;
  715. inline char * const pszType( void ) const { return ((char *)this) + sztypeindex; }
  716. int sznameindex;
  717. inline char * const pszName( void ) const { return ((char *)this) + sznameindex; }
  718. mutable int localToGlobal; // remapped at load time to master list
  719. float min;
  720. float max;
  721. };
  722. enum FlexControllerRemapType_t
  723. {
  724. FLEXCONTROLLER_REMAP_PASSTHRU = 0,
  725. FLEXCONTROLLER_REMAP_2WAY, // Control 0 -> ramps from 1-0 from 0->0.5. Control 1 -> ramps from 0-1 from 0.5->1
  726. FLEXCONTROLLER_REMAP_NWAY, // StepSize = 1 / (control count-1) Control n -> ramps from 0-1-0 from (n-1)*StepSize to n*StepSize to (n+1)*StepSize. A second control is needed to specify amount to use
  727. FLEXCONTROLLER_REMAP_EYELID
  728. };
  729. class CStudioHdr;
  730. struct mstudioflexcontrollerui_t
  731. {
  732. DECLARE_BYTESWAP_DATADESC();
  733. int sznameindex;
  734. inline char * const pszName( void ) const { return ((char *)this) + sznameindex; }
  735. // These are used like a union to save space
  736. // Here are the possible configurations for a UI controller
  737. //
  738. // SIMPLE NON-STEREO: 0: control 1: unused 2: unused
  739. // STEREO: 0: left 1: right 2: unused
  740. // NWAY NON-STEREO: 0: control 1: unused 2: value
  741. // NWAY STEREO: 0: left 1: right 2: value
  742. int szindex0;
  743. int szindex1;
  744. int szindex2;
  745. inline const mstudioflexcontroller_t *pController( void ) const
  746. {
  747. return !stereo ? (mstudioflexcontroller_t *)( (char *)this + szindex0 ) : NULL;
  748. }
  749. inline char * const pszControllerName( void ) const { return !stereo ? pController()->pszName() : NULL; }
  750. inline int controllerIndex( const CStudioHdr &cStudioHdr ) const;
  751. inline const mstudioflexcontroller_t *pLeftController( void ) const
  752. {
  753. return stereo ? (mstudioflexcontroller_t *)( (char *)this + szindex0 ) : NULL;
  754. }
  755. inline char * const pszLeftName( void ) const { return stereo ? pLeftController()->pszName() : NULL; }
  756. inline int leftIndex( const CStudioHdr &cStudioHdr ) const;
  757. inline const mstudioflexcontroller_t *pRightController( void ) const
  758. {
  759. return stereo ? (mstudioflexcontroller_t *)( (char *)this + szindex1 ): NULL;
  760. }
  761. inline char * const pszRightName( void ) const { return stereo ? pRightController()->pszName() : NULL; }
  762. inline int rightIndex( const CStudioHdr &cStudioHdr ) const;
  763. inline const mstudioflexcontroller_t *pNWayValueController( void ) const
  764. {
  765. return remaptype == FLEXCONTROLLER_REMAP_NWAY ? (mstudioflexcontroller_t *)( (char *)this + szindex2 ) : NULL;
  766. }
  767. inline char * const pszNWayValueName( void ) const { return remaptype == FLEXCONTROLLER_REMAP_NWAY ? pNWayValueController()->pszName() : NULL; }
  768. inline int nWayValueIndex( const CStudioHdr &cStudioHdr ) const;
  769. // Number of controllers this ui description contains, 1, 2 or 3
  770. inline int Count() const { return ( stereo ? 2 : 1 ) + ( remaptype == FLEXCONTROLLER_REMAP_NWAY ? 1 : 0 ); }
  771. inline const mstudioflexcontroller_t *pController( int index ) const;
  772. unsigned char remaptype; // See the FlexControllerRemapType_t enum
  773. bool stereo; // Is this a stereo control?
  774. byte unused[2];
  775. };
  776. // this is the memory image of vertex anims (16-bit fixed point)
  777. struct mstudiovertanim_t
  778. {
  779. DECLARE_BYTESWAP_DATADESC();
  780. unsigned short index;
  781. byte speed; // 255/max_length_in_flex
  782. byte side; // 255/left_right
  783. protected:
  784. // JasonM changing this type a lot, to prefer fixed point 16 bit...
  785. union
  786. {
  787. short delta[3];
  788. float16 flDelta[3];
  789. };
  790. union
  791. {
  792. short ndelta[3];
  793. float16 flNDelta[3];
  794. };
  795. public:
  796. inline void ConvertToFixed( float flVertAnimFixedPointScale )
  797. {
  798. delta[0] = flDelta[0].GetFloat() / flVertAnimFixedPointScale;
  799. delta[1] = flDelta[1].GetFloat() / flVertAnimFixedPointScale;
  800. delta[2] = flDelta[2].GetFloat() / flVertAnimFixedPointScale;
  801. ndelta[0] = flNDelta[0].GetFloat() / flVertAnimFixedPointScale;
  802. ndelta[1] = flNDelta[1].GetFloat() / flVertAnimFixedPointScale;
  803. ndelta[2] = flNDelta[2].GetFloat() / flVertAnimFixedPointScale;
  804. }
  805. inline Vector GetDeltaFixed( float flVertAnimFixedPointScale )
  806. {
  807. return Vector( delta[0] * flVertAnimFixedPointScale, delta[1] * flVertAnimFixedPointScale, delta[2] * flVertAnimFixedPointScale );
  808. }
  809. inline Vector GetNDeltaFixed( float flVertAnimFixedPointScale )
  810. {
  811. return Vector( ndelta[0] * flVertAnimFixedPointScale, ndelta[1] * flVertAnimFixedPointScale, ndelta[2] * flVertAnimFixedPointScale );
  812. }
  813. inline void GetDeltaFixed4DAligned( Vector4DAligned *vFillIn, float flVertAnimFixedPointScale )
  814. {
  815. vFillIn->Set( delta[0] * flVertAnimFixedPointScale, delta[1] * flVertAnimFixedPointScale, delta[2] * flVertAnimFixedPointScale, 0.0f );
  816. }
  817. inline void GetNDeltaFixed4DAligned( Vector4DAligned *vFillIn, float flVertAnimFixedPointScale )
  818. {
  819. vFillIn->Set( ndelta[0] * flVertAnimFixedPointScale, ndelta[1] * flVertAnimFixedPointScale, ndelta[2] * flVertAnimFixedPointScale, 0.0f );
  820. }
  821. inline Vector GetDeltaFloat()
  822. {
  823. return Vector (flDelta[0].GetFloat(), flDelta[1].GetFloat(), flDelta[2].GetFloat());
  824. }
  825. inline Vector GetNDeltaFloat()
  826. {
  827. return Vector (flNDelta[0].GetFloat(), flNDelta[1].GetFloat(), flNDelta[2].GetFloat());
  828. }
  829. inline void SetDeltaFixed( const Vector& vInput, float flVertAnimFixedPointScale )
  830. {
  831. delta[0] = vInput.x / flVertAnimFixedPointScale;
  832. delta[1] = vInput.y / flVertAnimFixedPointScale;
  833. delta[2] = vInput.z / flVertAnimFixedPointScale;
  834. }
  835. inline void SetNDeltaFixed( const Vector& vInputNormal, float flVertAnimFixedPointScale )
  836. {
  837. ndelta[0] = vInputNormal.x / flVertAnimFixedPointScale;
  838. ndelta[1] = vInputNormal.y / flVertAnimFixedPointScale;
  839. ndelta[2] = vInputNormal.z / flVertAnimFixedPointScale;
  840. }
  841. // Ick...can also force fp16 data into this structure for writing to file in legacy format...
  842. inline void SetDeltaFloat( const Vector& vInput )
  843. {
  844. flDelta[0].SetFloat( vInput.x );
  845. flDelta[1].SetFloat( vInput.y );
  846. flDelta[2].SetFloat( vInput.z );
  847. }
  848. inline void SetNDeltaFloat( const Vector& vInputNormal )
  849. {
  850. flNDelta[0].SetFloat( vInputNormal.x );
  851. flNDelta[1].SetFloat( vInputNormal.y );
  852. flNDelta[2].SetFloat( vInputNormal.z );
  853. }
  854. class CSortByIndex
  855. {
  856. public:
  857. bool operator()(const mstudiovertanim_t &left, const mstudiovertanim_t & right)const
  858. {
  859. return left.index < right.index;
  860. }
  861. };
  862. friend class CSortByIndex;
  863. mstudiovertanim_t(){}
  864. //private:
  865. // No copy constructors allowed, but it's needed for std::sort()
  866. // mstudiovertanim_t(const mstudiovertanim_t& vOther);
  867. };
  868. // this is the memory image of vertex anims (16-bit fixed point)
  869. struct mstudiovertanim_wrinkle_t : public mstudiovertanim_t
  870. {
  871. DECLARE_BYTESWAP_DATADESC();
  872. short wrinkledelta;
  873. inline void SetWrinkleFixed( float flWrinkle, float flVertAnimFixedPointScale )
  874. {
  875. int nWrinkleDeltaInt = flWrinkle / flVertAnimFixedPointScale;
  876. wrinkledelta = clamp( nWrinkleDeltaInt, -32767, 32767 );
  877. }
  878. inline Vector4D GetDeltaFixed( float flVertAnimFixedPointScale )
  879. {
  880. return Vector4D( delta[0] * flVertAnimFixedPointScale, delta[1] * flVertAnimFixedPointScale, delta[2] * flVertAnimFixedPointScale, wrinkledelta * flVertAnimFixedPointScale );
  881. }
  882. inline void GetDeltaFixed4DAligned( Vector4DAligned *vFillIn, float flVertAnimFixedPointScale )
  883. {
  884. vFillIn->Set( delta[0] * flVertAnimFixedPointScale, delta[1] * flVertAnimFixedPointScale, delta[2] * flVertAnimFixedPointScale, wrinkledelta * flVertAnimFixedPointScale );
  885. }
  886. inline float GetWrinkleDeltaFixed( float flVertAnimFixedPointScale )
  887. {
  888. return wrinkledelta * flVertAnimFixedPointScale;
  889. }
  890. };
  891. enum StudioVertAnimType_t
  892. {
  893. STUDIO_VERT_ANIM_NORMAL = 0,
  894. STUDIO_VERT_ANIM_WRINKLE,
  895. };
  896. struct mstudioflex_t
  897. {
  898. DECLARE_BYTESWAP_DATADESC();
  899. int flexdesc; // input value
  900. float target0; // zero
  901. float target1; // one
  902. float target2; // one
  903. float target3; // zero
  904. int numverts;
  905. int vertindex;
  906. inline mstudiovertanim_t *pVertanim( int i ) const { Assert( vertanimtype == STUDIO_VERT_ANIM_NORMAL ); return (mstudiovertanim_t *)(((byte *)this) + vertindex) + i; };
  907. inline mstudiovertanim_wrinkle_t *pVertanimWrinkle( int i ) const { Assert( vertanimtype == STUDIO_VERT_ANIM_WRINKLE ); return (mstudiovertanim_wrinkle_t *)(((byte *)this) + vertindex) + i; };
  908. inline byte *pBaseVertanim( ) const { return ((byte *)this) + vertindex; };
  909. inline int VertAnimSizeBytes() const { return ( vertanimtype == STUDIO_VERT_ANIM_NORMAL ) ? sizeof(mstudiovertanim_t) : sizeof(mstudiovertanim_wrinkle_t); }
  910. int flexpair; // second flex desc
  911. unsigned char vertanimtype; // See StudioVertAnimType_t
  912. unsigned char unusedchar[3];
  913. int unused[6];
  914. };
  915. struct mstudioflexop_t
  916. {
  917. DECLARE_BYTESWAP_DATADESC();
  918. int op;
  919. union
  920. {
  921. int index;
  922. float value;
  923. } d;
  924. };
  925. struct mstudioflexrule_t
  926. {
  927. DECLARE_BYTESWAP_DATADESC();
  928. int flex;
  929. int numops;
  930. int opindex;
  931. inline mstudioflexop_t *iFlexOp( int i ) const { return (mstudioflexop_t *)(((byte *)this) + opindex) + i; };
  932. };
  933. // 16 bytes
  934. struct mstudioboneweight_t
  935. {
  936. DECLARE_BYTESWAP_DATADESC();
  937. float weight[MAX_NUM_BONES_PER_VERT];
  938. char bone[MAX_NUM_BONES_PER_VERT];
  939. byte numbones;
  940. // byte material;
  941. // short firstref;
  942. // short lastref;
  943. };
  944. // NOTE: This is exactly 48 bytes
  945. struct mstudiovertex_t
  946. {
  947. DECLARE_BYTESWAP_DATADESC();
  948. mstudioboneweight_t m_BoneWeights;
  949. Vector m_vecPosition;
  950. Vector m_vecNormal;
  951. Vector2D m_vecTexCoord;
  952. mstudiovertex_t() {}
  953. private:
  954. // No copy constructors allowed
  955. mstudiovertex_t(const mstudiovertex_t& vOther);
  956. };
  957. // skin info
  958. struct mstudiotexture_t
  959. {
  960. DECLARE_BYTESWAP_DATADESC();
  961. int sznameindex;
  962. inline char * const pszName( void ) const { return ((char *)this) + sznameindex; }
  963. int flags;
  964. int used;
  965. int unused1;
  966. mutable IMaterial *material; // fixme: this needs to go away . .isn't used by the engine, but is used by studiomdl
  967. mutable void *clientmaterial; // gary, replace with client material pointer if used
  968. int unused[10];
  969. };
  970. // eyeball
  971. struct mstudioeyeball_t
  972. {
  973. DECLARE_BYTESWAP_DATADESC();
  974. int sznameindex;
  975. inline char * const pszName( void ) const { return ((char *)this) + sznameindex; }
  976. int bone;
  977. Vector org;
  978. float zoffset;
  979. float radius;
  980. Vector up;
  981. Vector forward;
  982. int texture;
  983. int unused1;
  984. float iris_scale;
  985. int unused2;
  986. int upperflexdesc[3]; // index of raiser, neutral, and lowerer flexdesc that is set by flex controllers
  987. int lowerflexdesc[3];
  988. float uppertarget[3]; // angle (radians) of raised, neutral, and lowered lid positions
  989. float lowertarget[3];
  990. int upperlidflexdesc; // index of flex desc that actual lid flexes look to
  991. int lowerlidflexdesc;
  992. int unused[4]; // These were used before, so not guaranteed to be 0
  993. bool m_bNonFACS; // Never used before version 44
  994. char unused3[3];
  995. int unused4[7];
  996. mstudioeyeball_t(){}
  997. private:
  998. // No copy constructors allowed
  999. mstudioeyeball_t(const mstudioeyeball_t& vOther);
  1000. };
  1001. // ikinfo
  1002. struct mstudioiklink_t
  1003. {
  1004. DECLARE_BYTESWAP_DATADESC();
  1005. int bone;
  1006. Vector kneeDir; // ideal bending direction (per link, if applicable)
  1007. Vector unused0; // unused
  1008. mstudioiklink_t(){}
  1009. private:
  1010. // No copy constructors allowed
  1011. mstudioiklink_t(const mstudioiklink_t& vOther);
  1012. };
  1013. struct mstudioikchain_t
  1014. {
  1015. DECLARE_BYTESWAP_DATADESC();
  1016. int sznameindex;
  1017. inline char * const pszName( void ) const { return ((char *)this) + sznameindex; }
  1018. int linktype;
  1019. int numlinks;
  1020. int linkindex;
  1021. inline mstudioiklink_t *pLink( int i ) const { return (mstudioiklink_t *)(((byte *)this) + linkindex) + i; };
  1022. // FIXME: add unused entries
  1023. };
  1024. struct mstudioiface_t
  1025. {
  1026. unsigned short a, b, c; // Indices to vertices
  1027. };
  1028. struct mstudiomodel_t;
  1029. struct mstudio_modelvertexdata_t
  1030. {
  1031. DECLARE_BYTESWAP_DATADESC();
  1032. Vector *Position( int i ) const;
  1033. Vector *Normal( int i ) const;
  1034. Vector4D *TangentS( int i ) const;
  1035. Vector2D *Texcoord( int i ) const;
  1036. mstudioboneweight_t *BoneWeights( int i ) const;
  1037. mstudiovertex_t *Vertex( int i ) const;
  1038. bool HasTangentData( void ) const;
  1039. int GetGlobalVertexIndex( int i ) const;
  1040. int GetGlobalTangentIndex( int i ) const;
  1041. // base of external vertex data stores
  1042. const void *pVertexData;
  1043. const void *pTangentData;
  1044. };
  1045. struct mstudio_meshvertexdata_t
  1046. {
  1047. DECLARE_BYTESWAP_DATADESC();
  1048. Vector *Position( int i ) const;
  1049. Vector *Normal( int i ) const;
  1050. Vector4D *TangentS( int i ) const;
  1051. Vector2D *Texcoord( int i ) const;
  1052. mstudioboneweight_t *BoneWeights( int i ) const;
  1053. mstudiovertex_t *Vertex( int i ) const;
  1054. bool HasTangentData( void ) const;
  1055. int GetModelVertexIndex( int i ) const;
  1056. int GetGlobalVertexIndex( int i ) const;
  1057. // indirection to this mesh's model's vertex data
  1058. const mstudio_modelvertexdata_t *modelvertexdata;
  1059. // used for fixup calcs when culling top level lods
  1060. // expected number of mesh verts at desired lod
  1061. int numLODVertexes[MAX_NUM_LODS];
  1062. };
  1063. struct mstudiomesh_t
  1064. {
  1065. DECLARE_BYTESWAP_DATADESC();
  1066. int material;
  1067. int modelindex;
  1068. mstudiomodel_t *pModel() const;
  1069. int numvertices; // number of unique vertices/normals/texcoords
  1070. int vertexoffset; // vertex mstudiovertex_t
  1071. // Access thin/fat mesh vertex data (only one will return a non-NULL result)
  1072. const mstudio_meshvertexdata_t *GetVertexData( void *pModelData = NULL );
  1073. const thinModelVertices_t *GetThinVertexData( void *pModelData = NULL );
  1074. int numflexes; // vertex animation
  1075. int flexindex;
  1076. inline mstudioflex_t *pFlex( int i ) const { return (mstudioflex_t *)(((byte *)this) + flexindex) + i; };
  1077. // special codes for material operations
  1078. int materialtype;
  1079. int materialparam;
  1080. // a unique ordinal for this mesh
  1081. int meshid;
  1082. Vector center;
  1083. mstudio_meshvertexdata_t vertexdata;
  1084. int unused[8]; // remove as appropriate
  1085. mstudiomesh_t(){}
  1086. private:
  1087. // No copy constructors allowed
  1088. mstudiomesh_t(const mstudiomesh_t& vOther);
  1089. };
  1090. // studio models
  1091. struct mstudiomodel_t
  1092. {
  1093. DECLARE_BYTESWAP_DATADESC();
  1094. inline const char * pszName( void ) const { return name; }
  1095. char name[64];
  1096. int type;
  1097. float boundingradius;
  1098. int nummeshes;
  1099. int meshindex;
  1100. inline mstudiomesh_t *pMesh( int i ) const { return (mstudiomesh_t *)(((byte *)this) + meshindex) + i; };
  1101. // cache purposes
  1102. int numvertices; // number of unique vertices/normals/texcoords
  1103. int vertexindex; // vertex Vector
  1104. int tangentsindex; // tangents Vector
  1105. // These functions are defined in application-specific code:
  1106. const vertexFileHeader_t *CacheVertexData( void *pModelData );
  1107. // Access thin/fat mesh vertex data (only one will return a non-NULL result)
  1108. const mstudio_modelvertexdata_t *GetVertexData( void *pModelData = NULL );
  1109. const thinModelVertices_t *GetThinVertexData( void *pModelData = NULL );
  1110. int numattachments;
  1111. int attachmentindex;
  1112. int numeyeballs;
  1113. int eyeballindex;
  1114. inline mstudioeyeball_t *pEyeball( int i ) { return (mstudioeyeball_t *)(((byte *)this) + eyeballindex) + i; };
  1115. mstudio_modelvertexdata_t vertexdata;
  1116. int unused[8]; // remove as appropriate
  1117. };
  1118. inline bool mstudio_modelvertexdata_t::HasTangentData( void ) const
  1119. {
  1120. return (pTangentData != NULL);
  1121. }
  1122. inline int mstudio_modelvertexdata_t::GetGlobalVertexIndex( int i ) const
  1123. {
  1124. mstudiomodel_t *modelptr = (mstudiomodel_t *)((byte *)this - offsetof(mstudiomodel_t, vertexdata));
  1125. Assert( ( modelptr->vertexindex % sizeof( mstudiovertex_t ) ) == 0 );
  1126. return ( i + ( modelptr->vertexindex / sizeof( mstudiovertex_t ) ) );
  1127. }
  1128. inline int mstudio_modelvertexdata_t::GetGlobalTangentIndex( int i ) const
  1129. {
  1130. mstudiomodel_t *modelptr = (mstudiomodel_t *)((byte *)this - offsetof(mstudiomodel_t, vertexdata));
  1131. Assert( ( modelptr->tangentsindex % sizeof( Vector4D ) ) == 0 );
  1132. return ( i + ( modelptr->tangentsindex / sizeof( Vector4D ) ) );
  1133. }
  1134. inline mstudiovertex_t *mstudio_modelvertexdata_t::Vertex( int i ) const
  1135. {
  1136. return (mstudiovertex_t *)pVertexData + GetGlobalVertexIndex( i );
  1137. }
  1138. inline Vector *mstudio_modelvertexdata_t::Position( int i ) const
  1139. {
  1140. return &Vertex(i)->m_vecPosition;
  1141. }
  1142. inline Vector *mstudio_modelvertexdata_t::Normal( int i ) const
  1143. {
  1144. return &Vertex(i)->m_vecNormal;
  1145. }
  1146. inline Vector4D *mstudio_modelvertexdata_t::TangentS( int i ) const
  1147. {
  1148. // NOTE: The tangents vector is 16-bytes in a separate array
  1149. // because it only exists on the high end, and if I leave it out
  1150. // of the mstudiovertex_t, the vertex is 64-bytes (good for low end)
  1151. return (Vector4D *)pTangentData + GetGlobalTangentIndex( i );
  1152. }
  1153. inline Vector2D *mstudio_modelvertexdata_t::Texcoord( int i ) const
  1154. {
  1155. return &Vertex(i)->m_vecTexCoord;
  1156. }
  1157. inline mstudioboneweight_t *mstudio_modelvertexdata_t::BoneWeights( int i ) const
  1158. {
  1159. return &Vertex(i)->m_BoneWeights;
  1160. }
  1161. inline mstudiomodel_t *mstudiomesh_t::pModel() const
  1162. {
  1163. return (mstudiomodel_t *)(((byte *)this) + modelindex);
  1164. }
  1165. inline bool mstudio_meshvertexdata_t::HasTangentData( void ) const
  1166. {
  1167. return modelvertexdata->HasTangentData();
  1168. }
  1169. inline const mstudio_meshvertexdata_t *mstudiomesh_t::GetVertexData( void *pModelData )
  1170. {
  1171. // get this mesh's model's vertex data (allow for mstudiomodel_t::GetVertexData
  1172. // returning NULL if the data has been converted to 'thin' vertices)
  1173. this->pModel()->GetVertexData( pModelData );
  1174. vertexdata.modelvertexdata = &( this->pModel()->vertexdata );
  1175. if ( !vertexdata.modelvertexdata->pVertexData )
  1176. return NULL;
  1177. return &vertexdata;
  1178. }
  1179. inline const thinModelVertices_t * mstudiomesh_t::GetThinVertexData( void *pModelData )
  1180. {
  1181. // get this mesh's model's thin vertex data
  1182. return this->pModel()->GetThinVertexData( pModelData );
  1183. }
  1184. inline int mstudio_meshvertexdata_t::GetModelVertexIndex( int i ) const
  1185. {
  1186. mstudiomesh_t *meshptr = (mstudiomesh_t *)((byte *)this - offsetof(mstudiomesh_t,vertexdata));
  1187. return meshptr->vertexoffset + i;
  1188. }
  1189. inline int mstudio_meshvertexdata_t::GetGlobalVertexIndex( int i ) const
  1190. {
  1191. return modelvertexdata->GetGlobalVertexIndex( GetModelVertexIndex( i ) );
  1192. }
  1193. inline Vector *mstudio_meshvertexdata_t::Position( int i ) const
  1194. {
  1195. return modelvertexdata->Position( GetModelVertexIndex( i ) );
  1196. };
  1197. inline Vector *mstudio_meshvertexdata_t::Normal( int i ) const
  1198. {
  1199. return modelvertexdata->Normal( GetModelVertexIndex( i ) );
  1200. };
  1201. inline Vector4D *mstudio_meshvertexdata_t::TangentS( int i ) const
  1202. {
  1203. return modelvertexdata->TangentS( GetModelVertexIndex( i ) );
  1204. }
  1205. inline Vector2D *mstudio_meshvertexdata_t::Texcoord( int i ) const
  1206. {
  1207. return modelvertexdata->Texcoord( GetModelVertexIndex( i ) );
  1208. };
  1209. inline mstudioboneweight_t *mstudio_meshvertexdata_t::BoneWeights( int i ) const
  1210. {
  1211. return modelvertexdata->BoneWeights( GetModelVertexIndex( i ) );
  1212. };
  1213. inline mstudiovertex_t *mstudio_meshvertexdata_t::Vertex( int i ) const
  1214. {
  1215. return modelvertexdata->Vertex( GetModelVertexIndex( i ) );
  1216. }
  1217. // a group of studio model data
  1218. enum studiomeshgroupflags_t
  1219. {
  1220. MESHGROUP_IS_FLEXED = 0x1,
  1221. MESHGROUP_IS_HWSKINNED = 0x2,
  1222. MESHGROUP_IS_DELTA_FLEXED = 0x4
  1223. };
  1224. // ----------------------------------------------------------
  1225. // runtime stuff
  1226. // ----------------------------------------------------------
  1227. struct studiomeshgroup_t
  1228. {
  1229. IMesh *m_pMesh;
  1230. int m_NumStrips;
  1231. int m_Flags; // see studiomeshgroupflags_t
  1232. OptimizedModel::StripHeader_t *m_pStripData;
  1233. unsigned short *m_pGroupIndexToMeshIndex;
  1234. int m_NumVertices;
  1235. int *m_pUniqueTris; // for performance measurements
  1236. unsigned short *m_pIndices;
  1237. bool m_MeshNeedsRestore;
  1238. short m_ColorMeshID;
  1239. IMorph *m_pMorph;
  1240. inline unsigned short MeshIndex( int i ) const { return m_pGroupIndexToMeshIndex[m_pIndices[i]]; }
  1241. };
  1242. // studio model data
  1243. struct studiomeshdata_t
  1244. {
  1245. int m_NumGroup;
  1246. studiomeshgroup_t* m_pMeshGroup;
  1247. };
  1248. struct studioloddata_t
  1249. {
  1250. // not needed - this is really the same as studiohwdata_t.m_NumStudioMeshes
  1251. //int m_NumMeshes;
  1252. studiomeshdata_t *m_pMeshData; // there are studiohwdata_t.m_NumStudioMeshes of these.
  1253. float m_SwitchPoint;
  1254. // one of these for each lod since we can switch to simpler materials on lower lods.
  1255. int numMaterials;
  1256. IMaterial **ppMaterials; /* will have studiohdr_t.numtextures elements allocated */
  1257. // hack - this needs to go away.
  1258. int *pMaterialFlags; /* will have studiohdr_t.numtextures elements allocated */
  1259. // For decals on hardware morphing, we must actually do hardware skinning
  1260. // For this to work, we have to hope that the total # of bones used by
  1261. // hw flexed verts is < than the max possible for the dx level we're running under
  1262. int *m_pHWMorphDecalBoneRemap;
  1263. int m_nDecalBoneCount;
  1264. };
  1265. struct studiohwdata_t
  1266. {
  1267. int m_RootLOD; // calced and clamped, nonzero for lod culling
  1268. int m_NumLODs;
  1269. studioloddata_t *m_pLODs;
  1270. int m_NumStudioMeshes;
  1271. inline float LODMetric( float unitSphereSize ) const { return ( unitSphereSize != 0.0f ) ? (100.0f / unitSphereSize) : 0.0f; }
  1272. inline int GetLODForMetric( float lodMetric ) const
  1273. {
  1274. if ( !m_NumLODs )
  1275. return 0;
  1276. // shadow lod is specified on the last lod with a negative switch
  1277. // never consider shadow lod as viable candidate
  1278. int numLODs = (m_pLODs[m_NumLODs-1].m_SwitchPoint < 0.0f) ? m_NumLODs-1 : m_NumLODs;
  1279. for ( int i = m_RootLOD; i < numLODs-1; i++ )
  1280. {
  1281. if ( m_pLODs[i+1].m_SwitchPoint > lodMetric )
  1282. return i;
  1283. }
  1284. return numLODs-1;
  1285. }
  1286. };
  1287. // ----------------------------------------------------------
  1288. // ----------------------------------------------------------
  1289. // body part index
  1290. struct mstudiobodyparts_t
  1291. {
  1292. DECLARE_BYTESWAP_DATADESC();
  1293. int sznameindex;
  1294. inline char * const pszName( void ) const { return ((char *)this) + sznameindex; }
  1295. int nummodels;
  1296. int base;
  1297. int modelindex; // index into models array
  1298. inline mstudiomodel_t *pModel( int i ) const { return (mstudiomodel_t *)(((byte *)this) + modelindex) + i; };
  1299. };
  1300. struct mstudiomouth_t
  1301. {
  1302. DECLARE_BYTESWAP_DATADESC();
  1303. int bone;
  1304. Vector forward;
  1305. int flexdesc;
  1306. mstudiomouth_t(){}
  1307. private:
  1308. // No copy constructors allowed
  1309. mstudiomouth_t(const mstudiomouth_t& vOther);
  1310. };
  1311. struct mstudiohitboxset_t
  1312. {
  1313. DECLARE_BYTESWAP_DATADESC();
  1314. int sznameindex;
  1315. inline char * const pszName( void ) const { return ((char *)this) + sznameindex; }
  1316. int numhitboxes;
  1317. int hitboxindex;
  1318. inline mstudiobbox_t *pHitbox( int i ) const { return (mstudiobbox_t *)(((byte *)this) + hitboxindex) + i; };
  1319. };
  1320. //-----------------------------------------------------------------------------
  1321. // Src bone transforms are transformations that will convert .dmx or .smd-based animations into .mdl-based animations
  1322. // NOTE: The operation you should apply is: pretransform * bone transform * posttransform
  1323. //-----------------------------------------------------------------------------
  1324. struct mstudiosrcbonetransform_t
  1325. {
  1326. DECLARE_BYTESWAP_DATADESC();
  1327. int sznameindex;
  1328. inline const char *pszName( void ) const { return ((char *)this) + sznameindex; }
  1329. matrix3x4_t pretransform;
  1330. matrix3x4_t posttransform;
  1331. };
  1332. // ----------------------------------------------------------
  1333. // Purpose: Load time results on model compositing
  1334. // ----------------------------------------------------------
  1335. class virtualgroup_t
  1336. {
  1337. public:
  1338. virtualgroup_t( void ) { cache = NULL; };
  1339. // tool dependant. In engine this is a model_t, in tool it's a direct pointer
  1340. void *cache;
  1341. // converts cache entry into a usable studiohdr_t *
  1342. const studiohdr_t *GetStudioHdr( void ) const;
  1343. CUtlVector< int > boneMap; // maps global bone to local bone
  1344. CUtlVector< int > masterBone; // maps local bone to global bone
  1345. CUtlVector< int > masterSeq; // maps local sequence to master sequence
  1346. CUtlVector< int > masterAnim; // maps local animation to master animation
  1347. CUtlVector< int > masterAttachment; // maps local attachment to global
  1348. CUtlVector< int > masterPose; // maps local pose parameter to global
  1349. CUtlVector< int > masterNode; // maps local transition nodes to global
  1350. };
  1351. struct virtualsequence_t
  1352. {
  1353. #ifdef _XBOX
  1354. short flags;
  1355. short activity;
  1356. short group;
  1357. short index;
  1358. #else
  1359. int flags;
  1360. int activity;
  1361. int group;
  1362. int index;
  1363. #endif
  1364. };
  1365. struct virtualgeneric_t
  1366. {
  1367. #ifdef _XBOX
  1368. short group;
  1369. short index;
  1370. #else
  1371. int group;
  1372. int index;
  1373. #endif
  1374. };
  1375. struct virtualmodel_t
  1376. {
  1377. void AppendSequences( int group, const studiohdr_t *pStudioHdr );
  1378. void AppendAnimations( int group, const studiohdr_t *pStudioHdr );
  1379. void AppendAttachments( int ground, const studiohdr_t *pStudioHdr );
  1380. void AppendPoseParameters( int group, const studiohdr_t *pStudioHdr );
  1381. void AppendBonemap( int group, const studiohdr_t *pStudioHdr );
  1382. void AppendNodes( int group, const studiohdr_t *pStudioHdr );
  1383. void AppendTransitions( int group, const studiohdr_t *pStudioHdr );
  1384. void AppendIKLocks( int group, const studiohdr_t *pStudioHdr );
  1385. void AppendModels( int group, const studiohdr_t *pStudioHdr );
  1386. void UpdateAutoplaySequences( const studiohdr_t *pStudioHdr );
  1387. virtualgroup_t *pAnimGroup( int animation ) { return &m_group[ m_anim[ animation ].group ]; } // Note: user must manage mutex for this
  1388. virtualgroup_t *pSeqGroup( int sequence )
  1389. {
  1390. // Check for out of range access that is causing crashes on some servers.
  1391. // Perhaps caused by sourcemod bugs. Typical sequence in these cases is ~292
  1392. // when the count is 234. Using unsigned math allows for free range
  1393. // checking against zero.
  1394. if ( (unsigned)sequence >= (unsigned)m_seq.Count() )
  1395. {
  1396. Assert( 0 );
  1397. return 0;
  1398. }
  1399. return &m_group[ m_seq[ sequence ].group ];
  1400. } // Note: user must manage mutex for this
  1401. CThreadFastMutex m_Lock;
  1402. CUtlVector< virtualsequence_t > m_seq;
  1403. CUtlVector< virtualgeneric_t > m_anim;
  1404. CUtlVector< virtualgeneric_t > m_attachment;
  1405. CUtlVector< virtualgeneric_t > m_pose;
  1406. CUtlVector< virtualgroup_t > m_group;
  1407. CUtlVector< virtualgeneric_t > m_node;
  1408. CUtlVector< virtualgeneric_t > m_iklock;
  1409. CUtlVector< unsigned short > m_autoplaySequences;
  1410. };
  1411. // 'thin' vertex data, used to do model decals (see Studio_CreateThinVertexes())
  1412. struct thinModelVertices_t
  1413. {
  1414. void Init( int numBoneInfluences, Vector *positions, unsigned short *normals, float *boneWeights, char *boneIndices )
  1415. {
  1416. Assert( positions != NULL );
  1417. Assert( normals != NULL );
  1418. Assert( ( numBoneInfluences >= 0 ) && ( numBoneInfluences <= 3 ) );
  1419. Assert( numBoneInfluences > 0 ? !!boneIndices : !boneIndices );
  1420. Assert( numBoneInfluences > 1 ? !!boneWeights : !boneWeights );
  1421. m_numBoneInfluences = numBoneInfluences;
  1422. m_vecPositions = positions;
  1423. m_vecNormals = normals;
  1424. m_boneWeights = boneWeights;
  1425. m_boneIndices = boneIndices;
  1426. }
  1427. void SetPosition( int vertIndex, const Vector & position )
  1428. {
  1429. Assert( m_vecPositions );
  1430. m_vecPositions[ vertIndex ] = position;
  1431. }
  1432. void SetNormal( int vertIndex, const Vector & normal )
  1433. {
  1434. Assert( m_vecNormals );
  1435. unsigned int packedNormal;
  1436. PackNormal_UBYTE4( normal.x, normal.y, normal.z, &packedNormal );
  1437. m_vecNormals[ vertIndex ] = (unsigned short)( 0x0000FFFF & packedNormal );
  1438. }
  1439. void SetBoneWeights( int vertIndex, const mstudioboneweight_t & boneWeights )
  1440. {
  1441. Assert( ( m_numBoneInfluences >= 1 ) && ( m_numBoneInfluences <= 3 ) );
  1442. Assert( ( boneWeights.numbones >= 1 ) && ( boneWeights.numbones <= m_numBoneInfluences ) );
  1443. int numStoredWeights = max( 0, ( m_numBoneInfluences - 1 ) );
  1444. float *pBaseWeight = m_boneWeights + vertIndex*numStoredWeights;
  1445. char *pBaseIndex = m_boneIndices + vertIndex*m_numBoneInfluences;
  1446. for ( int i = 0; i < m_numBoneInfluences; i++ )
  1447. {
  1448. pBaseIndex[i] = boneWeights.bone[i];
  1449. }
  1450. for ( int i = 0; i < numStoredWeights; i++ )
  1451. {
  1452. pBaseWeight[i] = boneWeights.weight[i];
  1453. }
  1454. }
  1455. void GetMeshPosition( mstudiomesh_t *pMesh, int meshIndex, Vector *pPosition ) const
  1456. {
  1457. Assert( pMesh );
  1458. GetPosition( pMesh->vertexdata.GetGlobalVertexIndex( meshIndex ), pPosition );
  1459. }
  1460. void GetMeshNormal( mstudiomesh_t *pMesh, int meshIndex, Vector *pNormal ) const
  1461. {
  1462. Assert( pMesh );
  1463. GetNormal( pMesh->vertexdata.GetGlobalVertexIndex( meshIndex ), pNormal );
  1464. }
  1465. void GetMeshBoneWeights( mstudiomesh_t *pMesh, int meshIndex, mstudioboneweight_t *pBoneWeights ) const
  1466. {
  1467. Assert( pMesh );
  1468. GetBoneWeights( pMesh->vertexdata.GetGlobalVertexIndex( meshIndex ), pBoneWeights );
  1469. }
  1470. void GetModelPosition( mstudiomodel_t *pModel, int modelIndex, Vector *pPosition ) const
  1471. {
  1472. Assert( pModel );
  1473. GetPosition( pModel->vertexdata.GetGlobalVertexIndex( modelIndex ), pPosition );
  1474. }
  1475. void GetModelNormal( mstudiomodel_t *pModel, int modelIndex, Vector *pNormal ) const
  1476. {
  1477. Assert( pModel );
  1478. GetNormal( pModel->vertexdata.GetGlobalVertexIndex( modelIndex ), pNormal );
  1479. }
  1480. void GetModelBoneWeights( mstudiomodel_t *pModel, int modelIndex, mstudioboneweight_t *pBoneWeights ) const
  1481. {
  1482. Assert( pModel );
  1483. GetBoneWeights( pModel->vertexdata.GetGlobalVertexIndex( modelIndex ), pBoneWeights );
  1484. }
  1485. private:
  1486. void GetPosition( int vertIndex, Vector *pPosition ) const
  1487. {
  1488. Assert( pPosition );
  1489. Assert( m_vecPositions );
  1490. *pPosition = m_vecPositions[ vertIndex ];
  1491. }
  1492. void GetNormal( int vertIndex, Vector *pNormal ) const
  1493. {
  1494. Assert( pNormal );
  1495. Assert( m_vecNormals );
  1496. unsigned int packedNormal = 0x0000FFFF & m_vecNormals[ vertIndex ];
  1497. UnpackNormal_UBYTE4( &packedNormal, pNormal->Base() );
  1498. }
  1499. void GetBoneWeights( int vertIndex, mstudioboneweight_t *pBoneWeights ) const
  1500. {
  1501. Assert( pBoneWeights );
  1502. Assert( ( m_numBoneInfluences <= 1 ) || ( m_boneWeights != NULL ) );
  1503. Assert( ( m_numBoneInfluences <= 0 ) || ( m_boneIndices != NULL ) );
  1504. int numStoredWeights = max( 0, ( m_numBoneInfluences - 1 ) );
  1505. float *pBaseWeight = m_boneWeights + vertIndex*numStoredWeights;
  1506. char *pBaseIndex = m_boneIndices + vertIndex*m_numBoneInfluences;
  1507. float sum = 0.0f;
  1508. for (int i = 0;i < MAX_NUM_BONES_PER_VERT;i++)
  1509. {
  1510. if ( i < ( m_numBoneInfluences - 1 ) )
  1511. pBoneWeights->weight[i] = pBaseWeight[i];
  1512. else
  1513. pBoneWeights->weight[i] = 1.0f - sum;
  1514. sum += pBoneWeights->weight[i];
  1515. pBoneWeights->bone[i] = ( i < m_numBoneInfluences ) ? pBaseIndex[i] : 0;
  1516. }
  1517. // Treat 'zero weights' as '100% binding to bone zero':
  1518. pBoneWeights->numbones = m_numBoneInfluences ? m_numBoneInfluences : 1;
  1519. }
  1520. int m_numBoneInfluences;// Number of bone influences per vertex, N
  1521. float *m_boneWeights; // This array stores (N-1) weights per vertex (unless N is zero)
  1522. char *m_boneIndices; // This array stores N indices per vertex
  1523. Vector *m_vecPositions;
  1524. unsigned short *m_vecNormals; // Normals are compressed into 16 bits apiece (see PackNormal_UBYTE4() )
  1525. };
  1526. // ----------------------------------------------------------
  1527. // Studio Model Vertex Data File
  1528. // Position independent flat data for cache manager
  1529. // ----------------------------------------------------------
  1530. // little-endian "IDSV"
  1531. #define MODEL_VERTEX_FILE_ID (('V'<<24)+('S'<<16)+('D'<<8)+'I')
  1532. #define MODEL_VERTEX_FILE_VERSION 4
  1533. // this id (IDCV) is used once the vertex data has been compressed (see CMDLCache::CreateThinVertexes)
  1534. #define MODEL_VERTEX_FILE_THIN_ID (('V'<<24)+('C'<<16)+('D'<<8)+'I')
  1535. struct vertexFileHeader_t
  1536. {
  1537. DECLARE_BYTESWAP_DATADESC();
  1538. int id; // MODEL_VERTEX_FILE_ID
  1539. int version; // MODEL_VERTEX_FILE_VERSION
  1540. int checksum; // same as studiohdr_t, ensures sync
  1541. int numLODs; // num of valid lods
  1542. int numLODVertexes[MAX_NUM_LODS]; // num verts for desired root lod
  1543. int numFixups; // num of vertexFileFixup_t
  1544. int fixupTableStart; // offset from base to fixup table
  1545. int vertexDataStart; // offset from base to vertex block
  1546. int tangentDataStart; // offset from base to tangent block
  1547. public:
  1548. // Accessor to fat vertex data
  1549. const mstudiovertex_t *GetVertexData() const
  1550. {
  1551. if ( ( id == MODEL_VERTEX_FILE_ID ) && ( vertexDataStart != 0 ) )
  1552. return ( mstudiovertex_t * ) ( vertexDataStart + (byte *)this );
  1553. else
  1554. return NULL;
  1555. }
  1556. // Accessor to (fat) tangent vertex data (tangents aren't stored in compressed data)
  1557. const Vector4D *GetTangentData() const
  1558. {
  1559. if ( ( id == MODEL_VERTEX_FILE_ID ) && ( tangentDataStart != 0 ) )
  1560. return ( Vector4D * ) ( tangentDataStart + (byte *)this );
  1561. else
  1562. return NULL;
  1563. }
  1564. // Accessor to thin vertex data
  1565. const thinModelVertices_t *GetThinVertexData() const
  1566. {
  1567. if ( ( id == MODEL_VERTEX_FILE_THIN_ID ) && ( vertexDataStart != 0 ) )
  1568. return ( thinModelVertices_t * ) ( vertexDataStart + (byte *)this );
  1569. else
  1570. return NULL;
  1571. }
  1572. };
  1573. // model vertex data accessor (defined here so vertexFileHeader_t can be used)
  1574. inline const mstudio_modelvertexdata_t * mstudiomodel_t::GetVertexData( void *pModelData )
  1575. {
  1576. const vertexFileHeader_t * pVertexHdr = CacheVertexData( pModelData );
  1577. if ( !pVertexHdr )
  1578. {
  1579. vertexdata.pVertexData = NULL;
  1580. vertexdata.pTangentData = NULL;
  1581. return NULL;
  1582. }
  1583. vertexdata.pVertexData = pVertexHdr->GetVertexData();
  1584. vertexdata.pTangentData = pVertexHdr->GetTangentData();
  1585. if ( !vertexdata.pVertexData )
  1586. return NULL;
  1587. return &vertexdata;
  1588. }
  1589. // model thin vertex data accessor (defined here so vertexFileHeader_t can be used)
  1590. inline const thinModelVertices_t * mstudiomodel_t::GetThinVertexData( void *pModelData )
  1591. {
  1592. const vertexFileHeader_t * pVertexHdr = CacheVertexData( pModelData );
  1593. if ( !pVertexHdr )
  1594. return NULL;
  1595. return pVertexHdr->GetThinVertexData();
  1596. }
  1597. // apply sequentially to lod sorted vertex and tangent pools to re-establish mesh order
  1598. struct vertexFileFixup_t
  1599. {
  1600. DECLARE_BYTESWAP_DATADESC();
  1601. int lod; // used to skip culled root lod
  1602. int sourceVertexID; // absolute index from start of vertex/tangent blocks
  1603. int numVertexes;
  1604. };
  1605. // This flag is set if no hitbox information was specified
  1606. #define STUDIOHDR_FLAGS_AUTOGENERATED_HITBOX 0x00000001
  1607. // NOTE: This flag is set at loadtime, not mdl build time so that we don't have to rebuild
  1608. // models when we change materials.
  1609. #define STUDIOHDR_FLAGS_USES_ENV_CUBEMAP 0x00000002
  1610. // Use this when there are translucent parts to the model but we're not going to sort it
  1611. #define STUDIOHDR_FLAGS_FORCE_OPAQUE 0x00000004
  1612. // Use this when we want to render the opaque parts during the opaque pass
  1613. // and the translucent parts during the translucent pass
  1614. #define STUDIOHDR_FLAGS_TRANSLUCENT_TWOPASS 0x00000008
  1615. // This is set any time the .qc files has $staticprop in it
  1616. // Means there's no bones and no transforms
  1617. #define STUDIOHDR_FLAGS_STATIC_PROP 0x00000010
  1618. // NOTE: This flag is set at loadtime, not mdl build time so that we don't have to rebuild
  1619. // models when we change materials.
  1620. #define STUDIOHDR_FLAGS_USES_FB_TEXTURE 0x00000020
  1621. // This flag is set by studiomdl.exe if a separate "$shadowlod" entry was present
  1622. // for the .mdl (the shadow lod is the last entry in the lod list if present)
  1623. #define STUDIOHDR_FLAGS_HASSHADOWLOD 0x00000040
  1624. // NOTE: This flag is set at loadtime, not mdl build time so that we don't have to rebuild
  1625. // models when we change materials.
  1626. #define STUDIOHDR_FLAGS_USES_BUMPMAPPING 0x00000080
  1627. // NOTE: This flag is set when we should use the actual materials on the shadow LOD
  1628. // instead of overriding them with the default one (necessary for translucent shadows)
  1629. #define STUDIOHDR_FLAGS_USE_SHADOWLOD_MATERIALS 0x00000100
  1630. // NOTE: This flag is set when we should use the actual materials on the shadow LOD
  1631. // instead of overriding them with the default one (necessary for translucent shadows)
  1632. #define STUDIOHDR_FLAGS_OBSOLETE 0x00000200
  1633. #define STUDIOHDR_FLAGS_UNUSED 0x00000400
  1634. // NOTE: This flag is set at mdl build time
  1635. #define STUDIOHDR_FLAGS_NO_FORCED_FADE 0x00000800
  1636. // NOTE: The npc will lengthen the viseme check to always include two phonemes
  1637. #define STUDIOHDR_FLAGS_FORCE_PHONEME_CROSSFADE 0x00001000
  1638. // This flag is set when the .qc has $constantdirectionallight in it
  1639. // If set, we use constantdirectionallightdot to calculate light intensity
  1640. // rather than the normal directional dot product
  1641. // only valid if STUDIOHDR_FLAGS_STATIC_PROP is also set
  1642. #define STUDIOHDR_FLAGS_CONSTANT_DIRECTIONAL_LIGHT_DOT 0x00002000
  1643. // Flag to mark delta flexes as already converted from disk format to memory format
  1644. #define STUDIOHDR_FLAGS_FLEXES_CONVERTED 0x00004000
  1645. // Indicates the studiomdl was built in preview mode
  1646. #define STUDIOHDR_FLAGS_BUILT_IN_PREVIEW_MODE 0x00008000
  1647. // Ambient boost (runtime flag)
  1648. #define STUDIOHDR_FLAGS_AMBIENT_BOOST 0x00010000
  1649. // Don't cast shadows from this model (useful on first-person models)
  1650. #define STUDIOHDR_FLAGS_DO_NOT_CAST_SHADOWS 0x00020000
  1651. // alpha textures should cast shadows in vrad on this model (ONLY prop_static!)
  1652. #define STUDIOHDR_FLAGS_CAST_TEXTURE_SHADOWS 0x00040000
  1653. // flagged on load to indicate no animation events on this model
  1654. #define STUDIOHDR_FLAGS_VERT_ANIM_FIXED_POINT_SCALE 0x00200000
  1655. // NOTE! Next time we up the .mdl file format, remove studiohdr2_t
  1656. // and insert all fields in this structure into studiohdr_t.
  1657. struct studiohdr2_t
  1658. {
  1659. // NOTE: For forward compat, make sure any methods in this struct
  1660. // are also available in studiohdr_t so no leaf code ever directly references
  1661. // a studiohdr2_t structure
  1662. DECLARE_BYTESWAP_DATADESC();
  1663. int numsrcbonetransform;
  1664. int srcbonetransformindex;
  1665. int illumpositionattachmentindex;
  1666. inline int IllumPositionAttachmentIndex() const { return illumpositionattachmentindex; }
  1667. float flMaxEyeDeflection;
  1668. inline float MaxEyeDeflection() const { return flMaxEyeDeflection != 0.0f ? flMaxEyeDeflection : 0.866f; } // default to cos(30) if not set
  1669. int linearboneindex;
  1670. inline mstudiolinearbone_t *pLinearBones() const { return (linearboneindex) ? (mstudiolinearbone_t *)(((byte *)this) + linearboneindex) : NULL; }
  1671. int sznameindex;
  1672. inline char *pszName() { return (sznameindex) ? (char *)(((byte *)this) + sznameindex ) : NULL; }
  1673. int m_nBoneFlexDriverCount;
  1674. int m_nBoneFlexDriverIndex;
  1675. inline mstudioboneflexdriver_t *pBoneFlexDriver( int i ) const { Assert( i >= 0 && i < m_nBoneFlexDriverCount ); return (mstudioboneflexdriver_t *)(((byte *)this) + m_nBoneFlexDriverIndex) + i; }
  1676. int reserved[56];
  1677. };
  1678. struct studiohdr_t
  1679. {
  1680. DECLARE_BYTESWAP_DATADESC();
  1681. int id;
  1682. int version;
  1683. int checksum; // this has to be the same in the phy and vtx files to load!
  1684. inline const char * pszName( void ) const { if (studiohdr2index && pStudioHdr2()->pszName()) return pStudioHdr2()->pszName(); else return name; }
  1685. char name[64];
  1686. int length;
  1687. Vector eyeposition; // ideal eye position
  1688. Vector illumposition; // illumination center
  1689. Vector hull_min; // ideal movement hull size
  1690. Vector hull_max;
  1691. Vector view_bbmin; // clipping bounding box
  1692. Vector view_bbmax;
  1693. int flags;
  1694. int numbones; // bones
  1695. int boneindex;
  1696. inline mstudiobone_t *pBone( int i ) const { Assert( i >= 0 && i < numbones); return (mstudiobone_t *)(((byte *)this) + boneindex) + i; };
  1697. int RemapSeqBone( int iSequence, int iLocalBone ) const; // maps local sequence bone to global bone
  1698. int RemapAnimBone( int iAnim, int iLocalBone ) const; // maps local animations bone to global bone
  1699. int numbonecontrollers; // bone controllers
  1700. int bonecontrollerindex;
  1701. inline mstudiobonecontroller_t *pBonecontroller( int i ) const { Assert( i >= 0 && i < numbonecontrollers); return (mstudiobonecontroller_t *)(((byte *)this) + bonecontrollerindex) + i; };
  1702. int numhitboxsets;
  1703. int hitboxsetindex;
  1704. // Look up hitbox set by index
  1705. mstudiohitboxset_t *pHitboxSet( int i ) const
  1706. {
  1707. Assert( i >= 0 && i < numhitboxsets);
  1708. return (mstudiohitboxset_t *)(((byte *)this) + hitboxsetindex ) + i;
  1709. };
  1710. // Calls through to hitbox to determine size of specified set
  1711. inline mstudiobbox_t *pHitbox( int i, int set ) const
  1712. {
  1713. mstudiohitboxset_t const *s = pHitboxSet( set );
  1714. if ( !s )
  1715. return NULL;
  1716. return s->pHitbox( i );
  1717. };
  1718. // Calls through to set to get hitbox count for set
  1719. inline int iHitboxCount( int set ) const
  1720. {
  1721. mstudiohitboxset_t const *s = pHitboxSet( set );
  1722. if ( !s )
  1723. return 0;
  1724. return s->numhitboxes;
  1725. };
  1726. // file local animations? and sequences
  1727. //private:
  1728. int numlocalanim; // animations/poses
  1729. int localanimindex; // animation descriptions
  1730. inline mstudioanimdesc_t *pLocalAnimdesc( int i ) const { if (i < 0 || i >= numlocalanim) i = 0; return (mstudioanimdesc_t *)(((byte *)this) + localanimindex) + i; };
  1731. int numlocalseq; // sequences
  1732. int localseqindex;
  1733. inline mstudioseqdesc_t *pLocalSeqdesc( int i ) const { if (i < 0 || i >= numlocalseq) i = 0; return (mstudioseqdesc_t *)(((byte *)this) + localseqindex) + i; };
  1734. //public:
  1735. bool SequencesAvailable() const;
  1736. int GetNumSeq() const;
  1737. mstudioanimdesc_t &pAnimdesc( int i ) const;
  1738. mstudioseqdesc_t &pSeqdesc( int i ) const;
  1739. int iRelativeAnim( int baseseq, int relanim ) const; // maps seq local anim reference to global anim index
  1740. int iRelativeSeq( int baseseq, int relseq ) const; // maps seq local seq reference to global seq index
  1741. //private:
  1742. mutable int activitylistversion; // initialization flag - have the sequences been indexed?
  1743. mutable int eventsindexed;
  1744. //public:
  1745. int GetSequenceActivity( int iSequence );
  1746. void SetSequenceActivity( int iSequence, int iActivity );
  1747. int GetActivityListVersion( void );
  1748. void SetActivityListVersion( int version ) const;
  1749. int GetEventListVersion( void );
  1750. void SetEventListVersion( int version );
  1751. // raw textures
  1752. int numtextures;
  1753. int textureindex;
  1754. inline mstudiotexture_t *pTexture( int i ) const { Assert( i >= 0 && i < numtextures ); return (mstudiotexture_t *)(((byte *)this) + textureindex) + i; };
  1755. // raw textures search paths
  1756. int numcdtextures;
  1757. int cdtextureindex;
  1758. inline char *pCdtexture( int i ) const { return (((char *)this) + *((int *)(((byte *)this) + cdtextureindex) + i)); };
  1759. // replaceable textures tables
  1760. int numskinref;
  1761. int numskinfamilies;
  1762. int skinindex;
  1763. inline short *pSkinref( int i ) const { return (short *)(((byte *)this) + skinindex) + i; };
  1764. int numbodyparts;
  1765. int bodypartindex;
  1766. inline mstudiobodyparts_t *pBodypart( int i ) const { return (mstudiobodyparts_t *)(((byte *)this) + bodypartindex) + i; };
  1767. // queryable attachable points
  1768. //private:
  1769. int numlocalattachments;
  1770. int localattachmentindex;
  1771. inline mstudioattachment_t *pLocalAttachment( int i ) const { Assert( i >= 0 && i < numlocalattachments); return (mstudioattachment_t *)(((byte *)this) + localattachmentindex) + i; };
  1772. //public:
  1773. int GetNumAttachments( void ) const;
  1774. const mstudioattachment_t &pAttachment( int i ) const;
  1775. int GetAttachmentBone( int i );
  1776. // used on my tools in hlmv, not persistant
  1777. void SetAttachmentBone( int iAttachment, int iBone );
  1778. // animation node to animation node transition graph
  1779. //private:
  1780. int numlocalnodes;
  1781. int localnodeindex;
  1782. int localnodenameindex;
  1783. inline char *pszLocalNodeName( int iNode ) const { Assert( iNode >= 0 && iNode < numlocalnodes); return (((char *)this) + *((int *)(((byte *)this) + localnodenameindex) + iNode)); }
  1784. inline byte *pLocalTransition( int i ) const { Assert( i >= 0 && i < (numlocalnodes * numlocalnodes)); return (byte *)(((byte *)this) + localnodeindex) + i; };
  1785. //public:
  1786. int EntryNode( int iSequence );
  1787. int ExitNode( int iSequence );
  1788. char *pszNodeName( int iNode );
  1789. int GetTransition( int iFrom, int iTo ) const;
  1790. int numflexdesc;
  1791. int flexdescindex;
  1792. inline mstudioflexdesc_t *pFlexdesc( int i ) const { Assert( i >= 0 && i < numflexdesc); return (mstudioflexdesc_t *)(((byte *)this) + flexdescindex) + i; };
  1793. int numflexcontrollers;
  1794. int flexcontrollerindex;
  1795. inline mstudioflexcontroller_t *pFlexcontroller( LocalFlexController_t i ) const { Assert( numflexcontrollers == 0 || ( i >= 0 && i < numflexcontrollers ) ); return (mstudioflexcontroller_t *)(((byte *)this) + flexcontrollerindex) + i; };
  1796. int numflexrules;
  1797. int flexruleindex;
  1798. inline mstudioflexrule_t *pFlexRule( int i ) const { Assert( i >= 0 && i < numflexrules); return (mstudioflexrule_t *)(((byte *)this) + flexruleindex) + i; };
  1799. int numikchains;
  1800. int ikchainindex;
  1801. inline mstudioikchain_t *pIKChain( int i ) const { Assert( i >= 0 && i < numikchains); return (mstudioikchain_t *)(((byte *)this) + ikchainindex) + i; };
  1802. int nummouths;
  1803. int mouthindex;
  1804. inline mstudiomouth_t *pMouth( int i ) const { Assert( i >= 0 && i < nummouths); return (mstudiomouth_t *)(((byte *)this) + mouthindex) + i; };
  1805. //private:
  1806. int numlocalposeparameters;
  1807. int localposeparamindex;
  1808. inline mstudioposeparamdesc_t *pLocalPoseParameter( int i ) const { Assert( i >= 0 && i < numlocalposeparameters); return (mstudioposeparamdesc_t *)(((byte *)this) + localposeparamindex) + i; };
  1809. //public:
  1810. int GetNumPoseParameters( void ) const;
  1811. const mstudioposeparamdesc_t &pPoseParameter( int i );
  1812. int GetSharedPoseParameter( int iSequence, int iLocalPose ) const;
  1813. int surfacepropindex;
  1814. inline char * const pszSurfaceProp( void ) const { return ((char *)this) + surfacepropindex; }
  1815. // Key values
  1816. int keyvalueindex;
  1817. int keyvaluesize;
  1818. inline const char * KeyValueText( void ) const { return keyvaluesize != 0 ? ((char *)this) + keyvalueindex : NULL; }
  1819. int numlocalikautoplaylocks;
  1820. int localikautoplaylockindex;
  1821. inline mstudioiklock_t *pLocalIKAutoplayLock( int i ) const { Assert( i >= 0 && i < numlocalikautoplaylocks); return (mstudioiklock_t *)(((byte *)this) + localikautoplaylockindex) + i; };
  1822. int GetNumIKAutoplayLocks( void ) const;
  1823. const mstudioiklock_t &pIKAutoplayLock( int i );
  1824. int CountAutoplaySequences() const;
  1825. int CopyAutoplaySequences( unsigned short *pOut, int outCount ) const;
  1826. int GetAutoplayList( unsigned short **pOut ) const;
  1827. // The collision model mass that jay wanted
  1828. float mass;
  1829. int contents;
  1830. // external animations, models, etc.
  1831. int numincludemodels;
  1832. int includemodelindex;
  1833. inline mstudiomodelgroup_t *pModelGroup( int i ) const { Assert( i >= 0 && i < numincludemodels); return (mstudiomodelgroup_t *)(((byte *)this) + includemodelindex) + i; };
  1834. // implementation specific call to get a named model
  1835. const studiohdr_t *FindModel( void **cache, char const *modelname ) const;
  1836. // implementation specific back pointer to virtual data
  1837. mutable void *virtualModel;
  1838. virtualmodel_t *GetVirtualModel( void ) const;
  1839. // for demand loaded animation blocks
  1840. int szanimblocknameindex;
  1841. inline char * const pszAnimBlockName( void ) const { return ((char *)this) + szanimblocknameindex; }
  1842. int numanimblocks;
  1843. int animblockindex;
  1844. inline mstudioanimblock_t *pAnimBlock( int i ) const { Assert( i > 0 && i < numanimblocks); return (mstudioanimblock_t *)(((byte *)this) + animblockindex) + i; };
  1845. mutable void *animblockModel;
  1846. byte * GetAnimBlock( int i ) const;
  1847. int bonetablebynameindex;
  1848. inline const byte *GetBoneTableSortedByName() const { return (byte *)this + bonetablebynameindex; }
  1849. // used by tools only that don't cache, but persist mdl's peer data
  1850. // engine uses virtualModel to back link to cache pointers
  1851. void *pVertexBase;
  1852. void *pIndexBase;
  1853. // if STUDIOHDR_FLAGS_CONSTANT_DIRECTIONAL_LIGHT_DOT is set,
  1854. // this value is used to calculate directional components of lighting
  1855. // on static props
  1856. byte constdirectionallightdot;
  1857. // set during load of mdl data to track *desired* lod configuration (not actual)
  1858. // the *actual* clamped root lod is found in studiohwdata
  1859. // this is stored here as a global store to ensure the staged loading matches the rendering
  1860. byte rootLOD;
  1861. // set in the mdl data to specify that lod configuration should only allow first numAllowRootLODs
  1862. // to be set as root LOD:
  1863. // numAllowedRootLODs = 0 means no restriction, any lod can be set as root lod.
  1864. // numAllowedRootLODs = N means that lod0 - lod(N-1) can be set as root lod, but not lodN or lower.
  1865. byte numAllowedRootLODs;
  1866. byte unused[1];
  1867. int unused4; // zero out if version < 47
  1868. int numflexcontrollerui;
  1869. int flexcontrolleruiindex;
  1870. mstudioflexcontrollerui_t *pFlexControllerUI( int i ) const { Assert( i >= 0 && i < numflexcontrollerui); return (mstudioflexcontrollerui_t *)(((byte *)this) + flexcontrolleruiindex) + i; }
  1871. float flVertAnimFixedPointScale;
  1872. inline float VertAnimFixedPointScale() const { return ( flags & STUDIOHDR_FLAGS_VERT_ANIM_FIXED_POINT_SCALE ) ? flVertAnimFixedPointScale : 1.0f / 4096.0f; }
  1873. int unused3[1];
  1874. // FIXME: Remove when we up the model version. Move all fields of studiohdr2_t into studiohdr_t.
  1875. int studiohdr2index;
  1876. studiohdr2_t* pStudioHdr2() const { return (studiohdr2_t *)( ( (byte *)this ) + studiohdr2index ); }
  1877. // Src bone transforms are transformations that will convert .dmx or .smd-based animations into .mdl-based animations
  1878. int NumSrcBoneTransforms() const { return studiohdr2index ? pStudioHdr2()->numsrcbonetransform : 0; }
  1879. const mstudiosrcbonetransform_t* SrcBoneTransform( int i ) const { Assert( i >= 0 && i < NumSrcBoneTransforms()); return (mstudiosrcbonetransform_t *)(((byte *)this) + pStudioHdr2()->srcbonetransformindex) + i; }
  1880. inline int IllumPositionAttachmentIndex() const { return studiohdr2index ? pStudioHdr2()->IllumPositionAttachmentIndex() : 0; }
  1881. inline float MaxEyeDeflection() const { return studiohdr2index ? pStudioHdr2()->MaxEyeDeflection() : 0.866f; } // default to cos(30) if not set
  1882. inline mstudiolinearbone_t *pLinearBones() const { return studiohdr2index ? pStudioHdr2()->pLinearBones() : NULL; }
  1883. inline int BoneFlexDriverCount() const { return studiohdr2index ? pStudioHdr2()->m_nBoneFlexDriverCount : 0; }
  1884. inline const mstudioboneflexdriver_t* BoneFlexDriver( int i ) const { Assert( i >= 0 && i < BoneFlexDriverCount() ); return studiohdr2index ? pStudioHdr2()->pBoneFlexDriver( i ) : NULL; }
  1885. // NOTE: No room to add stuff? Up the .mdl file format version
  1886. // [and move all fields in studiohdr2_t into studiohdr_t and kill studiohdr2_t],
  1887. // or add your stuff to studiohdr2_t. See NumSrcBoneTransforms/SrcBoneTransform for the pattern to use.
  1888. int unused2[1];
  1889. studiohdr_t() {}
  1890. private:
  1891. // No copy constructors allowed
  1892. studiohdr_t(const studiohdr_t& vOther);
  1893. friend struct virtualmodel_t;
  1894. };
  1895. //-----------------------------------------------------------------------------
  1896. // Purpose:
  1897. //-----------------------------------------------------------------------------
  1898. class IDataCache;
  1899. class IMDLCache;
  1900. class CStudioHdr
  1901. {
  1902. public:
  1903. CStudioHdr( void );
  1904. CStudioHdr( const studiohdr_t *pStudioHdr, IMDLCache *mdlcache = NULL );
  1905. ~CStudioHdr() { Term(); }
  1906. void Init( const studiohdr_t *pStudioHdr, IMDLCache *mdlcache = NULL );
  1907. void Term();
  1908. public:
  1909. inline bool IsVirtual( void ) { return (m_pVModel != NULL); };
  1910. inline bool IsValid( void ) { return (m_pStudioHdr != NULL); };
  1911. inline bool IsReadyForAccess( void ) const { return (m_pStudioHdr != NULL); };
  1912. inline virtualmodel_t *GetVirtualModel( void ) const { return m_pVModel; };
  1913. inline const studiohdr_t *GetRenderHdr( void ) const { return m_pStudioHdr; };
  1914. const studiohdr_t *pSeqStudioHdr( int sequence );
  1915. const studiohdr_t *pAnimStudioHdr( int animation );
  1916. private:
  1917. mutable const studiohdr_t *m_pStudioHdr;
  1918. mutable virtualmodel_t *m_pVModel;
  1919. const virtualmodel_t * ResetVModel( const virtualmodel_t *pVModel ) const;
  1920. const studiohdr_t *GroupStudioHdr( int group );
  1921. mutable CUtlVector< const studiohdr_t * > m_pStudioHdrCache;
  1922. mutable int m_nFrameUnlockCounter;
  1923. int * m_pFrameUnlockCounter;
  1924. CThreadFastMutex m_FrameUnlockCounterMutex;
  1925. public:
  1926. inline int numbones( void ) const { return m_pStudioHdr->numbones; };
  1927. inline mstudiobone_t *pBone( int i ) const { return m_pStudioHdr->pBone( i ); };
  1928. int RemapAnimBone( int iAnim, int iLocalBone ) const; // maps local animations bone to global bone
  1929. int RemapSeqBone( int iSequence, int iLocalBone ) const; // maps local sequence bone to global bone
  1930. bool SequencesAvailable() const;
  1931. int GetNumSeq( void ) const;
  1932. mstudioanimdesc_t &pAnimdesc( int i );
  1933. mstudioseqdesc_t &pSeqdesc( int iSequence );
  1934. int iRelativeAnim( int baseseq, int relanim ) const; // maps seq local anim reference to global anim index
  1935. int iRelativeSeq( int baseseq, int relseq ) const; // maps seq local seq reference to global seq index
  1936. int GetSequenceActivity( int iSequence );
  1937. void SetSequenceActivity( int iSequence, int iActivity );
  1938. int GetActivityListVersion( void );
  1939. void SetActivityListVersion( int version );
  1940. int GetEventListVersion( void );
  1941. void SetEventListVersion( int version );
  1942. int GetNumAttachments( void ) const;
  1943. const mstudioattachment_t &pAttachment( int i );
  1944. int GetAttachmentBone( int i );
  1945. // used on my tools in hlmv, not persistant
  1946. void SetAttachmentBone( int iAttachment, int iBone );
  1947. int EntryNode( int iSequence );
  1948. int ExitNode( int iSequence );
  1949. char *pszNodeName( int iNode );
  1950. // FIXME: where should this one be?
  1951. int GetTransition( int iFrom, int iTo ) const;
  1952. int GetNumPoseParameters( void ) const;
  1953. const mstudioposeparamdesc_t &pPoseParameter( int i );
  1954. int GetSharedPoseParameter( int iSequence, int iLocalPose ) const;
  1955. int GetNumIKAutoplayLocks( void ) const;
  1956. const mstudioiklock_t &pIKAutoplayLock( int i );
  1957. inline int CountAutoplaySequences() const { return m_pStudioHdr->CountAutoplaySequences(); };
  1958. inline int CopyAutoplaySequences( unsigned short *pOut, int outCount ) const { return m_pStudioHdr->CopyAutoplaySequences( pOut, outCount ); };
  1959. inline int GetAutoplayList( unsigned short **pOut ) const { return m_pStudioHdr->GetAutoplayList( pOut ); };
  1960. inline int GetNumBoneControllers( void ) const { return m_pStudioHdr->numbonecontrollers; };
  1961. inline mstudiobonecontroller_t *pBonecontroller( int i ) const { return m_pStudioHdr->pBonecontroller( i ); };
  1962. inline int numikchains() const { return m_pStudioHdr->numikchains; };
  1963. inline int GetNumIKChains( void ) const { return m_pStudioHdr->numikchains; };
  1964. inline mstudioikchain_t *pIKChain( int i ) const { return m_pStudioHdr->pIKChain( i ); };
  1965. inline int numflexrules() const { return m_pStudioHdr->numflexrules; };
  1966. inline mstudioflexrule_t *pFlexRule( int i ) const { return m_pStudioHdr->pFlexRule( i ); };
  1967. inline int numflexdesc() const{ return m_pStudioHdr->numflexdesc; };
  1968. inline mstudioflexdesc_t *pFlexdesc( int i ) const { return m_pStudioHdr->pFlexdesc( i ); };
  1969. inline LocalFlexController_t numflexcontrollers() const{ return (LocalFlexController_t)m_pStudioHdr->numflexcontrollers; };
  1970. inline mstudioflexcontroller_t *pFlexcontroller( LocalFlexController_t i ) const { return m_pStudioHdr->pFlexcontroller( i ); };
  1971. inline int numflexcontrollerui() const{ return m_pStudioHdr->numflexcontrollerui; };
  1972. inline mstudioflexcontrollerui_t *pFlexcontrollerUI( int i ) const { return m_pStudioHdr->pFlexControllerUI( i ); };
  1973. //inline const char *name() const { return m_pStudioHdr->name; }; // deprecated -- remove after full xbox merge
  1974. inline const char *pszName() const { return m_pStudioHdr->pszName(); };
  1975. inline int numbonecontrollers() const { return m_pStudioHdr->numbonecontrollers; };
  1976. inline int numhitboxsets() const { return m_pStudioHdr->numhitboxsets; };
  1977. inline mstudiohitboxset_t *pHitboxSet( int i ) const { return m_pStudioHdr->pHitboxSet( i ); };
  1978. inline mstudiobbox_t *pHitbox( int i, int set ) const { return m_pStudioHdr->pHitbox( i, set ); };
  1979. inline int iHitboxCount( int set ) const { return m_pStudioHdr->iHitboxCount( set ); };
  1980. inline int numbodyparts() const { return m_pStudioHdr->numbodyparts; };
  1981. inline mstudiobodyparts_t *pBodypart( int i ) const { return m_pStudioHdr->pBodypart( i ); };
  1982. inline int numskinfamilies() const { return m_pStudioHdr->numskinfamilies; }
  1983. inline Vector eyeposition() const { return m_pStudioHdr->eyeposition; };
  1984. inline int flags() const { return m_pStudioHdr->flags; };
  1985. inline char *const pszSurfaceProp( void ) const { return m_pStudioHdr->pszSurfaceProp(); };
  1986. inline float mass() const { return m_pStudioHdr->mass; };
  1987. inline int contents() const { return m_pStudioHdr->contents; }
  1988. inline const byte *GetBoneTableSortedByName() const { return m_pStudioHdr->GetBoneTableSortedByName(); };
  1989. inline Vector illumposition() const { return m_pStudioHdr->illumposition; };
  1990. inline Vector hull_min() const { return m_pStudioHdr->hull_min; }; // ideal movement hull size
  1991. inline Vector hull_max() const { return m_pStudioHdr->hull_max; };
  1992. inline Vector view_bbmin() const { return m_pStudioHdr->view_bbmin; }; // clipping bounding box
  1993. inline Vector view_bbmax() const { return m_pStudioHdr->view_bbmax; };
  1994. inline int numtextures() const { return m_pStudioHdr->numtextures; };
  1995. inline int IllumPositionAttachmentIndex() const { return m_pStudioHdr->IllumPositionAttachmentIndex(); }
  1996. inline float MaxEyeDeflection() const { return m_pStudioHdr->MaxEyeDeflection(); }
  1997. inline mstudiolinearbone_t *pLinearBones() const { return m_pStudioHdr->pLinearBones(); }
  1998. inline int BoneFlexDriverCount() const { return m_pStudioHdr->BoneFlexDriverCount(); }
  1999. inline const mstudioboneflexdriver_t *BoneFlexDriver( int i ) const { return m_pStudioHdr->BoneFlexDriver( i ); }
  2000. inline float VertAnimFixedPointScale() const { return m_pStudioHdr->VertAnimFixedPointScale(); }
  2001. public:
  2002. int IsSequenceLooping( int iSequence );
  2003. float GetSequenceCycleRate( int iSequence );
  2004. void RunFlexRules( const float *src, float *dest );
  2005. public:
  2006. inline int boneFlags( int iBone ) const { return m_boneFlags[ iBone ]; }
  2007. inline int boneParent( int iBone ) const { return m_boneParent[ iBone ]; }
  2008. private:
  2009. CUtlVector< int > m_boneFlags;
  2010. CUtlVector< int > m_boneParent;
  2011. public:
  2012. // This class maps an activity to sequences allowed for that activity, accelerating the resolution
  2013. // of SelectWeightedSequence(), especially on PowerPC. Iterating through every sequence
  2014. // attached to a model turned out to be a very destructive cache access pattern on 360.
  2015. //
  2016. // I've encapsulated this behavior inside a nested class for organizational reasons; there is
  2017. // no particular programmatic or efficiency benefit to it. It just makes clearer what particular
  2018. // code in the otherwise very complicated StudioHdr class has to do with this particular
  2019. // optimization, and it lets you collapse the whole definition down to a single line in Visual
  2020. // Studio.
  2021. class CActivityToSequenceMapping /* final */
  2022. {
  2023. public:
  2024. // A tuple of a sequence and its corresponding weight. Lists of these correspond to activities.
  2025. struct SequenceTuple
  2026. {
  2027. short seqnum;
  2028. short weight; // the absolute value of the weight from the sequence header
  2029. CUtlSymbol *pActivityModifiers; // list of activity modifier symbols
  2030. int iNumActivityModifiers;
  2031. };
  2032. // The type of the hash's stored data, a composite of both key and value
  2033. // (because that's how CUtlHash works):
  2034. // key: an int, the activity #
  2035. // values: an index into the m_pSequenceTuples array, a count of the
  2036. // total sequences present for an activity, and the sum of their
  2037. // weights.
  2038. // Note this struct is 128-bits wide, exactly coincident to a PowerPC
  2039. // cache line and VMX register. Please consider very carefully the
  2040. // performance implications before adding any additional fields to this.
  2041. // You could probably do away with totalWeight if you really had to.
  2042. struct HashValueType
  2043. {
  2044. // KEY (hashed)
  2045. int activityIdx;
  2046. // VALUE (not hashed)
  2047. int startingIdx;
  2048. int count;
  2049. int totalWeight;
  2050. HashValueType(int _actIdx, int _stIdx, int _ct, int _tW) :
  2051. activityIdx(_actIdx), startingIdx(_stIdx), count(_ct), totalWeight(_tW) {}
  2052. // default constructor (ought not to be actually used)
  2053. HashValueType() : activityIdx(-1), startingIdx(-1), count(-1), totalWeight(-1)
  2054. { AssertMsg(false, "Don't use default HashValueType()!"); }
  2055. class HashFuncs
  2056. {
  2057. public:
  2058. // dummy constructor (gndn)
  2059. HashFuncs( int ) {}
  2060. // COMPARE
  2061. // compare two entries for uniqueness. We should never have two different
  2062. // entries for the same activity, so we only compare the activity index;
  2063. // this allows us to use the utlhash as a dict by constructing dummy entries
  2064. // as hash lookup keys.
  2065. bool operator()( const HashValueType &lhs, const HashValueType &rhs ) const
  2066. {
  2067. return lhs.activityIdx == rhs.activityIdx;
  2068. }
  2069. // HASH
  2070. // We only hash on the activity index; everything else is data.
  2071. unsigned int operator()( const HashValueType &item ) const
  2072. {
  2073. return HashInt( item.activityIdx );
  2074. }
  2075. };
  2076. };
  2077. typedef CUtlHash<HashValueType, HashValueType::HashFuncs, HashValueType::HashFuncs> ActivityToValueIdxHash;
  2078. // These must be here because IFM does not compile/link studio.cpp (?!?)
  2079. // ctor
  2080. CActivityToSequenceMapping( void )
  2081. : m_pSequenceTuples(NULL), m_iSequenceTuplesCount(0), m_ActToSeqHash(8,0,0), m_expectedPStudioHdr(NULL), m_expectedVModel(NULL)
  2082. #if STUDIO_SEQUENCE_ACTIVITY_LAZY_INITIALIZE
  2083. , m_bIsInitialized(false)
  2084. #endif
  2085. {};
  2086. // dtor -- not virtual because this class has no inheritors
  2087. ~CActivityToSequenceMapping()
  2088. {
  2089. if ( m_pSequenceTuples != NULL )
  2090. {
  2091. if ( m_pSequenceTuples->pActivityModifiers != NULL )
  2092. {
  2093. delete[] m_pSequenceTuples->pActivityModifiers;
  2094. }
  2095. delete[] m_pSequenceTuples;
  2096. }
  2097. }
  2098. /// Get the list of sequences for an activity. Returns the pointer to the
  2099. /// first sequence tuple. Output parameters are a count of sequences present,
  2100. /// and the total weight of all the sequences. (it would be more LHS-friendly
  2101. /// to return these on registers, if only C++ offered more than one return
  2102. /// value....)
  2103. const SequenceTuple *GetSequences( int forActivity, int *outSequenceCount, int *outTotalWeight );
  2104. /// The number of sequences available for an activity.
  2105. int NumSequencesForActivity( int forActivity );
  2106. #if STUDIO_SEQUENCE_ACTIVITY_LAZY_INITIALIZE
  2107. inline bool IsInitialized( void ) { return m_bIsInitialized; }
  2108. #endif
  2109. private:
  2110. /// Allocate my internal array. (It is freed in the destructor.) Also,
  2111. /// build the hash of activities to sequences and populate m_pSequenceTuples.
  2112. void Initialize( CStudioHdr *pstudiohdr );
  2113. /// Force Initialize() to occur again, even if it has already occured.
  2114. void Reinitialize( CStudioHdr *pstudiohdr );
  2115. /// A more efficient version of the old SelectWeightedSequence() function in animation.cpp.
  2116. int SelectWeightedSequence( CStudioHdr *pstudiohdr, int activity, int curSequence );
  2117. // selects the sequence with the most matching modifiers
  2118. int SelectWeightedSequenceFromModifiers( CStudioHdr *pstudiohdr, int activity, CUtlSymbol *pActivityModifiers, int iModifierCount );
  2119. // Actually a big array, into which the hash values index.
  2120. SequenceTuple *m_pSequenceTuples;
  2121. unsigned int m_iSequenceTuplesCount; // (size of the whole array)
  2122. #if STUDIO_SEQUENCE_ACTIVITY_LAZY_INITIALIZE
  2123. bool m_bIsInitialized;
  2124. #endif
  2125. // we don't store an outer pointer because we can't initialize it at construction time
  2126. // (warning c4355) -- there are ways around this but it's easier to just pass in a
  2127. // pointer to the CStudioHdr when we need it, since this class isn't supposed to
  2128. // export its interface outside the studio header anyway.
  2129. // CStudioHdr * const m_pOuter;
  2130. ActivityToValueIdxHash m_ActToSeqHash;
  2131. // we store these so we can know if the contents of the studiohdr have changed
  2132. // from underneath our feet (this is an emergency data integrity check)
  2133. const void *m_expectedPStudioHdr;
  2134. const void *m_expectedVModel;
  2135. // double-check that the data I point to hasn't changed
  2136. bool ValidateAgainst( const CStudioHdr * RESTRICT pstudiohdr );
  2137. void SetValidationPair( const CStudioHdr *RESTRICT pstudiohdr );
  2138. friend class CStudioHdr;
  2139. };
  2140. CActivityToSequenceMapping m_ActivityToSequence;
  2141. /// A more efficient version of the old SelectWeightedSequence() function in animation.cpp.
  2142. /// Returns -1 on failure to find a sequence
  2143. inline int SelectWeightedSequence( int activity, int curSequence )
  2144. {
  2145. #if STUDIO_SEQUENCE_ACTIVITY_LAZY_INITIALIZE
  2146. // We lazy-initialize the header on demand here, because CStudioHdr::Init() is
  2147. // called from the constructor, at which time the this pointer is illegitimate.
  2148. if ( !m_ActivityToSequence.IsInitialized() )
  2149. {
  2150. m_ActivityToSequence.Initialize(this);
  2151. }
  2152. #endif
  2153. return m_ActivityToSequence.SelectWeightedSequence( this, activity, curSequence );
  2154. }
  2155. inline int SelectWeightedSequenceFromModifiers( int activity, CUtlSymbol *pActivityModifiers, int iModifierCount )
  2156. {
  2157. #if STUDIO_SEQUENCE_ACTIVITY_LAZY_INITIALIZE
  2158. // We lazy-initialize the header on demand here, because CStudioHdr::Init() is
  2159. // called from the constructor, at which time the this pointer is illegitimate.
  2160. if ( !m_ActivityToSequence.IsInitialized() )
  2161. {
  2162. m_ActivityToSequence.Initialize( this );
  2163. }
  2164. #endif
  2165. return m_ActivityToSequence.SelectWeightedSequenceFromModifiers( this, activity, pActivityModifiers, iModifierCount );
  2166. }
  2167. /// True iff there is at least one sequence for the given activity.
  2168. inline bool HaveSequenceForActivity( int activity )
  2169. {
  2170. #if STUDIO_SEQUENCE_ACTIVITY_LAZY_INITIALIZE
  2171. if ( !m_ActivityToSequence.IsInitialized() )
  2172. {
  2173. m_ActivityToSequence.Initialize(this);
  2174. }
  2175. #endif
  2176. return (m_ActivityToSequence.NumSequencesForActivity( activity ) > 0);
  2177. }
  2178. // Force this CStudioHdr's activity-to-sequence mapping to be reinitialized
  2179. inline void ReinitializeSequenceMapping(void)
  2180. {
  2181. m_ActivityToSequence.Reinitialize(this);
  2182. }
  2183. #ifdef STUDIO_ENABLE_PERF_COUNTERS
  2184. public:
  2185. inline void ClearPerfCounters( void )
  2186. {
  2187. m_nPerfAnimatedBones = 0;
  2188. m_nPerfUsedBones = 0;
  2189. m_nPerfAnimationLayers = 0;
  2190. };
  2191. // timing info
  2192. mutable int m_nPerfAnimatedBones;
  2193. mutable int m_nPerfUsedBones;
  2194. mutable int m_nPerfAnimationLayers;
  2195. #endif
  2196. };
  2197. /*
  2198. class CModelAccess
  2199. {
  2200. public:
  2201. CModelAccess(CStudioHdr *pSemaphore)
  2202. : m_pStudioHdr(pSemaphore)
  2203. {
  2204. m_pStudioHdr->IncrementAccess();
  2205. }
  2206. ~CModelAccess()
  2207. {
  2208. m_pStudioHdr->DecrementAccess();
  2209. }
  2210. private:
  2211. CStudioHdr *m_pStudioHdr;
  2212. };
  2213. #define ENABLE_MODEL_ACCESS( a ) \
  2214. CModelAccess ModelAccess##__LINE__( a->m_pStudioHdr )
  2215. */
  2216. //-----------------------------------------------------------------------------
  2217. // Purpose:
  2218. //-----------------------------------------------------------------------------
  2219. struct flexweight_t
  2220. {
  2221. DECLARE_BYTESWAP_DATADESC();
  2222. int key;
  2223. float weight;
  2224. float influence;
  2225. };
  2226. struct flexsetting_t
  2227. {
  2228. DECLARE_BYTESWAP_DATADESC();
  2229. int nameindex;
  2230. inline char *pszName( void ) const
  2231. {
  2232. return (char *)(((byte *)this) + nameindex);
  2233. }
  2234. // Leaving this for legacy support
  2235. int obsolete1;
  2236. // Number of flex settings
  2237. int numsettings;
  2238. int index;
  2239. // OBSOLETE:
  2240. int obsolete2;
  2241. // Index of start of contiguous array of flexweight_t structures
  2242. int settingindex;
  2243. //-----------------------------------------------------------------------------
  2244. // Purpose: Retrieves a pointer to the flexweight_t, including resolving
  2245. // any markov chain hierarchy. Because of this possibility, we return
  2246. // the number of settings in the weights array returned. We'll generally
  2247. // call this function with i == 0
  2248. // Input : *base -
  2249. // i -
  2250. // **weights -
  2251. // Output : int
  2252. //-----------------------------------------------------------------------------
  2253. inline int psetting( byte *base, int i, flexweight_t **weights ) const;
  2254. };
  2255. struct flexsettinghdr_t
  2256. {
  2257. DECLARE_BYTESWAP_DATADESC();
  2258. int id;
  2259. int version;
  2260. inline const char * pszName( void ) const { return name; }
  2261. char name[64];
  2262. int length;
  2263. int numflexsettings;
  2264. int flexsettingindex;
  2265. inline flexsetting_t *pSetting( int i ) const { return (flexsetting_t *)(((byte *)this) + flexsettingindex) + i; };
  2266. int nameindex;
  2267. // look up flex settings by "index"
  2268. int numindexes;
  2269. int indexindex;
  2270. inline flexsetting_t *pIndexedSetting( int index ) const
  2271. {
  2272. if ( index < 0 || index >= numindexes )
  2273. {
  2274. return NULL;
  2275. }
  2276. int i = *((int *)(((byte *)this) + indexindex) + index);
  2277. if (i == -1)
  2278. {
  2279. return NULL;
  2280. }
  2281. return pSetting( i );
  2282. }
  2283. // index names of "flexcontrollers"
  2284. int numkeys;
  2285. int keynameindex;
  2286. inline char *pLocalName( int i ) const { return (char *)(((byte *)this) + *((int *)(((byte *)this) + keynameindex) + i)); };
  2287. int keymappingindex;
  2288. inline int *pLocalToGlobal( int i ) const { return (int *)(((byte *)this) + keymappingindex) + i; };
  2289. inline int LocalToGlobal( int i ) const { return *pLocalToGlobal( i ); };
  2290. };
  2291. //-----------------------------------------------------------------------------
  2292. // Purpose: Retrieves a pointer to the flexweight_t.
  2293. // Input : *base - flexsettinghdr_t * pointer
  2294. // i - index of flex setting to retrieve
  2295. // **weights - destination for weights array starting at index i.
  2296. // Output : int
  2297. //-----------------------------------------------------------------------------
  2298. inline int flexsetting_t::psetting( byte *base, int i, flexweight_t **weights ) const
  2299. {
  2300. // Grab array pointer
  2301. *weights = (flexweight_t *)(((byte *)this) + settingindex) + i;
  2302. // Return true number of settings
  2303. return numsettings;
  2304. };
  2305. //-----------------------------------------------------------------------------
  2306. // For a given flex controller ui struct, these return the index of the
  2307. // studiohdr_t flex controller that correspond to the the left and right
  2308. // flex controllers if the ui controller is a stereo control.
  2309. // nWayValueIndex returns the index of the flex controller that is the value
  2310. // flex controller for an NWAY combination
  2311. // If these functions are called and the ui controller isn't of the type
  2312. // specified then -1 is returned
  2313. //-----------------------------------------------------------------------------
  2314. inline int mstudioflexcontrollerui_t::controllerIndex( const CStudioHdr &cStudioHdr ) const
  2315. {
  2316. return !stereo ? pController() - cStudioHdr.pFlexcontroller( (LocalFlexController_t)0 ) : -1;
  2317. }
  2318. inline int mstudioflexcontrollerui_t::rightIndex( const CStudioHdr &cStudioHdr ) const
  2319. {
  2320. return stereo ? pRightController() - cStudioHdr.pFlexcontroller( (LocalFlexController_t)0 ) : -1;
  2321. }
  2322. inline int mstudioflexcontrollerui_t::leftIndex( const CStudioHdr &cStudioHdr ) const
  2323. {
  2324. return stereo ? pLeftController() - cStudioHdr.pFlexcontroller((LocalFlexController_t) 0 ) : -1;
  2325. }
  2326. inline int mstudioflexcontrollerui_t::nWayValueIndex( const CStudioHdr &cStudioHdr ) const
  2327. {
  2328. return remaptype == FLEXCONTROLLER_REMAP_NWAY ? pNWayValueController() - cStudioHdr.pFlexcontroller( (LocalFlexController_t)0 ) : -1;
  2329. }
  2330. inline const mstudioflexcontroller_t *mstudioflexcontrollerui_t::pController( int index ) const
  2331. {
  2332. if ( index < 0 || index > Count() )
  2333. return NULL;
  2334. if ( remaptype == FLEXCONTROLLER_REMAP_NWAY )
  2335. {
  2336. if ( stereo )
  2337. return (mstudioflexcontroller_t *)( ( char * ) this ) + *( &szindex0 + index );
  2338. if ( index == 0 )
  2339. return pController();
  2340. if ( index == 1 )
  2341. return pNWayValueController();
  2342. return NULL;
  2343. }
  2344. if ( index > 1 )
  2345. return NULL;
  2346. if ( stereo )
  2347. return (mstudioflexcontroller_t *)( ( char * ) this ) + *( &szindex0 + index );
  2348. if ( index > 0 )
  2349. return NULL;
  2350. return pController();
  2351. }
  2352. #define STUDIO_CONST 1 // get float
  2353. #define STUDIO_FETCH1 2 // get Flexcontroller value
  2354. #define STUDIO_FETCH2 3 // get flex weight
  2355. #define STUDIO_ADD 4
  2356. #define STUDIO_SUB 5
  2357. #define STUDIO_MUL 6
  2358. #define STUDIO_DIV 7
  2359. #define STUDIO_NEG 8 // not implemented
  2360. #define STUDIO_EXP 9 // not implemented
  2361. #define STUDIO_OPEN 10 // only used in token parsing
  2362. #define STUDIO_CLOSE 11
  2363. #define STUDIO_COMMA 12 // only used in token parsing
  2364. #define STUDIO_MAX 13
  2365. #define STUDIO_MIN 14
  2366. #define STUDIO_2WAY_0 15 // Fetch a value from a 2 Way slider for the 1st value RemapVal( 0.0, 0.5, 0.0, 1.0 )
  2367. #define STUDIO_2WAY_1 16 // Fetch a value from a 2 Way slider for the 2nd value RemapVal( 0.5, 1.0, 0.0, 1.0 )
  2368. #define STUDIO_NWAY 17 // Fetch a value from a 2 Way slider for the 2nd value RemapVal( 0.5, 1.0, 0.0, 1.0 )
  2369. #define STUDIO_COMBO 18 // Perform a combo operation (essentially multiply the last N values on the stack)
  2370. #define STUDIO_DOMINATE 19 // Performs a combination domination operation
  2371. #define STUDIO_DME_LOWER_EYELID 20 //
  2372. #define STUDIO_DME_UPPER_EYELID 21 //
  2373. // motion flags
  2374. #define STUDIO_X 0x00000001
  2375. #define STUDIO_Y 0x00000002
  2376. #define STUDIO_Z 0x00000004
  2377. #define STUDIO_XR 0x00000008
  2378. #define STUDIO_YR 0x00000010
  2379. #define STUDIO_ZR 0x00000020
  2380. #define STUDIO_LX 0x00000040
  2381. #define STUDIO_LY 0x00000080
  2382. #define STUDIO_LZ 0x00000100
  2383. #define STUDIO_LXR 0x00000200
  2384. #define STUDIO_LYR 0x00000400
  2385. #define STUDIO_LZR 0x00000800
  2386. #define STUDIO_LINEAR 0x00001000
  2387. #define STUDIO_TYPES 0x0003FFFF
  2388. #define STUDIO_RLOOP 0x00040000 // controller that wraps shortest distance
  2389. // sequence and autolayer flags
  2390. #define STUDIO_LOOPING 0x0001 // ending frame should be the same as the starting frame
  2391. #define STUDIO_SNAP 0x0002 // do not interpolate between previous animation and this one
  2392. #define STUDIO_DELTA 0x0004 // this sequence "adds" to the base sequences, not slerp blends
  2393. #define STUDIO_AUTOPLAY 0x0008 // temporary flag that forces the sequence to always play
  2394. #define STUDIO_POST 0x0010 //
  2395. #define STUDIO_ALLZEROS 0x0020 // this animation/sequence has no real animation data
  2396. // 0x0040
  2397. #define STUDIO_CYCLEPOSE 0x0080 // cycle index is taken from a pose parameter index
  2398. #define STUDIO_REALTIME 0x0100 // cycle index is taken from a real-time clock, not the animations cycle index
  2399. #define STUDIO_LOCAL 0x0200 // sequence has a local context sequence
  2400. #define STUDIO_HIDDEN 0x0400 // don't show in default selection views
  2401. #define STUDIO_OVERRIDE 0x0800 // a forward declared sequence (empty)
  2402. #define STUDIO_ACTIVITY 0x1000 // Has been updated at runtime to activity index
  2403. #define STUDIO_EVENT 0x2000 // Has been updated at runtime to event index
  2404. #define STUDIO_WORLD 0x4000 // sequence blends in worldspace
  2405. // autolayer flags
  2406. // 0x0001
  2407. // 0x0002
  2408. // 0x0004
  2409. // 0x0008
  2410. #define STUDIO_AL_POST 0x0010 //
  2411. // 0x0020
  2412. #define STUDIO_AL_SPLINE 0x0040 // convert layer ramp in/out curve is a spline instead of linear
  2413. #define STUDIO_AL_XFADE 0x0080 // pre-bias the ramp curve to compense for a non-1 weight, assuming a second layer is also going to accumulate
  2414. // 0x0100
  2415. #define STUDIO_AL_NOBLEND 0x0200 // animation always blends at 1.0 (ignores weight)
  2416. // 0x0400
  2417. // 0x0800
  2418. #define STUDIO_AL_LOCAL 0x1000 // layer is a local context sequence
  2419. // 0x2000
  2420. #define STUDIO_AL_POSE 0x4000 // layer blends using a pose parameter instead of parent cycle
  2421. // Insert this code anywhere that you need to allow for conversion from an old STUDIO_VERSION
  2422. // to a new one.
  2423. // If we only support the current version, this function should be empty.
  2424. inline bool Studio_ConvertStudioHdrToNewVersion( studiohdr_t *pStudioHdr )
  2425. {
  2426. COMPILE_TIME_ASSERT( STUDIO_VERSION == 48 ); // put this to make sure this code is updated upon changing version.
  2427. int version = pStudioHdr->version;
  2428. if ( version == STUDIO_VERSION )
  2429. return true;
  2430. bool bResult = true;
  2431. if (version < 46)
  2432. {
  2433. // some of the anim index data is incompatible
  2434. for (int i = 0; i < pStudioHdr->numlocalanim; i++)
  2435. {
  2436. mstudioanimdesc_t *pAnim = (mstudioanimdesc_t *)pStudioHdr->pLocalAnimdesc( i );
  2437. // old ANI files that used sections (v45 only) are not compatible
  2438. if ( pAnim->sectionframes != 0 )
  2439. {
  2440. // zero most everything out
  2441. memset( &(pAnim->numframes), 0, (byte *)(pAnim + 1) - (byte *)&(pAnim->numframes) );
  2442. pAnim->numframes = 1;
  2443. pAnim->animblock = -1; // disable animation fetching
  2444. bResult = false;
  2445. }
  2446. }
  2447. }
  2448. if (version < 47)
  2449. {
  2450. // used to contain zeroframe cache data
  2451. if (pStudioHdr->unused4 != 0)
  2452. {
  2453. pStudioHdr->unused4 = 0;
  2454. bResult = false;
  2455. }
  2456. for (int i = 0; i < pStudioHdr->numlocalanim; i++)
  2457. {
  2458. mstudioanimdesc_t *pAnim = (mstudioanimdesc_t *)pStudioHdr->pLocalAnimdesc( i );
  2459. pAnim->zeroframeindex = 0;
  2460. pAnim->zeroframespan = 0;
  2461. }
  2462. }
  2463. else if (version == 47)
  2464. {
  2465. for (int i = 0; i < pStudioHdr->numlocalanim; i++)
  2466. {
  2467. mstudioanimdesc_t *pAnim = (mstudioanimdesc_t *)pStudioHdr->pLocalAnimdesc( i );
  2468. if (pAnim->zeroframeindex != 0)
  2469. {
  2470. pAnim->zeroframeindex = 0;
  2471. pAnim->zeroframespan = 0;
  2472. bResult = false;
  2473. }
  2474. }
  2475. }
  2476. // for now, just slam the version number since they're compatible
  2477. pStudioHdr->version = STUDIO_VERSION;
  2478. return bResult;
  2479. }
  2480. // must be run to fixup with specified rootLOD
  2481. inline void Studio_SetRootLOD( studiohdr_t *pStudioHdr, int rootLOD )
  2482. {
  2483. // honor studiohdr restriction of root lod in case requested root lod exceeds restriction.
  2484. if ( pStudioHdr->numAllowedRootLODs > 0 &&
  2485. rootLOD >= pStudioHdr->numAllowedRootLODs )
  2486. {
  2487. rootLOD = pStudioHdr->numAllowedRootLODs - 1;
  2488. }
  2489. Assert( rootLOD >= 0 && rootLOD < MAX_NUM_LODS );
  2490. Clamp( rootLOD, 0, MAX_NUM_LODS - 1 );
  2491. // run the lod fixups that culls higher detail lods
  2492. // vertexes are external, fixups ensure relative offsets and counts are cognizant of shrinking data
  2493. // indexes are built in lodN..lod0 order so higher detail lod data can be truncated at load
  2494. // the fixup lookup arrays are filled (or replicated) to ensure all slots valid
  2495. int vertexindex = 0;
  2496. int tangentsindex = 0;
  2497. int bodyPartID;
  2498. for ( bodyPartID = 0; bodyPartID < pStudioHdr->numbodyparts; bodyPartID++ )
  2499. {
  2500. mstudiobodyparts_t *pBodyPart = pStudioHdr->pBodypart( bodyPartID );
  2501. int modelID;
  2502. for ( modelID = 0; modelID < pBodyPart->nummodels; modelID++ )
  2503. {
  2504. mstudiomodel_t *pModel = pBodyPart->pModel( modelID );
  2505. int totalMeshVertexes = 0;
  2506. int meshID;
  2507. for ( meshID = 0; meshID < pModel->nummeshes; meshID++ )
  2508. {
  2509. mstudiomesh_t *pMesh = pModel->pMesh( meshID );
  2510. // get the fixup, vertexes are reduced
  2511. pMesh->numvertices = pMesh->vertexdata.numLODVertexes[rootLOD];
  2512. pMesh->vertexoffset = totalMeshVertexes;
  2513. totalMeshVertexes += pMesh->numvertices;
  2514. }
  2515. // stay in sync
  2516. pModel->numvertices = totalMeshVertexes;
  2517. pModel->vertexindex = vertexindex;
  2518. pModel->tangentsindex = tangentsindex;
  2519. vertexindex += totalMeshVertexes*sizeof(mstudiovertex_t);
  2520. tangentsindex += totalMeshVertexes*sizeof(Vector4D);
  2521. }
  2522. }
  2523. // track the set desired configuration
  2524. pStudioHdr->rootLOD = rootLOD;
  2525. }
  2526. // Determines allocation requirements for vertexes
  2527. inline int Studio_VertexDataSize( const vertexFileHeader_t *pVvdHdr, int rootLOD, bool bNeedsTangentS )
  2528. {
  2529. // the quantity of vertexes necessary for root lod and all lower detail lods
  2530. // add one extra vertex to each section
  2531. // the extra vertex allows prefetch hints to read ahead 1 vertex without faulting
  2532. int numVertexes = pVvdHdr->numLODVertexes[rootLOD] + 1;
  2533. int dataLength = pVvdHdr->vertexDataStart + numVertexes*sizeof(mstudiovertex_t);
  2534. if (bNeedsTangentS)
  2535. {
  2536. dataLength += numVertexes*sizeof(Vector4D);
  2537. }
  2538. // allocate this much
  2539. return dataLength;
  2540. }
  2541. // Load the minimum quantity of verts and run fixups
  2542. inline int Studio_LoadVertexes( const vertexFileHeader_t *pTempVvdHdr, vertexFileHeader_t *pNewVvdHdr, int rootLOD, bool bNeedsTangentS )
  2543. {
  2544. int i;
  2545. int target;
  2546. int numVertexes;
  2547. vertexFileFixup_t *pFixupTable;
  2548. numVertexes = pTempVvdHdr->numLODVertexes[rootLOD];
  2549. // copy all data up to start of vertexes
  2550. memcpy((void*)pNewVvdHdr, (void*)pTempVvdHdr, pTempVvdHdr->vertexDataStart);
  2551. for ( i = 0; i < rootLOD; i++)
  2552. {
  2553. pNewVvdHdr->numLODVertexes[i] = pNewVvdHdr->numLODVertexes[rootLOD];
  2554. }
  2555. // fixup data starts
  2556. if (bNeedsTangentS)
  2557. {
  2558. // tangent data follows possibly reduced vertex data
  2559. pNewVvdHdr->tangentDataStart = pNewVvdHdr->vertexDataStart + numVertexes*sizeof(mstudiovertex_t);
  2560. }
  2561. else
  2562. {
  2563. // no tangent data will be available, mark for identification
  2564. pNewVvdHdr->tangentDataStart = 0;
  2565. }
  2566. if (!pNewVvdHdr->numFixups)
  2567. {
  2568. // fixups not required
  2569. // transfer vertex data
  2570. memcpy(
  2571. (byte *)pNewVvdHdr+pNewVvdHdr->vertexDataStart,
  2572. (byte *)pTempVvdHdr+pTempVvdHdr->vertexDataStart,
  2573. numVertexes*sizeof(mstudiovertex_t) );
  2574. if (bNeedsTangentS)
  2575. {
  2576. // transfer tangent data to cache memory
  2577. memcpy(
  2578. (byte *)pNewVvdHdr+pNewVvdHdr->tangentDataStart,
  2579. (byte *)pTempVvdHdr+pTempVvdHdr->tangentDataStart,
  2580. numVertexes*sizeof(Vector4D) );
  2581. }
  2582. return numVertexes;
  2583. }
  2584. // fixups required
  2585. // re-establish mesh ordered vertexes into cache memory, according to table
  2586. target = 0;
  2587. pFixupTable = (vertexFileFixup_t *)((byte *)pTempVvdHdr + pTempVvdHdr->fixupTableStart);
  2588. for (i=0; i<pTempVvdHdr->numFixups; i++)
  2589. {
  2590. if (pFixupTable[i].lod < rootLOD)
  2591. {
  2592. // working bottom up, skip over copying higher detail lods
  2593. continue;
  2594. }
  2595. // copy vertexes
  2596. memcpy(
  2597. (mstudiovertex_t *)((byte *)pNewVvdHdr+pNewVvdHdr->vertexDataStart) + target,
  2598. (mstudiovertex_t *)((byte *)pTempVvdHdr+pTempVvdHdr->vertexDataStart) + pFixupTable[i].sourceVertexID,
  2599. pFixupTable[i].numVertexes*sizeof(mstudiovertex_t) );
  2600. if (bNeedsTangentS)
  2601. {
  2602. // copy tangents
  2603. memcpy(
  2604. (Vector4D *)((byte *)pNewVvdHdr+pNewVvdHdr->tangentDataStart) + target,
  2605. (Vector4D *)((byte *)pTempVvdHdr+pTempVvdHdr->tangentDataStart) + pFixupTable[i].sourceVertexID,
  2606. pFixupTable[i].numVertexes*sizeof(Vector4D) );
  2607. }
  2608. // data is placed consecutively
  2609. target += pFixupTable[i].numVertexes;
  2610. }
  2611. pNewVvdHdr->numFixups = 0;
  2612. return target;
  2613. }
  2614. #endif // STUDIO_H