59d6acbe8c5288e16858063bd6ee5ed5464fda1c
[csRadar.git] / vmdl.h
1 // VVD
2 //=======================================================================================================================
3 //StudioMDL constants
4
5 #define MAX_NUM_LODS 8
6 #define MAX_NUM_BONES_PER_VERT 3
7
8 #pragma pack(push, 1)
9 typedef struct
10 {
11 float weight[MAX_NUM_BONES_PER_VERT];
12 char bone[MAX_NUM_BONES_PER_VERT];
13 char numbones;
14 }
15 boneWeight_t;
16
17 typedef struct
18 {
19 boneWeight_t boneweights;
20 float pos[3];
21 float norm[3];
22 float uv[2];
23 }
24 mstudiovertex_t;
25
26 typedef struct
27 {
28 int id;
29 int version;
30 int checksum;
31 int numLods;
32 int numLodVertexes[MAX_NUM_LODS];
33 int numFixups;
34 int fixupTableStart;
35 int vertexDataStart;
36 int tangentDataStart;
37 }
38 vertexFileHeader_t;
39
40 #pragma pack(pop)
41
42 mstudiovertex_t *GetVertexData( vertexFileHeader_t *t )
43 {
44 return (mstudiovertex_t *) ( (char *)t + t->vertexDataStart );
45 }
46
47 // VTX
48 //=======================================================================================================================
49
50 #pragma pack(push, 1)
51
52 typedef struct
53 {
54 // these index into the mesh's vert[origMeshVertID]'s bones
55 unsigned char boneWeightIndex[3];
56 unsigned char numBones;
57
58 unsigned short origMeshVertID;
59
60 // for sw skinned verts, these are indices into the global list of bones
61 // for hw skinned verts, these are hardware bone indices
62 char boneID[3];
63 }
64 VTXVertex_t;
65
66 enum StripGroupFlags
67 {
68 STRIPGROUP_IS_FLEXED = 0x01,
69 STRIPGROUP_IS_HWSKINNED = 0x02,
70 STRIPGROUP_IS_DELTA_FLEXED = 0x04,
71 STRIPGROUP_SUPPRESS_HW_MORPH = 0x08, // NOTE: This is a temporary flag used at run time.
72 };
73
74 enum StripHeaderFlags_t {
75 STRIP_IS_TRILIST = 0x01,
76 STRIP_IS_TRISTRIP = 0x02
77 };
78
79 // A strip is a piece of a stripgroup which is divided by bones
80 typedef struct
81 {
82 //Indices array
83 int numIndices;
84 int indexOffset;
85
86 //Vertices array
87 int numVerts;
88 int vertOffset;
89
90 short numBones;
91
92 unsigned char flags;
93
94 int numBoneStateChanges;
95 int boneStateChangeOffset;
96 }
97 VTXStripHeader_t;
98 // Bone state change inline code ommited
99
100 // a locking group
101 // a single vertex buffer
102 // a single index buffer
103 typedef struct
104 {
105 // These are the arrays of all verts and indices for this mesh. strips index into this.
106 int numVerts;
107 int vertOffset;
108
109 int numIndices;
110 int indexOffset;
111
112 int numStrips;
113 int stripOffset;
114
115 unsigned char flags;
116 }
117 VTXStripGroupHeader_t;
118
119 VTXVertex_t *pVertexVTX( VTXStripGroupHeader_t *t, int i )
120 {
121 return (VTXVertex_t *)(((char *)t) + t->vertOffset) + i;
122 }
123 unsigned short *pIndexVTX( VTXStripGroupHeader_t *t, int i )
124 {
125 return (unsigned short *)(((char *)t) + t->indexOffset) + i;
126 }
127 VTXStripHeader_t *pStripVTX( VTXStripGroupHeader_t *t, int i )
128 {
129 return (VTXStripHeader_t *)(((char *)t) + t->stripOffset) + i;
130 }
131
132 typedef struct
133 {
134 int numStripGroups;
135 int stripGroupHeaderOffset;
136
137 unsigned char flags;
138 }
139 VTXMeshHeader_t;
140 VTXStripGroupHeader_t *pStripGroupVTX( VTXMeshHeader_t *t, int i )
141 {
142 return (VTXStripGroupHeader_t *)(((char *)t) + t->stripGroupHeaderOffset) + i;
143 }
144
145 typedef struct
146 {
147 //Mesh array
148 int numMeshes;
149 int meshOffset;
150
151 float switchPoint;
152 }
153 VTXModelLODHeader_t;
154 VTXMeshHeader_t *pMeshVTX( VTXModelLODHeader_t *t, int i )
155 {
156 return (VTXMeshHeader_t *)(((char *)t) + t->meshOffset) + i;
157 }
158
159 // This maps one to one with models in the mdl file.
160 typedef struct
161 {
162 //LOD mesh array
163 int numLODs; //This is also specified in FileHeader_t
164 int lodOffset;
165 }
166 VTXModelHeader_t;
167 VTXModelLODHeader_t *pLODVTX( VTXModelHeader_t *t, int i )
168 {
169 return (VTXModelLODHeader_t *)(((char *)t) + t->lodOffset) + i;
170 }
171
172 typedef struct
173 {
174 //Model array
175 int numModels;
176 int modelOffset;
177 }
178 VTXBodyPartHeader_t;
179 VTXModelHeader_t *pModelVTX( VTXBodyPartHeader_t *t, int i )
180 {
181 return (VTXModelHeader_t *)(((char *)t) + t->modelOffset) + i;
182 }
183
184 typedef struct
185 {
186 // file version as defined by OPTIMIZED_MODEL_FILE_VERSION (currently 7)
187 int version;
188
189 // hardware params that affect how the model is to be optimized.
190 int vertCacheSize;
191 unsigned short maxBonesPerStrip;
192 unsigned short maxBonesPerTri;
193 int maxBonesPerVert;
194
195 // must match checkSum in the .mdl
196 int checkSum;
197
198 int numLODs; // Also specified in ModelHeader_t's and should match
199
200 // Offset to materialReplacementList Array. one of these for each LOD, 8 in total
201 int materialReplacementListOffset;
202
203 //Defines the size and location of the body part array
204 int numBodyParts;
205 int bodyPartOffset;
206 }
207 VTXFileHeader_t;
208 VTXBodyPartHeader_t *pBodyPartVTX( VTXFileHeader_t *t, int i )
209 {
210 return (VTXBodyPartHeader_t *)(((char *)t) + t->bodyPartOffset) + i;
211 }
212
213 /*
214 .VTX file structure
215 =============================================
216
217 FileHeader
218 L BodyParts::
219 L Models::
220 L LODS::
221 L Meshes::
222 L StripGroups::
223 L VerticesTable[StudioMDL.Vertex]
224 L IndicesTable[UINT16]
225 |
226 L Strips::
227 L Vertices[UINT16]
228 L Indices[UINT16]
229 */
230
231 #pragma pack(pop)
232
233 u32 vtx_count_indices( VTXFileHeader_t *t )
234 {
235 u32 indices = 0;
236
237 for ( int bodyID = 0; bodyID < t->numBodyParts; ++bodyID )
238 {
239 VTXBodyPartHeader_t* pVtxBodyPart = pBodyPartVTX( t, bodyID );
240 for ( int modelID = 0; modelID < pVtxBodyPart->numModels; ++modelID )
241 {
242 VTXModelHeader_t* pVtxModel = pModelVTX( pVtxBodyPart, modelID );
243
244 int nLod = 0;
245 VTXModelLODHeader_t *pVtxLOD = pLODVTX( pVtxModel, nLod );
246
247 for ( int nMesh = 0; nMesh < pVtxLOD->numMeshes; ++nMesh )
248 {
249 VTXMeshHeader_t* pVtxMesh = pMeshVTX( pVtxLOD, nMesh );
250
251 for ( int nGroup = 0; nGroup < pVtxMesh->numStripGroups; ++nGroup )
252 {
253 VTXStripGroupHeader_t* pStripGroup = pStripGroupVTX( pVtxMesh, nGroup );
254
255 for ( int nStrip = 0; nStrip < pStripGroup->numStrips; nStrip++ )
256 {
257 VTXStripHeader_t *pStrip = pStripVTX( pStripGroup, nStrip );
258
259 if ( pStrip->flags & STRIP_IS_TRILIST )
260 {
261 indices += pStrip->numIndices;
262 }
263 }
264 }
265 }
266 }
267 }
268
269 return indices;
270 }
271
272 // MDL
273 //=======================================================================================================================
274
275 #pragma pack(push, 1)
276
277 typedef struct
278 {
279 // base of external vertex data stores
280 void *pVertexData;
281 void *pTangentData;
282 }
283 mstudio_modelvertexdata_t;
284
285 typedef struct
286 {
287 // indirection to this mesh's model's vertex data
288 int unused_modelvertexdata; // 64b - Moved to follow num_LOD_Vertexes.
289
290 // used for fixup calcs when culling top level lods
291 // expected number of mesh verts at desired lod
292 int numLODVertexes[MAX_NUM_LODS];
293
294 mstudio_modelvertexdata_t *_the_death_ptr;
295 }
296 mstudio_meshvertexdata_t;
297
298 typedef struct mstudiomodel_t mstudiomodel_t;
299
300 typedef struct
301 {
302 int material;
303 int modelindex;
304 int numvertices; // number of unique vertices/normals/texcoords
305 int vertexoffset; // vertex mstudiovertex_t
306 int numflexes; // vertex animation
307 int flexindex;
308 // special codes for material operations
309 int materialtype;
310 int materialparam;
311 // a unique ordinal for this mesh
312 int meshid;
313 float center[3];
314 mstudio_meshvertexdata_t vertexdata;
315
316 int unused[6]; // remove as appropriate
317 }
318 mstudiomesh_t;
319
320 // studio models
321 struct mstudiomodel_t
322 {
323 char name[64];
324 int type;
325 float boundingradius;
326
327 int nummeshes;
328 int meshindex;
329
330 int numvertices; // number of unique vertices/normals/texcoords
331 int vertexindex; // vertex Vector
332 int tangentsindex; // tangents Vector
333
334 int numattachments;
335 int attachmentindex;
336
337 int numeyeballs;
338 int eyeballindex;
339
340 mstudio_modelvertexdata_t vertexdata;
341
342 int unused[8]; // remove as appropriate
343 };
344 mstudiomesh_t *studiomodel_pMesh( mstudiomodel_t *t, int i )
345 {
346 return (mstudiomesh_t *)(((char *)t) + t->meshindex) + i;
347 };
348
349 typedef struct
350 {
351 int sznameindex;
352 int nummodels;
353 int base;
354 int modelindex; // index into models array
355 } mstudiobodyparts_t;
356
357 mstudiomodel_t *mstudiobodyparts_pModel( mstudiobodyparts_t *t, int i )
358 {
359 return (mstudiomodel_t *)(((char *)t) + t->modelindex) + i;
360 };
361
362 typedef struct {
363 int id;
364 int version;
365 int checksum; // this has to be the same in the phy and vtx files to load!
366 char name[64];
367 int length;
368 float eyeposition[3]; // ideal eye position
369 float illumposition[3]; // illumination center
370 float hull_min[3]; // ideal movement hull size
371 float hull_max[3];
372 float view_bbmin[3]; // clipping bounding box
373 float view_bbmax[3];
374 int flags;
375 int numbones; // bones
376 int boneindex;
377 int numbonecontrollers; // bone controllers
378 int bonecontrollerindex;
379 int numhitboxsets;
380 int hitboxsetindex;
381 int numlocalanim; // animations/poses
382 int localanimindex; // animation descriptions
383 int numlocalseq; // sequences
384 int localseqindex;
385 int activitylistversion;
386 int eventsindexed;
387 // raw textures
388 int numtextures;
389 int textureindex;
390 // raw textures search paths
391 int numcdtextures;
392 int cdtextureindex;
393 // replaceable textures tables
394 int numskinref;
395 int numskinfamilies;
396 int skinindex;
397 int numbodyparts;
398 int bodypartindex;
399 // queryable attachable points
400 int numlocalattachments;
401 int localattachmentindex;
402 // animation node to animation node transition graph
403 int numlocalnodes;
404 int localnodeindex;
405 int localnodenameindex;
406 int numflexdesc;
407 int flexdescindex;
408 int numflexcontrollers;
409 int flexcontrollerindex;
410 int numflexrules;
411 int flexruleindex;
412 int numikchains;
413 int ikchainindex;
414 int nummouths;
415 int mouthindex;
416 int numlocalposeparameters;
417 int localposeparamindex;
418 int surfacepropindex;
419 // Key values
420 int keyvalueindex;
421 int keyvaluesize;
422 int numlocalikautoplaylocks;
423 int localikautoplaylockindex;
424 // The collision model mass that jay wanted
425 float mass;
426 int contents;
427 // external animations, models, etc.
428 int numincludemodels;
429 int includemodelindex;
430 // for demand loaded animation blocks
431 int szanimblocknameindex;
432 int numanimblocks;
433 int animblockindex;
434 int bonetablebynameindex;
435 char constdirectionallightdot;
436 char rootLOD;
437 char numAllowedRootLODs;
438 char unused[1];
439 int unused4; // zero out if version < 47
440 int numflexcontrollerui;
441 int flexcontrolleruiindex;
442 float flVertAnimFixedPointScale;
443 int unused3[1];
444 int studiohdr2index;
445 int unused2[1];
446 }
447 studiohdr_t;
448
449 mstudiobodyparts_t *studiohdr_pBodypart( studiohdr_t *t, int i )
450 {
451 return (mstudiobodyparts_t *)(((char *)t) + t->bodypartindex) + i;
452 };
453
454 #pragma pack(pop)
455
456 typedef struct
457 {
458 u16 *indices;
459 u32 num_indices;
460
461 float *vertices;
462 u32 num_vertices;
463
464 // Bounding box
465 boxf bounds;
466 }
467 mdl_mesh_t;
468
469 void mdl_free( mdl_mesh_t *m )
470 {
471 free( m->indices );
472 free( m->vertices );
473 }
474
475 void mdl_error( mdl_mesh_t *m )
476 {
477 m->num_indices = 0;
478 m->num_vertices = 0;
479 m->indices = NULL;
480 m->vertices = NULL;
481 }
482
483 int mdl_from_find_files( const char *mdlname, mdl_mesh_t *ctx )
484 {
485 // Read entire files into memory (inline functions map memory)
486 // .DX90.VTX
487 char path[1024];
488 strcpy( path, mdlname );
489 csr_stripext( path );
490 strcat( path, ".dx90.vtx" );
491 VTXFileHeader_t *pVtxHdr = (VTXFileHeader_t *)valve_fs_get( path );
492
493 if( !pVtxHdr )
494 {
495 mdl_error( ctx );
496 return 0;
497 }
498
499 // .VVD
500 strcpy( path, mdlname );
501 csr_stripext( path );
502 strcat( path, ".vvd" );
503 vertexFileHeader_t *pVvdHdr = (vertexFileHeader_t *)valve_fs_get( path );
504
505 if( !pVvdHdr )
506 {
507 free( pVtxHdr );
508 mdl_error( ctx );
509 return 0;
510 }
511
512 // .MDL
513 strcpy( path, mdlname );
514 csr_stripext( path );
515 strcat( path, ".mdl" );
516 studiohdr_t *pMdl = (studiohdr_t *)valve_fs_get( path );
517
518 if( !pMdl )
519 {
520 free( pVtxHdr );
521 free( pVvdHdr );
522 mdl_error( ctx );
523 return 0;
524 }
525
526 v3_copy( pMdl->view_bbmin, ctx->bounds[0] );
527 v3_copy( pMdl->view_bbmax, ctx->bounds[1] );
528
529 ctx->num_indices = vtx_count_indices( pVtxHdr );
530
531 // Allocate and read indices
532 ctx->indices = (u16 *)csr_malloc( ctx->num_indices * sizeof( u16 ) );
533 ctx->num_indices = 0;
534
535 for ( int bodyID = 0; bodyID < pMdl->numbodyparts; ++bodyID )
536 {
537 // Body parts
538 VTXBodyPartHeader_t* pVtxBodyPart = pBodyPartVTX( pVtxHdr, bodyID );
539 mstudiobodyparts_t *pBodyPart = studiohdr_pBodypart( pMdl, bodyID );
540
541 for ( int modelID = 0; modelID < pBodyPart->nummodels; ++modelID )
542 {
543 // Models
544 VTXModelHeader_t* pVtxModel = pModelVTX( pVtxBodyPart, modelID );
545 mstudiomodel_t *pStudioModel = mstudiobodyparts_pModel( pBodyPart, modelID );
546
547 int nLod = 0;
548 VTXModelLODHeader_t *pVtxLOD = pLODVTX( pVtxModel, nLod );
549
550 for ( int nMesh = 0; nMesh < pStudioModel->nummeshes; ++nMesh )
551 {
552 // Meshes
553 VTXMeshHeader_t* pVtxMesh = pMeshVTX( pVtxLOD, nMesh );
554 mstudiomesh_t* pMesh = studiomodel_pMesh( pStudioModel, nMesh );
555
556 for ( int nGroup = 0; nGroup < pVtxMesh->numStripGroups; ++nGroup )
557 {
558 // Groups
559 VTXStripGroupHeader_t* pStripGroup = pStripGroupVTX( pVtxMesh, nGroup );
560
561 for ( int nStrip = 0; nStrip < pStripGroup->numStrips; nStrip++ )
562 {
563 // Strips
564 VTXStripHeader_t *pStrip = pStripVTX( pStripGroup, nStrip );
565
566 if ( pStrip->flags & STRIP_IS_TRILIST )
567 {
568 // Indices
569 for ( int i = 0; i < pStrip->numIndices; i ++ )
570 {
571 u16 i1 = *pIndexVTX( pStripGroup, pStrip->indexOffset + i );
572 ctx->indices[ ctx->num_indices ++ ] = pVertexVTX( pStripGroup, i1 )->origMeshVertID + pMesh->vertexoffset;
573 }
574 }
575 }
576 }
577 }
578 }
579 }
580
581 mstudiovertex_t *vertexData = GetVertexData( pVvdHdr );
582
583 // Allocate vertex blob (XYZ|NRM|UV)
584 ctx->num_vertices = pVvdHdr->numLodVertexes[0];
585 ctx->vertices = (float *)csr_malloc( ctx->num_vertices * 8 * sizeof( float ) );
586
587 for( int i = 0; i < ctx->num_vertices; i ++ )
588 {
589 mstudiovertex_t *vert = vertexData + i;
590 memcpy( ctx->vertices + i * 8, vert->pos, 8 * sizeof(float) );
591 }
592
593 free( pVtxHdr );
594 free( pVvdHdr );
595 free( pMdl );
596
597 return 1;
598 }