1 // This software is not affiliated with Valve Corporation
2 // We are not affiliated, associated, authorized, endorsed by, or in any way officially
3 // connected with Valve Corporation, or any of its subsidiaries or its affiliates.
5 // All trademarks are property of their respective owners
7 typedef struct mdl_mesh mdl_mesh_t
;
10 //=======================================================================================================================
12 // Load model from vfs
13 int mdl_from_find_files( const char *mdlname
, mdl_mesh_t
*ctx
);
14 void mdl_free( mdl_mesh_t
*m
);
16 // Set ctx to blank / 0,0
17 void mdl_error( mdl_mesh_t
*m
);
20 //=======================================================================================================================
34 #ifdef VALVE_IMPLEMENTATION
37 //=======================================================================================================================
40 #define MAX_NUM_LODS 8
41 #define MAX_NUM_BONES_PER_VERT 3
46 float weight
[MAX_NUM_BONES_PER_VERT
];
47 char bone
[MAX_NUM_BONES_PER_VERT
];
54 boneWeight_t boneweights
;
67 int numLodVertexes
[MAX_NUM_LODS
];
77 mstudiovertex_t
*GetVertexData( vertexFileHeader_t
*t
)
79 return (mstudiovertex_t
*) ( (char *)t
+ t
->vertexDataStart
);
83 //=======================================================================================================================
89 // these index into the mesh's vert[origMeshVertID]'s bones
90 unsigned char boneWeightIndex
[3];
91 unsigned char numBones
;
93 unsigned short origMeshVertID
;
95 // for sw skinned verts, these are indices into the global list of bones
96 // for hw skinned verts, these are hardware bone indices
103 STRIPGROUP_IS_FLEXED
= 0x01,
104 STRIPGROUP_IS_HWSKINNED
= 0x02,
105 STRIPGROUP_IS_DELTA_FLEXED
= 0x04,
106 STRIPGROUP_SUPPRESS_HW_MORPH
= 0x08, // NOTE: This is a temporary flag used at run time.
109 enum StripHeaderFlags_t
{
110 STRIP_IS_TRILIST
= 0x01,
111 STRIP_IS_TRISTRIP
= 0x02
114 // A strip is a piece of a stripgroup which is divided by bones
129 int numBoneStateChanges
;
130 int boneStateChangeOffset
;
133 // Bone state change inline code ommited
136 // a single vertex buffer
137 // a single index buffer
140 // These are the arrays of all verts and indices for this mesh. strips index into this.
152 VTXStripGroupHeader_t
;
154 VTXVertex_t
*pVertexVTX( VTXStripGroupHeader_t
*t
, int i
)
156 return (VTXVertex_t
*)(((char *)t
) + t
->vertOffset
) + i
;
158 unsigned short *pIndexVTX( VTXStripGroupHeader_t
*t
, int i
)
160 return (unsigned short *)(((char *)t
) + t
->indexOffset
) + i
;
162 VTXStripHeader_t
*pStripVTX( VTXStripGroupHeader_t
*t
, int i
)
164 return (VTXStripHeader_t
*)(((char *)t
) + t
->stripOffset
) + i
;
170 int stripGroupHeaderOffset
;
175 VTXStripGroupHeader_t
*pStripGroupVTX( VTXMeshHeader_t
*t
, int i
)
177 return (VTXStripGroupHeader_t
*)(((char *)t
) + t
->stripGroupHeaderOffset
) + i
;
189 VTXMeshHeader_t
*pMeshVTX( VTXModelLODHeader_t
*t
, int i
)
191 return (VTXMeshHeader_t
*)(((char *)t
) + t
->meshOffset
) + i
;
194 // This maps one to one with models in the mdl file.
198 int numLODs
; //This is also specified in FileHeader_t
202 VTXModelLODHeader_t
*pLODVTX( VTXModelHeader_t
*t
, int i
)
204 return (VTXModelLODHeader_t
*)(((char *)t
) + t
->lodOffset
) + i
;
214 VTXModelHeader_t
*pModelVTX( VTXBodyPartHeader_t
*t
, int i
)
216 return (VTXModelHeader_t
*)(((char *)t
) + t
->modelOffset
) + i
;
221 // file version as defined by OPTIMIZED_MODEL_FILE_VERSION (currently 7)
224 // hardware params that affect how the model is to be optimized.
226 unsigned short maxBonesPerStrip
;
227 unsigned short maxBonesPerTri
;
230 // must match checkSum in the .mdl
233 int numLODs
; // Also specified in ModelHeader_t's and should match
235 // Offset to materialReplacementList Array. one of these for each LOD, 8 in total
236 int materialReplacementListOffset
;
238 //Defines the size and location of the body part array
243 VTXBodyPartHeader_t
*pBodyPartVTX( VTXFileHeader_t
*t
, int i
)
245 return (VTXBodyPartHeader_t
*)(((char *)t
) + t
->bodyPartOffset
) + i
;
250 =============================================
258 L VerticesTable[StudioMDL.Vertex]
259 L IndicesTable[UINT16]
268 u32
vtx_count_indices( VTXFileHeader_t
*t
)
272 for ( int bodyID
= 0; bodyID
< t
->numBodyParts
; ++bodyID
)
274 VTXBodyPartHeader_t
* pVtxBodyPart
= pBodyPartVTX( t
, bodyID
);
275 for ( int modelID
= 0; modelID
< pVtxBodyPart
->numModels
; ++modelID
)
277 VTXModelHeader_t
* pVtxModel
= pModelVTX( pVtxBodyPart
, modelID
);
280 VTXModelLODHeader_t
*pVtxLOD
= pLODVTX( pVtxModel
, nLod
);
282 for ( int nMesh
= 0; nMesh
< pVtxLOD
->numMeshes
; ++nMesh
)
284 VTXMeshHeader_t
* pVtxMesh
= pMeshVTX( pVtxLOD
, nMesh
);
286 for ( int nGroup
= 0; nGroup
< pVtxMesh
->numStripGroups
; ++nGroup
)
288 VTXStripGroupHeader_t
* pStripGroup
= pStripGroupVTX( pVtxMesh
, nGroup
);
290 for ( int nStrip
= 0; nStrip
< pStripGroup
->numStrips
; nStrip
++ )
292 VTXStripHeader_t
*pStrip
= pStripVTX( pStripGroup
, nStrip
);
294 if ( pStrip
->flags
& STRIP_IS_TRILIST
)
296 indices
+= pStrip
->numIndices
;
308 //=======================================================================================================================
310 #pragma pack(push, 1)
314 // base of external vertex data stores
318 mstudio_modelvertexdata_t
;
322 // indirection to this mesh's model's vertex data
323 int unused_modelvertexdata
; // 64b - Moved to follow num_LOD_Vertexes.
325 // used for fixup calcs when culling top level lods
326 // expected number of mesh verts at desired lod
327 int numLODVertexes
[MAX_NUM_LODS
];
329 mstudio_modelvertexdata_t
*_the_death_ptr
;
331 mstudio_meshvertexdata_t
;
333 typedef struct mstudiomodel_t mstudiomodel_t
;
339 int numvertices
; // number of unique vertices/normals/texcoords
340 int vertexoffset
; // vertex mstudiovertex_t
341 int numflexes
; // vertex animation
343 // special codes for material operations
346 // a unique ordinal for this mesh
349 mstudio_meshvertexdata_t vertexdata
;
351 int unused
[6]; // remove as appropriate
356 struct mstudiomodel_t
360 float boundingradius
;
365 int numvertices
; // number of unique vertices/normals/texcoords
366 int vertexindex
; // vertex Vector
367 int tangentsindex
; // tangents Vector
375 mstudio_modelvertexdata_t vertexdata
;
377 int unused
[8]; // remove as appropriate
379 mstudiomesh_t
*studiomodel_pMesh( mstudiomodel_t
*t
, int i
)
381 return (mstudiomesh_t
*)(((char *)t
) + t
->meshindex
) + i
;
389 int modelindex
; // index into models array
390 } mstudiobodyparts_t
;
392 mstudiomodel_t
*mstudiobodyparts_pModel( mstudiobodyparts_t
*t
, int i
)
394 return (mstudiomodel_t
*)(((char *)t
) + t
->modelindex
) + i
;
400 int checksum
; // this has to be the same in the phy and vtx files to load!
403 float eyeposition
[3]; // ideal eye position
404 float illumposition
[3]; // illumination center
405 float hull_min
[3]; // ideal movement hull size
407 float view_bbmin
[3]; // clipping bounding box
410 int numbones
; // bones
412 int numbonecontrollers
; // bone controllers
413 int bonecontrollerindex
;
416 int numlocalanim
; // animations/poses
417 int localanimindex
; // animation descriptions
418 int numlocalseq
; // sequences
420 int activitylistversion
;
425 // raw textures search paths
428 // replaceable textures tables
434 // queryable attachable points
435 int numlocalattachments
;
436 int localattachmentindex
;
437 // animation node to animation node transition graph
440 int localnodenameindex
;
443 int numflexcontrollers
;
444 int flexcontrollerindex
;
451 int numlocalposeparameters
;
452 int localposeparamindex
;
453 int surfacepropindex
;
457 int numlocalikautoplaylocks
;
458 int localikautoplaylockindex
;
459 // The collision model mass that jay wanted
462 // external animations, models, etc.
463 int numincludemodels
;
464 int includemodelindex
;
465 // for demand loaded animation blocks
466 int szanimblocknameindex
;
469 int bonetablebynameindex
;
470 char constdirectionallightdot
;
472 char numAllowedRootLODs
;
474 int unused4
; // zero out if version < 47
475 int numflexcontrollerui
;
476 int flexcontrolleruiindex
;
477 float flVertAnimFixedPointScale
;
484 mstudiobodyparts_t
*studiohdr_pBodypart( studiohdr_t
*t
, int i
)
486 return (mstudiobodyparts_t
*)(((char *)t
) + t
->bodypartindex
) + i
;
491 void mdl_free( mdl_mesh_t
*m
)
497 void mdl_error( mdl_mesh_t
*m
)
505 int mdl_from_find_files( const char *mdlname
, mdl_mesh_t
*ctx
)
507 // Read entire files into memory (inline functions map memory)
510 strcpy( path
, mdlname
);
511 csr_stripext( path
);
512 strcat( path
, ".dx90.vtx" );
513 VTXFileHeader_t
*pVtxHdr
= (VTXFileHeader_t
*)valve_fs_get( path
);
522 strcpy( path
, mdlname
);
523 csr_stripext( path
);
524 strcat( path
, ".vvd" );
525 vertexFileHeader_t
*pVvdHdr
= (vertexFileHeader_t
*)valve_fs_get( path
);
535 strcpy( path
, mdlname
);
536 csr_stripext( path
);
537 strcat( path
, ".mdl" );
538 studiohdr_t
*pMdl
= (studiohdr_t
*)valve_fs_get( path
);
548 v3_copy( pMdl
->hull_min
, ctx
->bounds
[0] );
549 v3_copy( pMdl
->hull_max
, ctx
->bounds
[1] );
551 ctx
->num_indices
= vtx_count_indices( pVtxHdr
);
553 // Allocate and read indices
554 ctx
->indices
= (u16
*)csr_malloc( ctx
->num_indices
* sizeof( u16
) );
555 ctx
->num_indices
= 0;
557 for ( int bodyID
= 0; bodyID
< pMdl
->numbodyparts
; ++bodyID
)
560 VTXBodyPartHeader_t
* pVtxBodyPart
= pBodyPartVTX( pVtxHdr
, bodyID
);
561 mstudiobodyparts_t
*pBodyPart
= studiohdr_pBodypart( pMdl
, bodyID
);
563 for ( int modelID
= 0; modelID
< pBodyPart
->nummodels
; ++modelID
)
566 VTXModelHeader_t
* pVtxModel
= pModelVTX( pVtxBodyPart
, modelID
);
567 mstudiomodel_t
*pStudioModel
= mstudiobodyparts_pModel( pBodyPart
, modelID
);
570 VTXModelLODHeader_t
*pVtxLOD
= pLODVTX( pVtxModel
, nLod
);
572 for ( int nMesh
= 0; nMesh
< pStudioModel
->nummeshes
; ++nMesh
)
575 VTXMeshHeader_t
* pVtxMesh
= pMeshVTX( pVtxLOD
, nMesh
);
576 mstudiomesh_t
* pMesh
= studiomodel_pMesh( pStudioModel
, nMesh
);
578 for ( int nGroup
= 0; nGroup
< pVtxMesh
->numStripGroups
; ++nGroup
)
581 VTXStripGroupHeader_t
* pStripGroup
= pStripGroupVTX( pVtxMesh
, nGroup
);
583 for ( int nStrip
= 0; nStrip
< pStripGroup
->numStrips
; nStrip
++ )
586 VTXStripHeader_t
*pStrip
= pStripVTX( pStripGroup
, nStrip
);
588 if ( pStrip
->flags
& STRIP_IS_TRILIST
)
591 for ( int i
= 0; i
< pStrip
->numIndices
; i
++ )
593 u16 i1
= *pIndexVTX( pStripGroup
, pStrip
->indexOffset
+ i
);
594 ctx
->indices
[ ctx
->num_indices
++ ] = pVertexVTX( pStripGroup
, i1
)->origMeshVertID
+ pMesh
->vertexoffset
;
603 mstudiovertex_t
*vertexData
= GetVertexData( pVvdHdr
);
605 // Allocate vertex blob (XYZ|NRM|UV)
606 ctx
->num_vertices
= pVvdHdr
->numLodVertexes
[0];
607 ctx
->vertices
= (float *)csr_malloc( ctx
->num_vertices
* 8 * sizeof( float ) );
609 for( int i
= 0; i
< ctx
->num_vertices
; i
++ )
611 mstudiovertex_t
*vert
= vertexData
+ i
;
612 memcpy( ctx
->vertices
+ i
* 8, vert
->pos
, 8 * sizeof(float) );