2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 cvar_t r_skeletal_debugbone = {0, "r_skeletal_debugbone", "-1", "development cvar for testing skeletal model code"};
26 cvar_t r_skeletal_debugbonecomponent = {0, "r_skeletal_debugbonecomponent", "3", "development cvar for testing skeletal model code"};
27 cvar_t r_skeletal_debugbonevalue = {0, "r_skeletal_debugbonevalue", "100", "development cvar for testing skeletal model code"};
28 cvar_t r_skeletal_debugtranslatex = {0, "r_skeletal_debugtranslatex", "1", "development cvar for testing skeletal model code"};
29 cvar_t r_skeletal_debugtranslatey = {0, "r_skeletal_debugtranslatey", "1", "development cvar for testing skeletal model code"};
30 cvar_t r_skeletal_debugtranslatez = {0, "r_skeletal_debugtranslatez", "1", "development cvar for testing skeletal model code"};
31 cvar_t mod_alias_supporttagscale = {0, "mod_alias_supporttagscale", "1", "support scaling factors in bone/tag attachment matrices as supported by MD3"};
33 float mod_md3_sin[320];
35 void Mod_AliasInit (void)
38 Cvar_RegisterVariable(&r_skeletal_debugbone);
39 Cvar_RegisterVariable(&r_skeletal_debugbonecomponent);
40 Cvar_RegisterVariable(&r_skeletal_debugbonevalue);
41 Cvar_RegisterVariable(&r_skeletal_debugtranslatex);
42 Cvar_RegisterVariable(&r_skeletal_debugtranslatey);
43 Cvar_RegisterVariable(&r_skeletal_debugtranslatez);
44 Cvar_RegisterVariable(&mod_alias_supporttagscale);
45 for (i = 0;i < 320;i++)
46 mod_md3_sin[i] = sin(i * M_PI * 2.0f / 256.0);
49 void Mod_Skeletal_InitBlends(dp_model_t *model)
52 int *weightindex = model->surfmesh.data_vertexweightindex4i;
53 float *weightinfluence = model->surfmesh.data_vertexweightinfluence4f;
54 model->surfmesh.num_blends = model->num_bones;
55 for (i = 0;i < model->surfmesh.num_blends;i++, weightindex += 4, weightinfluence += 4)
61 weightinfluence[0] = 1;
62 weightinfluence[1] = 0;
63 weightinfluence[2] = 0;
64 weightinfluence[3] = 0;
68 int Mod_Skeletal_AddBlend(dp_model_t *model, const int *newindex, const float *newinfluence)
71 int *weightindex = model->surfmesh.data_vertexweightindex4i;
72 float *weightinfluence = model->surfmesh.data_vertexweightinfluence4f;
73 for (i = 0;i < model->surfmesh.num_blends;i++, weightindex += 4, weightinfluence += 4)
75 if (weightindex[0] == newindex[0] && weightindex[1] == newindex[1] && weightindex[2] == newindex[2] && weightindex[3] == newindex[3] &&
76 weightinfluence[0] == newinfluence[0] && weightinfluence[1] == newinfluence[1] && weightinfluence[2] == newinfluence[2] && weightinfluence[3] == newinfluence[3])
79 model->surfmesh.num_blends++;
80 memcpy(weightindex, newindex, 4*sizeof(int));
81 memcpy(weightinfluence, newinfluence, 4*sizeof(float));
85 static int maxbonepose = 0;
86 static float (*bonepose)[12] = NULL;
88 void Mod_Skeletal_FreeBuffers(void)
96 #if defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1400)
97 #define RESTRICT __restrict
102 void Mod_Skeletal_AnimateVertices(const dp_model_t * RESTRICT model, const frameblend_t * RESTRICT frameblend, const skeleton_t *skeleton, float * RESTRICT vertex3f, float * RESTRICT normal3f, float * RESTRICT svector3f, float * RESTRICT tvector3f)
104 // vertex weighted skeletal
108 float (*boneposerelative)[12];
109 const int * RESTRICT weightindex;
110 const float * RESTRICT weightinfluence;
112 if (maxbonepose < model->num_bones + model->surfmesh.num_blends)
116 maxbonepose = model->num_bones + model->surfmesh.num_blends;
117 bonepose = (float (*)[12])Mem_Alloc(r_main_mempool, maxbonepose * sizeof(float[12]));
120 boneposerelative = bonepose + model->num_bones;
122 if (skeleton && !skeleton->relativetransforms)
125 // interpolate matrices
128 for (i = 0;i < model->num_bones;i++)
130 Matrix4x4_ToArray12FloatD3D(&skeleton->relativetransforms[i], m);
131 if (model->data_bones[i].parent >= 0)
132 R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
134 memcpy(bonepose[i], m, sizeof(m));
136 // create a relative deformation matrix to describe displacement
137 // from the base mesh, which is used by the actual weighting
138 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]);
143 float originscale = model->num_posescale;
145 const short * RESTRICT pose6s;
146 for (i = 0;i < model->num_bones;i++)
148 memset(m, 0, sizeof(m));
149 for (blends = 0;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++)
151 pose6s = model->data_poses6s + 6 * (frameblend[blends].subframe * model->num_bones + i);
152 lerp = frameblend[blends].lerp;
153 x = pose6s[3] * (1.0f / 32767.0f);
154 y = pose6s[4] * (1.0f / 32767.0f);
155 z = pose6s[5] * (1.0f / 32767.0f);
156 w = 1.0f - (x*x+y*y+z*z);
157 w = w > 0.0f ? -sqrt(w) : 0.0f;
158 m[ 0] += (1-2*(y*y+z*z)) * lerp;
159 m[ 1] += ( 2*(x*y-z*w)) * lerp;
160 m[ 2] += ( 2*(x*z+y*w)) * lerp;
161 m[ 3] += (pose6s[0] * originscale) * lerp;
162 m[ 4] += ( 2*(x*y+z*w)) * lerp;
163 m[ 5] += (1-2*(x*x+z*z)) * lerp;
164 m[ 6] += ( 2*(y*z-x*w)) * lerp;
165 m[ 7] += (pose6s[1] * originscale) * lerp;
166 m[ 8] += ( 2*(x*z-y*w)) * lerp;
167 m[ 9] += ( 2*(y*z+x*w)) * lerp;
168 m[10] += (1-2*(x*x+y*y)) * lerp;
169 m[11] += (pose6s[2] * originscale) * lerp;
172 VectorNormalize(m + 4);
173 VectorNormalize(m + 8);
174 if (i == r_skeletal_debugbone.integer)
175 m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
176 m[3] *= r_skeletal_debugtranslatex.value;
177 m[7] *= r_skeletal_debugtranslatey.value;
178 m[11] *= r_skeletal_debugtranslatez.value;
179 if (model->data_bones[i].parent >= 0)
180 R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
182 memcpy(bonepose[i], m, sizeof(m));
183 // create a relative deformation matrix to describe displacement
184 // from the base mesh, which is used by the actual weighting
185 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]);
189 // generate matrices for all blend combinations
190 weightindex = model->surfmesh.data_vertexweightindex4i + model->num_bones*4;
191 weightinfluence = model->surfmesh.data_vertexweightinfluence4f + model->num_bones*4;
192 for (i = model->num_bones;i < model->surfmesh.num_blends;i++, weightindex += 4, weightinfluence += 4)
194 float * RESTRICT b = boneposerelative[i];
195 const float * RESTRICT m = boneposerelative[weightindex[0]];
196 float f = weightinfluence[0];
197 b[ 0] = f*m[ 0]; b[ 1] = f*m[ 1]; b[ 2] = f*m[ 2]; b[ 3] = f*m[ 3];
198 b[ 4] = f*m[ 4]; b[ 5] = f*m[ 5]; b[ 6] = f*m[ 6]; b[ 7] = f*m[ 7];
199 b[ 8] = f*m[ 8]; b[ 9] = f*m[ 9]; b[10] = f*m[10]; b[11] = f*m[11];
200 for (k = 1;k < 4 && weightinfluence[k];k++)
202 m = boneposerelative[weightindex[k]];
203 f = weightinfluence[k];
204 b[ 0] += f*m[ 0]; b[ 1] += f*m[ 1]; b[ 2] += f*m[ 2]; b[ 3] += f*m[ 3];
205 b[ 4] += f*m[ 4]; b[ 5] += f*m[ 5]; b[ 6] += f*m[ 6]; b[ 7] += f*m[ 7];
206 b[ 8] += f*m[ 8]; b[ 9] += f*m[ 9]; b[10] += f*m[10]; b[11] += f*m[11];
210 // transform vertex attributes by blended matrices
213 const float * RESTRICT v = model->surfmesh.data_vertex3f;
214 const unsigned short * RESTRICT b = model->surfmesh.blends;
215 // special case common combinations of attributes to avoid repeated loading of matrices
218 const float * RESTRICT n = model->surfmesh.data_normal3f;
219 if (svector3f && tvector3f)
221 const float * RESTRICT sv = model->surfmesh.data_svector3f;
222 const float * RESTRICT tv = model->surfmesh.data_tvector3f;
223 for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, n += 3, sv += 3, tv += 3, b++, vertex3f += 3, normal3f += 3, svector3f += 3, tvector3f += 3)
225 const float * RESTRICT m = boneposerelative[*b];
226 vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
227 vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
228 vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
229 normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
230 normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
231 normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
232 svector3f[0] = (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
233 svector3f[1] = (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
234 svector3f[2] = (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
235 tvector3f[0] = (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
236 tvector3f[1] = (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
237 tvector3f[2] = (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
241 for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, n += 3, b++, vertex3f += 3, normal3f += 3)
243 const float * RESTRICT m = boneposerelative[*b];
244 vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
245 vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
246 vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
247 normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
248 normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
249 normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
254 for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, b++, vertex3f += 3)
256 const float * RESTRICT m = boneposerelative[*b];
257 vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
258 vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
259 vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
265 const float * RESTRICT n = model->surfmesh.data_normal3f;
266 const unsigned short * RESTRICT b = model->surfmesh.blends;
267 for (i = 0;i < model->surfmesh.num_vertices;i++, n += 3, b++, normal3f += 3)
269 const float * RESTRICT m = boneposerelative[*b];
270 normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
271 normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
272 normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
278 const float * RESTRICT sv = model->surfmesh.data_svector3f;
279 const unsigned short * RESTRICT b = model->surfmesh.blends;
280 for (i = 0;i < model->surfmesh.num_vertices;i++, sv += 3, b++, svector3f += 3)
282 const float *m = boneposerelative[*b];
283 svector3f[0] = (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
284 svector3f[1] = (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
285 svector3f[2] = (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
291 const float * RESTRICT tv = model->surfmesh.data_tvector3f;
292 const unsigned short * RESTRICT b = model->surfmesh.blends;
293 for (i = 0;i < model->surfmesh.num_vertices;i++, tv += 3, b++, tvector3f += 3)
295 const float * RESTRICT m = boneposerelative[*b];
296 tvector3f[0] = (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
297 tvector3f[1] = (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
298 tvector3f[2] = (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
303 void Mod_MD3_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
306 int i, numblends, blendnum;
307 int numverts = model->surfmesh.num_vertices;
309 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
311 //VectorMA(translate, model->surfmesh.num_morphmdlframetranslate, frameblend[blendnum].lerp, translate);
312 if (frameblend[blendnum].lerp > 0)
313 numblends = blendnum + 1;
315 // special case for the first blend because it avoids some adds and the need to memset the arrays first
316 for (blendnum = 0;blendnum < numblends;blendnum++)
318 const md3vertex_t *verts = model->surfmesh.data_morphmd3vertex + numverts * frameblend[blendnum].subframe;
321 float scale = frameblend[blendnum].lerp * (1.0f / 64.0f);
324 for (i = 0;i < numverts;i++)
326 vertex3f[i * 3 + 0] = verts[i].origin[0] * scale;
327 vertex3f[i * 3 + 1] = verts[i].origin[1] * scale;
328 vertex3f[i * 3 + 2] = verts[i].origin[2] * scale;
333 for (i = 0;i < numverts;i++)
335 vertex3f[i * 3 + 0] += verts[i].origin[0] * scale;
336 vertex3f[i * 3 + 1] += verts[i].origin[1] * scale;
337 vertex3f[i * 3 + 2] += verts[i].origin[2] * scale;
341 // the yaw and pitch stored in md3 models are 8bit quantized angles
342 // (0-255), and as such a lookup table is very well suited to
343 // decoding them, and since cosine is equivilant to sine with an
344 // extra 45 degree rotation, this uses one lookup table for both
345 // sine and cosine with a +64 bias to get cosine.
348 float lerp = frameblend[blendnum].lerp;
351 for (i = 0;i < numverts;i++)
353 normal3f[i * 3 + 0] = mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
354 normal3f[i * 3 + 1] = mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
355 normal3f[i * 3 + 2] = mod_md3_sin[verts[i].pitch + 64] * lerp;
360 for (i = 0;i < numverts;i++)
362 normal3f[i * 3 + 0] += mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
363 normal3f[i * 3 + 1] += mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
364 normal3f[i * 3 + 2] += mod_md3_sin[verts[i].pitch + 64] * lerp;
370 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
371 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
374 for (i = 0;i < numverts;i++, texvecvert++)
376 VectorScale(texvecvert->svec, f, svector3f + i*3);
377 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
382 for (i = 0;i < numverts;i++, texvecvert++)
384 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
385 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
392 void Mod_MDL_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
395 int i, numblends, blendnum;
396 int numverts = model->surfmesh.num_vertices;
398 VectorClear(translate);
400 // blend the frame translates to avoid redundantly doing so on each vertex
401 // (a bit of a brain twister but it works)
402 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
404 if (model->surfmesh.data_morphmd2framesize6f)
405 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6 + 3, translate);
407 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.num_morphmdlframetranslate, translate);
408 if (frameblend[blendnum].lerp > 0)
409 numblends = blendnum + 1;
411 // special case for the first blend because it avoids some adds and the need to memset the arrays first
412 for (blendnum = 0;blendnum < numblends;blendnum++)
414 const trivertx_t *verts = model->surfmesh.data_morphmdlvertex + numverts * frameblend[blendnum].subframe;
418 if (model->surfmesh.data_morphmd2framesize6f)
419 VectorScale(model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6, frameblend[blendnum].lerp, scale);
421 VectorScale(model->surfmesh.num_morphmdlframescale, frameblend[blendnum].lerp, scale);
424 for (i = 0;i < numverts;i++)
426 vertex3f[i * 3 + 0] = translate[0] + verts[i].v[0] * scale[0];
427 vertex3f[i * 3 + 1] = translate[1] + verts[i].v[1] * scale[1];
428 vertex3f[i * 3 + 2] = translate[2] + verts[i].v[2] * scale[2];
433 for (i = 0;i < numverts;i++)
435 vertex3f[i * 3 + 0] += verts[i].v[0] * scale[0];
436 vertex3f[i * 3 + 1] += verts[i].v[1] * scale[1];
437 vertex3f[i * 3 + 2] += verts[i].v[2] * scale[2];
441 // the vertex normals in mdl models are an index into a table of
442 // 162 unique values, this very crude quantization reduces the
443 // vertex normal to only one byte, which saves a lot of space but
444 // also makes lighting pretty coarse
447 float lerp = frameblend[blendnum].lerp;
450 for (i = 0;i < numverts;i++)
452 const float *vn = m_bytenormals[verts[i].lightnormalindex];
453 VectorScale(vn, lerp, normal3f + i*3);
458 for (i = 0;i < numverts;i++)
460 const float *vn = m_bytenormals[verts[i].lightnormalindex];
461 VectorMA(normal3f + i*3, lerp, vn, normal3f + i*3);
467 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
468 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
471 for (i = 0;i < numverts;i++, texvecvert++)
473 VectorScale(texvecvert->svec, f, svector3f + i*3);
474 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
479 for (i = 0;i < numverts;i++, texvecvert++)
481 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
482 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
489 int Mod_Alias_GetTagMatrix(const dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, int tagindex, matrix4x4_t *outmatrix)
492 matrix4x4_t parentbonematrix;
493 matrix4x4_t tempbonematrix;
494 matrix4x4_t bonematrix;
495 matrix4x4_t blendmatrix;
502 *outmatrix = identitymatrix;
503 if (skeleton && skeleton->relativetransforms)
505 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
507 *outmatrix = skeleton->relativetransforms[tagindex];
508 while ((tagindex = model->data_bones[tagindex].parent) >= 0)
511 Matrix4x4_Concat(outmatrix, &skeleton->relativetransforms[tagindex], &temp);
514 else if (model->num_bones)
516 if (tagindex < 0 || tagindex >= model->num_bones)
518 Matrix4x4_Clear(&blendmatrix);
519 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
521 lerp = frameblend[blendindex].lerp;
522 Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
523 parenttagindex = tagindex;
524 while ((parenttagindex = model->data_bones[parenttagindex].parent) >= 0)
526 Matrix4x4_FromBonePose6s(&parentbonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + parenttagindex));
527 tempbonematrix = bonematrix;
528 Matrix4x4_Concat(&bonematrix, &parentbonematrix, &tempbonematrix);
530 Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
532 *outmatrix = blendmatrix;
534 else if (model->num_tags)
536 if (tagindex < 0 || tagindex >= model->num_tags)
538 for (k = 0;k < 12;k++)
540 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
542 lerp = frameblend[blendindex].lerp;
543 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
544 for (k = 0;k < 12;k++)
545 blendtag[k] += input[k] * lerp;
547 Matrix4x4_FromArray12FloatGL(outmatrix, blendtag);
550 if(!mod_alias_supporttagscale.integer)
551 Matrix4x4_Normalize3(outmatrix, outmatrix);
556 int Mod_Alias_GetExtendedTagInfoForIndex(const dp_model_t *model, unsigned int skin, const frameblend_t *frameblend, const skeleton_t *skeleton, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
561 matrix4x4_t bonematrix;
562 matrix4x4_t blendmatrix;
566 if (skeleton && skeleton->relativetransforms)
568 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
570 *parentindex = skeleton->model->data_bones[tagindex].parent;
571 *tagname = skeleton->model->data_bones[tagindex].name;
572 *tag_localmatrix = skeleton->relativetransforms[tagindex];
575 else if (model->num_bones)
577 if (tagindex < 0 || tagindex >= model->num_bones)
579 *parentindex = model->data_bones[tagindex].parent;
580 *tagname = model->data_bones[tagindex].name;
581 Matrix4x4_Clear(&blendmatrix);
582 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
584 lerp = frameblend[blendindex].lerp;
585 Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
586 Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
588 *tag_localmatrix = blendmatrix;
591 else if (model->num_tags)
593 if (tagindex < 0 || tagindex >= model->num_tags)
596 *tagname = model->data_tags[tagindex].name;
597 for (k = 0;k < 12;k++)
599 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
601 lerp = frameblend[blendindex].lerp;
602 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
603 for (k = 0;k < 12;k++)
604 blendtag[k] += input[k] * lerp;
606 Matrix4x4_FromArray12FloatGL(tag_localmatrix, blendtag);
613 int Mod_Alias_GetTagIndexForName(const dp_model_t *model, unsigned int skin, const char *tagname)
616 if(skin >= (unsigned int)model->numskins)
618 if (model->num_bones)
619 for (i = 0;i < model->num_bones;i++)
620 if (!strcasecmp(tagname, model->data_bones[i].name))
623 for (i = 0;i < model->num_tags;i++)
624 if (!strcasecmp(tagname, model->data_tags[i].name))
629 static void Mod_BuildBaseBonePoses(void)
632 matrix4x4_t *basebonepose;
633 float *outinvmatrix = loadmodel->data_baseboneposeinverse;
634 matrix4x4_t bonematrix;
635 matrix4x4_t tempbonematrix;
636 if (!loadmodel->num_bones)
638 basebonepose = (matrix4x4_t *)Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(matrix4x4_t));
639 for (boneindex = 0;boneindex < loadmodel->num_bones;boneindex++)
641 Matrix4x4_FromBonePose6s(&bonematrix, loadmodel->num_posescale, loadmodel->data_poses6s + 6 * boneindex);
642 if (loadmodel->data_bones[boneindex].parent >= 0)
644 tempbonematrix = bonematrix;
645 Matrix4x4_Concat(&bonematrix, basebonepose + loadmodel->data_bones[boneindex].parent, &tempbonematrix);
647 basebonepose[boneindex] = bonematrix;
648 Matrix4x4_Invert_Simple(&tempbonematrix, basebonepose + boneindex);
649 Matrix4x4_ToArray12FloatD3D(&tempbonematrix, outinvmatrix + 12*boneindex);
651 Mem_Free(basebonepose);
654 static void Mod_Alias_CalculateBoundingBox(void)
657 qboolean firstvertex = true;
658 float dist, yawradius, radius;
661 frameblend_t frameblend[MAX_FRAMEBLENDS];
662 memset(frameblend, 0, sizeof(frameblend));
663 frameblend[0].lerp = 1;
664 vertex3f = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
665 VectorClear(loadmodel->normalmins);
666 VectorClear(loadmodel->normalmaxs);
669 for (frameblend[0].subframe = 0;frameblend[0].subframe < loadmodel->num_poses;frameblend[0].subframe++)
671 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, vertex3f, NULL, NULL, NULL);
672 for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
677 VectorCopy(v, loadmodel->normalmins);
678 VectorCopy(v, loadmodel->normalmaxs);
682 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
683 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
684 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
685 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
686 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
687 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
689 dist = v[0] * v[0] + v[1] * v[1];
690 if (yawradius < dist)
699 radius = sqrt(radius);
700 yawradius = sqrt(yawradius);
701 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
702 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
703 loadmodel->yawmins[2] = loadmodel->normalmins[2];
704 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
705 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
706 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
707 loadmodel->radius = radius;
708 loadmodel->radius2 = radius * radius;
711 static void Mod_Alias_MorphMesh_CompileFrames(void)
714 frameblend_t frameblend[MAX_FRAMEBLENDS];
715 unsigned char *datapointer;
716 memset(frameblend, 0, sizeof(frameblend));
717 frameblend[0].lerp = 1;
718 datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
719 loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
720 loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
721 loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
722 loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
723 loadmodel->surfmesh.data_morphtexvecvertex = (texvecvertex_t *)datapointer;datapointer += loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices * sizeof(texvecvertex_t);
724 // this counts down from the last frame to the first so that the final data in surfmesh is for frame zero (which is what the renderer expects to be there)
725 for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
727 frameblend[0].subframe = i;
728 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
729 Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, r_smoothnormals_areaweighting.integer != 0);
730 // encode the svector and tvector in 3 byte format for permanent storage
731 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
733 VectorScaleCast(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
734 VectorScaleCast(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
739 static void Mod_MDLMD2MD3_TraceLine(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask)
742 float segmentmins[3], segmentmaxs[3];
744 static int maxvertices = 0;
745 static float *vertex3f = NULL;
746 memset(trace, 0, sizeof(*trace));
748 trace->realfraction = 1;
749 trace->hitsupercontentsmask = hitsupercontentsmask;
750 if (maxvertices < model->surfmesh.num_vertices)
754 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
755 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
757 segmentmins[0] = min(start[0], end[0]) - 1;
758 segmentmins[1] = min(start[1], end[1]) - 1;
759 segmentmins[2] = min(start[2], end[2]) - 1;
760 segmentmaxs[0] = max(start[0], end[0]) + 1;
761 segmentmaxs[1] = max(start[1], end[1]) + 1;
762 segmentmaxs[2] = max(start[2], end[2]) + 1;
763 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
764 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
765 Collision_TraceLineTriangleMeshFloat(trace, start, end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs);
768 static int maxvertices = 0;
769 static float *vertex3f = NULL;
771 static void Mod_MDLMD2MD3_TraceBox(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask)
774 vec3_t shiftstart, shiftend;
775 float segmentmins[3], segmentmaxs[3];
777 colboxbrushf_t thisbrush_start, thisbrush_end;
778 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
780 if (VectorCompare(boxmins, boxmaxs))
782 VectorAdd(start, boxmins, shiftstart);
783 VectorAdd(end, boxmins, shiftend);
784 Mod_MDLMD2MD3_TraceLine(model, frameblend, skeleton, trace, shiftstart, shiftend, hitsupercontentsmask);
785 VectorSubtract(trace->endpos, boxmins, trace->endpos);
789 // box trace, performed as brush trace
790 memset(trace, 0, sizeof(*trace));
792 trace->realfraction = 1;
793 trace->hitsupercontentsmask = hitsupercontentsmask;
794 if (maxvertices < model->surfmesh.num_vertices)
798 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
799 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
801 segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
802 segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
803 segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
804 segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
805 segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
806 segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
807 VectorAdd(start, boxmins, boxstartmins);
808 VectorAdd(start, boxmaxs, boxstartmaxs);
809 VectorAdd(end, boxmins, boxendmins);
810 VectorAdd(end, boxmaxs, boxendmaxs);
811 Collision_BrushForBox(&thisbrush_start, boxstartmins, boxstartmaxs, 0, 0, NULL);
812 Collision_BrushForBox(&thisbrush_end, boxendmins, boxendmaxs, 0, 0, NULL);
813 if (maxvertices < model->surfmesh.num_vertices)
817 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
818 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
820 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
821 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
822 Collision_TraceBrushTriangleMeshFloat(trace, &thisbrush_start.brush, &thisbrush_end.brush, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs);
825 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
828 for (i = 0;i < inverts;i++)
830 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
832 j = vertremap[i]; // not onseam
835 j = vertremap[i+inverts]; // onseam
841 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
843 int i, f, pose, groupframes;
845 daliasframetype_t *pframetype;
846 daliasframe_t *pinframe;
847 daliasgroup_t *group;
848 daliasinterval_t *intervals;
851 scene = loadmodel->animscenes;
852 for (f = 0;f < loadmodel->numframes;f++)
854 pframetype = (daliasframetype_t *)datapointer;
855 datapointer += sizeof(daliasframetype_t);
856 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
858 // a single frame is still treated as a group
865 group = (daliasgroup_t *)datapointer;
866 datapointer += sizeof(daliasgroup_t);
867 groupframes = LittleLong (group->numframes);
869 // intervals (time per frame)
870 intervals = (daliasinterval_t *)datapointer;
871 datapointer += sizeof(daliasinterval_t) * groupframes;
873 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
874 if (interval < 0.01f)
876 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
881 // get scene name from first frame
882 pinframe = (daliasframe_t *)datapointer;
884 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
885 scene->firstframe = pose;
886 scene->framecount = groupframes;
887 scene->framerate = 1.0f / interval;
892 for (i = 0;i < groupframes;i++)
894 pinframe = (daliasframe_t *)datapointer;
895 datapointer += sizeof(daliasframe_t);
896 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
897 datapointer += sizeof(trivertx_t) * inverts;
903 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
905 if (cls.state == ca_dedicated)
909 skinframe = R_SkinFrame_LoadMissing();
910 memset(texture, 0, sizeof(*texture));
911 texture->currentframe = texture;
912 //texture->animated = false;
913 texture->numskinframes = 1;
914 texture->skinframerate = 1;
915 texture->skinframes[0] = skinframe;
916 texture->currentskinframe = skinframe;
917 //texture->backgroundnumskinframes = 0;
918 //texture->customblendfunc[0] = 0;
919 //texture->customblendfunc[1] = 0;
920 //texture->surfaceflags = 0;
921 //texture->supercontents = 0;
922 //texture->surfaceparms = 0;
923 //texture->textureflags = 0;
925 texture->basematerialflags = MATERIALFLAG_WALL;
926 if (texture->currentskinframe->hasalpha)
927 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
928 texture->currentmaterialflags = texture->basematerialflags;
929 texture->specularscalemod = 1;
930 texture->specularpowermod = 1;
933 void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
936 skinfileitem_t *skinfileitem;
939 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
940 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
942 memset(skin, 0, sizeof(*skin));
944 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
946 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
947 if (!strcmp(skinfileitem->name, meshname))
949 Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
955 // don't render unmentioned meshes
956 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
957 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
962 Mod_LoadTextureFromQ3Shader(skin, shadername, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
965 #define BOUNDI(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid ##VALUE (%d exceeds %d - %d)", loadmodel->name, VALUE, MIN, MAX);
966 #define BOUNDF(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid ##VALUE (%f exceeds %f - %f)", loadmodel->name, VALUE, MIN, MAX);
967 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
969 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
970 float scales, scalet, interval;
974 stvert_t *pinstverts;
975 dtriangle_t *pintriangles;
976 daliasskintype_t *pinskintype;
977 daliasskingroup_t *pinskingroup;
978 daliasskininterval_t *pinskinintervals;
979 daliasframetype_t *pinframetype;
980 daliasgroup_t *pinframegroup;
981 unsigned char *datapointer, *startframes, *startskins;
982 char name[MAX_QPATH];
983 skinframe_t *tempskinframe;
984 animscene_t *tempskinscenes;
985 texture_t *tempaliasskins;
987 int *vertonseam, *vertremap;
988 skinfile_t *skinfiles;
990 datapointer = (unsigned char *)buffer;
991 pinmodel = (mdl_t *)datapointer;
992 datapointer += sizeof(mdl_t);
994 version = LittleLong (pinmodel->version);
995 if (version != ALIAS_VERSION)
996 Host_Error ("%s has wrong version number (%i should be %i)",
997 loadmodel->name, version, ALIAS_VERSION);
999 loadmodel->modeldatatypestring = "MDL";
1001 loadmodel->type = mod_alias;
1002 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1003 loadmodel->DrawSky = NULL;
1004 loadmodel->DrawAddWaterPlanes = NULL;
1005 loadmodel->Draw = R_Q1BSP_Draw;
1006 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1007 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1008 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1009 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1010 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1011 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1012 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1013 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1014 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1015 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1016 loadmodel->PointSuperContents = NULL;
1018 loadmodel->num_surfaces = 1;
1019 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1020 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
1021 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1022 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1023 loadmodel->sortedmodelsurfaces[0] = 0;
1025 loadmodel->numskins = LittleLong(pinmodel->numskins);
1026 BOUNDI(loadmodel->numskins,0,65536);
1027 skinwidth = LittleLong (pinmodel->skinwidth);
1028 BOUNDI(skinwidth,0,65536);
1029 skinheight = LittleLong (pinmodel->skinheight);
1030 BOUNDI(skinheight,0,65536);
1031 numverts = LittleLong(pinmodel->numverts);
1032 BOUNDI(numverts,0,65536);
1033 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
1034 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
1035 loadmodel->numframes = LittleLong(pinmodel->numframes);
1036 BOUNDI(loadmodel->numframes,0,65536);
1037 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
1038 BOUNDI((int)loadmodel->synctype,0,2);
1039 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1040 i = LittleLong (pinmodel->flags);
1041 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1043 for (i = 0;i < 3;i++)
1045 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
1046 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
1049 startskins = datapointer;
1051 for (i = 0;i < loadmodel->numskins;i++)
1053 pinskintype = (daliasskintype_t *)datapointer;
1054 datapointer += sizeof(daliasskintype_t);
1055 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
1059 pinskingroup = (daliasskingroup_t *)datapointer;
1060 datapointer += sizeof(daliasskingroup_t);
1061 groupskins = LittleLong(pinskingroup->numskins);
1062 datapointer += sizeof(daliasskininterval_t) * groupskins;
1065 for (j = 0;j < groupskins;j++)
1067 datapointer += skinwidth * skinheight;
1072 pinstverts = (stvert_t *)datapointer;
1073 datapointer += sizeof(stvert_t) * numverts;
1075 pintriangles = (dtriangle_t *)datapointer;
1076 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
1078 startframes = datapointer;
1079 loadmodel->surfmesh.num_morphframes = 0;
1080 for (i = 0;i < loadmodel->numframes;i++)
1082 pinframetype = (daliasframetype_t *)datapointer;
1083 datapointer += sizeof(daliasframetype_t);
1084 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
1088 pinframegroup = (daliasgroup_t *)datapointer;
1089 datapointer += sizeof(daliasgroup_t);
1090 groupframes = LittleLong(pinframegroup->numframes);
1091 datapointer += sizeof(daliasinterval_t) * groupframes;
1094 for (j = 0;j < groupframes;j++)
1096 datapointer += sizeof(daliasframe_t);
1097 datapointer += sizeof(trivertx_t) * numverts;
1098 loadmodel->surfmesh.num_morphframes++;
1101 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1103 // store texture coordinates into temporary array, they will be stored
1104 // after usage is determined (triangle data)
1105 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
1106 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
1107 vertonseam = vertremap + numverts * 2;
1109 scales = 1.0 / skinwidth;
1110 scalet = 1.0 / skinheight;
1111 for (i = 0;i < numverts;i++)
1113 vertonseam[i] = LittleLong(pinstverts[i].onseam);
1114 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
1115 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
1116 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
1117 vertst[(i+numverts)*2+1] = vertst[i*2+1];
1120 // load triangle data
1121 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1123 // read the triangle elements
1124 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1125 for (j = 0;j < 3;j++)
1126 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1127 // validate (note numverts is used because this is the original data)
1128 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1129 // now butcher the elements according to vertonseam and tri->facesfront
1130 // and then compact the vertex set to remove duplicates
1131 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1132 if (!LittleLong(pintriangles[i].facesfront)) // backface
1133 for (j = 0;j < 3;j++)
1134 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1135 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1137 // (this uses vertremap to count usage to save some memory)
1138 for (i = 0;i < numverts*2;i++)
1140 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1141 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1142 // build remapping table and compact array
1143 loadmodel->surfmesh.num_vertices = 0;
1144 for (i = 0;i < numverts*2;i++)
1148 vertremap[i] = loadmodel->surfmesh.num_vertices;
1149 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1150 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1151 loadmodel->surfmesh.num_vertices++;
1154 vertremap[i] = -1; // not used at all
1156 // remap the elements to the new vertex set
1157 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1158 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1159 // store the texture coordinates
1160 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1161 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1163 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1164 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1167 // generate ushort elements array if possible
1168 if (loadmodel->surfmesh.num_vertices <= 65536)
1169 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1170 if (loadmodel->surfmesh.data_element3s)
1171 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1172 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1175 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1176 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1177 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1178 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1179 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1180 Mod_Alias_CalculateBoundingBox();
1181 Mod_Alias_MorphMesh_CompileFrames();
1184 Mem_Free(vertremap);
1187 skinfiles = Mod_LoadSkinFiles();
1190 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1191 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1192 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1193 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1194 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1195 Mod_FreeSkinFiles(skinfiles);
1196 for (i = 0;i < loadmodel->numskins;i++)
1198 loadmodel->skinscenes[i].firstframe = i;
1199 loadmodel->skinscenes[i].framecount = 1;
1200 loadmodel->skinscenes[i].loop = true;
1201 loadmodel->skinscenes[i].framerate = 10;
1206 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1207 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1208 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1209 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1211 datapointer = startskins;
1212 for (i = 0;i < loadmodel->numskins;i++)
1214 pinskintype = (daliasskintype_t *)datapointer;
1215 datapointer += sizeof(daliasskintype_t);
1217 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1224 pinskingroup = (daliasskingroup_t *)datapointer;
1225 datapointer += sizeof(daliasskingroup_t);
1227 groupskins = LittleLong (pinskingroup->numskins);
1229 pinskinintervals = (daliasskininterval_t *)datapointer;
1230 datapointer += sizeof(daliasskininterval_t) * groupskins;
1232 interval = LittleFloat(pinskinintervals[0].interval);
1233 if (interval < 0.01f)
1235 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1240 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1241 loadmodel->skinscenes[i].firstframe = totalskins;
1242 loadmodel->skinscenes[i].framecount = groupskins;
1243 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1244 loadmodel->skinscenes[i].loop = true;
1246 for (j = 0;j < groupskins;j++)
1249 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1251 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1252 if (!Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, name, false, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS))
1253 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, R_SkinFrame_LoadInternalQuake(name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP, true, r_fullbrights.integer, (unsigned char *)datapointer, skinwidth, skinheight));
1254 datapointer += skinwidth * skinheight;
1258 // check for skins that don't exist in the model, but do exist as external images
1259 // (this was added because yummyluv kept pestering me about support for it)
1260 // TODO: support shaders here?
1261 while ((tempskinframe = R_SkinFrame_LoadExternal(va("%s_%i", loadmodel->name, loadmodel->numskins), (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS, false)))
1263 // expand the arrays to make room
1264 tempskinscenes = loadmodel->skinscenes;
1265 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1266 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1267 Mem_Free(tempskinscenes);
1269 tempaliasskins = loadmodel->data_textures;
1270 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1271 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1272 Mem_Free(tempaliasskins);
1274 // store the info about the new skin
1275 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1276 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1277 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1278 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1279 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1280 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1282 //increase skin counts
1283 loadmodel->numskins++;
1286 // fix up the pointers since they are pointing at the old textures array
1287 // FIXME: this is a hack!
1288 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1289 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1293 surface = loadmodel->data_surfaces;
1294 surface->texture = loadmodel->data_textures;
1295 surface->num_firsttriangle = 0;
1296 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1297 surface->num_firstvertex = 0;
1298 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1300 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1303 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1305 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1306 float iskinwidth, iskinheight;
1307 unsigned char *data;
1308 msurface_t *surface;
1310 unsigned char *base, *datapointer;
1311 md2frame_t *pinframe;
1313 md2triangle_t *intri;
1314 unsigned short *inst;
1315 struct md2verthash_s
1317 struct md2verthash_s *next;
1321 *hash, **md2verthash, *md2verthashdata;
1322 skinfile_t *skinfiles;
1324 pinmodel = (md2_t *)buffer;
1325 base = (unsigned char *)buffer;
1327 version = LittleLong (pinmodel->version);
1328 if (version != MD2ALIAS_VERSION)
1329 Host_Error ("%s has wrong version number (%i should be %i)",
1330 loadmodel->name, version, MD2ALIAS_VERSION);
1332 loadmodel->modeldatatypestring = "MD2";
1334 loadmodel->type = mod_alias;
1335 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1336 loadmodel->DrawSky = NULL;
1337 loadmodel->DrawAddWaterPlanes = NULL;
1338 loadmodel->Draw = R_Q1BSP_Draw;
1339 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1340 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1341 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1342 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1343 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1344 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1345 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1346 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1347 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1348 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1349 loadmodel->PointSuperContents = NULL;
1351 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1352 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1353 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1354 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1355 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1356 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1357 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1358 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1360 end = LittleLong(pinmodel->ofs_end);
1361 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1362 Host_Error ("%s is not a valid model", loadmodel->name);
1363 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1364 Host_Error ("%s is not a valid model", loadmodel->name);
1365 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1366 Host_Error ("%s is not a valid model", loadmodel->name);
1367 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1368 Host_Error ("%s is not a valid model", loadmodel->name);
1369 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1370 Host_Error ("%s is not a valid model", loadmodel->name);
1372 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1373 numxyz = LittleLong(pinmodel->num_xyz);
1374 numst = LittleLong(pinmodel->num_st);
1375 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1376 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1377 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1378 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1379 skinwidth = LittleLong(pinmodel->skinwidth);
1380 skinheight = LittleLong(pinmodel->skinheight);
1381 iskinwidth = 1.0f / skinwidth;
1382 iskinheight = 1.0f / skinheight;
1384 loadmodel->num_surfaces = 1;
1385 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1386 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->numframes * sizeof(animscene_t) + loadmodel->numframes * sizeof(float[6]) + loadmodel->surfmesh.num_triangles * sizeof(int[3]) + loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1387 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1388 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1389 loadmodel->sortedmodelsurfaces[0] = 0;
1390 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1391 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1392 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1393 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1395 loadmodel->synctype = ST_RAND;
1398 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1399 skinfiles = Mod_LoadSkinFiles();
1402 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1403 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1404 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1405 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1406 Mod_FreeSkinFiles(skinfiles);
1408 else if (loadmodel->numskins)
1410 // skins found (most likely not a player model)
1411 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1412 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1413 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1414 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1415 Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
1419 // no skins (most likely a player model)
1420 loadmodel->numskins = 1;
1421 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1422 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1423 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1424 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1427 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1428 for (i = 0;i < loadmodel->numskins;i++)
1430 loadmodel->skinscenes[i].firstframe = i;
1431 loadmodel->skinscenes[i].framecount = 1;
1432 loadmodel->skinscenes[i].loop = true;
1433 loadmodel->skinscenes[i].framerate = 10;
1436 // load the triangles and stvert data
1437 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1438 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1439 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1440 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1441 // swap the triangle list
1442 loadmodel->surfmesh.num_vertices = 0;
1443 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1445 for (j = 0;j < 3;j++)
1447 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1448 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1451 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1456 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1459 hashindex = (xyz * 256 + st) & 65535;
1460 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1461 if (hash->xyz == xyz && hash->st == st)
1465 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1468 hash->next = md2verthash[hashindex];
1469 md2verthash[hashindex] = hash;
1471 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1475 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1476 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[2]) + loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t));
1477 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1478 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1479 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1482 hash = md2verthashdata + i;
1483 vertremap[i] = hash->xyz;
1484 sts = LittleShort(inst[hash->st*2+0]);
1485 stt = LittleShort(inst[hash->st*2+1]);
1486 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1488 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1492 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1493 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1496 Mem_Free(md2verthash);
1497 Mem_Free(md2verthashdata);
1499 // generate ushort elements array if possible
1500 if (loadmodel->surfmesh.num_vertices <= 65536)
1501 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1502 if (loadmodel->surfmesh.data_element3s)
1503 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1504 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1507 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1508 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1513 pinframe = (md2frame_t *)datapointer;
1514 datapointer += sizeof(md2frame_t);
1515 // store the frame scale/translate into the appropriate array
1516 for (j = 0;j < 3;j++)
1518 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1519 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1521 // convert the vertices
1522 v = (trivertx_t *)datapointer;
1523 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1524 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1525 out[k] = v[vertremap[k]];
1526 datapointer += numxyz * sizeof(trivertx_t);
1528 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1529 loadmodel->animscenes[i].firstframe = i;
1530 loadmodel->animscenes[i].framecount = 1;
1531 loadmodel->animscenes[i].framerate = 10;
1532 loadmodel->animscenes[i].loop = true;
1535 Mem_Free(vertremap);
1537 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1538 Mod_Alias_CalculateBoundingBox();
1539 Mod_Alias_MorphMesh_CompileFrames();
1541 surface = loadmodel->data_surfaces;
1542 surface->texture = loadmodel->data_textures;
1543 surface->num_firsttriangle = 0;
1544 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1545 surface->num_firstvertex = 0;
1546 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1548 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1551 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1553 int i, j, k, version, meshvertices, meshtriangles;
1554 unsigned char *data;
1555 msurface_t *surface;
1556 md3modelheader_t *pinmodel;
1557 md3frameinfo_t *pinframe;
1560 skinfile_t *skinfiles;
1562 pinmodel = (md3modelheader_t *)buffer;
1564 if (memcmp(pinmodel->identifier, "IDP3", 4))
1565 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1566 version = LittleLong (pinmodel->version);
1567 if (version != MD3VERSION)
1568 Host_Error ("%s has wrong version number (%i should be %i)",
1569 loadmodel->name, version, MD3VERSION);
1571 skinfiles = Mod_LoadSkinFiles();
1572 if (loadmodel->numskins < 1)
1573 loadmodel->numskins = 1;
1575 loadmodel->modeldatatypestring = "MD3";
1577 loadmodel->type = mod_alias;
1578 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1579 loadmodel->DrawSky = NULL;
1580 loadmodel->DrawAddWaterPlanes = NULL;
1581 loadmodel->Draw = R_Q1BSP_Draw;
1582 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1583 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1584 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1585 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1586 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1587 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1588 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1589 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1590 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1591 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1592 loadmodel->PointSuperContents = NULL;
1593 loadmodel->synctype = ST_RAND;
1594 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1595 i = LittleLong (pinmodel->flags);
1596 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1598 // set up some global info about the model
1599 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1600 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1602 // make skinscenes for the skins (no groups)
1603 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1604 for (i = 0;i < loadmodel->numskins;i++)
1606 loadmodel->skinscenes[i].firstframe = i;
1607 loadmodel->skinscenes[i].framecount = 1;
1608 loadmodel->skinscenes[i].loop = true;
1609 loadmodel->skinscenes[i].framerate = 10;
1613 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1614 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1616 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1617 loadmodel->animscenes[i].firstframe = i;
1618 loadmodel->animscenes[i].framecount = 1;
1619 loadmodel->animscenes[i].framerate = 10;
1620 loadmodel->animscenes[i].loop = true;
1624 loadmodel->num_tagframes = loadmodel->numframes;
1625 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1626 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1627 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1629 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1630 for (j = 0;j < 9;j++)
1631 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1632 for (j = 0;j < 3;j++)
1633 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1634 //Con_Printf("model \"%s\" frame #%i tag #%i \"%s\"\n", loadmodel->name, i / loadmodel->num_tags, i % loadmodel->num_tags, loadmodel->data_tags[i].name);
1640 for (i = 0, pinmesh = (md3mesh_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_meshes));i < loadmodel->num_surfaces;i++, pinmesh = (md3mesh_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_end)))
1642 if (memcmp(pinmesh->identifier, "IDP3", 4))
1643 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1644 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1645 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1646 meshvertices += LittleLong(pinmesh->num_vertices);
1647 meshtriangles += LittleLong(pinmesh->num_triangles);
1650 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1651 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1652 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1653 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshvertices * sizeof(float[2]) + meshvertices * loadmodel->numframes * sizeof(md3vertex_t));
1654 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1655 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1656 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1657 loadmodel->surfmesh.num_vertices = meshvertices;
1658 loadmodel->surfmesh.num_triangles = meshtriangles;
1659 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1660 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1661 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1662 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1663 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1664 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1665 if (meshvertices <= 65536)
1666 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1670 for (i = 0, pinmesh = (md3mesh_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_meshes));i < loadmodel->num_surfaces;i++, pinmesh = (md3mesh_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_end)))
1672 if (memcmp(pinmesh->identifier, "IDP3", 4))
1673 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1674 loadmodel->sortedmodelsurfaces[i] = i;
1675 surface = loadmodel->data_surfaces + i;
1676 surface->texture = loadmodel->data_textures + i;
1677 surface->num_firsttriangle = meshtriangles;
1678 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1679 surface->num_firstvertex = meshvertices;
1680 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1681 meshvertices += surface->num_vertices;
1682 meshtriangles += surface->num_triangles;
1684 for (j = 0;j < surface->num_triangles * 3;j++)
1685 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1686 for (j = 0;j < surface->num_vertices;j++)
1688 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1689 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1691 for (j = 0;j < loadmodel->numframes;j++)
1693 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1694 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1695 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1697 out->origin[0] = LittleShort(in->origin[0]);
1698 out->origin[1] = LittleShort(in->origin[1]);
1699 out->origin[2] = LittleShort(in->origin[2]);
1700 out->pitch = in->pitch;
1705 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1707 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1709 if (loadmodel->surfmesh.data_element3s)
1710 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1711 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1712 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1713 Mod_Alias_MorphMesh_CompileFrames();
1714 Mod_Alias_CalculateBoundingBox();
1715 Mod_FreeSkinFiles(skinfiles);
1716 Mod_MakeSortedSurfaces(loadmodel);
1718 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1719 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1722 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1724 zymtype1header_t *pinmodel, *pheader;
1725 unsigned char *pbase;
1726 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1727 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose, f, biggestorigin, tempvec[3], modelscale;
1728 zymvertex_t *verts, *vertdata;
1732 skinfile_t *skinfiles;
1733 unsigned char *data;
1734 msurface_t *surface;
1736 pinmodel = (zymtype1header_t *)buffer;
1737 pbase = (unsigned char *)buffer;
1738 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1739 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1740 if (BigLong(pinmodel->type) != 1)
1741 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1743 loadmodel->modeldatatypestring = "ZYM";
1745 loadmodel->type = mod_alias;
1746 loadmodel->synctype = ST_RAND;
1750 pheader->type = BigLong(pinmodel->type);
1751 pheader->filesize = BigLong(pinmodel->filesize);
1752 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1753 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1754 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1755 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1756 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1757 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1758 pheader->radius = BigFloat(pinmodel->radius);
1759 pheader->numverts = BigLong(pinmodel->numverts);
1760 pheader->numtris = BigLong(pinmodel->numtris);
1761 pheader->numshaders = BigLong(pinmodel->numshaders);
1762 pheader->numbones = BigLong(pinmodel->numbones);
1763 pheader->numscenes = BigLong(pinmodel->numscenes);
1764 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1765 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1766 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1767 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1768 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1769 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1770 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1771 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1772 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1773 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1774 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1775 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1776 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1777 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1778 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1779 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1780 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1781 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1783 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1785 Con_Printf("%s has no geometry\n", loadmodel->name);
1788 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1790 Con_Printf("%s has no animations\n", loadmodel->name);
1794 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1795 loadmodel->DrawSky = NULL;
1796 loadmodel->DrawAddWaterPlanes = NULL;
1797 loadmodel->Draw = R_Q1BSP_Draw;
1798 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1799 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1800 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1801 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1802 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1803 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1804 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1805 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1806 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1807 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1808 loadmodel->PointSuperContents = NULL;
1810 loadmodel->numframes = pheader->numscenes;
1811 loadmodel->num_surfaces = pheader->numshaders;
1813 skinfiles = Mod_LoadSkinFiles();
1814 if (loadmodel->numskins < 1)
1815 loadmodel->numskins = 1;
1817 // make skinscenes for the skins (no groups)
1818 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1819 for (i = 0;i < loadmodel->numskins;i++)
1821 loadmodel->skinscenes[i].firstframe = i;
1822 loadmodel->skinscenes[i].framecount = 1;
1823 loadmodel->skinscenes[i].loop = true;
1824 loadmodel->skinscenes[i].framerate = 10;
1828 modelradius = pheader->radius;
1829 for (i = 0;i < 3;i++)
1831 loadmodel->normalmins[i] = pheader->mins[i];
1832 loadmodel->normalmaxs[i] = pheader->maxs[i];
1833 loadmodel->rotatedmins[i] = -modelradius;
1834 loadmodel->rotatedmaxs[i] = modelradius;
1836 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1837 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1838 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1839 if (loadmodel->yawmaxs[0] > modelradius)
1840 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1841 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1842 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1843 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1844 loadmodel->radius = modelradius;
1845 loadmodel->radius2 = modelradius * modelradius;
1847 // go through the lumps, swapping things
1849 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1850 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1851 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1852 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1853 for (i = 0;i < pheader->numscenes;i++)
1855 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1856 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1857 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1858 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1859 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1860 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1861 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1862 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1863 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1864 if (loadmodel->animscenes[i].framerate < 0)
1865 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1869 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1870 loadmodel->num_bones = pheader->numbones;
1871 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1872 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1873 for (i = 0;i < pheader->numbones;i++)
1875 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1876 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1877 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1878 if (loadmodel->data_bones[i].parent >= i)
1879 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1882 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1883 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1884 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1885 for (i = 0;i < pheader->numverts;i++)
1887 vertbonecounts[i] = BigLong(bonecount[i]);
1888 if (vertbonecounts[i] != 1)
1889 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1892 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1894 meshvertices = pheader->numverts;
1895 meshtriangles = pheader->numtris;
1897 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1898 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1899 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1900 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshvertices * sizeof(float[14]) + meshvertices * sizeof(int[4]) + meshvertices * sizeof(float[4]) + meshvertices * sizeof(unsigned short) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]) + loadmodel->num_bones * sizeof(float[12]));
1901 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1902 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1903 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1904 loadmodel->surfmesh.num_vertices = meshvertices;
1905 loadmodel->surfmesh.num_triangles = meshtriangles;
1906 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1907 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1908 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1909 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1910 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1911 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1912 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1913 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1914 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1915 loadmodel->surfmesh.num_blends = 0;
1916 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
1917 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1918 if (loadmodel->surfmesh.num_vertices <= 65536)
1919 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1920 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
1922 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1923 poses = (float *) (pheader->lump_poses.start + pbase);
1924 // figure out scale of model from root bone, for compatibility with old zmodel versions
1925 tempvec[0] = BigFloat(poses[0]);
1926 tempvec[1] = BigFloat(poses[1]);
1927 tempvec[2] = BigFloat(poses[2]);
1928 modelscale = VectorLength(tempvec);
1930 for (i = 0;i < loadmodel->num_bones * numposes * 12;i++)
1932 f = fabs(BigFloat(poses[i]));
1933 biggestorigin = max(biggestorigin, f);
1935 loadmodel->num_posescale = biggestorigin / 32767.0f;
1936 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
1937 for (i = 0;i < numposes;i++)
1939 const float *frameposes = (float *) (pheader->lump_poses.start + pbase) + 12*i*loadmodel->num_bones;
1940 for (j = 0;j < loadmodel->num_bones;j++)
1943 matrix4x4_t posematrix;
1944 for (k = 0;k < 12;k++)
1945 pose[k] = BigFloat(frameposes[j*12+k]);
1946 //if (j < loadmodel->num_bones)
1947 // Con_Printf("%s: bone %i = %f %f %f %f : %f %f %f %f : %f %f %f %f : scale = %f\n", loadmodel->name, j, pose[0], pose[1], pose[2], pose[3], pose[4], pose[5], pose[6], pose[7], pose[8], pose[9], pose[10], pose[11], VectorLength(pose));
1948 // scale child bones to match the root scale
1949 if (loadmodel->data_bones[j].parent >= 0)
1951 pose[3] *= modelscale;
1952 pose[7] *= modelscale;
1953 pose[11] *= modelscale;
1955 // normalize rotation matrix
1956 VectorNormalize(pose + 0);
1957 VectorNormalize(pose + 4);
1958 VectorNormalize(pose + 8);
1959 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
1960 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
1964 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1965 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1966 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1967 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1968 // (converting from weight-blending skeletal animation to
1969 // deformation-based skeletal animation)
1970 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1971 for (i = 0;i < loadmodel->num_bones;i++)
1974 for (k = 0;k < 12;k++)
1975 m[k] = BigFloat(poses[i*12+k]);
1976 if (loadmodel->data_bones[i].parent >= 0)
1977 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1979 for (k = 0;k < 12;k++)
1980 bonepose[12*i+k] = m[k];
1982 Mod_Skeletal_InitBlends(loadmodel);
1983 for (j = 0;j < pheader->numverts;j++)
1985 // this format really should have had a per vertexweight weight value...
1986 // but since it does not, the weighting is completely ignored and
1987 // only one weight is allowed per vertex
1988 int boneindex = BigLong(vertdata[j].bonenum);
1989 const float *m = bonepose + 12 * boneindex;
1990 float relativeorigin[3];
1991 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1992 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1993 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1994 // transform the vertex bone weight into the base mesh
1995 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1996 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1997 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1998 // store the weight as the primary weight on this vertex
1999 loadmodel->surfmesh.blends[j] = boneindex;
2002 // normals and tangents are calculated after elements are loaded
2004 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
2005 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
2006 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
2007 for (i = 0;i < pheader->numverts;i++)
2009 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
2010 // flip T coordinate for OpenGL
2011 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
2014 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
2015 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
2016 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
2018 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
2019 //zymlump_t lump_render; // int renderlist[rendersize]; // sorted by shader with run lengths (int count), shaders are sequentially used, each run can be used with glDrawElements (each triangle is 3 int indices)
2020 // byteswap, validate, and swap winding order of tris
2021 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
2022 if (pheader->lump_render.length != count)
2023 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
2024 renderlist = (int *) (pheader->lump_render.start + pbase);
2025 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
2027 for (i = 0;i < loadmodel->num_surfaces;i++)
2029 int firstvertex, lastvertex;
2030 if (renderlist >= renderlistend)
2031 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2032 count = BigLong(*renderlist);renderlist++;
2033 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
2034 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2036 loadmodel->sortedmodelsurfaces[i] = i;
2037 surface = loadmodel->data_surfaces + i;
2038 surface->texture = loadmodel->data_textures + i;
2039 surface->num_firsttriangle = meshtriangles;
2040 surface->num_triangles = count;
2041 meshtriangles += surface->num_triangles;
2043 // load the elements
2044 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2045 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
2047 outelements[j*3+2] = BigLong(renderlist[0]);
2048 outelements[j*3+1] = BigLong(renderlist[1]);
2049 outelements[j*3+0] = BigLong(renderlist[2]);
2051 // validate the elements and find the used vertex range
2052 firstvertex = meshvertices;
2054 for (j = 0;j < surface->num_triangles * 3;j++)
2056 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
2057 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
2058 firstvertex = min(firstvertex, outelements[j]);
2059 lastvertex = max(lastvertex, outelements[j]);
2061 surface->num_firstvertex = firstvertex;
2062 surface->num_vertices = lastvertex + 1 - firstvertex;
2064 // since zym models do not have named sections, reuse their shader
2065 // name as the section name
2066 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
2067 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
2069 Mod_FreeSkinFiles(skinfiles);
2070 Mem_Free(vertbonecounts);
2072 Mod_MakeSortedSurfaces(loadmodel);
2074 // compute all the mesh information that was not loaded from the file
2075 if (loadmodel->surfmesh.data_element3s)
2076 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2077 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2078 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2079 Mod_BuildBaseBonePoses();
2080 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2081 Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, true);
2082 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2084 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2087 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2089 dpmheader_t *pheader;
2093 unsigned char *pbase;
2094 int i, j, k, meshvertices, meshtriangles;
2095 skinfile_t *skinfiles;
2096 unsigned char *data;
2098 float biggestorigin, tempvec[3], modelscale;
2102 pheader = (dpmheader_t *)buffer;
2103 pbase = (unsigned char *)buffer;
2104 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2105 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2106 if (BigLong(pheader->type) != 2)
2107 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2109 loadmodel->modeldatatypestring = "DPM";
2111 loadmodel->type = mod_alias;
2112 loadmodel->synctype = ST_RAND;
2115 pheader->type = BigLong(pheader->type);
2116 pheader->filesize = BigLong(pheader->filesize);
2117 pheader->mins[0] = BigFloat(pheader->mins[0]);
2118 pheader->mins[1] = BigFloat(pheader->mins[1]);
2119 pheader->mins[2] = BigFloat(pheader->mins[2]);
2120 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2121 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2122 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2123 pheader->yawradius = BigFloat(pheader->yawradius);
2124 pheader->allradius = BigFloat(pheader->allradius);
2125 pheader->num_bones = BigLong(pheader->num_bones);
2126 pheader->num_meshs = BigLong(pheader->num_meshs);
2127 pheader->num_frames = BigLong(pheader->num_frames);
2128 pheader->ofs_bones = BigLong(pheader->ofs_bones);
2129 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2130 pheader->ofs_frames = BigLong(pheader->ofs_frames);
2132 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2134 Con_Printf("%s has no geometry\n", loadmodel->name);
2137 if (pheader->num_frames < 1)
2139 Con_Printf("%s has no frames\n", loadmodel->name);
2143 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2144 loadmodel->DrawSky = NULL;
2145 loadmodel->DrawAddWaterPlanes = NULL;
2146 loadmodel->Draw = R_Q1BSP_Draw;
2147 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2148 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2149 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2150 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2151 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2152 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2153 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2154 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2155 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2156 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2157 loadmodel->PointSuperContents = NULL;
2160 for (i = 0;i < 3;i++)
2162 loadmodel->normalmins[i] = pheader->mins[i];
2163 loadmodel->normalmaxs[i] = pheader->maxs[i];
2164 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2165 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2166 loadmodel->rotatedmins[i] = -pheader->allradius;
2167 loadmodel->rotatedmaxs[i] = pheader->allradius;
2169 loadmodel->radius = pheader->allradius;
2170 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2172 // load external .skin files if present
2173 skinfiles = Mod_LoadSkinFiles();
2174 if (loadmodel->numskins < 1)
2175 loadmodel->numskins = 1;
2180 // gather combined statistics from the meshes
2181 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2182 for (i = 0;i < (int)pheader->num_meshs;i++)
2184 int numverts = BigLong(dpmmesh->num_verts);
2185 meshvertices += numverts;
2186 meshtriangles += BigLong(dpmmesh->num_tris);
2190 loadmodel->numframes = pheader->num_frames;
2191 loadmodel->num_bones = pheader->num_bones;
2192 loadmodel->num_poses = loadmodel->numframes;
2193 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2194 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2195 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2196 // do most allocations as one merged chunk
2197 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshtriangles * sizeof(int[3]) + meshvertices * (sizeof(float[14]) + sizeof(int[4]) + sizeof(float[4]) + sizeof(unsigned short)) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
2198 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2199 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2200 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2201 loadmodel->surfmesh.num_vertices = meshvertices;
2202 loadmodel->surfmesh.num_triangles = meshtriangles;
2203 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2204 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2205 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2206 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2207 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2208 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2209 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2210 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
2211 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
2212 loadmodel->surfmesh.num_blends = 0;
2213 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2214 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2215 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2216 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2217 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2218 if (meshvertices <= 65536)
2219 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2220 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2222 for (i = 0;i < loadmodel->numskins;i++)
2224 loadmodel->skinscenes[i].firstframe = i;
2225 loadmodel->skinscenes[i].framecount = 1;
2226 loadmodel->skinscenes[i].loop = true;
2227 loadmodel->skinscenes[i].framerate = 10;
2230 // load the bone info
2231 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2232 for (i = 0;i < loadmodel->num_bones;i++)
2234 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2235 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2236 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2237 if (loadmodel->data_bones[i].parent >= i)
2238 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2242 frames = (dpmframe_t *) (pbase + pheader->ofs_frames);
2243 // figure out scale of model from root bone, for compatibility with old dpmodel versions
2244 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2245 tempvec[0] = BigFloat(poses[0]);
2246 tempvec[1] = BigFloat(poses[1]);
2247 tempvec[2] = BigFloat(poses[2]);
2248 modelscale = VectorLength(tempvec);
2250 for (i = 0;i < loadmodel->numframes;i++)
2252 memcpy(loadmodel->animscenes[i].name, frames[i].name, sizeof(frames[i].name));
2253 loadmodel->animscenes[i].firstframe = i;
2254 loadmodel->animscenes[i].framecount = 1;
2255 loadmodel->animscenes[i].loop = true;
2256 loadmodel->animscenes[i].framerate = 10;
2257 // load the bone poses for this frame
2258 poses = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2259 for (j = 0;j < loadmodel->num_bones*12;j++)
2261 f = fabs(BigFloat(poses[j]));
2262 biggestorigin = max(biggestorigin, f);
2264 // stuff not processed here: mins, maxs, yawradius, allradius
2266 loadmodel->num_posescale = biggestorigin / 32767.0f;
2267 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2268 for (i = 0;i < loadmodel->numframes;i++)
2270 const float *frameposes = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2271 for (j = 0;j < loadmodel->num_bones;j++)
2274 matrix4x4_t posematrix;
2275 for (k = 0;k < 12;k++)
2276 pose[k] = BigFloat(frameposes[j*12+k]);
2277 // scale child bones to match the root scale
2278 if (loadmodel->data_bones[j].parent >= 0)
2280 pose[3] *= modelscale;
2281 pose[7] *= modelscale;
2282 pose[11] *= modelscale;
2284 // normalize rotation matrix
2285 VectorNormalize(pose + 0);
2286 VectorNormalize(pose + 4);
2287 VectorNormalize(pose + 8);
2288 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2289 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
2293 // load the meshes now
2294 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2297 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2298 // (converting from weight-blending skeletal animation to
2299 // deformation-based skeletal animation)
2300 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2301 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2302 for (i = 0;i < loadmodel->num_bones;i++)
2305 for (k = 0;k < 12;k++)
2306 m[k] = BigFloat(poses[i*12+k]);
2307 if (loadmodel->data_bones[i].parent >= 0)
2308 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2310 for (k = 0;k < 12;k++)
2311 bonepose[12*i+k] = m[k];
2313 Mod_Skeletal_InitBlends(loadmodel);
2314 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2316 const int *inelements;
2318 const float *intexcoord;
2319 msurface_t *surface;
2321 loadmodel->sortedmodelsurfaces[i] = i;
2322 surface = loadmodel->data_surfaces + i;
2323 surface->texture = loadmodel->data_textures + i;
2324 surface->num_firsttriangle = meshtriangles;
2325 surface->num_triangles = BigLong(dpmmesh->num_tris);
2326 surface->num_firstvertex = meshvertices;
2327 surface->num_vertices = BigLong(dpmmesh->num_verts);
2328 meshvertices += surface->num_vertices;
2329 meshtriangles += surface->num_triangles;
2331 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2332 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2333 for (j = 0;j < surface->num_triangles;j++)
2335 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2336 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2337 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2338 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2343 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2344 for (j = 0;j < surface->num_vertices*2;j++)
2345 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2347 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2348 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2350 int weightindex[4] = { 0, 0, 0, 0 };
2351 float weightinfluence[4] = { 0, 0, 0, 0 };
2354 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2355 data += sizeof(dpmvertex_t);
2356 for (k = 0;k < numweights;k++)
2358 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2359 int boneindex = BigLong(vert->bonenum);
2360 const float *m = bonepose + 12 * boneindex;
2361 float influence = BigFloat(vert->influence);
2362 float relativeorigin[3], relativenormal[3];
2363 relativeorigin[0] = BigFloat(vert->origin[0]);
2364 relativeorigin[1] = BigFloat(vert->origin[1]);
2365 relativeorigin[2] = BigFloat(vert->origin[2]);
2366 relativenormal[0] = BigFloat(vert->normal[0]);
2367 relativenormal[1] = BigFloat(vert->normal[1]);
2368 relativenormal[2] = BigFloat(vert->normal[2]);
2369 // blend the vertex bone weights into the base mesh
2370 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2371 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2372 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2373 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2374 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2375 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2378 // store the first (and often only) weight
2379 weightinfluence[0] = influence;
2380 weightindex[0] = boneindex;
2384 // sort the new weight into this vertex's weight table
2385 // (which only accepts up to 4 bones per vertex)
2386 for (l = 0;l < 4;l++)
2388 if (weightinfluence[l] < influence)
2390 // move weaker influence weights out of the way first
2392 for (l2 = 3;l2 > l;l2--)
2394 weightinfluence[l2] = weightinfluence[l2-1];
2395 weightindex[l2] = weightindex[l2-1];
2397 // store the new weight
2398 weightinfluence[l] = influence;
2399 weightindex[l] = boneindex;
2404 data += sizeof(dpmbonevert_t);
2407 for (l = 0;l < 4;l++)
2408 sum += weightinfluence[l];
2409 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2411 float f = 1.0f / sum;
2412 for (l = 0;l < 4;l++)
2413 weightinfluence[l] *= f;
2415 loadmodel->surfmesh.blends[j] = Mod_Skeletal_AddBlend(loadmodel, weightindex, weightinfluence);
2418 // since dpm models do not have named sections, reuse their shader name as the section name
2419 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2421 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2424 Mod_FreeSkinFiles(skinfiles);
2425 Mod_MakeSortedSurfaces(loadmodel);
2427 // compute all the mesh information that was not loaded from the file
2428 if (loadmodel->surfmesh.data_element3s)
2429 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2430 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2431 Mod_BuildBaseBonePoses();
2432 Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, true);
2433 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2435 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2438 // no idea why PSK/PSA files contain weird quaternions but they do...
2439 #define PSKQUATNEGATIONS
2440 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2442 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2443 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2444 fs_offset_t filesize;
2449 pskboneinfo_t *bones;
2450 pskrawweights_t *rawweights;
2451 //pskboneinfo_t *animbones;
2452 pskaniminfo_t *anims;
2453 pskanimkeys_t *animkeys;
2454 void *animfilebuffer, *animbuffer, *animbufferend;
2455 unsigned char *data;
2457 skinfile_t *skinfiles;
2458 char animname[MAX_QPATH];
2460 float biggestorigin;
2462 pchunk = (pskchunk_t *)buffer;
2463 if (strcmp(pchunk->id, "ACTRHEAD"))
2464 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2466 loadmodel->modeldatatypestring = "PSK";
2468 loadmodel->type = mod_alias;
2469 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2470 loadmodel->DrawSky = NULL;
2471 loadmodel->DrawAddWaterPlanes = NULL;
2472 loadmodel->Draw = R_Q1BSP_Draw;
2473 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2474 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2475 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2476 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2477 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2478 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2479 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2480 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2481 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2482 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2483 loadmodel->PointSuperContents = NULL;
2484 loadmodel->synctype = ST_RAND;
2486 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2487 strlcat(animname, ".psa", sizeof(animname));
2488 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2489 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2490 if (animbuffer == NULL)
2491 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2510 while (buffer < bufferend)
2512 pchunk = (pskchunk_t *)buffer;
2513 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2514 version = LittleLong(pchunk->version);
2515 recordsize = LittleLong(pchunk->recordsize);
2516 numrecords = LittleLong(pchunk->numrecords);
2517 if (developer_extra.integer)
2518 Con_DPrintf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2519 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2520 Con_Printf ("%s: chunk %s has unknown version %x (0x1e83b9, 0x1e9179, 0x2e, 0x12f2bc, 0x12f2f0 are currently supported), trying to load anyway!\n", loadmodel->name, pchunk->id, version);
2521 if (!strcmp(pchunk->id, "ACTRHEAD"))
2525 else if (!strcmp(pchunk->id, "PNTS0000"))
2528 if (recordsize != sizeof(*p))
2529 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2530 // byteswap in place and keep the pointer
2531 numpnts = numrecords;
2532 pnts = (pskpnts_t *)buffer;
2533 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2535 p->origin[0] = LittleFloat(p->origin[0]);
2536 p->origin[1] = LittleFloat(p->origin[1]);
2537 p->origin[2] = LittleFloat(p->origin[2]);
2541 else if (!strcmp(pchunk->id, "VTXW0000"))
2544 if (recordsize != sizeof(*p))
2545 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2546 // byteswap in place and keep the pointer
2547 numvtxw = numrecords;
2548 vtxw = (pskvtxw_t *)buffer;
2549 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2551 p->pntsindex = LittleShort(p->pntsindex);
2552 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2553 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2554 if (p->pntsindex >= numpnts)
2556 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2562 else if (!strcmp(pchunk->id, "FACE0000"))
2565 if (recordsize != sizeof(*p))
2566 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2567 // byteswap in place and keep the pointer
2568 numfaces = numrecords;
2569 faces = (pskface_t *)buffer;
2570 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2572 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2573 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2574 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2575 p->group = LittleLong(p->group);
2576 if (p->vtxwindex[0] >= numvtxw)
2578 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2579 p->vtxwindex[0] = 0;
2581 if (p->vtxwindex[1] >= numvtxw)
2583 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2584 p->vtxwindex[1] = 0;
2586 if (p->vtxwindex[2] >= numvtxw)
2588 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2589 p->vtxwindex[2] = 0;
2594 else if (!strcmp(pchunk->id, "MATT0000"))
2597 if (recordsize != sizeof(*p))
2598 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2599 // byteswap in place and keep the pointer
2600 nummatts = numrecords;
2601 matts = (pskmatt_t *)buffer;
2602 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2608 else if (!strcmp(pchunk->id, "REFSKELT"))
2611 if (recordsize != sizeof(*p))
2612 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2613 // byteswap in place and keep the pointer
2614 numbones = numrecords;
2615 bones = (pskboneinfo_t *)buffer;
2616 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2618 p->numchildren = LittleLong(p->numchildren);
2619 p->parent = LittleLong(p->parent);
2620 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2621 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2622 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2623 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2624 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2625 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2626 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2627 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2628 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2629 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2630 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2631 #ifdef PSKQUATNEGATIONS
2634 p->basepose.quat[0] *= -1;
2635 p->basepose.quat[1] *= -1;
2636 p->basepose.quat[2] *= -1;
2640 p->basepose.quat[0] *= 1;
2641 p->basepose.quat[1] *= -1;
2642 p->basepose.quat[2] *= 1;
2645 if (p->parent < 0 || p->parent >= numbones)
2647 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2653 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2656 if (recordsize != sizeof(*p))
2657 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2658 // byteswap in place and keep the pointer
2659 numrawweights = numrecords;
2660 rawweights = (pskrawweights_t *)buffer;
2661 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2663 p->weight = LittleFloat(p->weight);
2664 p->pntsindex = LittleLong(p->pntsindex);
2665 p->boneindex = LittleLong(p->boneindex);
2666 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2668 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2671 if (p->boneindex < 0 || p->boneindex >= numbones)
2673 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2681 while (animbuffer < animbufferend)
2683 pchunk = (pskchunk_t *)animbuffer;
2684 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2685 version = LittleLong(pchunk->version);
2686 recordsize = LittleLong(pchunk->recordsize);
2687 numrecords = LittleLong(pchunk->numrecords);
2688 if (developer_extra.integer)
2689 Con_DPrintf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2690 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2691 Con_Printf ("%s: chunk %s has unknown version %x (0x1e83b9, 0x1e9179, 0x2e, 0x12f2bc, 0x12f2f0 are currently supported), trying to load anyway!\n", animname, pchunk->id, version);
2692 if (!strcmp(pchunk->id, "ANIMHEAD"))
2696 else if (!strcmp(pchunk->id, "BONENAMES"))
2699 if (recordsize != sizeof(*p))
2700 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2701 // byteswap in place and keep the pointer
2702 numanimbones = numrecords;
2703 //animbones = (pskboneinfo_t *)animbuffer;
2704 // NOTE: supposedly psa does not need to match the psk model, the
2705 // bones missing from the psa would simply use their base
2706 // positions from the psk, but this is hard for me to implement
2707 // and people can easily make animations that match.
2708 if (numanimbones != numbones)
2709 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2710 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2712 p->numchildren = LittleLong(p->numchildren);
2713 p->parent = LittleLong(p->parent);
2714 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2715 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2716 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2717 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2718 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2719 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2720 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2721 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2722 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2723 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2724 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2725 #ifdef PSKQUATNEGATIONS
2728 p->basepose.quat[0] *= -1;
2729 p->basepose.quat[1] *= -1;
2730 p->basepose.quat[2] *= -1;
2734 p->basepose.quat[0] *= 1;
2735 p->basepose.quat[1] *= -1;
2736 p->basepose.quat[2] *= 1;
2739 if (p->parent < 0 || p->parent >= numanimbones)
2741 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2744 // check that bones are the same as in the base
2745 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2746 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2750 else if (!strcmp(pchunk->id, "ANIMINFO"))
2753 if (recordsize != sizeof(*p))
2754 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2755 // byteswap in place and keep the pointer
2756 numanims = numrecords;
2757 anims = (pskaniminfo_t *)animbuffer;
2758 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2760 p->numbones = LittleLong(p->numbones);
2761 p->playtime = LittleFloat(p->playtime);
2762 p->fps = LittleFloat(p->fps);
2763 p->firstframe = LittleLong(p->firstframe);
2764 p->numframes = LittleLong(p->numframes);
2765 if (p->numbones != numbones)
2766 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2770 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2773 if (recordsize != sizeof(*p))
2774 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2775 numanimkeys = numrecords;
2776 animkeys = (pskanimkeys_t *)animbuffer;
2777 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2779 p->origin[0] = LittleFloat(p->origin[0]);
2780 p->origin[1] = LittleFloat(p->origin[1]);
2781 p->origin[2] = LittleFloat(p->origin[2]);
2782 p->quat[0] = LittleFloat(p->quat[0]);
2783 p->quat[1] = LittleFloat(p->quat[1]);
2784 p->quat[2] = LittleFloat(p->quat[2]);
2785 p->quat[3] = LittleFloat(p->quat[3]);
2786 p->frametime = LittleFloat(p->frametime);
2787 #ifdef PSKQUATNEGATIONS
2788 if (index % numbones)
2803 // TODO: allocate bonepose stuff
2806 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2809 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2810 Host_Error("%s: missing required chunks", loadmodel->name);
2812 loadmodel->numframes = 0;
2813 for (index = 0;index < numanims;index++)
2814 loadmodel->numframes += anims[index].numframes;
2816 if (numanimkeys != numbones * loadmodel->numframes)
2817 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2819 meshvertices = numvtxw;
2820 meshtriangles = numfaces;
2822 // load external .skin files if present
2823 skinfiles = Mod_LoadSkinFiles();
2824 if (loadmodel->numskins < 1)
2825 loadmodel->numskins = 1;
2826 loadmodel->num_bones = numbones;
2827 loadmodel->num_poses = loadmodel->numframes;
2828 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2829 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2830 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2831 loadmodel->surfmesh.num_vertices = meshvertices;
2832 loadmodel->surfmesh.num_triangles = meshtriangles;
2833 // do most allocations as one merged chunk
2834 size = loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + loadmodel->surfmesh.num_triangles * sizeof(int[3]) + loadmodel->surfmesh.num_triangles * sizeof(int[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[2]) + loadmodel->surfmesh.num_vertices * sizeof(int[4]) + loadmodel->surfmesh.num_vertices * sizeof(float[4]) + loadmodel->surfmesh.num_vertices * sizeof(unsigned short) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t) + ((loadmodel->surfmesh.num_vertices <= 65536) ? (loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3])) : 0);
2835 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2836 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2837 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2838 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2839 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2840 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2841 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2842 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2843 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2844 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2845 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2846 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += loadmodel->surfmesh.num_vertices * sizeof(int[4]);
2847 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[4]);
2848 loadmodel->surfmesh.num_blends = 0;
2849 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2850 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2851 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2852 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2853 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2854 if (loadmodel->surfmesh.num_vertices <= 65536)
2855 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2856 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2858 for (i = 0;i < loadmodel->numskins;i++)
2860 loadmodel->skinscenes[i].firstframe = i;
2861 loadmodel->skinscenes[i].framecount = 1;
2862 loadmodel->skinscenes[i].loop = true;
2863 loadmodel->skinscenes[i].framerate = 10;
2867 for (index = 0, i = 0;index < nummatts;index++)
2869 // since psk models do not have named sections, reuse their shader name as the section name
2870 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2871 loadmodel->sortedmodelsurfaces[index] = index;
2872 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2873 loadmodel->data_surfaces[index].num_firstvertex = 0;
2874 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2877 // copy over the vertex locations and texcoords
2878 for (index = 0;index < numvtxw;index++)
2880 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2881 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2882 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2883 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2884 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2887 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2888 for (index = 0;index < numfaces;index++)
2889 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2890 for (index = 0, i = 0;index < nummatts;index++)
2892 loadmodel->data_surfaces[index].num_firsttriangle = i;
2893 i += loadmodel->data_surfaces[index].num_triangles;
2894 loadmodel->data_surfaces[index].num_triangles = 0;
2896 for (index = 0;index < numfaces;index++)
2898 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2899 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2900 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2901 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2904 // copy over the bones
2905 for (index = 0;index < numbones;index++)
2907 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2908 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2909 if (loadmodel->data_bones[index].parent >= index)
2910 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2913 // sort the psk point weights into the vertex weight tables
2914 // (which only accept up to 4 bones per vertex)
2915 Mod_Skeletal_InitBlends(loadmodel);
2916 for (index = 0;index < numvtxw;index++)
2919 float weightinfluence[4];
2922 for (j = 0;j < numrawweights;j++)
2924 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2926 int boneindex = rawweights[j].boneindex;
2927 float influence = rawweights[j].weight;
2928 for (l = 0;l < 4;l++)
2930 if (weightinfluence[l] < influence)
2932 // move lower influence weights out of the way first
2934 for (l2 = 3;l2 > l;l2--)
2936 weightinfluence[l2] = weightinfluence[l2-1];
2937 weightindex[l2] = weightindex[l2-1];
2939 // store the new weight
2940 weightinfluence[l] = influence;
2941 weightindex[l] = boneindex;
2948 for (l = 0;l < 4;l++)
2949 sum += weightinfluence[l];
2950 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2952 float f = 1.0f / sum;
2953 for (l = 0;l < 4;l++)
2954 weightinfluence[l] *= f;
2956 loadmodel->surfmesh.blends[index] = Mod_Skeletal_AddBlend(loadmodel, weightindex, weightinfluence);
2959 // set up the animscenes based on the anims
2960 for (index = 0, i = 0;index < numanims;index++)
2962 for (j = 0;j < anims[index].numframes;j++, i++)
2964 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2965 loadmodel->animscenes[i].firstframe = i;
2966 loadmodel->animscenes[i].framecount = 1;
2967 loadmodel->animscenes[i].loop = true;
2968 loadmodel->animscenes[i].framerate = 10;
2972 // calculate the scaling value for bone origins so they can be compressed to short
2974 for (index = 0;index < numanimkeys;index++)
2976 pskanimkeys_t *k = animkeys + index;
2977 biggestorigin = max(biggestorigin, fabs(k->origin[0]));
2978 biggestorigin = max(biggestorigin, fabs(k->origin[1]));
2979 biggestorigin = max(biggestorigin, fabs(k->origin[2]));
2981 loadmodel->num_posescale = biggestorigin / 32767.0f;
2982 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2984 // load the poses from the animkeys
2985 for (index = 0;index < numanimkeys;index++)
2987 pskanimkeys_t *k = animkeys + index;
2989 Vector4Copy(k->quat, quat);
2991 Vector4Negate(quat, quat);
2992 Vector4Normalize2(quat, quat);
2993 // compress poses to the short[6] format for longterm storage
2994 loadmodel->data_poses6s[index*6+0] = k->origin[0] * loadmodel->num_poseinvscale;
2995 loadmodel->data_poses6s[index*6+1] = k->origin[1] * loadmodel->num_poseinvscale;
2996 loadmodel->data_poses6s[index*6+2] = k->origin[2] * loadmodel->num_poseinvscale;
2997 loadmodel->data_poses6s[index*6+3] = quat[0] * 32767.0f;
2998 loadmodel->data_poses6s[index*6+4] = quat[1] * 32767.0f;
2999 loadmodel->data_poses6s[index*6+5] = quat[2] * 32767.0f;
3001 Mod_FreeSkinFiles(skinfiles);
3002 Mem_Free(animfilebuffer);
3003 Mod_MakeSortedSurfaces(loadmodel);
3005 // compute all the mesh information that was not loaded from the file
3006 // TODO: honor smoothing groups somehow?
3007 if (loadmodel->surfmesh.data_element3s)
3008 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3009 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3010 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
3011 Mod_BuildBaseBonePoses();
3012 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
3013 Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, true);
3014 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3015 Mod_Alias_CalculateBoundingBox();
3017 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;