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
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef OPTIMIZE_H
#define OPTIMIZE_H
#ifdef _WIN32
#pragma once
#endif
#include "studio.h"
// NOTE: You can change this without affecting the vtx file format.
#define MAX_NUM_BONES_PER_TRI ( MAX_NUM_BONES_PER_VERT * 3 )
#define MAX_NUM_BONES_PER_STRIP 512
#define OPTIMIZED_MODEL_FILE_VERSION 7
extern bool g_bDumpGLViewFiles;
struct s_bodypart_t;
namespace OptimizedModel
{
#pragma pack(1)
struct BoneStateChangeHeader_t
{
DECLARE_BYTESWAP_DATADESC();
int hardwareID;
int newBoneID;
};
struct Vertex_t
{
DECLARE_BYTESWAP_DATADESC();
// these index into the mesh's vert[origMeshVertID]'s bones
unsigned char boneWeightIndex[MAX_NUM_BONES_PER_VERT];
unsigned char numBones;
unsigned short origMeshVertID;
// for sw skinned verts, these are indices into the global list of bones
// for hw skinned verts, these are hardware bone indices
char boneID[MAX_NUM_BONES_PER_VERT];
};
enum StripHeaderFlags_t {
STRIP_IS_TRILIST = 0x01,
STRIP_IS_TRISTRIP = 0x02
};
// a strip is a piece of a stripgroup that is divided by bones
// (and potentially tristrips if we remove some degenerates.)
struct StripHeader_t
{
DECLARE_BYTESWAP_DATADESC();
// indexOffset offsets into the mesh's index array.
int numIndices;
int indexOffset;
// vertexOffset offsets into the mesh's vert array.
int numVerts;
int vertOffset;
// use this to enable/disable skinning.
// May decide (in optimize.cpp) to put all with 1 bone in a different strip
// than those that need skinning.
short numBones;
unsigned char flags;
int numBoneStateChanges;
int boneStateChangeOffset;
inline BoneStateChangeHeader_t *pBoneStateChange( int i ) const
{
return (BoneStateChangeHeader_t *)(((byte *)this) + boneStateChangeOffset) + i;
};
};
enum StripGroupFlags_t
{
STRIPGROUP_IS_FLEXED = 0x01,
STRIPGROUP_IS_HWSKINNED = 0x02,
STRIPGROUP_IS_DELTA_FLEXED = 0x04,
STRIPGROUP_SUPPRESS_HW_MORPH = 0x08, // NOTE: This is a temporary flag used at run time.
};
// a locking group
// a single vertex buffer
// a single index buffer
struct StripGroupHeader_t
{
DECLARE_BYTESWAP_DATADESC();
// These are the arrays of all verts and indices for this mesh. strips index into this.
int numVerts;
int vertOffset;
inline Vertex_t *pVertex( int i ) const
{
return (Vertex_t *)(((byte *)this) + vertOffset) + i;
};
int numIndices;
int indexOffset;
inline unsigned short *pIndex( int i ) const
{
return (unsigned short *)(((byte *)this) + indexOffset) + i;
};
int numStrips;
int stripOffset;
inline StripHeader_t *pStrip( int i ) const
{
return (StripHeader_t *)(((byte *)this) + stripOffset) + i;
};
unsigned char flags;
};
enum MeshFlags_t {
// these are both material properties, and a mesh has a single material.
MESH_IS_TEETH = 0x01,
MESH_IS_EYES = 0x02
};
// a collection of locking groups:
// up to 4:
// non-flexed, hardware skinned
// flexed, hardware skinned
// non-flexed, software skinned
// flexed, software skinned
//
// A mesh has a material associated with it.
struct MeshHeader_t
{
DECLARE_BYTESWAP_DATADESC();
int numStripGroups;
int stripGroupHeaderOffset;
inline StripGroupHeader_t *pStripGroup( int i ) const
{
StripGroupHeader_t *pDebug = (StripGroupHeader_t *)(((byte *)this) + stripGroupHeaderOffset) + i;
return pDebug;
};
unsigned char flags;
};
struct ModelLODHeader_t
{
DECLARE_BYTESWAP_DATADESC();
int numMeshes;
int meshOffset;
float switchPoint;
inline MeshHeader_t *pMesh( int i ) const
{
MeshHeader_t *pDebug = (MeshHeader_t *)(((byte *)this) + meshOffset) + i;
return pDebug;
};
};
// This maps one to one with models in the mdl file.
// There are a bunch of model LODs stored inside potentially due to the qc $lod command
struct ModelHeader_t
{
DECLARE_BYTESWAP_DATADESC();
int numLODs; // garymcthack - this is also specified in FileHeader_t
int lodOffset;
inline ModelLODHeader_t *pLOD( int i ) const
{
ModelLODHeader_t *pDebug = ( ModelLODHeader_t *)(((byte *)this) + lodOffset) + i;
return pDebug;
};
};
struct BodyPartHeader_t
{
DECLARE_BYTESWAP_DATADESC();
int numModels;
int modelOffset;
inline ModelHeader_t *pModel( int i ) const
{
ModelHeader_t *pDebug = (ModelHeader_t *)(((byte *)this) + modelOffset) + i;
return pDebug;
};
};
struct MaterialReplacementHeader_t
{
DECLARE_BYTESWAP_DATADESC();
short materialID;
int replacementMaterialNameOffset;
inline const char *pMaterialReplacementName( void )
{
const char *pDebug = (const char *)(((byte *)this) + replacementMaterialNameOffset);
return pDebug;
}
};
struct MaterialReplacementListHeader_t
{
DECLARE_BYTESWAP_DATADESC();
int numReplacements;
int replacementOffset;
inline MaterialReplacementHeader_t *pMaterialReplacement( int i ) const
{
MaterialReplacementHeader_t *pDebug = ( MaterialReplacementHeader_t *)(((byte *)this) + replacementOffset) + i;
return pDebug;
}
};
struct FileHeader_t
{
DECLARE_BYTESWAP_DATADESC();
// file version as defined by OPTIMIZED_MODEL_FILE_VERSION
int version;
// hardware params that affect how the model is to be optimized.
int vertCacheSize;
unsigned short maxBonesPerStrip;
unsigned short maxBonesPerTri;
int maxBonesPerVert;
// must match checkSum in the .mdl
int checkSum;
int numLODs; // garymcthack - this is also specified in ModelHeader_t and should match
// one of these for each LOD
int materialReplacementListOffset;
MaterialReplacementListHeader_t *pMaterialReplacementList( int lodID ) const
{
MaterialReplacementListHeader_t *pDebug =
(MaterialReplacementListHeader_t *)(((byte *)this) + materialReplacementListOffset) + lodID;
return pDebug;
}
int numBodyParts;
int bodyPartOffset;
inline BodyPartHeader_t *pBodyPart( int i ) const
{
BodyPartHeader_t *pDebug = (BodyPartHeader_t *)(((byte *)this) + bodyPartOffset) + i;
return pDebug;
};
};
#pragma pack()
void WriteOptimizedFiles( studiohdr_t *phdr, s_bodypart_t *pSrcBodyParts );
}; // namespace OptimizedModel
#endif // OPTIMIZE_H
|