-
Notifications
You must be signed in to change notification settings - Fork 2k
/
Copy pathstudio.h
3194 lines (2584 loc) · 105 KB
/
studio.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//===========================================================================//
#ifndef STUDIO_H
#define STUDIO_H
#ifdef _WIN32
#pragma once
#endif
#include "basetypes.h"
#include "mathlib/vector2d.h"
#include "mathlib/vector.h"
#include "mathlib/vector4d.h"
#include "mathlib/compressed_vector.h"
#include "tier0/dbg.h"
#include "tier0/threadtools.h"
#include "mathlib/mathlib.h"
#include "utlvector.h"
#include "utlhash.h"
#include "datamap.h"
#include "generichash.h"
#include "localflexcontroller.h"
#define STUDIO_ENABLE_PERF_COUNTERS
#define STUDIO_SEQUENCE_ACTIVITY_LOOKUPS_ARE_SLOW 0
// If this is set to 1, then the activity->sequence mapping inside
// the CStudioHdr will not be initialized until the first call to
// SelectWeightedSequence() or HaveSequenceForActivity(). If set
// to zero, the mapping will be initialized from CStudioHdr::Init()
// (itself called from the constructor).
// As of June 4 2007, this was set to 1 because physics, among other
// systems, extemporaneously declares CStudioHdrs inside local function
// scopes without querying their activity/sequence mapping at all.
#define STUDIO_SEQUENCE_ACTIVITY_LAZY_INITIALIZE 1
//-----------------------------------------------------------------------------
// forward declarations
//-----------------------------------------------------------------------------
class IMaterial;
class IMesh;
class IMorph;
struct virtualmodel_t;
struct vertexFileHeader_t;
struct thinModelVertices_t;
namespace OptimizedModel
{
struct StripHeader_t;
}
/*
==============================================================================
STUDIO MODELS
Studio models are position independent, so the cache manager can move them.
==============================================================================
*/
#define STUDIO_VERSION 48
#ifndef _XBOX
#define MAXSTUDIOTRIANGLES 65536 // TODO: tune this
#define MAXSTUDIOVERTS 65536 // TODO: tune this
#define MAXSTUDIOFLEXVERTS 10000 // max number of verts that can be flexed per mesh. TODO: tune this
#else
#define MAXSTUDIOTRIANGLES 25000
#define MAXSTUDIOVERTS 10000
#define MAXSTUDIOFLEXVERTS 1000
#endif
#define MAXSTUDIOSKINS 32 // total textures
#define MAXSTUDIOBONES 128 // total bones actually used
#define MAXSTUDIOFLEXDESC 1024 // maximum number of low level flexes (actual morph targets)
#define MAXSTUDIOFLEXCTRL 96 // maximum number of flexcontrollers (input sliders)
#define MAXSTUDIOPOSEPARAM 24
#define MAXSTUDIOBONECTRLS 4
#define MAXSTUDIOANIMBLOCKS 256
#define MAXSTUDIOBONEBITS 7 // NOTE: MUST MATCH MAXSTUDIOBONES
// NOTE!!! : Changing this number also changes the vtx file format!!!!!
#define MAX_NUM_BONES_PER_VERT 3
//Adrian - Remove this when we completely phase out the old event system.
#define NEW_EVENT_STYLE ( 1 << 10 )
struct mstudiodata_t
{
int count;
int offset;
};
#define STUDIO_PROC_AXISINTERP 1
#define STUDIO_PROC_QUATINTERP 2
#define STUDIO_PROC_AIMATBONE 3
#define STUDIO_PROC_AIMATATTACH 4
#define STUDIO_PROC_JIGGLE 5
struct mstudioaxisinterpbone_t
{
DECLARE_BYTESWAP_DATADESC();
int control;// local transformation of this bone used to calc 3 point blend
int axis; // axis to check
Vector pos[6]; // X+, X-, Y+, Y-, Z+, Z-
Quaternion quat[6];// X+, X-, Y+, Y-, Z+, Z-
mstudioaxisinterpbone_t(){}
private:
// No copy constructors allowed
mstudioaxisinterpbone_t(const mstudioaxisinterpbone_t& vOther);
};
struct mstudioquatinterpinfo_t
{
DECLARE_BYTESWAP_DATADESC();
float inv_tolerance; // 1 / radian angle of trigger influence
Quaternion trigger; // angle to match
Vector pos; // new position
Quaternion quat; // new angle
mstudioquatinterpinfo_t(){}
private:
// No copy constructors allowed
mstudioquatinterpinfo_t(const mstudioquatinterpinfo_t& vOther);
};
struct mstudioquatinterpbone_t
{
DECLARE_BYTESWAP_DATADESC();
int control;// local transformation to check
int numtriggers;
int triggerindex;
inline mstudioquatinterpinfo_t *pTrigger( int i ) const { return (mstudioquatinterpinfo_t *)(((byte *)this) + triggerindex) + i; };
mstudioquatinterpbone_t(){}
private:
// No copy constructors allowed
mstudioquatinterpbone_t(const mstudioquatinterpbone_t& vOther);
};
#define JIGGLE_IS_FLEXIBLE 0x01
#define JIGGLE_IS_RIGID 0x02
#define JIGGLE_HAS_YAW_CONSTRAINT 0x04
#define JIGGLE_HAS_PITCH_CONSTRAINT 0x08
#define JIGGLE_HAS_ANGLE_CONSTRAINT 0x10
#define JIGGLE_HAS_LENGTH_CONSTRAINT 0x20
#define JIGGLE_HAS_BASE_SPRING 0x40
#define JIGGLE_IS_BOING 0x80 // simple squash and stretch sinusoid "boing"
struct mstudiojigglebone_t
{
DECLARE_BYTESWAP_DATADESC();
int flags;
// general params
float length; // how from from bone base, along bone, is tip
float tipMass;
// flexible params
float yawStiffness;
float yawDamping;
float pitchStiffness;
float pitchDamping;
float alongStiffness;
float alongDamping;
// angle constraint
float angleLimit; // maximum deflection of tip in radians
// yaw constraint
float minYaw; // in radians
float maxYaw; // in radians
float yawFriction;
float yawBounce;
// pitch constraint
float minPitch; // in radians
float maxPitch; // in radians
float pitchFriction;
float pitchBounce;
// base spring
float baseMass;
float baseStiffness;
float baseDamping;
float baseMinLeft;
float baseMaxLeft;
float baseLeftFriction;
float baseMinUp;
float baseMaxUp;
float baseUpFriction;
float baseMinForward;
float baseMaxForward;
float baseForwardFriction;
// boing
float boingImpactSpeed;
float boingImpactAngle;
float boingDampingRate;
float boingFrequency;
float boingAmplitude;
private:
// No copy constructors allowed
//mstudiojigglebone_t(const mstudiojigglebone_t& vOther);
};
struct mstudioaimatbone_t
{
DECLARE_BYTESWAP_DATADESC();
int parent;
int aim; // Might be bone or attach
Vector aimvector;
Vector upvector;
Vector basepos;
mstudioaimatbone_t() {}
private:
// No copy constructors allowed
mstudioaimatbone_t(const mstudioaimatbone_t& vOther);
};
// bones
struct mstudiobone_t
{
DECLARE_BYTESWAP_DATADESC();
int sznameindex;
inline char * const pszName( void ) const { return ((char *)this) + sznameindex; }
int parent; // parent bone
int bonecontroller[6]; // bone controller index, -1 == none
// default values
Vector pos;
Quaternion quat;
RadianEuler rot;
// compression scale
Vector posscale;
Vector rotscale;
matrix3x4_t poseToBone;
Quaternion qAlignment;
int flags;
int proctype;
int procindex; // procedural rule
mutable int physicsbone; // index into physically simulated bone
inline void *pProcedure( ) const { if (procindex == 0) return NULL; else return (void *)(((byte *)this) + procindex); };
int surfacepropidx; // index into string tablefor property name
inline char * const pszSurfaceProp( void ) const { return ((char *)this) + surfacepropidx; }
int contents; // See BSPFlags.h for the contents flags
int unused[8]; // remove as appropriate
mstudiobone_t(){}
private:
// No copy constructors allowed
mstudiobone_t(const mstudiobone_t& vOther);
};
struct mstudiolinearbone_t
{
DECLARE_BYTESWAP_DATADESC();
int numbones;
int flagsindex;
inline int flags( int i ) const { Assert( i >= 0 && i < numbones); return *((int *)(((byte *)this) + flagsindex) + i); };
inline int *pflags( int i ) { Assert( i >= 0 && i < numbones); return ((int *)(((byte *)this) + flagsindex) + i); };
int parentindex;
inline int parent( int i ) const { Assert( i >= 0 && i < numbones); return *((int *)(((byte *)this) + parentindex) + i); };
int posindex;
inline Vector pos( int i ) const { Assert( i >= 0 && i < numbones); return *((Vector *)(((byte *)this) + posindex) + i); };
int quatindex;
inline Quaternion quat( int i ) const { Assert( i >= 0 && i < numbones); return *((Quaternion *)(((byte *)this) + quatindex) + i); };
int rotindex;
inline RadianEuler rot( int i ) const { Assert( i >= 0 && i < numbones); return *((RadianEuler *)(((byte *)this) + rotindex) + i); };
int posetoboneindex;
inline matrix3x4_t poseToBone( int i ) const { Assert( i >= 0 && i < numbones); return *((matrix3x4_t *)(((byte *)this) + posetoboneindex) + i); };
int posscaleindex;
inline Vector posscale( int i ) const { Assert( i >= 0 && i < numbones); return *((Vector *)(((byte *)this) + posscaleindex) + i); };
int rotscaleindex;
inline Vector rotscale( int i ) const { Assert( i >= 0 && i < numbones); return *((Vector *)(((byte *)this) + rotscaleindex) + i); };
int qalignmentindex;
inline Quaternion qalignment( int i ) const { Assert( i >= 0 && i < numbones); return *((Quaternion *)(((byte *)this) + qalignmentindex) + i); };
int unused[6];
mstudiolinearbone_t(){}
private:
// No copy constructors allowed
mstudiolinearbone_t(const mstudiolinearbone_t& vOther);
};
//-----------------------------------------------------------------------------
// The component of the bone used by mstudioboneflexdriver_t
//-----------------------------------------------------------------------------
enum StudioBoneFlexComponent_t
{
STUDIO_BONE_FLEX_INVALID = -1, // Invalid
STUDIO_BONE_FLEX_TX = 0, // Translate X
STUDIO_BONE_FLEX_TY = 1, // Translate Y
STUDIO_BONE_FLEX_TZ = 2 // Translate Z
};
//-----------------------------------------------------------------------------
// Component is one of Translate X, Y or Z [0,2] (StudioBoneFlexComponent_t)
//-----------------------------------------------------------------------------
struct mstudioboneflexdrivercontrol_t
{
DECLARE_BYTESWAP_DATADESC();
int m_nBoneComponent; // Bone component that drives flex, StudioBoneFlexComponent_t
int m_nFlexControllerIndex; // Flex controller to drive
float m_flMin; // Min value of bone component mapped to 0 on flex controller
float m_flMax; // Max value of bone component mapped to 1 on flex controller
mstudioboneflexdrivercontrol_t(){}
private:
// No copy constructors allowed
mstudioboneflexdrivercontrol_t( const mstudioboneflexdrivercontrol_t &vOther );
};
//-----------------------------------------------------------------------------
// Drive flex controllers from bone components
//-----------------------------------------------------------------------------
struct mstudioboneflexdriver_t
{
DECLARE_BYTESWAP_DATADESC();
int m_nBoneIndex; // Bone to drive flex controller
int m_nControlCount; // Number of flex controllers being driven
int m_nControlIndex; // Index into data where controllers are (relative to this)
inline mstudioboneflexdrivercontrol_t *pBoneFlexDriverControl( int i ) const
{
Assert( i >= 0 && i < m_nControlCount );
return (mstudioboneflexdrivercontrol_t *)(((byte *)this) + m_nControlIndex) + i;
}
int unused[3];
mstudioboneflexdriver_t(){}
private:
// No copy constructors allowed
mstudioboneflexdriver_t( const mstudioboneflexdriver_t &vOther );
};
#define BONE_CALCULATE_MASK 0x1F
#define BONE_PHYSICALLY_SIMULATED 0x01 // bone is physically simulated when physics are active
#define BONE_PHYSICS_PROCEDURAL 0x02 // procedural when physics is active
#define BONE_ALWAYS_PROCEDURAL 0x04 // bone is always procedurally animated
#define BONE_SCREEN_ALIGN_SPHERE 0x08 // bone aligns to the screen, not constrained in motion.
#define BONE_SCREEN_ALIGN_CYLINDER 0x10 // bone aligns to the screen, constrained by it's own axis.
#define BONE_USED_MASK 0x0007FF00
#define BONE_USED_BY_ANYTHING 0x0007FF00
#define BONE_USED_BY_HITBOX 0x00000100 // bone (or child) is used by a hit box
#define BONE_USED_BY_ATTACHMENT 0x00000200 // bone (or child) is used by an attachment point
#define BONE_USED_BY_VERTEX_MASK 0x0003FC00
#define BONE_USED_BY_VERTEX_LOD0 0x00000400 // bone (or child) is used by the toplevel model via skinned vertex
#define BONE_USED_BY_VERTEX_LOD1 0x00000800
#define BONE_USED_BY_VERTEX_LOD2 0x00001000
#define BONE_USED_BY_VERTEX_LOD3 0x00002000
#define BONE_USED_BY_VERTEX_LOD4 0x00004000
#define BONE_USED_BY_VERTEX_LOD5 0x00008000
#define BONE_USED_BY_VERTEX_LOD6 0x00010000
#define BONE_USED_BY_VERTEX_LOD7 0x00020000
#define BONE_USED_BY_BONE_MERGE 0x00040000 // bone is available for bone merge to occur against it
#define BONE_USED_BY_VERTEX_AT_LOD(lod) ( BONE_USED_BY_VERTEX_LOD0 << (lod) )
#define BONE_USED_BY_ANYTHING_AT_LOD(lod) ( ( BONE_USED_BY_ANYTHING & ~BONE_USED_BY_VERTEX_MASK ) | BONE_USED_BY_VERTEX_AT_LOD(lod) )
#define MAX_NUM_LODS 8
#define BONE_TYPE_MASK 0x00F00000
#define BONE_FIXED_ALIGNMENT 0x00100000 // bone can't spin 360 degrees, all interpolation is normalized around a fixed orientation
#define BONE_HAS_SAVEFRAME_POS 0x00200000 // Vector48
#define BONE_HAS_SAVEFRAME_ROT 0x00400000 // Quaternion64
// bone controllers
struct mstudiobonecontroller_t
{
DECLARE_BYTESWAP_DATADESC();
int bone; // -1 == 0
int type; // X, Y, Z, XR, YR, ZR, M
float start;
float end;
int rest; // byte index value at rest
int inputfield; // 0-3 user set controller, 4 mouth
int unused[8];
};
// intersection boxes
struct mstudiobbox_t
{
DECLARE_BYTESWAP_DATADESC();
int bone;
int group; // intersection group
Vector bbmin; // bounding box
Vector bbmax;
int szhitboxnameindex; // offset to the name of the hitbox.
int unused[8];
const char* pszHitboxName()
{
if( szhitboxnameindex == 0 )
return "";
return ((const char*)this) + szhitboxnameindex;
}
mstudiobbox_t() {}
private:
// No copy constructors allowed
mstudiobbox_t(const mstudiobbox_t& vOther);
};
// demand loaded sequence groups
struct mstudiomodelgroup_t
{
DECLARE_BYTESWAP_DATADESC();
int szlabelindex; // textual name
inline char * const pszLabel( void ) const { return ((char *)this) + szlabelindex; }
int sznameindex; // file name
inline char * const pszName( void ) const { return ((char *)this) + sznameindex; }
};
struct mstudiomodelgrouplookup_t
{
int modelgroup;
int indexwithingroup;
};
// events
struct mstudioevent_t
{
DECLARE_BYTESWAP_DATADESC();
float cycle;
int event;
int type;
inline const char * pszOptions( void ) const { return options; }
char options[64];
int szeventindex;
inline char * const pszEventName( void ) const { return ((char *)this) + szeventindex; }
};
#define ATTACHMENT_FLAG_WORLD_ALIGN 0x10000
// attachment
struct mstudioattachment_t
{
DECLARE_BYTESWAP_DATADESC();
int sznameindex;
inline char * const pszName( void ) const { return ((char *)this) + sznameindex; }
unsigned int flags;
int localbone;
matrix3x4_t local; // attachment point
int unused[8];
};
#define IK_SELF 1
#define IK_WORLD 2
#define IK_GROUND 3
#define IK_RELEASE 4
#define IK_ATTACHMENT 5
#define IK_UNLATCH 6
struct mstudioikerror_t
{
DECLARE_BYTESWAP_DATADESC();
Vector pos;
Quaternion q;
mstudioikerror_t() {}
private:
// No copy constructors allowed
mstudioikerror_t(const mstudioikerror_t& vOther);
};
union mstudioanimvalue_t;
struct mstudiocompressedikerror_t
{
DECLARE_BYTESWAP_DATADESC();
float scale[6];
short offset[6];
inline mstudioanimvalue_t *pAnimvalue( int i ) const { if (offset[i] > 0) return (mstudioanimvalue_t *)(((byte *)this) + offset[i]); else return NULL; };
mstudiocompressedikerror_t(){}
private:
// No copy constructors allowed
mstudiocompressedikerror_t(const mstudiocompressedikerror_t& vOther);
};
struct mstudioikrule_t
{
DECLARE_BYTESWAP_DATADESC();
int index;
int type;
int chain;
int bone;
int slot; // iktarget slot. Usually same as chain.
float height;
float radius;
float floor;
Vector pos;
Quaternion q;
int compressedikerrorindex;
inline mstudiocompressedikerror_t *pCompressedError() const { return (mstudiocompressedikerror_t *)(((byte *)this) + compressedikerrorindex); };
int unused2;
int iStart;
int ikerrorindex;
inline mstudioikerror_t *pError( int i ) const { return (ikerrorindex) ? (mstudioikerror_t *)(((byte *)this) + ikerrorindex) + (i - iStart) : NULL; };
float start; // beginning of influence
float peak; // start of full influence
float tail; // end of full influence
float end; // end of all influence
float unused3; //
float contact; // frame footstep makes ground concact
float drop; // how far down the foot should drop when reaching for IK
float top; // top of the foot box
int unused6;
int unused7;
int unused8;
int szattachmentindex; // name of world attachment
inline char * const pszAttachment( void ) const { return ((char *)this) + szattachmentindex; }
int unused[7];
mstudioikrule_t() {}
private:
// No copy constructors allowed
mstudioikrule_t(const mstudioikrule_t& vOther);
};
struct mstudioiklock_t
{
DECLARE_BYTESWAP_DATADESC();
int chain;
float flPosWeight;
float flLocalQWeight;
int flags;
int unused[4];
};
struct mstudiolocalhierarchy_t
{
DECLARE_BYTESWAP_DATADESC();
int iBone; // bone being adjusted
int iNewParent; // the bones new parent
float start; // beginning of influence
float peak; // start of full influence
float tail; // end of full influence
float end; // end of all influence
int iStart; // first frame
int localanimindex;
inline mstudiocompressedikerror_t *pLocalAnim() const { return (mstudiocompressedikerror_t *)(((byte *)this) + localanimindex); };
int unused[4];
};
// animation frames
union mstudioanimvalue_t
{
struct
{
byte valid;
byte total;
} num;
short value;
};
struct mstudioanim_valueptr_t
{
DECLARE_BYTESWAP_DATADESC();
short offset[3];
inline mstudioanimvalue_t *pAnimvalue( int i ) const { if (offset[i] > 0) return (mstudioanimvalue_t *)(((byte *)this) + offset[i]); else return NULL; };
};
#define STUDIO_ANIM_RAWPOS 0x01 // Vector48
#define STUDIO_ANIM_RAWROT 0x02 // Quaternion48
#define STUDIO_ANIM_ANIMPOS 0x04 // mstudioanim_valueptr_t
#define STUDIO_ANIM_ANIMROT 0x08 // mstudioanim_valueptr_t
#define STUDIO_ANIM_DELTA 0x10
#define STUDIO_ANIM_RAWROT2 0x20 // Quaternion64
// per bone per animation DOF and weight pointers
struct mstudioanim_t
{
DECLARE_BYTESWAP_DATADESC();
byte bone;
byte flags; // weighing options
// valid for animating data only
inline byte *pData( void ) const { return (((byte *)this) + sizeof( struct mstudioanim_t )); };
inline mstudioanim_valueptr_t *pRotV( void ) const { return (mstudioanim_valueptr_t *)(pData()); };
inline mstudioanim_valueptr_t *pPosV( void ) const { return (mstudioanim_valueptr_t *)(pData()) + ((flags & STUDIO_ANIM_ANIMROT) != 0); };
// valid if animation unvaring over timeline
inline Quaternion48 *pQuat48( void ) const { return (Quaternion48 *)(pData()); };
inline Quaternion64 *pQuat64( void ) const { return (Quaternion64 *)(pData()); };
inline Vector48 *pPos( void ) const { return (Vector48 *)(pData() + ((flags & STUDIO_ANIM_RAWROT) != 0) * sizeof( *pQuat48() ) + ((flags & STUDIO_ANIM_RAWROT2) != 0) * sizeof( *pQuat64() ) ); };
short nextoffset;
inline mstudioanim_t *pNext( void ) const { if (nextoffset != 0) return (mstudioanim_t *)(((byte *)this) + nextoffset); else return NULL; };
};
struct mstudiomovement_t
{
DECLARE_BYTESWAP_DATADESC();
int endframe;
int motionflags;
float v0; // velocity at start of block
float v1; // velocity at end of block
float angle; // YAW rotation at end of this blocks movement
Vector vector; // movement vector relative to this blocks initial angle
Vector position; // relative to start of animation???
mstudiomovement_t(){}
private:
// No copy constructors allowed
mstudiomovement_t(const mstudiomovement_t& vOther);
};
struct studiohdr_t;
// used for piecewise loading of animation data
struct mstudioanimblock_t
{
DECLARE_BYTESWAP_DATADESC();
int datastart;
int dataend;
};
struct mstudioanimsections_t
{
DECLARE_BYTESWAP_DATADESC();
int animblock;
int animindex;
};
struct mstudioanimdesc_t
{
DECLARE_BYTESWAP_DATADESC();
int baseptr;
inline studiohdr_t *pStudiohdr( void ) const { return (studiohdr_t *)(((byte *)this) + baseptr); }
int sznameindex;
inline char * const pszName( void ) const { return ((char *)this) + sznameindex; }
float fps; // frames per second
int flags; // looping/non-looping flags
int numframes;
// piecewise movement
int nummovements;
int movementindex;
inline mstudiomovement_t * const pMovement( int i ) const { return (mstudiomovement_t *)(((byte *)this) + movementindex) + i; };
int unused1[6]; // remove as appropriate (and zero if loading older versions)
int animblock;
int animindex; // non-zero when anim data isn't in sections
mstudioanim_t *pAnimBlock( int block, int index ) const; // returns pointer to a specific anim block (local or external)
mstudioanim_t *pAnim( int *piFrame, float &flStall ) const; // returns pointer to data and new frame index
mstudioanim_t *pAnim( int *piFrame ) const; // returns pointer to data and new frame index
int numikrules;
int ikruleindex; // non-zero when IK data is stored in the mdl
int animblockikruleindex; // non-zero when IK data is stored in animblock file
mstudioikrule_t *pIKRule( int i ) const;
int numlocalhierarchy;
int localhierarchyindex;
mstudiolocalhierarchy_t *pHierarchy( int i ) const;
int sectionindex;
int sectionframes; // number of frames used in each fast lookup section, zero if not used
inline mstudioanimsections_t * const pSection( int i ) const { return (mstudioanimsections_t *)(((byte *)this) + sectionindex) + i; }
short zeroframespan; // frames per span
short zeroframecount; // number of spans
int zeroframeindex;
byte *pZeroFrameData( ) const { if (zeroframeindex) return (((byte *)this) + zeroframeindex); else return NULL; };
mutable float zeroframestalltime; // saved during read stalls
mstudioanimdesc_t(){}
private:
// No copy constructors allowed
mstudioanimdesc_t(const mstudioanimdesc_t& vOther);
};
struct mstudioikrule_t;
struct mstudioautolayer_t
{
DECLARE_BYTESWAP_DATADESC();
//private:
short iSequence;
short iPose;
//public:
int flags;
float start; // beginning of influence
float peak; // start of full influence
float tail; // end of full influence
float end; // end of all influence
};
// sequence descriptions
struct mstudioseqdesc_t
{
DECLARE_BYTESWAP_DATADESC();
int baseptr;
inline studiohdr_t *pStudiohdr( void ) const { return (studiohdr_t *)(((byte *)this) + baseptr); }
int szlabelindex;
inline char * const pszLabel( void ) const { return ((char *)this) + szlabelindex; }
int szactivitynameindex;
inline char * const pszActivityName( void ) const { return ((char *)this) + szactivitynameindex; }
int flags; // looping/non-looping flags
int activity; // initialized at loadtime to game DLL values
int actweight;
int numevents;
int eventindex;
inline mstudioevent_t *pEvent( int i ) const { Assert( i >= 0 && i < numevents); return (mstudioevent_t *)(((byte *)this) + eventindex) + i; };
Vector bbmin; // per sequence bounding box
Vector bbmax;
int numblends;
// Index into array of shorts which is groupsize[0] x groupsize[1] in length
int animindexindex;
inline int anim( int x, int y ) const
{
if ( x >= groupsize[0] )
{
x = groupsize[0] - 1;
}
if ( y >= groupsize[1] )
{
y = groupsize[ 1 ] - 1;
}
int offset = y * groupsize[0] + x;
short *blends = (short *)(((byte *)this) + animindexindex);
int value = (int)blends[ offset ];
return value;
}
int movementindex; // [blend] float array for blended movement
int groupsize[2];
int paramindex[2]; // X, Y, Z, XR, YR, ZR
float paramstart[2]; // local (0..1) starting value
float paramend[2]; // local (0..1) ending value
int paramparent;
float fadeintime; // ideal cross fate in time (0.2 default)
float fadeouttime; // ideal cross fade out time (0.2 default)
int localentrynode; // transition node at entry
int localexitnode; // transition node at exit
int nodeflags; // transition rules
float entryphase; // used to match entry gait
float exitphase; // used to match exit gait
float lastframe; // frame that should generation EndOfSequence
int nextseq; // auto advancing sequences
int pose; // index of delta animation between end and nextseq
int numikrules;
int numautolayers; //
int autolayerindex;
inline mstudioautolayer_t *pAutolayer( int i ) const { Assert( i >= 0 && i < numautolayers); return (mstudioautolayer_t *)(((byte *)this) + autolayerindex) + i; };
int weightlistindex;
inline float *pBoneweight( int i ) const { return ((float *)(((byte *)this) + weightlistindex) + i); };
inline float weight( int i ) const { return *(pBoneweight( i)); };
// FIXME: make this 2D instead of 2x1D arrays
int posekeyindex;
float *pPoseKey( int iParam, int iAnim ) const { return (float *)(((byte *)this) + posekeyindex) + iParam * groupsize[0] + iAnim; }
float poseKey( int iParam, int iAnim ) const { return *(pPoseKey( iParam, iAnim )); }
int numiklocks;
int iklockindex;
inline mstudioiklock_t *pIKLock( int i ) const { Assert( i >= 0 && i < numiklocks); return (mstudioiklock_t *)(((byte *)this) + iklockindex) + i; };
// Key values
int keyvalueindex;
int keyvaluesize;
inline const char * KeyValueText( void ) const { return keyvaluesize != 0 ? ((char *)this) + keyvalueindex : NULL; }
int cycleposeindex; // index of pose parameter to use as cycle index
int unused[7]; // remove/add as appropriate (grow back to 8 ints on version change!)
mstudioseqdesc_t(){}
private:
// No copy constructors allowed
mstudioseqdesc_t(const mstudioseqdesc_t& vOther);
};
struct mstudioposeparamdesc_t
{
DECLARE_BYTESWAP_DATADESC();
int sznameindex;
inline char * const pszName( void ) const { return ((char *)this) + sznameindex; }
int flags; // ????
float start; // starting value
float end; // ending value
float loop; // looping range, 0 for no looping, 360 for rotations, etc.
};
struct mstudioflexdesc_t
{
DECLARE_BYTESWAP_DATADESC();
int szFACSindex;
inline char * const pszFACS( void ) const { return ((char *)this) + szFACSindex; }
};
struct mstudioflexcontroller_t
{
DECLARE_BYTESWAP_DATADESC();
int sztypeindex;
inline char * const pszType( void ) const { return ((char *)this) + sztypeindex; }
int sznameindex;
inline char * const pszName( void ) const { return ((char *)this) + sznameindex; }
mutable int localToGlobal; // remapped at load time to master list
float min;
float max;
};
enum FlexControllerRemapType_t
{
FLEXCONTROLLER_REMAP_PASSTHRU = 0,
FLEXCONTROLLER_REMAP_2WAY, // Control 0 -> ramps from 1-0 from 0->0.5. Control 1 -> ramps from 0-1 from 0.5->1
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
FLEXCONTROLLER_REMAP_EYELID
};
class CStudioHdr;
struct mstudioflexcontrollerui_t
{
DECLARE_BYTESWAP_DATADESC();
int sznameindex;
inline char * const pszName( void ) const { return ((char *)this) + sznameindex; }
// These are used like a union to save space
// Here are the possible configurations for a UI controller
//
// SIMPLE NON-STEREO: 0: control 1: unused 2: unused
// STEREO: 0: left 1: right 2: unused
// NWAY NON-STEREO: 0: control 1: unused 2: value
// NWAY STEREO: 0: left 1: right 2: value
int szindex0;
int szindex1;
int szindex2;
inline const mstudioflexcontroller_t *pController( void ) const
{
return !stereo ? (mstudioflexcontroller_t *)( (char *)this + szindex0 ) : NULL;
}
inline char * const pszControllerName( void ) const { return !stereo ? pController()->pszName() : NULL; }
inline int controllerIndex( const CStudioHdr &cStudioHdr ) const;
inline const mstudioflexcontroller_t *pLeftController( void ) const
{
return stereo ? (mstudioflexcontroller_t *)( (char *)this + szindex0 ) : NULL;
}
inline char * const pszLeftName( void ) const { return stereo ? pLeftController()->pszName() : NULL; }
inline int leftIndex( const CStudioHdr &cStudioHdr ) const;
inline const mstudioflexcontroller_t *pRightController( void ) const
{
return stereo ? (mstudioflexcontroller_t *)( (char *)this + szindex1 ): NULL;
}
inline char * const pszRightName( void ) const { return stereo ? pRightController()->pszName() : NULL; }
inline int rightIndex( const CStudioHdr &cStudioHdr ) const;
inline const mstudioflexcontroller_t *pNWayValueController( void ) const
{
return remaptype == FLEXCONTROLLER_REMAP_NWAY ? (mstudioflexcontroller_t *)( (char *)this + szindex2 ) : NULL;
}
inline char * const pszNWayValueName( void ) const { return remaptype == FLEXCONTROLLER_REMAP_NWAY ? pNWayValueController()->pszName() : NULL; }
inline int nWayValueIndex( const CStudioHdr &cStudioHdr ) const;
// Number of controllers this ui description contains, 1, 2 or 3
inline int Count() const { return ( stereo ? 2 : 1 ) + ( remaptype == FLEXCONTROLLER_REMAP_NWAY ? 1 : 0 ); }
inline const mstudioflexcontroller_t *pController( int index ) const;
unsigned char remaptype; // See the FlexControllerRemapType_t enum
bool stereo; // Is this a stereo control?
byte unused[2];
};
// this is the memory image of vertex anims (16-bit fixed point)
struct mstudiovertanim_t
{
DECLARE_BYTESWAP_DATADESC();
unsigned short index;
byte speed; // 255/max_length_in_flex
byte side; // 255/left_right
protected:
// JasonM changing this type a lot, to prefer fixed point 16 bit...
union
{
short delta[3];
float16 flDelta[3];
};
union
{
short ndelta[3];
float16 flNDelta[3];
};
public:
inline void ConvertToFixed( float flVertAnimFixedPointScale )
{
delta[0] = flDelta[0].GetFloat() / flVertAnimFixedPointScale;
delta[1] = flDelta[1].GetFloat() / flVertAnimFixedPointScale;
delta[2] = flDelta[2].GetFloat() / flVertAnimFixedPointScale;
ndelta[0] = flNDelta[0].GetFloat() / flVertAnimFixedPointScale;
ndelta[1] = flNDelta[1].GetFloat() / flVertAnimFixedPointScale;
ndelta[2] = flNDelta[2].GetFloat() / flVertAnimFixedPointScale;
}
inline Vector GetDeltaFixed( float flVertAnimFixedPointScale )
{
return Vector( delta[0] * flVertAnimFixedPointScale, delta[1] * flVertAnimFixedPointScale, delta[2] * flVertAnimFixedPointScale );
}
inline Vector GetNDeltaFixed( float flVertAnimFixedPointScale )
{