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)
51 model->surfmesh.num_blends = 0;
54 int Mod_Skeletal_AddBlend(dp_model_t *model, const int *newindex, const float *newinfluence)
57 int *weightindex = model->surfmesh.data_vertexweightindex4i;
58 float *weightinfluence = model->surfmesh.data_vertexweightinfluence4f;
59 if(newinfluence[0] == 1)
61 for (i = 0;i < model->surfmesh.num_blends;i++, weightindex += 4, weightinfluence += 4)
63 if (weightindex[0] == newindex[0] && weightindex[1] == newindex[1] && weightindex[2] == newindex[2] && weightindex[3] == newindex[3] &&
64 weightinfluence[0] == newinfluence[0] && weightinfluence[1] == newinfluence[1] && weightinfluence[2] == newinfluence[2] && weightinfluence[3] == newinfluence[3])
65 return model->num_bones + i;
67 model->surfmesh.num_blends++;
68 memcpy(weightindex, newindex, 4*sizeof(int));
69 memcpy(weightinfluence, newinfluence, 4*sizeof(float));
70 return model->num_bones + i;
73 static int maxbonepose = 0;
74 static float (*bonepose)[12] = NULL;
76 void Mod_Skeletal_FreeBuffers(void)
84 #if defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1400)
85 #define RESTRICT __restrict
90 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)
92 // vertex weighted skeletal
96 float (*boneposerelative)[12];
97 const int * RESTRICT weightindex;
98 const float * RESTRICT weightinfluence;
100 if (maxbonepose < model->num_bones*2 + model->surfmesh.num_blends)
104 maxbonepose = model->num_bones*2 + model->surfmesh.num_blends;
105 bonepose = (float (*)[12])Mem_Alloc(r_main_mempool, maxbonepose * sizeof(float[12]));
108 boneposerelative = bonepose + model->num_bones;
110 if (skeleton && !skeleton->relativetransforms)
113 // interpolate matrices
116 for (i = 0;i < model->num_bones;i++)
118 Matrix4x4_ToArray12FloatD3D(&skeleton->relativetransforms[i], m);
119 if (model->data_bones[i].parent >= 0)
120 R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
122 memcpy(bonepose[i], m, sizeof(m));
124 // create a relative deformation matrix to describe displacement
125 // from the base mesh, which is used by the actual weighting
126 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]);
131 float originscale = model->num_posescale;
133 const short * RESTRICT pose6s;
134 for (i = 0;i < model->num_bones;i++)
136 memset(m, 0, sizeof(m));
137 for (blends = 0;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++)
139 pose6s = model->data_poses6s + 6 * (frameblend[blends].subframe * model->num_bones + i);
140 lerp = frameblend[blends].lerp;
141 x = pose6s[3] * (1.0f / 32767.0f);
142 y = pose6s[4] * (1.0f / 32767.0f);
143 z = pose6s[5] * (1.0f / 32767.0f);
144 w = 1.0f - (x*x+y*y+z*z);
145 w = w > 0.0f ? -sqrt(w) : 0.0f;
146 m[ 0] += (1-2*(y*y+z*z)) * lerp;
147 m[ 1] += ( 2*(x*y-z*w)) * lerp;
148 m[ 2] += ( 2*(x*z+y*w)) * lerp;
149 m[ 3] += (pose6s[0] * originscale) * lerp;
150 m[ 4] += ( 2*(x*y+z*w)) * lerp;
151 m[ 5] += (1-2*(x*x+z*z)) * lerp;
152 m[ 6] += ( 2*(y*z-x*w)) * lerp;
153 m[ 7] += (pose6s[1] * originscale) * lerp;
154 m[ 8] += ( 2*(x*z-y*w)) * lerp;
155 m[ 9] += ( 2*(y*z+x*w)) * lerp;
156 m[10] += (1-2*(x*x+y*y)) * lerp;
157 m[11] += (pose6s[2] * originscale) * lerp;
160 VectorNormalize(m + 4);
161 VectorNormalize(m + 8);
162 if (i == r_skeletal_debugbone.integer)
163 m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
164 m[3] *= r_skeletal_debugtranslatex.value;
165 m[7] *= r_skeletal_debugtranslatey.value;
166 m[11] *= r_skeletal_debugtranslatez.value;
167 if (model->data_bones[i].parent >= 0)
168 R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
170 memcpy(bonepose[i], m, sizeof(m));
171 // create a relative deformation matrix to describe displacement
172 // from the base mesh, which is used by the actual weighting
173 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]);
177 // generate matrices for all blend combinations
178 weightindex = model->surfmesh.data_vertexweightindex4i + model->num_bones*4;
179 weightinfluence = model->surfmesh.data_vertexweightinfluence4f + model->num_bones*4;
180 for (i = 0;i < model->surfmesh.num_blends;i++, weightindex += 4, weightinfluence += 4)
182 float * RESTRICT b = boneposerelative[model->num_bones + i];
183 const float * RESTRICT m = boneposerelative[weightindex[0]];
184 float f = weightinfluence[0];
185 b[ 0] = f*m[ 0]; b[ 1] = f*m[ 1]; b[ 2] = f*m[ 2]; b[ 3] = f*m[ 3];
186 b[ 4] = f*m[ 4]; b[ 5] = f*m[ 5]; b[ 6] = f*m[ 6]; b[ 7] = f*m[ 7];
187 b[ 8] = f*m[ 8]; b[ 9] = f*m[ 9]; b[10] = f*m[10]; b[11] = f*m[11];
188 for (k = 1;k < 4 && weightinfluence[k];k++)
190 m = boneposerelative[weightindex[k]];
191 f = weightinfluence[k];
192 b[ 0] += f*m[ 0]; b[ 1] += f*m[ 1]; b[ 2] += f*m[ 2]; b[ 3] += f*m[ 3];
193 b[ 4] += f*m[ 4]; b[ 5] += f*m[ 5]; b[ 6] += f*m[ 6]; b[ 7] += f*m[ 7];
194 b[ 8] += f*m[ 8]; b[ 9] += f*m[ 9]; b[10] += f*m[10]; b[11] += f*m[11];
198 // transform vertex attributes by blended matrices
201 const float * RESTRICT v = model->surfmesh.data_vertex3f;
202 const unsigned short * RESTRICT b = model->surfmesh.blends;
203 // special case common combinations of attributes to avoid repeated loading of matrices
206 const float * RESTRICT n = model->surfmesh.data_normal3f;
207 if (svector3f && tvector3f)
209 const float * RESTRICT sv = model->surfmesh.data_svector3f;
210 const float * RESTRICT tv = model->surfmesh.data_tvector3f;
211 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)
213 const float * RESTRICT m = boneposerelative[*b];
214 vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
215 vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
216 vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
217 normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
218 normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
219 normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
220 svector3f[0] = (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
221 svector3f[1] = (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
222 svector3f[2] = (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
223 tvector3f[0] = (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
224 tvector3f[1] = (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
225 tvector3f[2] = (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
229 for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, n += 3, b++, vertex3f += 3, normal3f += 3)
231 const float * RESTRICT m = boneposerelative[*b];
232 vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
233 vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
234 vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
235 normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
236 normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
237 normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
242 for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, b++, vertex3f += 3)
244 const float * RESTRICT m = boneposerelative[*b];
245 vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
246 vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
247 vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
253 const float * RESTRICT n = model->surfmesh.data_normal3f;
254 const unsigned short * RESTRICT b = model->surfmesh.blends;
255 for (i = 0;i < model->surfmesh.num_vertices;i++, n += 3, b++, normal3f += 3)
257 const float * RESTRICT m = boneposerelative[*b];
258 normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
259 normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
260 normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
266 const float * RESTRICT sv = model->surfmesh.data_svector3f;
267 const unsigned short * RESTRICT b = model->surfmesh.blends;
268 for (i = 0;i < model->surfmesh.num_vertices;i++, sv += 3, b++, svector3f += 3)
270 const float * RESTRICT m = boneposerelative[*b];
271 svector3f[0] = (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
272 svector3f[1] = (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
273 svector3f[2] = (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
279 const float * RESTRICT tv = model->surfmesh.data_tvector3f;
280 const unsigned short * RESTRICT b = model->surfmesh.blends;
281 for (i = 0;i < model->surfmesh.num_vertices;i++, tv += 3, b++, tvector3f += 3)
283 const float * RESTRICT m = boneposerelative[*b];
284 tvector3f[0] = (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
285 tvector3f[1] = (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
286 tvector3f[2] = (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
291 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)
294 int i, numblends, blendnum;
295 int numverts = model->surfmesh.num_vertices;
297 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
299 //VectorMA(translate, model->surfmesh.num_morphmdlframetranslate, frameblend[blendnum].lerp, translate);
300 if (frameblend[blendnum].lerp > 0)
301 numblends = blendnum + 1;
303 // special case for the first blend because it avoids some adds and the need to memset the arrays first
304 for (blendnum = 0;blendnum < numblends;blendnum++)
306 const md3vertex_t *verts = model->surfmesh.data_morphmd3vertex + numverts * frameblend[blendnum].subframe;
309 float scale = frameblend[blendnum].lerp * (1.0f / 64.0f);
312 for (i = 0;i < numverts;i++)
314 vertex3f[i * 3 + 0] = verts[i].origin[0] * scale;
315 vertex3f[i * 3 + 1] = verts[i].origin[1] * scale;
316 vertex3f[i * 3 + 2] = verts[i].origin[2] * scale;
321 for (i = 0;i < numverts;i++)
323 vertex3f[i * 3 + 0] += verts[i].origin[0] * scale;
324 vertex3f[i * 3 + 1] += verts[i].origin[1] * scale;
325 vertex3f[i * 3 + 2] += verts[i].origin[2] * scale;
329 // the yaw and pitch stored in md3 models are 8bit quantized angles
330 // (0-255), and as such a lookup table is very well suited to
331 // decoding them, and since cosine is equivilant to sine with an
332 // extra 45 degree rotation, this uses one lookup table for both
333 // sine and cosine with a +64 bias to get cosine.
336 float lerp = frameblend[blendnum].lerp;
339 for (i = 0;i < numverts;i++)
341 normal3f[i * 3 + 0] = mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
342 normal3f[i * 3 + 1] = mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
343 normal3f[i * 3 + 2] = mod_md3_sin[verts[i].pitch + 64] * lerp;
348 for (i = 0;i < numverts;i++)
350 normal3f[i * 3 + 0] += mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
351 normal3f[i * 3 + 1] += mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
352 normal3f[i * 3 + 2] += mod_md3_sin[verts[i].pitch + 64] * lerp;
358 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
359 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
362 for (i = 0;i < numverts;i++, texvecvert++)
364 VectorScale(texvecvert->svec, f, svector3f + i*3);
365 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
370 for (i = 0;i < numverts;i++, texvecvert++)
372 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
373 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
380 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)
383 int i, numblends, blendnum;
384 int numverts = model->surfmesh.num_vertices;
386 VectorClear(translate);
388 // blend the frame translates to avoid redundantly doing so on each vertex
389 // (a bit of a brain twister but it works)
390 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
392 if (model->surfmesh.data_morphmd2framesize6f)
393 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6 + 3, translate);
395 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.num_morphmdlframetranslate, translate);
396 if (frameblend[blendnum].lerp > 0)
397 numblends = blendnum + 1;
399 // special case for the first blend because it avoids some adds and the need to memset the arrays first
400 for (blendnum = 0;blendnum < numblends;blendnum++)
402 const trivertx_t *verts = model->surfmesh.data_morphmdlvertex + numverts * frameblend[blendnum].subframe;
406 if (model->surfmesh.data_morphmd2framesize6f)
407 VectorScale(model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6, frameblend[blendnum].lerp, scale);
409 VectorScale(model->surfmesh.num_morphmdlframescale, frameblend[blendnum].lerp, scale);
412 for (i = 0;i < numverts;i++)
414 vertex3f[i * 3 + 0] = translate[0] + verts[i].v[0] * scale[0];
415 vertex3f[i * 3 + 1] = translate[1] + verts[i].v[1] * scale[1];
416 vertex3f[i * 3 + 2] = translate[2] + verts[i].v[2] * scale[2];
421 for (i = 0;i < numverts;i++)
423 vertex3f[i * 3 + 0] += verts[i].v[0] * scale[0];
424 vertex3f[i * 3 + 1] += verts[i].v[1] * scale[1];
425 vertex3f[i * 3 + 2] += verts[i].v[2] * scale[2];
429 // the vertex normals in mdl models are an index into a table of
430 // 162 unique values, this very crude quantization reduces the
431 // vertex normal to only one byte, which saves a lot of space but
432 // also makes lighting pretty coarse
435 float lerp = frameblend[blendnum].lerp;
438 for (i = 0;i < numverts;i++)
440 const float *vn = m_bytenormals[verts[i].lightnormalindex];
441 VectorScale(vn, lerp, normal3f + i*3);
446 for (i = 0;i < numverts;i++)
448 const float *vn = m_bytenormals[verts[i].lightnormalindex];
449 VectorMA(normal3f + i*3, lerp, vn, normal3f + i*3);
455 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
456 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
459 for (i = 0;i < numverts;i++, texvecvert++)
461 VectorScale(texvecvert->svec, f, svector3f + i*3);
462 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
467 for (i = 0;i < numverts;i++, texvecvert++)
469 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
470 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
477 int Mod_Alias_GetTagMatrix(const dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, int tagindex, matrix4x4_t *outmatrix)
480 matrix4x4_t parentbonematrix;
481 matrix4x4_t tempbonematrix;
482 matrix4x4_t bonematrix;
483 matrix4x4_t blendmatrix;
490 *outmatrix = identitymatrix;
491 if (skeleton && skeleton->relativetransforms)
493 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
495 *outmatrix = skeleton->relativetransforms[tagindex];
496 while ((tagindex = model->data_bones[tagindex].parent) >= 0)
499 Matrix4x4_Concat(outmatrix, &skeleton->relativetransforms[tagindex], &temp);
502 else if (model->num_bones)
504 if (tagindex < 0 || tagindex >= model->num_bones)
506 Matrix4x4_Clear(&blendmatrix);
507 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
509 lerp = frameblend[blendindex].lerp;
510 Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
511 parenttagindex = tagindex;
512 while ((parenttagindex = model->data_bones[parenttagindex].parent) >= 0)
514 Matrix4x4_FromBonePose6s(&parentbonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + parenttagindex));
515 tempbonematrix = bonematrix;
516 Matrix4x4_Concat(&bonematrix, &parentbonematrix, &tempbonematrix);
518 Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
520 *outmatrix = blendmatrix;
522 else if (model->num_tags)
524 if (tagindex < 0 || tagindex >= model->num_tags)
526 for (k = 0;k < 12;k++)
528 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
530 lerp = frameblend[blendindex].lerp;
531 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
532 for (k = 0;k < 12;k++)
533 blendtag[k] += input[k] * lerp;
535 Matrix4x4_FromArray12FloatGL(outmatrix, blendtag);
538 if(!mod_alias_supporttagscale.integer)
539 Matrix4x4_Normalize3(outmatrix, outmatrix);
544 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)
549 matrix4x4_t bonematrix;
550 matrix4x4_t blendmatrix;
554 if (skeleton && skeleton->relativetransforms)
556 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
558 *parentindex = skeleton->model->data_bones[tagindex].parent;
559 *tagname = skeleton->model->data_bones[tagindex].name;
560 *tag_localmatrix = skeleton->relativetransforms[tagindex];
563 else if (model->num_bones)
565 if (tagindex < 0 || tagindex >= model->num_bones)
567 *parentindex = model->data_bones[tagindex].parent;
568 *tagname = model->data_bones[tagindex].name;
569 Matrix4x4_Clear(&blendmatrix);
570 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
572 lerp = frameblend[blendindex].lerp;
573 Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
574 Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
576 *tag_localmatrix = blendmatrix;
579 else if (model->num_tags)
581 if (tagindex < 0 || tagindex >= model->num_tags)
584 *tagname = model->data_tags[tagindex].name;
585 for (k = 0;k < 12;k++)
587 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
589 lerp = frameblend[blendindex].lerp;
590 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
591 for (k = 0;k < 12;k++)
592 blendtag[k] += input[k] * lerp;
594 Matrix4x4_FromArray12FloatGL(tag_localmatrix, blendtag);
601 int Mod_Alias_GetTagIndexForName(const dp_model_t *model, unsigned int skin, const char *tagname)
604 if(skin >= (unsigned int)model->numskins)
606 if (model->num_bones)
607 for (i = 0;i < model->num_bones;i++)
608 if (!strcasecmp(tagname, model->data_bones[i].name))
611 for (i = 0;i < model->num_tags;i++)
612 if (!strcasecmp(tagname, model->data_tags[i].name))
617 static void Mod_BuildBaseBonePoses(void)
620 matrix4x4_t *basebonepose;
621 float *outinvmatrix = loadmodel->data_baseboneposeinverse;
622 matrix4x4_t bonematrix;
623 matrix4x4_t tempbonematrix;
624 if (!loadmodel->num_bones)
626 basebonepose = (matrix4x4_t *)Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(matrix4x4_t));
627 for (boneindex = 0;boneindex < loadmodel->num_bones;boneindex++)
629 Matrix4x4_FromBonePose6s(&bonematrix, loadmodel->num_posescale, loadmodel->data_poses6s + 6 * boneindex);
630 if (loadmodel->data_bones[boneindex].parent >= 0)
632 tempbonematrix = bonematrix;
633 Matrix4x4_Concat(&bonematrix, basebonepose + loadmodel->data_bones[boneindex].parent, &tempbonematrix);
635 basebonepose[boneindex] = bonematrix;
636 Matrix4x4_Invert_Simple(&tempbonematrix, basebonepose + boneindex);
637 Matrix4x4_ToArray12FloatD3D(&tempbonematrix, outinvmatrix + 12*boneindex);
639 Mem_Free(basebonepose);
642 static void Mod_Alias_CalculateBoundingBox(void)
645 qboolean firstvertex = true;
646 float dist, yawradius, radius;
649 frameblend_t frameblend[MAX_FRAMEBLENDS];
650 memset(frameblend, 0, sizeof(frameblend));
651 frameblend[0].lerp = 1;
652 vertex3f = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
653 VectorClear(loadmodel->normalmins);
654 VectorClear(loadmodel->normalmaxs);
657 for (frameblend[0].subframe = 0;frameblend[0].subframe < loadmodel->num_poses;frameblend[0].subframe++)
659 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, vertex3f, NULL, NULL, NULL);
660 for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
665 VectorCopy(v, loadmodel->normalmins);
666 VectorCopy(v, loadmodel->normalmaxs);
670 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
671 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
672 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
673 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
674 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
675 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
677 dist = v[0] * v[0] + v[1] * v[1];
678 if (yawradius < dist)
687 radius = sqrt(radius);
688 yawradius = sqrt(yawradius);
689 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
690 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
691 loadmodel->yawmins[2] = loadmodel->normalmins[2];
692 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
693 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
694 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
695 loadmodel->radius = radius;
696 loadmodel->radius2 = radius * radius;
699 static void Mod_Alias_MorphMesh_CompileFrames(void)
702 frameblend_t frameblend[MAX_FRAMEBLENDS];
703 unsigned char *datapointer;
704 memset(frameblend, 0, sizeof(frameblend));
705 frameblend[0].lerp = 1;
706 datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
707 loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
708 loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
709 loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
710 loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
711 loadmodel->surfmesh.data_morphtexvecvertex = (texvecvertex_t *)datapointer;datapointer += loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices * sizeof(texvecvertex_t);
712 // 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)
713 for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
715 frameblend[0].subframe = i;
716 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
717 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);
718 // encode the svector and tvector in 3 byte format for permanent storage
719 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
721 VectorScaleCast(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
722 VectorScaleCast(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
727 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)
730 float segmentmins[3], segmentmaxs[3];
732 static int maxvertices = 0;
733 static float *vertex3f = NULL;
734 memset(trace, 0, sizeof(*trace));
736 trace->realfraction = 1;
737 trace->hitsupercontentsmask = hitsupercontentsmask;
738 if (maxvertices < model->surfmesh.num_vertices)
742 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
743 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
745 segmentmins[0] = min(start[0], end[0]) - 1;
746 segmentmins[1] = min(start[1], end[1]) - 1;
747 segmentmins[2] = min(start[2], end[2]) - 1;
748 segmentmaxs[0] = max(start[0], end[0]) + 1;
749 segmentmaxs[1] = max(start[1], end[1]) + 1;
750 segmentmaxs[2] = max(start[2], end[2]) + 1;
751 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
752 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
753 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);
756 static int maxvertices = 0;
757 static float *vertex3f = NULL;
759 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)
762 vec3_t shiftstart, shiftend;
763 float segmentmins[3], segmentmaxs[3];
765 colboxbrushf_t thisbrush_start, thisbrush_end;
766 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
768 if (VectorCompare(boxmins, boxmaxs))
770 VectorAdd(start, boxmins, shiftstart);
771 VectorAdd(end, boxmins, shiftend);
772 Mod_MDLMD2MD3_TraceLine(model, frameblend, skeleton, trace, shiftstart, shiftend, hitsupercontentsmask);
773 VectorSubtract(trace->endpos, boxmins, trace->endpos);
777 // box trace, performed as brush trace
778 memset(trace, 0, sizeof(*trace));
780 trace->realfraction = 1;
781 trace->hitsupercontentsmask = hitsupercontentsmask;
782 if (maxvertices < model->surfmesh.num_vertices)
786 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
787 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
789 segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
790 segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
791 segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
792 segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
793 segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
794 segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
795 VectorAdd(start, boxmins, boxstartmins);
796 VectorAdd(start, boxmaxs, boxstartmaxs);
797 VectorAdd(end, boxmins, boxendmins);
798 VectorAdd(end, boxmaxs, boxendmaxs);
799 Collision_BrushForBox(&thisbrush_start, boxstartmins, boxstartmaxs, 0, 0, NULL);
800 Collision_BrushForBox(&thisbrush_end, boxendmins, boxendmaxs, 0, 0, NULL);
801 if (maxvertices < model->surfmesh.num_vertices)
805 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
806 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
808 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
809 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
810 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);
813 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
816 for (i = 0;i < inverts;i++)
818 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
820 j = vertremap[i]; // not onseam
823 j = vertremap[i+inverts]; // onseam
829 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
831 int i, f, pose, groupframes;
833 daliasframetype_t *pframetype;
834 daliasframe_t *pinframe;
835 daliasgroup_t *group;
836 daliasinterval_t *intervals;
839 scene = loadmodel->animscenes;
840 for (f = 0;f < loadmodel->numframes;f++)
842 pframetype = (daliasframetype_t *)datapointer;
843 datapointer += sizeof(daliasframetype_t);
844 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
846 // a single frame is still treated as a group
853 group = (daliasgroup_t *)datapointer;
854 datapointer += sizeof(daliasgroup_t);
855 groupframes = LittleLong (group->numframes);
857 // intervals (time per frame)
858 intervals = (daliasinterval_t *)datapointer;
859 datapointer += sizeof(daliasinterval_t) * groupframes;
861 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
862 if (interval < 0.01f)
864 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
869 // get scene name from first frame
870 pinframe = (daliasframe_t *)datapointer;
872 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
873 scene->firstframe = pose;
874 scene->framecount = groupframes;
875 scene->framerate = 1.0f / interval;
880 for (i = 0;i < groupframes;i++)
882 pinframe = (daliasframe_t *)datapointer;
883 datapointer += sizeof(daliasframe_t);
884 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
885 datapointer += sizeof(trivertx_t) * inverts;
891 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
893 if (cls.state == ca_dedicated)
897 skinframe = R_SkinFrame_LoadMissing();
898 memset(texture, 0, sizeof(*texture));
899 texture->currentframe = texture;
900 //texture->animated = false;
901 texture->numskinframes = 1;
902 texture->skinframerate = 1;
903 texture->skinframes[0] = skinframe;
904 texture->currentskinframe = skinframe;
905 //texture->backgroundnumskinframes = 0;
906 //texture->customblendfunc[0] = 0;
907 //texture->customblendfunc[1] = 0;
908 //texture->surfaceflags = 0;
909 //texture->supercontents = 0;
910 //texture->surfaceparms = 0;
911 //texture->textureflags = 0;
913 texture->basematerialflags = MATERIALFLAG_WALL;
914 if (texture->currentskinframe->hasalpha)
915 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
916 texture->currentmaterialflags = texture->basematerialflags;
917 texture->specularscalemod = 1;
918 texture->specularpowermod = 1;
921 void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
924 skinfileitem_t *skinfileitem;
927 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
928 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
930 memset(skin, 0, sizeof(*skin));
932 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
934 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
935 if (!strcmp(skinfileitem->name, meshname))
937 Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
943 // don't render unmentioned meshes
944 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
945 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
950 Mod_LoadTextureFromQ3Shader(skin, shadername, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
953 #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);
954 #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);
955 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
957 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
958 float scales, scalet, interval;
962 stvert_t *pinstverts;
963 dtriangle_t *pintriangles;
964 daliasskintype_t *pinskintype;
965 daliasskingroup_t *pinskingroup;
966 daliasskininterval_t *pinskinintervals;
967 daliasframetype_t *pinframetype;
968 daliasgroup_t *pinframegroup;
969 unsigned char *datapointer, *startframes, *startskins;
970 char name[MAX_QPATH];
971 skinframe_t *tempskinframe;
972 animscene_t *tempskinscenes;
973 texture_t *tempaliasskins;
975 int *vertonseam, *vertremap;
976 skinfile_t *skinfiles;
978 datapointer = (unsigned char *)buffer;
979 pinmodel = (mdl_t *)datapointer;
980 datapointer += sizeof(mdl_t);
982 version = LittleLong (pinmodel->version);
983 if (version != ALIAS_VERSION)
984 Host_Error ("%s has wrong version number (%i should be %i)",
985 loadmodel->name, version, ALIAS_VERSION);
987 loadmodel->modeldatatypestring = "MDL";
989 loadmodel->type = mod_alias;
990 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
991 loadmodel->DrawSky = NULL;
992 loadmodel->DrawAddWaterPlanes = NULL;
993 loadmodel->Draw = R_Q1BSP_Draw;
994 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
995 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
996 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
997 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
998 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
999 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1000 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1001 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1002 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1003 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1004 loadmodel->PointSuperContents = NULL;
1006 loadmodel->num_surfaces = 1;
1007 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1008 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
1009 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1010 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1011 loadmodel->sortedmodelsurfaces[0] = 0;
1013 loadmodel->numskins = LittleLong(pinmodel->numskins);
1014 BOUNDI(loadmodel->numskins,0,65536);
1015 skinwidth = LittleLong (pinmodel->skinwidth);
1016 BOUNDI(skinwidth,0,65536);
1017 skinheight = LittleLong (pinmodel->skinheight);
1018 BOUNDI(skinheight,0,65536);
1019 numverts = LittleLong(pinmodel->numverts);
1020 BOUNDI(numverts,0,65536);
1021 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
1022 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
1023 loadmodel->numframes = LittleLong(pinmodel->numframes);
1024 BOUNDI(loadmodel->numframes,0,65536);
1025 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
1026 BOUNDI((int)loadmodel->synctype,0,2);
1027 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1028 i = LittleLong (pinmodel->flags);
1029 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1031 for (i = 0;i < 3;i++)
1033 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
1034 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
1037 startskins = datapointer;
1039 for (i = 0;i < loadmodel->numskins;i++)
1041 pinskintype = (daliasskintype_t *)datapointer;
1042 datapointer += sizeof(daliasskintype_t);
1043 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
1047 pinskingroup = (daliasskingroup_t *)datapointer;
1048 datapointer += sizeof(daliasskingroup_t);
1049 groupskins = LittleLong(pinskingroup->numskins);
1050 datapointer += sizeof(daliasskininterval_t) * groupskins;
1053 for (j = 0;j < groupskins;j++)
1055 datapointer += skinwidth * skinheight;
1060 pinstverts = (stvert_t *)datapointer;
1061 datapointer += sizeof(stvert_t) * numverts;
1063 pintriangles = (dtriangle_t *)datapointer;
1064 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
1066 startframes = datapointer;
1067 loadmodel->surfmesh.num_morphframes = 0;
1068 for (i = 0;i < loadmodel->numframes;i++)
1070 pinframetype = (daliasframetype_t *)datapointer;
1071 datapointer += sizeof(daliasframetype_t);
1072 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
1076 pinframegroup = (daliasgroup_t *)datapointer;
1077 datapointer += sizeof(daliasgroup_t);
1078 groupframes = LittleLong(pinframegroup->numframes);
1079 datapointer += sizeof(daliasinterval_t) * groupframes;
1082 for (j = 0;j < groupframes;j++)
1084 datapointer += sizeof(daliasframe_t);
1085 datapointer += sizeof(trivertx_t) * numverts;
1086 loadmodel->surfmesh.num_morphframes++;
1089 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1091 // store texture coordinates into temporary array, they will be stored
1092 // after usage is determined (triangle data)
1093 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
1094 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
1095 vertonseam = vertremap + numverts * 2;
1097 scales = 1.0 / skinwidth;
1098 scalet = 1.0 / skinheight;
1099 for (i = 0;i < numverts;i++)
1101 vertonseam[i] = LittleLong(pinstverts[i].onseam);
1102 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
1103 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
1104 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
1105 vertst[(i+numverts)*2+1] = vertst[i*2+1];
1108 // load triangle data
1109 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1111 // read the triangle elements
1112 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1113 for (j = 0;j < 3;j++)
1114 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1115 // validate (note numverts is used because this is the original data)
1116 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1117 // now butcher the elements according to vertonseam and tri->facesfront
1118 // and then compact the vertex set to remove duplicates
1119 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1120 if (!LittleLong(pintriangles[i].facesfront)) // backface
1121 for (j = 0;j < 3;j++)
1122 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1123 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1125 // (this uses vertremap to count usage to save some memory)
1126 for (i = 0;i < numverts*2;i++)
1128 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1129 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1130 // build remapping table and compact array
1131 loadmodel->surfmesh.num_vertices = 0;
1132 for (i = 0;i < numverts*2;i++)
1136 vertremap[i] = loadmodel->surfmesh.num_vertices;
1137 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1138 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1139 loadmodel->surfmesh.num_vertices++;
1142 vertremap[i] = -1; // not used at all
1144 // remap the elements to the new vertex set
1145 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1146 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1147 // store the texture coordinates
1148 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1149 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1151 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1152 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1155 // generate ushort elements array if possible
1156 if (loadmodel->surfmesh.num_vertices <= 65536)
1157 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1158 if (loadmodel->surfmesh.data_element3s)
1159 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1160 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1163 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1164 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1165 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1166 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1167 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1168 Mod_Alias_CalculateBoundingBox();
1169 Mod_Alias_MorphMesh_CompileFrames();
1172 Mem_Free(vertremap);
1175 skinfiles = Mod_LoadSkinFiles();
1178 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1179 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1180 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1181 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1182 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1183 Mod_FreeSkinFiles(skinfiles);
1184 for (i = 0;i < loadmodel->numskins;i++)
1186 loadmodel->skinscenes[i].firstframe = i;
1187 loadmodel->skinscenes[i].framecount = 1;
1188 loadmodel->skinscenes[i].loop = true;
1189 loadmodel->skinscenes[i].framerate = 10;
1194 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1195 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1196 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1197 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1199 datapointer = startskins;
1200 for (i = 0;i < loadmodel->numskins;i++)
1202 pinskintype = (daliasskintype_t *)datapointer;
1203 datapointer += sizeof(daliasskintype_t);
1205 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1212 pinskingroup = (daliasskingroup_t *)datapointer;
1213 datapointer += sizeof(daliasskingroup_t);
1215 groupskins = LittleLong (pinskingroup->numskins);
1217 pinskinintervals = (daliasskininterval_t *)datapointer;
1218 datapointer += sizeof(daliasskininterval_t) * groupskins;
1220 interval = LittleFloat(pinskinintervals[0].interval);
1221 if (interval < 0.01f)
1223 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1228 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1229 loadmodel->skinscenes[i].firstframe = totalskins;
1230 loadmodel->skinscenes[i].framecount = groupskins;
1231 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1232 loadmodel->skinscenes[i].loop = true;
1234 for (j = 0;j < groupskins;j++)
1237 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1239 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1240 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))
1241 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));
1242 datapointer += skinwidth * skinheight;
1246 // check for skins that don't exist in the model, but do exist as external images
1247 // (this was added because yummyluv kept pestering me about support for it)
1248 // TODO: support shaders here?
1249 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)))
1251 // expand the arrays to make room
1252 tempskinscenes = loadmodel->skinscenes;
1253 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1254 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1255 Mem_Free(tempskinscenes);
1257 tempaliasskins = loadmodel->data_textures;
1258 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1259 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1260 Mem_Free(tempaliasskins);
1262 // store the info about the new skin
1263 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1264 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1265 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1266 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1267 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1268 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1270 //increase skin counts
1271 loadmodel->numskins++;
1274 // fix up the pointers since they are pointing at the old textures array
1275 // FIXME: this is a hack!
1276 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1277 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1281 surface = loadmodel->data_surfaces;
1282 surface->texture = loadmodel->data_textures;
1283 surface->num_firsttriangle = 0;
1284 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1285 surface->num_firstvertex = 0;
1286 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1288 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1291 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1293 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1294 float iskinwidth, iskinheight;
1295 unsigned char *data;
1296 msurface_t *surface;
1298 unsigned char *base, *datapointer;
1299 md2frame_t *pinframe;
1301 md2triangle_t *intri;
1302 unsigned short *inst;
1303 struct md2verthash_s
1305 struct md2verthash_s *next;
1309 *hash, **md2verthash, *md2verthashdata;
1310 skinfile_t *skinfiles;
1312 pinmodel = (md2_t *)buffer;
1313 base = (unsigned char *)buffer;
1315 version = LittleLong (pinmodel->version);
1316 if (version != MD2ALIAS_VERSION)
1317 Host_Error ("%s has wrong version number (%i should be %i)",
1318 loadmodel->name, version, MD2ALIAS_VERSION);
1320 loadmodel->modeldatatypestring = "MD2";
1322 loadmodel->type = mod_alias;
1323 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1324 loadmodel->DrawSky = NULL;
1325 loadmodel->DrawAddWaterPlanes = NULL;
1326 loadmodel->Draw = R_Q1BSP_Draw;
1327 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1328 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1329 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1330 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1331 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1332 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1333 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1334 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1335 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1336 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1337 loadmodel->PointSuperContents = NULL;
1339 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1340 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1341 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1342 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1343 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1344 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1345 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1346 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1348 end = LittleLong(pinmodel->ofs_end);
1349 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1350 Host_Error ("%s is not a valid model", loadmodel->name);
1351 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1352 Host_Error ("%s is not a valid model", loadmodel->name);
1353 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1354 Host_Error ("%s is not a valid model", loadmodel->name);
1355 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1356 Host_Error ("%s is not a valid model", loadmodel->name);
1357 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1358 Host_Error ("%s is not a valid model", loadmodel->name);
1360 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1361 numxyz = LittleLong(pinmodel->num_xyz);
1362 numst = LittleLong(pinmodel->num_st);
1363 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1364 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1365 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1366 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1367 skinwidth = LittleLong(pinmodel->skinwidth);
1368 skinheight = LittleLong(pinmodel->skinheight);
1369 iskinwidth = 1.0f / skinwidth;
1370 iskinheight = 1.0f / skinheight;
1372 loadmodel->num_surfaces = 1;
1373 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1374 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]));
1375 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1376 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1377 loadmodel->sortedmodelsurfaces[0] = 0;
1378 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1379 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1380 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1381 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1383 loadmodel->synctype = ST_RAND;
1386 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1387 skinfiles = Mod_LoadSkinFiles();
1390 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1391 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1392 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1393 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1394 Mod_FreeSkinFiles(skinfiles);
1396 else if (loadmodel->numskins)
1398 // skins found (most likely not a player model)
1399 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1400 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1401 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1402 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1403 Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
1407 // no skins (most likely a player model)
1408 loadmodel->numskins = 1;
1409 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1410 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1411 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1412 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1415 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1416 for (i = 0;i < loadmodel->numskins;i++)
1418 loadmodel->skinscenes[i].firstframe = i;
1419 loadmodel->skinscenes[i].framecount = 1;
1420 loadmodel->skinscenes[i].loop = true;
1421 loadmodel->skinscenes[i].framerate = 10;
1424 // load the triangles and stvert data
1425 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1426 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1427 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1428 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1429 // swap the triangle list
1430 loadmodel->surfmesh.num_vertices = 0;
1431 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1433 for (j = 0;j < 3;j++)
1435 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1436 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1439 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1444 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1447 hashindex = (xyz * 256 + st) & 65535;
1448 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1449 if (hash->xyz == xyz && hash->st == st)
1453 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1456 hash->next = md2verthash[hashindex];
1457 md2verthash[hashindex] = hash;
1459 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1463 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1464 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));
1465 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1466 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1467 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1470 hash = md2verthashdata + i;
1471 vertremap[i] = hash->xyz;
1472 sts = LittleShort(inst[hash->st*2+0]);
1473 stt = LittleShort(inst[hash->st*2+1]);
1474 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1476 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1480 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1481 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1484 Mem_Free(md2verthash);
1485 Mem_Free(md2verthashdata);
1487 // generate ushort elements array if possible
1488 if (loadmodel->surfmesh.num_vertices <= 65536)
1489 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1490 if (loadmodel->surfmesh.data_element3s)
1491 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1492 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1495 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1496 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1501 pinframe = (md2frame_t *)datapointer;
1502 datapointer += sizeof(md2frame_t);
1503 // store the frame scale/translate into the appropriate array
1504 for (j = 0;j < 3;j++)
1506 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1507 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1509 // convert the vertices
1510 v = (trivertx_t *)datapointer;
1511 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1512 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1513 out[k] = v[vertremap[k]];
1514 datapointer += numxyz * sizeof(trivertx_t);
1516 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1517 loadmodel->animscenes[i].firstframe = i;
1518 loadmodel->animscenes[i].framecount = 1;
1519 loadmodel->animscenes[i].framerate = 10;
1520 loadmodel->animscenes[i].loop = true;
1523 Mem_Free(vertremap);
1525 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1526 Mod_Alias_CalculateBoundingBox();
1527 Mod_Alias_MorphMesh_CompileFrames();
1529 surface = loadmodel->data_surfaces;
1530 surface->texture = loadmodel->data_textures;
1531 surface->num_firsttriangle = 0;
1532 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1533 surface->num_firstvertex = 0;
1534 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1536 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1539 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1541 int i, j, k, version, meshvertices, meshtriangles;
1542 unsigned char *data;
1543 msurface_t *surface;
1544 md3modelheader_t *pinmodel;
1545 md3frameinfo_t *pinframe;
1548 skinfile_t *skinfiles;
1550 pinmodel = (md3modelheader_t *)buffer;
1552 if (memcmp(pinmodel->identifier, "IDP3", 4))
1553 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1554 version = LittleLong (pinmodel->version);
1555 if (version != MD3VERSION)
1556 Host_Error ("%s has wrong version number (%i should be %i)",
1557 loadmodel->name, version, MD3VERSION);
1559 skinfiles = Mod_LoadSkinFiles();
1560 if (loadmodel->numskins < 1)
1561 loadmodel->numskins = 1;
1563 loadmodel->modeldatatypestring = "MD3";
1565 loadmodel->type = mod_alias;
1566 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1567 loadmodel->DrawSky = NULL;
1568 loadmodel->DrawAddWaterPlanes = NULL;
1569 loadmodel->Draw = R_Q1BSP_Draw;
1570 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1571 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1572 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1573 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1574 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1575 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1576 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1577 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1578 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1579 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1580 loadmodel->PointSuperContents = NULL;
1581 loadmodel->synctype = ST_RAND;
1582 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1583 i = LittleLong (pinmodel->flags);
1584 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1586 // set up some global info about the model
1587 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1588 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1590 // make skinscenes for the skins (no groups)
1591 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1592 for (i = 0;i < loadmodel->numskins;i++)
1594 loadmodel->skinscenes[i].firstframe = i;
1595 loadmodel->skinscenes[i].framecount = 1;
1596 loadmodel->skinscenes[i].loop = true;
1597 loadmodel->skinscenes[i].framerate = 10;
1601 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1602 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1604 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1605 loadmodel->animscenes[i].firstframe = i;
1606 loadmodel->animscenes[i].framecount = 1;
1607 loadmodel->animscenes[i].framerate = 10;
1608 loadmodel->animscenes[i].loop = true;
1612 loadmodel->num_tagframes = loadmodel->numframes;
1613 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1614 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1615 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1617 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1618 for (j = 0;j < 9;j++)
1619 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1620 for (j = 0;j < 3;j++)
1621 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1622 //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);
1628 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)))
1630 if (memcmp(pinmesh->identifier, "IDP3", 4))
1631 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1632 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1633 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1634 meshvertices += LittleLong(pinmesh->num_vertices);
1635 meshtriangles += LittleLong(pinmesh->num_triangles);
1638 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1639 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1640 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1641 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));
1642 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1643 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1644 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1645 loadmodel->surfmesh.num_vertices = meshvertices;
1646 loadmodel->surfmesh.num_triangles = meshtriangles;
1647 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1648 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1649 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1650 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1651 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1652 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1653 if (meshvertices <= 65536)
1654 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1658 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)))
1660 if (memcmp(pinmesh->identifier, "IDP3", 4))
1661 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1662 loadmodel->sortedmodelsurfaces[i] = i;
1663 surface = loadmodel->data_surfaces + i;
1664 surface->texture = loadmodel->data_textures + i;
1665 surface->num_firsttriangle = meshtriangles;
1666 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1667 surface->num_firstvertex = meshvertices;
1668 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1669 meshvertices += surface->num_vertices;
1670 meshtriangles += surface->num_triangles;
1672 for (j = 0;j < surface->num_triangles * 3;j++)
1673 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1674 for (j = 0;j < surface->num_vertices;j++)
1676 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1677 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1679 for (j = 0;j < loadmodel->numframes;j++)
1681 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1682 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1683 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1685 out->origin[0] = LittleShort(in->origin[0]);
1686 out->origin[1] = LittleShort(in->origin[1]);
1687 out->origin[2] = LittleShort(in->origin[2]);
1688 out->pitch = in->pitch;
1693 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1695 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1697 if (loadmodel->surfmesh.data_element3s)
1698 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1699 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1700 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1701 Mod_Alias_MorphMesh_CompileFrames();
1702 Mod_Alias_CalculateBoundingBox();
1703 Mod_FreeSkinFiles(skinfiles);
1704 Mod_MakeSortedSurfaces(loadmodel);
1706 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1707 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1710 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1712 zymtype1header_t *pinmodel, *pheader;
1713 unsigned char *pbase;
1714 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1715 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose, f, biggestorigin, tempvec[3], modelscale;
1716 zymvertex_t *verts, *vertdata;
1720 skinfile_t *skinfiles;
1721 unsigned char *data;
1722 msurface_t *surface;
1724 pinmodel = (zymtype1header_t *)buffer;
1725 pbase = (unsigned char *)buffer;
1726 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1727 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1728 if (BigLong(pinmodel->type) != 1)
1729 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1731 loadmodel->modeldatatypestring = "ZYM";
1733 loadmodel->type = mod_alias;
1734 loadmodel->synctype = ST_RAND;
1738 pheader->type = BigLong(pinmodel->type);
1739 pheader->filesize = BigLong(pinmodel->filesize);
1740 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1741 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1742 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1743 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1744 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1745 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1746 pheader->radius = BigFloat(pinmodel->radius);
1747 pheader->numverts = BigLong(pinmodel->numverts);
1748 pheader->numtris = BigLong(pinmodel->numtris);
1749 pheader->numshaders = BigLong(pinmodel->numshaders);
1750 pheader->numbones = BigLong(pinmodel->numbones);
1751 pheader->numscenes = BigLong(pinmodel->numscenes);
1752 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1753 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1754 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1755 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1756 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1757 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1758 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1759 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1760 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1761 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1762 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1763 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1764 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1765 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1766 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1767 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1768 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1769 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1771 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1773 Con_Printf("%s has no geometry\n", loadmodel->name);
1776 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1778 Con_Printf("%s has no animations\n", loadmodel->name);
1782 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1783 loadmodel->DrawSky = NULL;
1784 loadmodel->DrawAddWaterPlanes = NULL;
1785 loadmodel->Draw = R_Q1BSP_Draw;
1786 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1787 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1788 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1789 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1790 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1791 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1792 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1793 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1794 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1795 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1796 loadmodel->PointSuperContents = NULL;
1798 loadmodel->numframes = pheader->numscenes;
1799 loadmodel->num_surfaces = pheader->numshaders;
1801 skinfiles = Mod_LoadSkinFiles();
1802 if (loadmodel->numskins < 1)
1803 loadmodel->numskins = 1;
1805 // make skinscenes for the skins (no groups)
1806 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1807 for (i = 0;i < loadmodel->numskins;i++)
1809 loadmodel->skinscenes[i].firstframe = i;
1810 loadmodel->skinscenes[i].framecount = 1;
1811 loadmodel->skinscenes[i].loop = true;
1812 loadmodel->skinscenes[i].framerate = 10;
1816 modelradius = pheader->radius;
1817 for (i = 0;i < 3;i++)
1819 loadmodel->normalmins[i] = pheader->mins[i];
1820 loadmodel->normalmaxs[i] = pheader->maxs[i];
1821 loadmodel->rotatedmins[i] = -modelradius;
1822 loadmodel->rotatedmaxs[i] = modelradius;
1824 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1825 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1826 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1827 if (loadmodel->yawmaxs[0] > modelradius)
1828 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1829 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1830 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1831 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1832 loadmodel->radius = modelradius;
1833 loadmodel->radius2 = modelradius * modelradius;
1835 // go through the lumps, swapping things
1837 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1838 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1839 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1840 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1841 for (i = 0;i < pheader->numscenes;i++)
1843 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1844 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1845 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1846 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1847 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1848 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1849 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1850 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1851 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1852 if (loadmodel->animscenes[i].framerate < 0)
1853 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1857 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1858 loadmodel->num_bones = pheader->numbones;
1859 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1860 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1861 for (i = 0;i < pheader->numbones;i++)
1863 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1864 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1865 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1866 if (loadmodel->data_bones[i].parent >= i)
1867 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1870 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1871 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1872 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1873 for (i = 0;i < pheader->numverts;i++)
1875 vertbonecounts[i] = BigLong(bonecount[i]);
1876 if (vertbonecounts[i] != 1)
1877 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1880 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1882 meshvertices = pheader->numverts;
1883 meshtriangles = pheader->numtris;
1885 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1886 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1887 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1888 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]));
1889 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1890 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1891 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1892 loadmodel->surfmesh.num_vertices = meshvertices;
1893 loadmodel->surfmesh.num_triangles = meshtriangles;
1894 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1895 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1896 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1897 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1898 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1899 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1900 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1901 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1902 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1903 loadmodel->surfmesh.num_blends = 0;
1904 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1905 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
1906 if (loadmodel->surfmesh.num_vertices <= 65536)
1907 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1908 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
1910 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1911 poses = (float *) (pheader->lump_poses.start + pbase);
1912 // figure out scale of model from root bone, for compatibility with old zmodel versions
1913 tempvec[0] = BigFloat(poses[0]);
1914 tempvec[1] = BigFloat(poses[1]);
1915 tempvec[2] = BigFloat(poses[2]);
1916 modelscale = VectorLength(tempvec);
1918 for (i = 0;i < loadmodel->num_bones * numposes * 12;i++)
1920 f = fabs(BigFloat(poses[i]));
1921 biggestorigin = max(biggestorigin, f);
1923 loadmodel->num_posescale = biggestorigin / 32767.0f;
1924 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
1925 for (i = 0;i < numposes;i++)
1927 const float *frameposes = (float *) (pheader->lump_poses.start + pbase) + 12*i*loadmodel->num_bones;
1928 for (j = 0;j < loadmodel->num_bones;j++)
1931 matrix4x4_t posematrix;
1932 for (k = 0;k < 12;k++)
1933 pose[k] = BigFloat(frameposes[j*12+k]);
1934 //if (j < loadmodel->num_bones)
1935 // 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));
1936 // scale child bones to match the root scale
1937 if (loadmodel->data_bones[j].parent >= 0)
1939 pose[3] *= modelscale;
1940 pose[7] *= modelscale;
1941 pose[11] *= modelscale;
1943 // normalize rotation matrix
1944 VectorNormalize(pose + 0);
1945 VectorNormalize(pose + 4);
1946 VectorNormalize(pose + 8);
1947 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
1948 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
1952 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1953 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1954 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1955 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1956 // (converting from weight-blending skeletal animation to
1957 // deformation-based skeletal animation)
1958 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1959 for (i = 0;i < loadmodel->num_bones;i++)
1962 for (k = 0;k < 12;k++)
1963 m[k] = BigFloat(poses[i*12+k]);
1964 if (loadmodel->data_bones[i].parent >= 0)
1965 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1967 for (k = 0;k < 12;k++)
1968 bonepose[12*i+k] = m[k];
1970 Mod_Skeletal_InitBlends(loadmodel);
1971 for (j = 0;j < pheader->numverts;j++)
1973 // this format really should have had a per vertexweight weight value...
1974 // but since it does not, the weighting is completely ignored and
1975 // only one weight is allowed per vertex
1976 int boneindex = BigLong(vertdata[j].bonenum);
1977 const float *m = bonepose + 12 * boneindex;
1978 float relativeorigin[3];
1979 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1980 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1981 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1982 // transform the vertex bone weight into the base mesh
1983 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1984 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1985 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1986 // store the weight as the primary weight on this vertex
1987 loadmodel->surfmesh.blends[j] = boneindex;
1990 // normals and tangents are calculated after elements are loaded
1992 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1993 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1994 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1995 for (i = 0;i < pheader->numverts;i++)
1997 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1998 // flip T coordinate for OpenGL
1999 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
2002 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
2003 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
2004 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
2006 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
2007 //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)
2008 // byteswap, validate, and swap winding order of tris
2009 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
2010 if (pheader->lump_render.length != count)
2011 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
2012 renderlist = (int *) (pheader->lump_render.start + pbase);
2013 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
2015 for (i = 0;i < loadmodel->num_surfaces;i++)
2017 int firstvertex, lastvertex;
2018 if (renderlist >= renderlistend)
2019 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2020 count = BigLong(*renderlist);renderlist++;
2021 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
2022 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2024 loadmodel->sortedmodelsurfaces[i] = i;
2025 surface = loadmodel->data_surfaces + i;
2026 surface->texture = loadmodel->data_textures + i;
2027 surface->num_firsttriangle = meshtriangles;
2028 surface->num_triangles = count;
2029 meshtriangles += surface->num_triangles;
2031 // load the elements
2032 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2033 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
2035 outelements[j*3+2] = BigLong(renderlist[0]);
2036 outelements[j*3+1] = BigLong(renderlist[1]);
2037 outelements[j*3+0] = BigLong(renderlist[2]);
2039 // validate the elements and find the used vertex range
2040 firstvertex = meshvertices;
2042 for (j = 0;j < surface->num_triangles * 3;j++)
2044 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
2045 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
2046 firstvertex = min(firstvertex, outelements[j]);
2047 lastvertex = max(lastvertex, outelements[j]);
2049 surface->num_firstvertex = firstvertex;
2050 surface->num_vertices = lastvertex + 1 - firstvertex;
2052 // since zym models do not have named sections, reuse their shader
2053 // name as the section name
2054 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
2055 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
2057 Mod_FreeSkinFiles(skinfiles);
2058 Mem_Free(vertbonecounts);
2060 Mod_MakeSortedSurfaces(loadmodel);
2062 // compute all the mesh information that was not loaded from the file
2063 if (loadmodel->surfmesh.data_element3s)
2064 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2065 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2066 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2067 Mod_BuildBaseBonePoses();
2068 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2069 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);
2070 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2072 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2075 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2077 dpmheader_t *pheader;
2081 unsigned char *pbase;
2082 int i, j, k, meshvertices, meshtriangles;
2083 skinfile_t *skinfiles;
2084 unsigned char *data;
2086 float biggestorigin, tempvec[3], modelscale;
2090 pheader = (dpmheader_t *)buffer;
2091 pbase = (unsigned char *)buffer;
2092 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2093 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2094 if (BigLong(pheader->type) != 2)
2095 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2097 loadmodel->modeldatatypestring = "DPM";
2099 loadmodel->type = mod_alias;
2100 loadmodel->synctype = ST_RAND;
2103 pheader->type = BigLong(pheader->type);
2104 pheader->filesize = BigLong(pheader->filesize);
2105 pheader->mins[0] = BigFloat(pheader->mins[0]);
2106 pheader->mins[1] = BigFloat(pheader->mins[1]);
2107 pheader->mins[2] = BigFloat(pheader->mins[2]);
2108 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2109 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2110 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2111 pheader->yawradius = BigFloat(pheader->yawradius);
2112 pheader->allradius = BigFloat(pheader->allradius);
2113 pheader->num_bones = BigLong(pheader->num_bones);
2114 pheader->num_meshs = BigLong(pheader->num_meshs);
2115 pheader->num_frames = BigLong(pheader->num_frames);
2116 pheader->ofs_bones = BigLong(pheader->ofs_bones);
2117 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2118 pheader->ofs_frames = BigLong(pheader->ofs_frames);
2120 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2122 Con_Printf("%s has no geometry\n", loadmodel->name);
2125 if (pheader->num_frames < 1)
2127 Con_Printf("%s has no frames\n", loadmodel->name);
2131 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2132 loadmodel->DrawSky = NULL;
2133 loadmodel->DrawAddWaterPlanes = NULL;
2134 loadmodel->Draw = R_Q1BSP_Draw;
2135 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2136 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2137 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2138 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2139 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2140 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2141 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2142 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2143 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2144 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2145 loadmodel->PointSuperContents = NULL;
2148 for (i = 0;i < 3;i++)
2150 loadmodel->normalmins[i] = pheader->mins[i];
2151 loadmodel->normalmaxs[i] = pheader->maxs[i];
2152 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2153 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2154 loadmodel->rotatedmins[i] = -pheader->allradius;
2155 loadmodel->rotatedmaxs[i] = pheader->allradius;
2157 loadmodel->radius = pheader->allradius;
2158 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2160 // load external .skin files if present
2161 skinfiles = Mod_LoadSkinFiles();
2162 if (loadmodel->numskins < 1)
2163 loadmodel->numskins = 1;
2168 // gather combined statistics from the meshes
2169 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2170 for (i = 0;i < (int)pheader->num_meshs;i++)
2172 int numverts = BigLong(dpmmesh->num_verts);
2173 meshvertices += numverts;
2174 meshtriangles += BigLong(dpmmesh->num_tris);
2178 loadmodel->numframes = pheader->num_frames;
2179 loadmodel->num_bones = pheader->num_bones;
2180 loadmodel->num_poses = loadmodel->numframes;
2181 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2182 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2183 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2184 // do most allocations as one merged chunk
2185 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));
2186 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2187 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2188 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2189 loadmodel->surfmesh.num_vertices = meshvertices;
2190 loadmodel->surfmesh.num_triangles = meshtriangles;
2191 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2192 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2193 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2194 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2195 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2196 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2197 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2198 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
2199 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
2200 loadmodel->surfmesh.num_blends = 0;
2201 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2202 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2203 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2204 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2205 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2206 if (meshvertices <= 65536)
2207 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2208 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2210 for (i = 0;i < loadmodel->numskins;i++)
2212 loadmodel->skinscenes[i].firstframe = i;
2213 loadmodel->skinscenes[i].framecount = 1;
2214 loadmodel->skinscenes[i].loop = true;
2215 loadmodel->skinscenes[i].framerate = 10;
2218 // load the bone info
2219 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2220 for (i = 0;i < loadmodel->num_bones;i++)
2222 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2223 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2224 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2225 if (loadmodel->data_bones[i].parent >= i)
2226 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2230 frames = (dpmframe_t *) (pbase + pheader->ofs_frames);
2231 // figure out scale of model from root bone, for compatibility with old dpmodel versions
2232 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2233 tempvec[0] = BigFloat(poses[0]);
2234 tempvec[1] = BigFloat(poses[1]);
2235 tempvec[2] = BigFloat(poses[2]);
2236 modelscale = VectorLength(tempvec);
2238 for (i = 0;i < loadmodel->numframes;i++)
2240 memcpy(loadmodel->animscenes[i].name, frames[i].name, sizeof(frames[i].name));
2241 loadmodel->animscenes[i].firstframe = i;
2242 loadmodel->animscenes[i].framecount = 1;
2243 loadmodel->animscenes[i].loop = true;
2244 loadmodel->animscenes[i].framerate = 10;
2245 // load the bone poses for this frame
2246 poses = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2247 for (j = 0;j < loadmodel->num_bones*12;j++)
2249 f = fabs(BigFloat(poses[j]));
2250 biggestorigin = max(biggestorigin, f);
2252 // stuff not processed here: mins, maxs, yawradius, allradius
2254 loadmodel->num_posescale = biggestorigin / 32767.0f;
2255 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2256 for (i = 0;i < loadmodel->numframes;i++)
2258 const float *frameposes = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2259 for (j = 0;j < loadmodel->num_bones;j++)
2262 matrix4x4_t posematrix;
2263 for (k = 0;k < 12;k++)
2264 pose[k] = BigFloat(frameposes[j*12+k]);
2265 // scale child bones to match the root scale
2266 if (loadmodel->data_bones[j].parent >= 0)
2268 pose[3] *= modelscale;
2269 pose[7] *= modelscale;
2270 pose[11] *= modelscale;
2272 // normalize rotation matrix
2273 VectorNormalize(pose + 0);
2274 VectorNormalize(pose + 4);
2275 VectorNormalize(pose + 8);
2276 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2277 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
2281 // load the meshes now
2282 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2285 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2286 // (converting from weight-blending skeletal animation to
2287 // deformation-based skeletal animation)
2288 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2289 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2290 for (i = 0;i < loadmodel->num_bones;i++)
2293 for (k = 0;k < 12;k++)
2294 m[k] = BigFloat(poses[i*12+k]);
2295 if (loadmodel->data_bones[i].parent >= 0)
2296 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2298 for (k = 0;k < 12;k++)
2299 bonepose[12*i+k] = m[k];
2301 Mod_Skeletal_InitBlends(loadmodel);
2302 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2304 const int *inelements;
2306 const float *intexcoord;
2307 msurface_t *surface;
2309 loadmodel->sortedmodelsurfaces[i] = i;
2310 surface = loadmodel->data_surfaces + i;
2311 surface->texture = loadmodel->data_textures + i;
2312 surface->num_firsttriangle = meshtriangles;
2313 surface->num_triangles = BigLong(dpmmesh->num_tris);
2314 surface->num_firstvertex = meshvertices;
2315 surface->num_vertices = BigLong(dpmmesh->num_verts);
2316 meshvertices += surface->num_vertices;
2317 meshtriangles += surface->num_triangles;
2319 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2320 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2321 for (j = 0;j < surface->num_triangles;j++)
2323 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2324 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2325 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2326 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2331 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2332 for (j = 0;j < surface->num_vertices*2;j++)
2333 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2335 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2336 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2338 int weightindex[4] = { 0, 0, 0, 0 };
2339 float weightinfluence[4] = { 0, 0, 0, 0 };
2342 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2343 data += sizeof(dpmvertex_t);
2344 for (k = 0;k < numweights;k++)
2346 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2347 int boneindex = BigLong(vert->bonenum);
2348 const float *m = bonepose + 12 * boneindex;
2349 float influence = BigFloat(vert->influence);
2350 float relativeorigin[3], relativenormal[3];
2351 relativeorigin[0] = BigFloat(vert->origin[0]);
2352 relativeorigin[1] = BigFloat(vert->origin[1]);
2353 relativeorigin[2] = BigFloat(vert->origin[2]);
2354 relativenormal[0] = BigFloat(vert->normal[0]);
2355 relativenormal[1] = BigFloat(vert->normal[1]);
2356 relativenormal[2] = BigFloat(vert->normal[2]);
2357 // blend the vertex bone weights into the base mesh
2358 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2359 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2360 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2361 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2362 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2363 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2366 // store the first (and often only) weight
2367 weightinfluence[0] = influence;
2368 weightindex[0] = boneindex;
2372 // sort the new weight into this vertex's weight table
2373 // (which only accepts up to 4 bones per vertex)
2374 for (l = 0;l < 4;l++)
2376 if (weightinfluence[l] < influence)
2378 // move weaker influence weights out of the way first
2380 for (l2 = 3;l2 > l;l2--)
2382 weightinfluence[l2] = weightinfluence[l2-1];
2383 weightindex[l2] = weightindex[l2-1];
2385 // store the new weight
2386 weightinfluence[l] = influence;
2387 weightindex[l] = boneindex;
2392 data += sizeof(dpmbonevert_t);
2395 for (l = 0;l < 4;l++)
2396 sum += weightinfluence[l];
2397 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2399 float f = 1.0f / sum;
2400 for (l = 0;l < 4;l++)
2401 weightinfluence[l] *= f;
2403 loadmodel->surfmesh.blends[j] = Mod_Skeletal_AddBlend(loadmodel, weightindex, weightinfluence);
2406 // since dpm models do not have named sections, reuse their shader name as the section name
2407 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2409 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2412 Mod_FreeSkinFiles(skinfiles);
2413 Mod_MakeSortedSurfaces(loadmodel);
2415 // compute all the mesh information that was not loaded from the file
2416 if (loadmodel->surfmesh.data_element3s)
2417 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2418 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2419 Mod_BuildBaseBonePoses();
2420 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);
2421 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2423 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2426 // no idea why PSK/PSA files contain weird quaternions but they do...
2427 #define PSKQUATNEGATIONS
2428 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2430 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2431 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2432 fs_offset_t filesize;
2437 pskboneinfo_t *bones;
2438 pskrawweights_t *rawweights;
2439 //pskboneinfo_t *animbones;
2440 pskaniminfo_t *anims;
2441 pskanimkeys_t *animkeys;
2442 void *animfilebuffer, *animbuffer, *animbufferend;
2443 unsigned char *data;
2445 skinfile_t *skinfiles;
2446 char animname[MAX_QPATH];
2448 float biggestorigin;
2450 pchunk = (pskchunk_t *)buffer;
2451 if (strcmp(pchunk->id, "ACTRHEAD"))
2452 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2454 loadmodel->modeldatatypestring = "PSK";
2456 loadmodel->type = mod_alias;
2457 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2458 loadmodel->DrawSky = NULL;
2459 loadmodel->DrawAddWaterPlanes = NULL;
2460 loadmodel->Draw = R_Q1BSP_Draw;
2461 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2462 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2463 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2464 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2465 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2466 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2467 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2468 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2469 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2470 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2471 loadmodel->PointSuperContents = NULL;
2472 loadmodel->synctype = ST_RAND;
2474 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2475 strlcat(animname, ".psa", sizeof(animname));
2476 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2477 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2478 if (animbuffer == NULL)
2479 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2498 while (buffer < bufferend)
2500 pchunk = (pskchunk_t *)buffer;
2501 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2502 version = LittleLong(pchunk->version);
2503 recordsize = LittleLong(pchunk->recordsize);
2504 numrecords = LittleLong(pchunk->numrecords);
2505 if (developer_extra.integer)
2506 Con_DPrintf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2507 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2508 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);
2509 if (!strcmp(pchunk->id, "ACTRHEAD"))
2513 else if (!strcmp(pchunk->id, "PNTS0000"))
2516 if (recordsize != sizeof(*p))
2517 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2518 // byteswap in place and keep the pointer
2519 numpnts = numrecords;
2520 pnts = (pskpnts_t *)buffer;
2521 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2523 p->origin[0] = LittleFloat(p->origin[0]);
2524 p->origin[1] = LittleFloat(p->origin[1]);
2525 p->origin[2] = LittleFloat(p->origin[2]);
2529 else if (!strcmp(pchunk->id, "VTXW0000"))
2532 if (recordsize != sizeof(*p))
2533 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2534 // byteswap in place and keep the pointer
2535 numvtxw = numrecords;
2536 vtxw = (pskvtxw_t *)buffer;
2537 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2539 p->pntsindex = LittleShort(p->pntsindex);
2540 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2541 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2542 if (p->pntsindex >= numpnts)
2544 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2550 else if (!strcmp(pchunk->id, "FACE0000"))
2553 if (recordsize != sizeof(*p))
2554 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2555 // byteswap in place and keep the pointer
2556 numfaces = numrecords;
2557 faces = (pskface_t *)buffer;
2558 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2560 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2561 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2562 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2563 p->group = LittleLong(p->group);
2564 if (p->vtxwindex[0] >= numvtxw)
2566 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2567 p->vtxwindex[0] = 0;
2569 if (p->vtxwindex[1] >= numvtxw)
2571 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2572 p->vtxwindex[1] = 0;
2574 if (p->vtxwindex[2] >= numvtxw)
2576 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2577 p->vtxwindex[2] = 0;
2582 else if (!strcmp(pchunk->id, "MATT0000"))
2585 if (recordsize != sizeof(*p))
2586 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2587 // byteswap in place and keep the pointer
2588 nummatts = numrecords;
2589 matts = (pskmatt_t *)buffer;
2590 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2596 else if (!strcmp(pchunk->id, "REFSKELT"))
2599 if (recordsize != sizeof(*p))
2600 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2601 // byteswap in place and keep the pointer
2602 numbones = numrecords;
2603 bones = (pskboneinfo_t *)buffer;
2604 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2606 p->numchildren = LittleLong(p->numchildren);
2607 p->parent = LittleLong(p->parent);
2608 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2609 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2610 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2611 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2612 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2613 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2614 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2615 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2616 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2617 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2618 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2619 #ifdef PSKQUATNEGATIONS
2622 p->basepose.quat[0] *= -1;
2623 p->basepose.quat[1] *= -1;
2624 p->basepose.quat[2] *= -1;
2628 p->basepose.quat[0] *= 1;
2629 p->basepose.quat[1] *= -1;
2630 p->basepose.quat[2] *= 1;
2633 if (p->parent < 0 || p->parent >= numbones)
2635 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2641 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2644 if (recordsize != sizeof(*p))
2645 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2646 // byteswap in place and keep the pointer
2647 numrawweights = numrecords;
2648 rawweights = (pskrawweights_t *)buffer;
2649 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2651 p->weight = LittleFloat(p->weight);
2652 p->pntsindex = LittleLong(p->pntsindex);
2653 p->boneindex = LittleLong(p->boneindex);
2654 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2656 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2659 if (p->boneindex < 0 || p->boneindex >= numbones)
2661 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2669 while (animbuffer < animbufferend)
2671 pchunk = (pskchunk_t *)animbuffer;
2672 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2673 version = LittleLong(pchunk->version);
2674 recordsize = LittleLong(pchunk->recordsize);
2675 numrecords = LittleLong(pchunk->numrecords);
2676 if (developer_extra.integer)
2677 Con_DPrintf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2678 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2679 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);
2680 if (!strcmp(pchunk->id, "ANIMHEAD"))
2684 else if (!strcmp(pchunk->id, "BONENAMES"))
2687 if (recordsize != sizeof(*p))
2688 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2689 // byteswap in place and keep the pointer
2690 numanimbones = numrecords;
2691 //animbones = (pskboneinfo_t *)animbuffer;
2692 // NOTE: supposedly psa does not need to match the psk model, the
2693 // bones missing from the psa would simply use their base
2694 // positions from the psk, but this is hard for me to implement
2695 // and people can easily make animations that match.
2696 if (numanimbones != numbones)
2697 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2698 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2700 p->numchildren = LittleLong(p->numchildren);
2701 p->parent = LittleLong(p->parent);
2702 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2703 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2704 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2705 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2706 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2707 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2708 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2709 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2710 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2711 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2712 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2713 #ifdef PSKQUATNEGATIONS
2716 p->basepose.quat[0] *= -1;
2717 p->basepose.quat[1] *= -1;
2718 p->basepose.quat[2] *= -1;
2722 p->basepose.quat[0] *= 1;
2723 p->basepose.quat[1] *= -1;
2724 p->basepose.quat[2] *= 1;
2727 if (p->parent < 0 || p->parent >= numanimbones)
2729 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2732 // check that bones are the same as in the base
2733 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2734 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2738 else if (!strcmp(pchunk->id, "ANIMINFO"))
2741 if (recordsize != sizeof(*p))
2742 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2743 // byteswap in place and keep the pointer
2744 numanims = numrecords;
2745 anims = (pskaniminfo_t *)animbuffer;
2746 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2748 p->numbones = LittleLong(p->numbones);
2749 p->playtime = LittleFloat(p->playtime);
2750 p->fps = LittleFloat(p->fps);
2751 p->firstframe = LittleLong(p->firstframe);
2752 p->numframes = LittleLong(p->numframes);
2753 if (p->numbones != numbones)
2754 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2758 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2761 if (recordsize != sizeof(*p))
2762 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2763 numanimkeys = numrecords;
2764 animkeys = (pskanimkeys_t *)animbuffer;
2765 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2767 p->origin[0] = LittleFloat(p->origin[0]);
2768 p->origin[1] = LittleFloat(p->origin[1]);
2769 p->origin[2] = LittleFloat(p->origin[2]);
2770 p->quat[0] = LittleFloat(p->quat[0]);
2771 p->quat[1] = LittleFloat(p->quat[1]);
2772 p->quat[2] = LittleFloat(p->quat[2]);
2773 p->quat[3] = LittleFloat(p->quat[3]);
2774 p->frametime = LittleFloat(p->frametime);
2775 #ifdef PSKQUATNEGATIONS
2776 if (index % numbones)
2791 // TODO: allocate bonepose stuff
2794 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2797 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2798 Host_Error("%s: missing required chunks", loadmodel->name);
2800 loadmodel->numframes = 0;
2801 for (index = 0;index < numanims;index++)
2802 loadmodel->numframes += anims[index].numframes;
2804 if (numanimkeys != numbones * loadmodel->numframes)
2805 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2807 meshvertices = numvtxw;
2808 meshtriangles = numfaces;
2810 // load external .skin files if present
2811 skinfiles = Mod_LoadSkinFiles();
2812 if (loadmodel->numskins < 1)
2813 loadmodel->numskins = 1;
2814 loadmodel->num_bones = numbones;
2815 loadmodel->num_poses = loadmodel->numframes;
2816 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2817 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2818 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2819 loadmodel->surfmesh.num_vertices = meshvertices;
2820 loadmodel->surfmesh.num_triangles = meshtriangles;
2821 // do most allocations as one merged chunk
2822 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);
2823 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2824 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2825 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2826 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2827 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2828 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2829 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2830 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2831 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2832 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2833 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2834 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += loadmodel->surfmesh.num_vertices * sizeof(int[4]);
2835 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[4]);
2836 loadmodel->surfmesh.num_blends = 0;
2837 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2838 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2839 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2840 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2841 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2842 if (loadmodel->surfmesh.num_vertices <= 65536)
2843 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2844 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2846 for (i = 0;i < loadmodel->numskins;i++)
2848 loadmodel->skinscenes[i].firstframe = i;
2849 loadmodel->skinscenes[i].framecount = 1;
2850 loadmodel->skinscenes[i].loop = true;
2851 loadmodel->skinscenes[i].framerate = 10;
2855 for (index = 0, i = 0;index < nummatts;index++)
2857 // since psk models do not have named sections, reuse their shader name as the section name
2858 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2859 loadmodel->sortedmodelsurfaces[index] = index;
2860 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2861 loadmodel->data_surfaces[index].num_firstvertex = 0;
2862 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2865 // copy over the vertex locations and texcoords
2866 for (index = 0;index < numvtxw;index++)
2868 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2869 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2870 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2871 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2872 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2875 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2876 for (index = 0;index < numfaces;index++)
2877 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2878 for (index = 0, i = 0;index < nummatts;index++)
2880 loadmodel->data_surfaces[index].num_firsttriangle = i;
2881 i += loadmodel->data_surfaces[index].num_triangles;
2882 loadmodel->data_surfaces[index].num_triangles = 0;
2884 for (index = 0;index < numfaces;index++)
2886 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2887 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2888 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2889 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2892 // copy over the bones
2893 for (index = 0;index < numbones;index++)
2895 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2896 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2897 if (loadmodel->data_bones[index].parent >= index)
2898 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2901 // sort the psk point weights into the vertex weight tables
2902 // (which only accept up to 4 bones per vertex)
2903 Mod_Skeletal_InitBlends(loadmodel);
2904 for (index = 0;index < numvtxw;index++)
2907 float weightinfluence[4];
2910 for (j = 0;j < numrawweights;j++)
2912 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2914 int boneindex = rawweights[j].boneindex;
2915 float influence = rawweights[j].weight;
2916 for (l = 0;l < 4;l++)
2918 if (weightinfluence[l] < influence)
2920 // move lower influence weights out of the way first
2922 for (l2 = 3;l2 > l;l2--)
2924 weightinfluence[l2] = weightinfluence[l2-1];
2925 weightindex[l2] = weightindex[l2-1];
2927 // store the new weight
2928 weightinfluence[l] = influence;
2929 weightindex[l] = boneindex;
2936 for (l = 0;l < 4;l++)
2937 sum += weightinfluence[l];
2938 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2940 float f = 1.0f / sum;
2941 for (l = 0;l < 4;l++)
2942 weightinfluence[l] *= f;
2944 loadmodel->surfmesh.blends[index] = Mod_Skeletal_AddBlend(loadmodel, weightindex, weightinfluence);
2947 // set up the animscenes based on the anims
2948 for (index = 0, i = 0;index < numanims;index++)
2950 for (j = 0;j < anims[index].numframes;j++, i++)
2952 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2953 loadmodel->animscenes[i].firstframe = i;
2954 loadmodel->animscenes[i].framecount = 1;
2955 loadmodel->animscenes[i].loop = true;
2956 loadmodel->animscenes[i].framerate = 10;
2960 // calculate the scaling value for bone origins so they can be compressed to short
2962 for (index = 0;index < numanimkeys;index++)
2964 pskanimkeys_t *k = animkeys + index;
2965 biggestorigin = max(biggestorigin, fabs(k->origin[0]));
2966 biggestorigin = max(biggestorigin, fabs(k->origin[1]));
2967 biggestorigin = max(biggestorigin, fabs(k->origin[2]));
2969 loadmodel->num_posescale = biggestorigin / 32767.0f;
2970 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2972 // load the poses from the animkeys
2973 for (index = 0;index < numanimkeys;index++)
2975 pskanimkeys_t *k = animkeys + index;
2977 Vector4Copy(k->quat, quat);
2979 Vector4Negate(quat, quat);
2980 Vector4Normalize2(quat, quat);
2981 // compress poses to the short[6] format for longterm storage
2982 loadmodel->data_poses6s[index*6+0] = k->origin[0] * loadmodel->num_poseinvscale;
2983 loadmodel->data_poses6s[index*6+1] = k->origin[1] * loadmodel->num_poseinvscale;
2984 loadmodel->data_poses6s[index*6+2] = k->origin[2] * loadmodel->num_poseinvscale;
2985 loadmodel->data_poses6s[index*6+3] = quat[0] * 32767.0f;
2986 loadmodel->data_poses6s[index*6+4] = quat[1] * 32767.0f;
2987 loadmodel->data_poses6s[index*6+5] = quat[2] * 32767.0f;
2989 Mod_FreeSkinFiles(skinfiles);
2990 Mem_Free(animfilebuffer);
2991 Mod_MakeSortedSurfaces(loadmodel);
2993 // compute all the mesh information that was not loaded from the file
2994 // TODO: honor smoothing groups somehow?
2995 if (loadmodel->surfmesh.data_element3s)
2996 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2997 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2998 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2999 Mod_BuildBaseBonePoses();
3000 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
3001 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);
3002 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3003 Mod_Alias_CalculateBoundingBox();
3005 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;