Counter Strike : Global Offensive Source Code
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.

3926 lines
129 KiB

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