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 int Mod_Skeletal_AddBlend(dp_model_t *model, const int *newindex, const float *newinfluence)
53 blendweights_t *weights;
54 blendweights_t newweights;
59 scale += newinfluence[i];
60 scale = 255.0f / scale;
64 newweights.index[i] = newindex[i];
65 newweights.influence[i] = (unsigned char)(newinfluence[i] * scale);
66 total += newweights.influence[i];
72 if(newweights.influence[i] > 0 && total > 255)
74 newweights.influence[i]--;
81 for (i = 0; i < 4;i++)
83 if(newweights.influence[i] < 255 && total < 255)
85 newweights.influence[i]++;
90 weights = model->surfmesh.data_blendweights;
91 for (i = 0;i < model->surfmesh.num_blends;i++, weights++)
93 if (!memcmp(weights, &newweights, sizeof(blendweights_t)))
94 return model->num_bones + i;
96 model->surfmesh.num_blends++;
97 memcpy(weights, &newweights, sizeof(blendweights_t));
98 return model->num_bones + i;
101 static int maxbonepose = 0;
102 static float (*bonepose)[12] = NULL;
104 void Mod_Skeletal_FreeBuffers(void)
112 #if defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1400)
113 #define RESTRICT __restrict
118 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)
120 // vertex weighted skeletal
124 float (*boneposerelative)[12];
125 const blendweights_t * RESTRICT weights;
127 if (maxbonepose < model->num_bones*2 + model->surfmesh.num_blends)
131 maxbonepose = model->num_bones*2 + model->surfmesh.num_blends;
132 bonepose = (float (*)[12])Mem_Alloc(r_main_mempool, maxbonepose * sizeof(float[12]));
135 boneposerelative = bonepose + model->num_bones;
137 if (skeleton && !skeleton->relativetransforms)
140 // interpolate matrices
143 for (i = 0;i < model->num_bones;i++)
145 Matrix4x4_ToArray12FloatD3D(&skeleton->relativetransforms[i], m);
146 if (model->data_bones[i].parent >= 0)
147 R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
149 memcpy(bonepose[i], m, sizeof(m));
151 // create a relative deformation matrix to describe displacement
152 // from the base mesh, which is used by the actual weighting
153 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]);
158 float originscale = model->num_posescale;
160 const short * RESTRICT pose6s;
161 for (i = 0;i < model->num_bones;i++)
163 memset(m, 0, sizeof(m));
164 for (blends = 0;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++)
166 pose6s = model->data_poses6s + 6 * (frameblend[blends].subframe * model->num_bones + i);
167 lerp = frameblend[blends].lerp;
168 x = pose6s[3] * (1.0f / 32767.0f);
169 y = pose6s[4] * (1.0f / 32767.0f);
170 z = pose6s[5] * (1.0f / 32767.0f);
171 w = 1.0f - (x*x+y*y+z*z);
172 w = w > 0.0f ? -sqrt(w) : 0.0f;
173 m[ 0] += (1-2*(y*y+z*z)) * lerp;
174 m[ 1] += ( 2*(x*y-z*w)) * lerp;
175 m[ 2] += ( 2*(x*z+y*w)) * lerp;
176 m[ 3] += (pose6s[0] * originscale) * lerp;
177 m[ 4] += ( 2*(x*y+z*w)) * lerp;
178 m[ 5] += (1-2*(x*x+z*z)) * lerp;
179 m[ 6] += ( 2*(y*z-x*w)) * lerp;
180 m[ 7] += (pose6s[1] * originscale) * lerp;
181 m[ 8] += ( 2*(x*z-y*w)) * lerp;
182 m[ 9] += ( 2*(y*z+x*w)) * lerp;
183 m[10] += (1-2*(x*x+y*y)) * lerp;
184 m[11] += (pose6s[2] * originscale) * lerp;
187 VectorNormalize(m + 4);
188 VectorNormalize(m + 8);
189 if (i == r_skeletal_debugbone.integer)
190 m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
191 m[3] *= r_skeletal_debugtranslatex.value;
192 m[7] *= r_skeletal_debugtranslatey.value;
193 m[11] *= r_skeletal_debugtranslatez.value;
194 if (model->data_bones[i].parent >= 0)
195 R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
197 memcpy(bonepose[i], m, sizeof(m));
198 // create a relative deformation matrix to describe displacement
199 // from the base mesh, which is used by the actual weighting
200 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]);
204 // generate matrices for all blend combinations
205 weights = model->surfmesh.data_blendweights;
206 for (i = 0;i < model->surfmesh.num_blends;i++, weights++)
208 float * RESTRICT b = boneposerelative[model->num_bones + i];
209 const float * RESTRICT m = boneposerelative[weights->index[0]];
210 float f = weights->influence[0] * (1.0f / 255.0f);
211 b[ 0] = f*m[ 0]; b[ 1] = f*m[ 1]; b[ 2] = f*m[ 2]; b[ 3] = f*m[ 3];
212 b[ 4] = f*m[ 4]; b[ 5] = f*m[ 5]; b[ 6] = f*m[ 6]; b[ 7] = f*m[ 7];
213 b[ 8] = f*m[ 8]; b[ 9] = f*m[ 9]; b[10] = f*m[10]; b[11] = f*m[11];
214 for (k = 1;k < 4 && weights->influence[k];k++)
216 m = boneposerelative[weights->index[k]];
217 f = weights->influence[k] * (1.0f / 255.0f);
218 b[ 0] += f*m[ 0]; b[ 1] += f*m[ 1]; b[ 2] += f*m[ 2]; b[ 3] += f*m[ 3];
219 b[ 4] += f*m[ 4]; b[ 5] += f*m[ 5]; b[ 6] += f*m[ 6]; b[ 7] += f*m[ 7];
220 b[ 8] += f*m[ 8]; b[ 9] += f*m[ 9]; b[10] += f*m[10]; b[11] += f*m[11];
224 // transform vertex attributes by blended matrices
227 const float * RESTRICT v = model->surfmesh.data_vertex3f;
228 const unsigned short * RESTRICT b = model->surfmesh.blends;
229 // special case common combinations of attributes to avoid repeated loading of matrices
232 const float * RESTRICT n = model->surfmesh.data_normal3f;
233 if (svector3f && tvector3f)
235 const float * RESTRICT sv = model->surfmesh.data_svector3f;
236 const float * RESTRICT tv = model->surfmesh.data_tvector3f;
237 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)
239 const float * RESTRICT m = boneposerelative[*b];
240 vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
241 vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
242 vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
243 normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
244 normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
245 normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
246 svector3f[0] = (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
247 svector3f[1] = (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
248 svector3f[2] = (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
249 tvector3f[0] = (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
250 tvector3f[1] = (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
251 tvector3f[2] = (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
255 for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, n += 3, b++, vertex3f += 3, normal3f += 3)
257 const float * RESTRICT m = boneposerelative[*b];
258 vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
259 vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
260 vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
261 normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
262 normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
263 normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
268 for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, b++, vertex3f += 3)
270 const float * RESTRICT m = boneposerelative[*b];
271 vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
272 vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
273 vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
279 const float * RESTRICT n = model->surfmesh.data_normal3f;
280 const unsigned short * RESTRICT b = model->surfmesh.blends;
281 for (i = 0;i < model->surfmesh.num_vertices;i++, n += 3, b++, normal3f += 3)
283 const float * RESTRICT m = boneposerelative[*b];
284 normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
285 normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
286 normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
292 const float * RESTRICT sv = model->surfmesh.data_svector3f;
293 const unsigned short * RESTRICT b = model->surfmesh.blends;
294 for (i = 0;i < model->surfmesh.num_vertices;i++, sv += 3, b++, svector3f += 3)
296 const float * RESTRICT m = boneposerelative[*b];
297 svector3f[0] = (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
298 svector3f[1] = (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
299 svector3f[2] = (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
305 const float * RESTRICT tv = model->surfmesh.data_tvector3f;
306 const unsigned short * RESTRICT b = model->surfmesh.blends;
307 for (i = 0;i < model->surfmesh.num_vertices;i++, tv += 3, b++, tvector3f += 3)
309 const float * RESTRICT m = boneposerelative[*b];
310 tvector3f[0] = (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
311 tvector3f[1] = (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
312 tvector3f[2] = (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
317 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)
320 int i, numblends, blendnum;
321 int numverts = model->surfmesh.num_vertices;
323 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
325 //VectorMA(translate, model->surfmesh.num_morphmdlframetranslate, frameblend[blendnum].lerp, translate);
326 if (frameblend[blendnum].lerp > 0)
327 numblends = blendnum + 1;
329 // special case for the first blend because it avoids some adds and the need to memset the arrays first
330 for (blendnum = 0;blendnum < numblends;blendnum++)
332 const md3vertex_t *verts = model->surfmesh.data_morphmd3vertex + numverts * frameblend[blendnum].subframe;
335 float scale = frameblend[blendnum].lerp * (1.0f / 64.0f);
338 for (i = 0;i < numverts;i++)
340 vertex3f[i * 3 + 0] = verts[i].origin[0] * scale;
341 vertex3f[i * 3 + 1] = verts[i].origin[1] * scale;
342 vertex3f[i * 3 + 2] = verts[i].origin[2] * scale;
347 for (i = 0;i < numverts;i++)
349 vertex3f[i * 3 + 0] += verts[i].origin[0] * scale;
350 vertex3f[i * 3 + 1] += verts[i].origin[1] * scale;
351 vertex3f[i * 3 + 2] += verts[i].origin[2] * scale;
355 // the yaw and pitch stored in md3 models are 8bit quantized angles
356 // (0-255), and as such a lookup table is very well suited to
357 // decoding them, and since cosine is equivilant to sine with an
358 // extra 45 degree rotation, this uses one lookup table for both
359 // sine and cosine with a +64 bias to get cosine.
362 float lerp = frameblend[blendnum].lerp;
365 for (i = 0;i < numverts;i++)
367 normal3f[i * 3 + 0] = mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
368 normal3f[i * 3 + 1] = mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
369 normal3f[i * 3 + 2] = mod_md3_sin[verts[i].pitch + 64] * lerp;
374 for (i = 0;i < numverts;i++)
376 normal3f[i * 3 + 0] += mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
377 normal3f[i * 3 + 1] += mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
378 normal3f[i * 3 + 2] += mod_md3_sin[verts[i].pitch + 64] * lerp;
384 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
385 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
388 for (i = 0;i < numverts;i++, texvecvert++)
390 VectorScale(texvecvert->svec, f, svector3f + i*3);
391 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
396 for (i = 0;i < numverts;i++, texvecvert++)
398 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
399 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
406 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)
409 int i, numblends, blendnum;
410 int numverts = model->surfmesh.num_vertices;
412 VectorClear(translate);
414 // blend the frame translates to avoid redundantly doing so on each vertex
415 // (a bit of a brain twister but it works)
416 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
418 if (model->surfmesh.data_morphmd2framesize6f)
419 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6 + 3, translate);
421 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.num_morphmdlframetranslate, translate);
422 if (frameblend[blendnum].lerp > 0)
423 numblends = blendnum + 1;
425 // special case for the first blend because it avoids some adds and the need to memset the arrays first
426 for (blendnum = 0;blendnum < numblends;blendnum++)
428 const trivertx_t *verts = model->surfmesh.data_morphmdlvertex + numverts * frameblend[blendnum].subframe;
432 if (model->surfmesh.data_morphmd2framesize6f)
433 VectorScale(model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6, frameblend[blendnum].lerp, scale);
435 VectorScale(model->surfmesh.num_morphmdlframescale, frameblend[blendnum].lerp, scale);
438 for (i = 0;i < numverts;i++)
440 vertex3f[i * 3 + 0] = translate[0] + verts[i].v[0] * scale[0];
441 vertex3f[i * 3 + 1] = translate[1] + verts[i].v[1] * scale[1];
442 vertex3f[i * 3 + 2] = translate[2] + verts[i].v[2] * scale[2];
447 for (i = 0;i < numverts;i++)
449 vertex3f[i * 3 + 0] += verts[i].v[0] * scale[0];
450 vertex3f[i * 3 + 1] += verts[i].v[1] * scale[1];
451 vertex3f[i * 3 + 2] += verts[i].v[2] * scale[2];
455 // the vertex normals in mdl models are an index into a table of
456 // 162 unique values, this very crude quantization reduces the
457 // vertex normal to only one byte, which saves a lot of space but
458 // also makes lighting pretty coarse
461 float lerp = frameblend[blendnum].lerp;
464 for (i = 0;i < numverts;i++)
466 const float *vn = m_bytenormals[verts[i].lightnormalindex];
467 VectorScale(vn, lerp, normal3f + i*3);
472 for (i = 0;i < numverts;i++)
474 const float *vn = m_bytenormals[verts[i].lightnormalindex];
475 VectorMA(normal3f + i*3, lerp, vn, normal3f + i*3);
481 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
482 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
485 for (i = 0;i < numverts;i++, texvecvert++)
487 VectorScale(texvecvert->svec, f, svector3f + i*3);
488 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
493 for (i = 0;i < numverts;i++, texvecvert++)
495 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
496 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
503 int Mod_Alias_GetTagMatrix(const dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, int tagindex, matrix4x4_t *outmatrix)
506 matrix4x4_t parentbonematrix;
507 matrix4x4_t tempbonematrix;
508 matrix4x4_t bonematrix;
509 matrix4x4_t blendmatrix;
516 *outmatrix = identitymatrix;
517 if (skeleton && skeleton->relativetransforms)
519 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
521 *outmatrix = skeleton->relativetransforms[tagindex];
522 while ((tagindex = model->data_bones[tagindex].parent) >= 0)
525 Matrix4x4_Concat(outmatrix, &skeleton->relativetransforms[tagindex], &temp);
528 else if (model->num_bones)
530 if (tagindex < 0 || tagindex >= model->num_bones)
532 Matrix4x4_Clear(&blendmatrix);
533 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
535 lerp = frameblend[blendindex].lerp;
536 Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
537 parenttagindex = tagindex;
538 while ((parenttagindex = model->data_bones[parenttagindex].parent) >= 0)
540 Matrix4x4_FromBonePose6s(&parentbonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + parenttagindex));
541 tempbonematrix = bonematrix;
542 Matrix4x4_Concat(&bonematrix, &parentbonematrix, &tempbonematrix);
544 Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
546 *outmatrix = blendmatrix;
548 else if (model->num_tags)
550 if (tagindex < 0 || tagindex >= model->num_tags)
552 for (k = 0;k < 12;k++)
554 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
556 lerp = frameblend[blendindex].lerp;
557 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
558 for (k = 0;k < 12;k++)
559 blendtag[k] += input[k] * lerp;
561 Matrix4x4_FromArray12FloatGL(outmatrix, blendtag);
564 if(!mod_alias_supporttagscale.integer)
565 Matrix4x4_Normalize3(outmatrix, outmatrix);
570 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)
575 matrix4x4_t bonematrix;
576 matrix4x4_t blendmatrix;
580 if (skeleton && skeleton->relativetransforms)
582 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
584 *parentindex = skeleton->model->data_bones[tagindex].parent;
585 *tagname = skeleton->model->data_bones[tagindex].name;
586 *tag_localmatrix = skeleton->relativetransforms[tagindex];
589 else if (model->num_bones)
591 if (tagindex < 0 || tagindex >= model->num_bones)
593 *parentindex = model->data_bones[tagindex].parent;
594 *tagname = model->data_bones[tagindex].name;
595 Matrix4x4_Clear(&blendmatrix);
596 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
598 lerp = frameblend[blendindex].lerp;
599 Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
600 Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
602 *tag_localmatrix = blendmatrix;
605 else if (model->num_tags)
607 if (tagindex < 0 || tagindex >= model->num_tags)
610 *tagname = model->data_tags[tagindex].name;
611 for (k = 0;k < 12;k++)
613 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
615 lerp = frameblend[blendindex].lerp;
616 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
617 for (k = 0;k < 12;k++)
618 blendtag[k] += input[k] * lerp;
620 Matrix4x4_FromArray12FloatGL(tag_localmatrix, blendtag);
627 int Mod_Alias_GetTagIndexForName(const dp_model_t *model, unsigned int skin, const char *tagname)
630 if(skin >= (unsigned int)model->numskins)
632 if (model->num_bones)
633 for (i = 0;i < model->num_bones;i++)
634 if (!strcasecmp(tagname, model->data_bones[i].name))
637 for (i = 0;i < model->num_tags;i++)
638 if (!strcasecmp(tagname, model->data_tags[i].name))
643 static void Mod_BuildBaseBonePoses(void)
646 matrix4x4_t *basebonepose;
647 float *outinvmatrix = loadmodel->data_baseboneposeinverse;
648 matrix4x4_t bonematrix;
649 matrix4x4_t tempbonematrix;
650 if (!loadmodel->num_bones)
652 basebonepose = (matrix4x4_t *)Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(matrix4x4_t));
653 for (boneindex = 0;boneindex < loadmodel->num_bones;boneindex++)
655 Matrix4x4_FromBonePose6s(&bonematrix, loadmodel->num_posescale, loadmodel->data_poses6s + 6 * boneindex);
656 if (loadmodel->data_bones[boneindex].parent >= 0)
658 tempbonematrix = bonematrix;
659 Matrix4x4_Concat(&bonematrix, basebonepose + loadmodel->data_bones[boneindex].parent, &tempbonematrix);
661 basebonepose[boneindex] = bonematrix;
662 Matrix4x4_Invert_Simple(&tempbonematrix, basebonepose + boneindex);
663 Matrix4x4_ToArray12FloatD3D(&tempbonematrix, outinvmatrix + 12*boneindex);
665 Mem_Free(basebonepose);
668 static void Mod_Alias_CalculateBoundingBox(void)
671 qboolean firstvertex = true;
672 float dist, yawradius, radius;
675 frameblend_t frameblend[MAX_FRAMEBLENDS];
676 memset(frameblend, 0, sizeof(frameblend));
677 frameblend[0].lerp = 1;
678 vertex3f = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
679 VectorClear(loadmodel->normalmins);
680 VectorClear(loadmodel->normalmaxs);
683 for (frameblend[0].subframe = 0;frameblend[0].subframe < loadmodel->num_poses;frameblend[0].subframe++)
685 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, vertex3f, NULL, NULL, NULL);
686 for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
691 VectorCopy(v, loadmodel->normalmins);
692 VectorCopy(v, loadmodel->normalmaxs);
696 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
697 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
698 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
699 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
700 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
701 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
703 dist = v[0] * v[0] + v[1] * v[1];
704 if (yawradius < dist)
713 radius = sqrt(radius);
714 yawradius = sqrt(yawradius);
715 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
716 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
717 loadmodel->yawmins[2] = loadmodel->normalmins[2];
718 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
719 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
720 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
721 loadmodel->radius = radius;
722 loadmodel->radius2 = radius * radius;
725 static void Mod_Alias_MorphMesh_CompileFrames(void)
728 frameblend_t frameblend[MAX_FRAMEBLENDS];
729 unsigned char *datapointer;
730 memset(frameblend, 0, sizeof(frameblend));
731 frameblend[0].lerp = 1;
732 datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
733 loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
734 loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
735 loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
736 loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
737 loadmodel->surfmesh.data_morphtexvecvertex = (texvecvertex_t *)datapointer;datapointer += loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices * sizeof(texvecvertex_t);
738 // 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)
739 for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
741 frameblend[0].subframe = i;
742 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
743 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);
744 // encode the svector and tvector in 3 byte format for permanent storage
745 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
747 VectorScaleCast(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
748 VectorScaleCast(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
753 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)
756 float segmentmins[3], segmentmaxs[3];
758 static int maxvertices = 0;
759 static float *vertex3f = NULL;
760 memset(trace, 0, sizeof(*trace));
762 trace->realfraction = 1;
763 trace->hitsupercontentsmask = hitsupercontentsmask;
764 if (maxvertices < model->surfmesh.num_vertices)
768 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
769 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
771 segmentmins[0] = min(start[0], end[0]) - 1;
772 segmentmins[1] = min(start[1], end[1]) - 1;
773 segmentmins[2] = min(start[2], end[2]) - 1;
774 segmentmaxs[0] = max(start[0], end[0]) + 1;
775 segmentmaxs[1] = max(start[1], end[1]) + 1;
776 segmentmaxs[2] = max(start[2], end[2]) + 1;
777 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
778 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
779 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);
782 static int maxvertices = 0;
783 static float *vertex3f = NULL;
785 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)
788 vec3_t shiftstart, shiftend;
789 float segmentmins[3], segmentmaxs[3];
791 colboxbrushf_t thisbrush_start, thisbrush_end;
792 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
794 if (VectorCompare(boxmins, boxmaxs))
796 VectorAdd(start, boxmins, shiftstart);
797 VectorAdd(end, boxmins, shiftend);
798 Mod_MDLMD2MD3_TraceLine(model, frameblend, skeleton, trace, shiftstart, shiftend, hitsupercontentsmask);
799 VectorSubtract(trace->endpos, boxmins, trace->endpos);
803 // box trace, performed as brush trace
804 memset(trace, 0, sizeof(*trace));
806 trace->realfraction = 1;
807 trace->hitsupercontentsmask = hitsupercontentsmask;
808 if (maxvertices < model->surfmesh.num_vertices)
812 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
813 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
815 segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
816 segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
817 segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
818 segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
819 segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
820 segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
821 VectorAdd(start, boxmins, boxstartmins);
822 VectorAdd(start, boxmaxs, boxstartmaxs);
823 VectorAdd(end, boxmins, boxendmins);
824 VectorAdd(end, boxmaxs, boxendmaxs);
825 Collision_BrushForBox(&thisbrush_start, boxstartmins, boxstartmaxs, 0, 0, NULL);
826 Collision_BrushForBox(&thisbrush_end, boxendmins, boxendmaxs, 0, 0, NULL);
827 if (maxvertices < model->surfmesh.num_vertices)
831 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
832 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
834 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
835 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
836 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);
839 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
842 for (i = 0;i < inverts;i++)
844 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
846 j = vertremap[i]; // not onseam
849 j = vertremap[i+inverts]; // onseam
855 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
857 int i, f, pose, groupframes;
859 daliasframetype_t *pframetype;
860 daliasframe_t *pinframe;
861 daliasgroup_t *group;
862 daliasinterval_t *intervals;
865 scene = loadmodel->animscenes;
866 for (f = 0;f < loadmodel->numframes;f++)
868 pframetype = (daliasframetype_t *)datapointer;
869 datapointer += sizeof(daliasframetype_t);
870 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
872 // a single frame is still treated as a group
879 group = (daliasgroup_t *)datapointer;
880 datapointer += sizeof(daliasgroup_t);
881 groupframes = LittleLong (group->numframes);
883 // intervals (time per frame)
884 intervals = (daliasinterval_t *)datapointer;
885 datapointer += sizeof(daliasinterval_t) * groupframes;
887 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
888 if (interval < 0.01f)
890 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
895 // get scene name from first frame
896 pinframe = (daliasframe_t *)datapointer;
898 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
899 scene->firstframe = pose;
900 scene->framecount = groupframes;
901 scene->framerate = 1.0f / interval;
906 for (i = 0;i < groupframes;i++)
908 pinframe = (daliasframe_t *)datapointer;
909 datapointer += sizeof(daliasframe_t);
910 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
911 datapointer += sizeof(trivertx_t) * inverts;
917 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
919 if (cls.state == ca_dedicated)
923 skinframe = R_SkinFrame_LoadMissing();
924 memset(texture, 0, sizeof(*texture));
925 texture->currentframe = texture;
926 //texture->animated = false;
927 texture->numskinframes = 1;
928 texture->skinframerate = 1;
929 texture->skinframes[0] = skinframe;
930 texture->currentskinframe = skinframe;
931 //texture->backgroundnumskinframes = 0;
932 //texture->customblendfunc[0] = 0;
933 //texture->customblendfunc[1] = 0;
934 //texture->surfaceflags = 0;
935 //texture->supercontents = 0;
936 //texture->surfaceparms = 0;
937 //texture->textureflags = 0;
939 texture->basematerialflags = MATERIALFLAG_WALL;
940 if (texture->currentskinframe->hasalpha)
941 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
942 texture->currentmaterialflags = texture->basematerialflags;
943 texture->specularscalemod = 1;
944 texture->specularpowermod = 1;
947 void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
950 skinfileitem_t *skinfileitem;
953 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
954 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
956 memset(skin, 0, sizeof(*skin));
958 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
960 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
961 if (!strcmp(skinfileitem->name, meshname))
963 Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
969 // don't render unmentioned meshes
970 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
971 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
976 Mod_LoadTextureFromQ3Shader(skin, shadername, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
979 #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);
980 #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);
981 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
983 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
984 float scales, scalet, interval;
988 stvert_t *pinstverts;
989 dtriangle_t *pintriangles;
990 daliasskintype_t *pinskintype;
991 daliasskingroup_t *pinskingroup;
992 daliasskininterval_t *pinskinintervals;
993 daliasframetype_t *pinframetype;
994 daliasgroup_t *pinframegroup;
995 unsigned char *datapointer, *startframes, *startskins;
996 char name[MAX_QPATH];
997 skinframe_t *tempskinframe;
998 animscene_t *tempskinscenes;
999 texture_t *tempaliasskins;
1001 int *vertonseam, *vertremap;
1002 skinfile_t *skinfiles;
1004 datapointer = (unsigned char *)buffer;
1005 pinmodel = (mdl_t *)datapointer;
1006 datapointer += sizeof(mdl_t);
1008 version = LittleLong (pinmodel->version);
1009 if (version != ALIAS_VERSION)
1010 Host_Error ("%s has wrong version number (%i should be %i)",
1011 loadmodel->name, version, ALIAS_VERSION);
1013 loadmodel->modeldatatypestring = "MDL";
1015 loadmodel->type = mod_alias;
1016 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1017 loadmodel->DrawSky = NULL;
1018 loadmodel->DrawAddWaterPlanes = NULL;
1019 loadmodel->Draw = R_Q1BSP_Draw;
1020 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1021 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1022 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1023 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1024 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1025 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1026 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1027 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1028 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1029 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1030 loadmodel->PointSuperContents = NULL;
1032 loadmodel->num_surfaces = 1;
1033 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1034 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
1035 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1036 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1037 loadmodel->sortedmodelsurfaces[0] = 0;
1039 loadmodel->numskins = LittleLong(pinmodel->numskins);
1040 BOUNDI(loadmodel->numskins,0,65536);
1041 skinwidth = LittleLong (pinmodel->skinwidth);
1042 BOUNDI(skinwidth,0,65536);
1043 skinheight = LittleLong (pinmodel->skinheight);
1044 BOUNDI(skinheight,0,65536);
1045 numverts = LittleLong(pinmodel->numverts);
1046 BOUNDI(numverts,0,65536);
1047 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
1048 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
1049 loadmodel->numframes = LittleLong(pinmodel->numframes);
1050 BOUNDI(loadmodel->numframes,0,65536);
1051 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
1052 BOUNDI((int)loadmodel->synctype,0,2);
1053 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1054 i = LittleLong (pinmodel->flags);
1055 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1057 for (i = 0;i < 3;i++)
1059 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
1060 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
1063 startskins = datapointer;
1065 for (i = 0;i < loadmodel->numskins;i++)
1067 pinskintype = (daliasskintype_t *)datapointer;
1068 datapointer += sizeof(daliasskintype_t);
1069 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
1073 pinskingroup = (daliasskingroup_t *)datapointer;
1074 datapointer += sizeof(daliasskingroup_t);
1075 groupskins = LittleLong(pinskingroup->numskins);
1076 datapointer += sizeof(daliasskininterval_t) * groupskins;
1079 for (j = 0;j < groupskins;j++)
1081 datapointer += skinwidth * skinheight;
1086 pinstverts = (stvert_t *)datapointer;
1087 datapointer += sizeof(stvert_t) * numverts;
1089 pintriangles = (dtriangle_t *)datapointer;
1090 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
1092 startframes = datapointer;
1093 loadmodel->surfmesh.num_morphframes = 0;
1094 for (i = 0;i < loadmodel->numframes;i++)
1096 pinframetype = (daliasframetype_t *)datapointer;
1097 datapointer += sizeof(daliasframetype_t);
1098 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
1102 pinframegroup = (daliasgroup_t *)datapointer;
1103 datapointer += sizeof(daliasgroup_t);
1104 groupframes = LittleLong(pinframegroup->numframes);
1105 datapointer += sizeof(daliasinterval_t) * groupframes;
1108 for (j = 0;j < groupframes;j++)
1110 datapointer += sizeof(daliasframe_t);
1111 datapointer += sizeof(trivertx_t) * numverts;
1112 loadmodel->surfmesh.num_morphframes++;
1115 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1117 // store texture coordinates into temporary array, they will be stored
1118 // after usage is determined (triangle data)
1119 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
1120 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
1121 vertonseam = vertremap + numverts * 2;
1123 scales = 1.0 / skinwidth;
1124 scalet = 1.0 / skinheight;
1125 for (i = 0;i < numverts;i++)
1127 vertonseam[i] = LittleLong(pinstverts[i].onseam);
1128 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
1129 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
1130 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
1131 vertst[(i+numverts)*2+1] = vertst[i*2+1];
1134 // load triangle data
1135 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1137 // read the triangle elements
1138 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1139 for (j = 0;j < 3;j++)
1140 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1141 // validate (note numverts is used because this is the original data)
1142 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1143 // now butcher the elements according to vertonseam and tri->facesfront
1144 // and then compact the vertex set to remove duplicates
1145 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1146 if (!LittleLong(pintriangles[i].facesfront)) // backface
1147 for (j = 0;j < 3;j++)
1148 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1149 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1151 // (this uses vertremap to count usage to save some memory)
1152 for (i = 0;i < numverts*2;i++)
1154 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1155 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1156 // build remapping table and compact array
1157 loadmodel->surfmesh.num_vertices = 0;
1158 for (i = 0;i < numverts*2;i++)
1162 vertremap[i] = loadmodel->surfmesh.num_vertices;
1163 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1164 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1165 loadmodel->surfmesh.num_vertices++;
1168 vertremap[i] = -1; // not used at all
1170 // remap the elements to the new vertex set
1171 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1172 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1173 // store the texture coordinates
1174 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1175 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1177 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1178 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1181 // generate ushort elements array if possible
1182 if (loadmodel->surfmesh.num_vertices <= 65536)
1183 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1184 if (loadmodel->surfmesh.data_element3s)
1185 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1186 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1189 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1190 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1191 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1192 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1193 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1194 Mod_Alias_CalculateBoundingBox();
1195 Mod_Alias_MorphMesh_CompileFrames();
1198 Mem_Free(vertremap);
1201 skinfiles = Mod_LoadSkinFiles();
1204 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1205 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1206 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1207 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1208 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1209 Mod_FreeSkinFiles(skinfiles);
1210 for (i = 0;i < loadmodel->numskins;i++)
1212 loadmodel->skinscenes[i].firstframe = i;
1213 loadmodel->skinscenes[i].framecount = 1;
1214 loadmodel->skinscenes[i].loop = true;
1215 loadmodel->skinscenes[i].framerate = 10;
1220 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1221 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1222 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1223 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1225 datapointer = startskins;
1226 for (i = 0;i < loadmodel->numskins;i++)
1228 pinskintype = (daliasskintype_t *)datapointer;
1229 datapointer += sizeof(daliasskintype_t);
1231 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1238 pinskingroup = (daliasskingroup_t *)datapointer;
1239 datapointer += sizeof(daliasskingroup_t);
1241 groupskins = LittleLong (pinskingroup->numskins);
1243 pinskinintervals = (daliasskininterval_t *)datapointer;
1244 datapointer += sizeof(daliasskininterval_t) * groupskins;
1246 interval = LittleFloat(pinskinintervals[0].interval);
1247 if (interval < 0.01f)
1249 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1254 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1255 loadmodel->skinscenes[i].firstframe = totalskins;
1256 loadmodel->skinscenes[i].framecount = groupskins;
1257 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1258 loadmodel->skinscenes[i].loop = true;
1260 for (j = 0;j < groupskins;j++)
1263 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1265 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1266 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))
1267 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));
1268 datapointer += skinwidth * skinheight;
1272 // check for skins that don't exist in the model, but do exist as external images
1273 // (this was added because yummyluv kept pestering me about support for it)
1274 // TODO: support shaders here?
1275 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)))
1277 // expand the arrays to make room
1278 tempskinscenes = loadmodel->skinscenes;
1279 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1280 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1281 Mem_Free(tempskinscenes);
1283 tempaliasskins = loadmodel->data_textures;
1284 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1285 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1286 Mem_Free(tempaliasskins);
1288 // store the info about the new skin
1289 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1290 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1291 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1292 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1293 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1294 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1296 //increase skin counts
1297 loadmodel->numskins++;
1300 // fix up the pointers since they are pointing at the old textures array
1301 // FIXME: this is a hack!
1302 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1303 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1307 surface = loadmodel->data_surfaces;
1308 surface->texture = loadmodel->data_textures;
1309 surface->num_firsttriangle = 0;
1310 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1311 surface->num_firstvertex = 0;
1312 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1314 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1316 if (!loadmodel->surfmesh.isanimated)
1318 Mod_MakeCollisionBIH(loadmodel, true);
1319 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1320 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1321 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1322 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1326 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1328 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1329 float iskinwidth, iskinheight;
1330 unsigned char *data;
1331 msurface_t *surface;
1333 unsigned char *base, *datapointer;
1334 md2frame_t *pinframe;
1336 md2triangle_t *intri;
1337 unsigned short *inst;
1338 struct md2verthash_s
1340 struct md2verthash_s *next;
1344 *hash, **md2verthash, *md2verthashdata;
1345 skinfile_t *skinfiles;
1347 pinmodel = (md2_t *)buffer;
1348 base = (unsigned char *)buffer;
1350 version = LittleLong (pinmodel->version);
1351 if (version != MD2ALIAS_VERSION)
1352 Host_Error ("%s has wrong version number (%i should be %i)",
1353 loadmodel->name, version, MD2ALIAS_VERSION);
1355 loadmodel->modeldatatypestring = "MD2";
1357 loadmodel->type = mod_alias;
1358 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1359 loadmodel->DrawSky = NULL;
1360 loadmodel->DrawAddWaterPlanes = NULL;
1361 loadmodel->Draw = R_Q1BSP_Draw;
1362 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1363 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1364 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1365 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1366 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1367 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1368 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1369 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1370 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1371 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1372 loadmodel->PointSuperContents = NULL;
1374 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1375 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1376 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1377 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1378 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1379 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1380 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1381 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1383 end = LittleLong(pinmodel->ofs_end);
1384 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1385 Host_Error ("%s is not a valid model", loadmodel->name);
1386 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1387 Host_Error ("%s is not a valid model", loadmodel->name);
1388 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1389 Host_Error ("%s is not a valid model", loadmodel->name);
1390 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1391 Host_Error ("%s is not a valid model", loadmodel->name);
1392 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1393 Host_Error ("%s is not a valid model", loadmodel->name);
1395 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1396 numxyz = LittleLong(pinmodel->num_xyz);
1397 numst = LittleLong(pinmodel->num_st);
1398 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1399 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1400 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1401 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1402 skinwidth = LittleLong(pinmodel->skinwidth);
1403 skinheight = LittleLong(pinmodel->skinheight);
1404 iskinwidth = 1.0f / skinwidth;
1405 iskinheight = 1.0f / skinheight;
1407 loadmodel->num_surfaces = 1;
1408 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1409 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]));
1410 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1411 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1412 loadmodel->sortedmodelsurfaces[0] = 0;
1413 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1414 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1415 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1416 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1418 loadmodel->synctype = ST_RAND;
1421 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1422 skinfiles = Mod_LoadSkinFiles();
1425 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1426 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1427 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1428 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1429 Mod_FreeSkinFiles(skinfiles);
1431 else if (loadmodel->numskins)
1433 // skins found (most likely not a player model)
1434 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1435 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1436 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1437 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1438 Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
1442 // no skins (most likely a player model)
1443 loadmodel->numskins = 1;
1444 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1445 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1446 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1447 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1450 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1451 for (i = 0;i < loadmodel->numskins;i++)
1453 loadmodel->skinscenes[i].firstframe = i;
1454 loadmodel->skinscenes[i].framecount = 1;
1455 loadmodel->skinscenes[i].loop = true;
1456 loadmodel->skinscenes[i].framerate = 10;
1459 // load the triangles and stvert data
1460 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1461 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1462 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1463 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1464 // swap the triangle list
1465 loadmodel->surfmesh.num_vertices = 0;
1466 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1468 for (j = 0;j < 3;j++)
1470 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1471 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1474 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1479 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1482 hashindex = (xyz * 256 + st) & 65535;
1483 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1484 if (hash->xyz == xyz && hash->st == st)
1488 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1491 hash->next = md2verthash[hashindex];
1492 md2verthash[hashindex] = hash;
1494 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1498 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1499 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));
1500 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1501 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1502 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1505 hash = md2verthashdata + i;
1506 vertremap[i] = hash->xyz;
1507 sts = LittleShort(inst[hash->st*2+0]);
1508 stt = LittleShort(inst[hash->st*2+1]);
1509 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1511 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1515 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1516 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1519 Mem_Free(md2verthash);
1520 Mem_Free(md2verthashdata);
1522 // generate ushort elements array if possible
1523 if (loadmodel->surfmesh.num_vertices <= 65536)
1524 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1525 if (loadmodel->surfmesh.data_element3s)
1526 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1527 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1530 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1531 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1536 pinframe = (md2frame_t *)datapointer;
1537 datapointer += sizeof(md2frame_t);
1538 // store the frame scale/translate into the appropriate array
1539 for (j = 0;j < 3;j++)
1541 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1542 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1544 // convert the vertices
1545 v = (trivertx_t *)datapointer;
1546 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1547 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1548 out[k] = v[vertremap[k]];
1549 datapointer += numxyz * sizeof(trivertx_t);
1551 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1552 loadmodel->animscenes[i].firstframe = i;
1553 loadmodel->animscenes[i].framecount = 1;
1554 loadmodel->animscenes[i].framerate = 10;
1555 loadmodel->animscenes[i].loop = true;
1558 Mem_Free(vertremap);
1560 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1561 Mod_Alias_CalculateBoundingBox();
1562 Mod_Alias_MorphMesh_CompileFrames();
1564 surface = loadmodel->data_surfaces;
1565 surface->texture = loadmodel->data_textures;
1566 surface->num_firsttriangle = 0;
1567 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1568 surface->num_firstvertex = 0;
1569 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1571 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1573 if (!loadmodel->surfmesh.isanimated)
1575 Mod_MakeCollisionBIH(loadmodel, true);
1576 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1577 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1578 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1579 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1583 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1585 int i, j, k, version, meshvertices, meshtriangles;
1586 unsigned char *data;
1587 msurface_t *surface;
1588 md3modelheader_t *pinmodel;
1589 md3frameinfo_t *pinframe;
1592 skinfile_t *skinfiles;
1594 pinmodel = (md3modelheader_t *)buffer;
1596 if (memcmp(pinmodel->identifier, "IDP3", 4))
1597 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1598 version = LittleLong (pinmodel->version);
1599 if (version != MD3VERSION)
1600 Host_Error ("%s has wrong version number (%i should be %i)",
1601 loadmodel->name, version, MD3VERSION);
1603 skinfiles = Mod_LoadSkinFiles();
1604 if (loadmodel->numskins < 1)
1605 loadmodel->numskins = 1;
1607 loadmodel->modeldatatypestring = "MD3";
1609 loadmodel->type = mod_alias;
1610 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1611 loadmodel->DrawSky = NULL;
1612 loadmodel->DrawAddWaterPlanes = NULL;
1613 loadmodel->Draw = R_Q1BSP_Draw;
1614 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1615 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1616 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1617 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1618 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1619 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1620 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1621 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1622 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1623 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1624 loadmodel->PointSuperContents = NULL;
1625 loadmodel->synctype = ST_RAND;
1626 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1627 i = LittleLong (pinmodel->flags);
1628 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1630 // set up some global info about the model
1631 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1632 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1634 // make skinscenes for the skins (no groups)
1635 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1636 for (i = 0;i < loadmodel->numskins;i++)
1638 loadmodel->skinscenes[i].firstframe = i;
1639 loadmodel->skinscenes[i].framecount = 1;
1640 loadmodel->skinscenes[i].loop = true;
1641 loadmodel->skinscenes[i].framerate = 10;
1645 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1646 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1648 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1649 loadmodel->animscenes[i].firstframe = i;
1650 loadmodel->animscenes[i].framecount = 1;
1651 loadmodel->animscenes[i].framerate = 10;
1652 loadmodel->animscenes[i].loop = true;
1656 loadmodel->num_tagframes = loadmodel->numframes;
1657 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1658 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1659 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1661 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1662 for (j = 0;j < 9;j++)
1663 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1664 for (j = 0;j < 3;j++)
1665 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1666 //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);
1672 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)))
1674 if (memcmp(pinmesh->identifier, "IDP3", 4))
1675 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1676 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1677 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1678 meshvertices += LittleLong(pinmesh->num_vertices);
1679 meshtriangles += LittleLong(pinmesh->num_triangles);
1682 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1683 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1684 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1685 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));
1686 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1687 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1688 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1689 loadmodel->surfmesh.num_vertices = meshvertices;
1690 loadmodel->surfmesh.num_triangles = meshtriangles;
1691 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1692 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1693 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1694 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1695 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1696 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1697 if (meshvertices <= 65536)
1698 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1702 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)))
1704 if (memcmp(pinmesh->identifier, "IDP3", 4))
1705 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1706 loadmodel->sortedmodelsurfaces[i] = i;
1707 surface = loadmodel->data_surfaces + i;
1708 surface->texture = loadmodel->data_textures + i;
1709 surface->num_firsttriangle = meshtriangles;
1710 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1711 surface->num_firstvertex = meshvertices;
1712 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1713 meshvertices += surface->num_vertices;
1714 meshtriangles += surface->num_triangles;
1716 for (j = 0;j < surface->num_triangles * 3;j++)
1717 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1718 for (j = 0;j < surface->num_vertices;j++)
1720 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1721 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1723 for (j = 0;j < loadmodel->numframes;j++)
1725 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1726 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1727 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1729 out->origin[0] = LittleShort(in->origin[0]);
1730 out->origin[1] = LittleShort(in->origin[1]);
1731 out->origin[2] = LittleShort(in->origin[2]);
1732 out->pitch = in->pitch;
1737 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1739 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1741 if (loadmodel->surfmesh.data_element3s)
1742 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1743 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1744 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1745 Mod_Alias_MorphMesh_CompileFrames();
1746 Mod_Alias_CalculateBoundingBox();
1747 Mod_FreeSkinFiles(skinfiles);
1748 Mod_MakeSortedSurfaces(loadmodel);
1750 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1751 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1753 if (!loadmodel->surfmesh.isanimated)
1755 Mod_MakeCollisionBIH(loadmodel, true);
1756 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1757 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1758 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1759 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1763 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1765 zymtype1header_t *pinmodel, *pheader;
1766 unsigned char *pbase;
1767 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1768 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose, f, biggestorigin, tempvec[3], modelscale;
1769 zymvertex_t *verts, *vertdata;
1773 skinfile_t *skinfiles;
1774 unsigned char *data;
1775 msurface_t *surface;
1777 pinmodel = (zymtype1header_t *)buffer;
1778 pbase = (unsigned char *)buffer;
1779 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1780 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1781 if (BigLong(pinmodel->type) != 1)
1782 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1784 loadmodel->modeldatatypestring = "ZYM";
1786 loadmodel->type = mod_alias;
1787 loadmodel->synctype = ST_RAND;
1791 pheader->type = BigLong(pinmodel->type);
1792 pheader->filesize = BigLong(pinmodel->filesize);
1793 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1794 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1795 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1796 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1797 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1798 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1799 pheader->radius = BigFloat(pinmodel->radius);
1800 pheader->numverts = BigLong(pinmodel->numverts);
1801 pheader->numtris = BigLong(pinmodel->numtris);
1802 pheader->numshaders = BigLong(pinmodel->numshaders);
1803 pheader->numbones = BigLong(pinmodel->numbones);
1804 pheader->numscenes = BigLong(pinmodel->numscenes);
1805 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1806 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1807 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1808 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1809 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1810 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1811 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1812 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1813 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1814 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1815 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1816 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1817 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1818 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1819 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1820 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1821 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1822 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1824 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1826 Con_Printf("%s has no geometry\n", loadmodel->name);
1829 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1831 Con_Printf("%s has no animations\n", loadmodel->name);
1835 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1836 loadmodel->DrawSky = NULL;
1837 loadmodel->DrawAddWaterPlanes = NULL;
1838 loadmodel->Draw = R_Q1BSP_Draw;
1839 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1840 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1841 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1842 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1843 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1844 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1845 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1846 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1847 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1848 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1849 loadmodel->PointSuperContents = NULL;
1851 loadmodel->numframes = pheader->numscenes;
1852 loadmodel->num_surfaces = pheader->numshaders;
1854 skinfiles = Mod_LoadSkinFiles();
1855 if (loadmodel->numskins < 1)
1856 loadmodel->numskins = 1;
1858 // make skinscenes for the skins (no groups)
1859 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1860 for (i = 0;i < loadmodel->numskins;i++)
1862 loadmodel->skinscenes[i].firstframe = i;
1863 loadmodel->skinscenes[i].framecount = 1;
1864 loadmodel->skinscenes[i].loop = true;
1865 loadmodel->skinscenes[i].framerate = 10;
1869 modelradius = pheader->radius;
1870 for (i = 0;i < 3;i++)
1872 loadmodel->normalmins[i] = pheader->mins[i];
1873 loadmodel->normalmaxs[i] = pheader->maxs[i];
1874 loadmodel->rotatedmins[i] = -modelradius;
1875 loadmodel->rotatedmaxs[i] = modelradius;
1877 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1878 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1879 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1880 if (loadmodel->yawmaxs[0] > modelradius)
1881 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1882 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1883 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1884 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1885 loadmodel->radius = modelradius;
1886 loadmodel->radius2 = modelradius * modelradius;
1888 // go through the lumps, swapping things
1890 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1891 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1892 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1893 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1894 for (i = 0;i < pheader->numscenes;i++)
1896 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1897 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1898 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1899 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1900 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1901 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1902 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1903 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1904 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1905 if (loadmodel->animscenes[i].framerate < 0)
1906 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1910 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1911 loadmodel->num_bones = pheader->numbones;
1912 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1913 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1914 for (i = 0;i < pheader->numbones;i++)
1916 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1917 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1918 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1919 if (loadmodel->data_bones[i].parent >= i)
1920 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1923 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1924 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1925 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1926 for (i = 0;i < pheader->numverts;i++)
1928 vertbonecounts[i] = BigLong(bonecount[i]);
1929 if (vertbonecounts[i] != 1)
1930 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1933 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1935 meshvertices = pheader->numverts;
1936 meshtriangles = pheader->numtris;
1938 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1939 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1940 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1941 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(unsigned short) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]) + loadmodel->num_bones * sizeof(float[12]));
1942 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1943 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1944 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1945 loadmodel->surfmesh.num_vertices = meshvertices;
1946 loadmodel->surfmesh.num_triangles = meshtriangles;
1947 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1948 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1949 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1950 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1951 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1952 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1953 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1954 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1955 loadmodel->surfmesh.num_blends = 0;
1956 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
1957 if (loadmodel->surfmesh.num_vertices <= 65536)
1958 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1959 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
1960 loadmodel->surfmesh.data_blendweights = NULL;
1962 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1963 poses = (float *) (pheader->lump_poses.start + pbase);
1964 // figure out scale of model from root bone, for compatibility with old zmodel versions
1965 tempvec[0] = BigFloat(poses[0]);
1966 tempvec[1] = BigFloat(poses[1]);
1967 tempvec[2] = BigFloat(poses[2]);
1968 modelscale = VectorLength(tempvec);
1970 for (i = 0;i < loadmodel->num_bones * numposes * 12;i++)
1972 f = fabs(BigFloat(poses[i]));
1973 biggestorigin = max(biggestorigin, f);
1975 loadmodel->num_posescale = biggestorigin / 32767.0f;
1976 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
1977 for (i = 0;i < numposes;i++)
1979 const float *frameposes = (float *) (pheader->lump_poses.start + pbase) + 12*i*loadmodel->num_bones;
1980 for (j = 0;j < loadmodel->num_bones;j++)
1983 matrix4x4_t posematrix;
1984 for (k = 0;k < 12;k++)
1985 pose[k] = BigFloat(frameposes[j*12+k]);
1986 //if (j < loadmodel->num_bones)
1987 // 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));
1988 // scale child bones to match the root scale
1989 if (loadmodel->data_bones[j].parent >= 0)
1991 pose[3] *= modelscale;
1992 pose[7] *= modelscale;
1993 pose[11] *= modelscale;
1995 // normalize rotation matrix
1996 VectorNormalize(pose + 0);
1997 VectorNormalize(pose + 4);
1998 VectorNormalize(pose + 8);
1999 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2000 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
2004 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
2005 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
2006 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
2007 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2008 // (converting from weight-blending skeletal animation to
2009 // deformation-based skeletal animation)
2010 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2011 for (i = 0;i < loadmodel->num_bones;i++)
2014 for (k = 0;k < 12;k++)
2015 m[k] = BigFloat(poses[i*12+k]);
2016 if (loadmodel->data_bones[i].parent >= 0)
2017 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2019 for (k = 0;k < 12;k++)
2020 bonepose[12*i+k] = m[k];
2022 for (j = 0;j < pheader->numverts;j++)
2024 // this format really should have had a per vertexweight weight value...
2025 // but since it does not, the weighting is completely ignored and
2026 // only one weight is allowed per vertex
2027 int boneindex = BigLong(vertdata[j].bonenum);
2028 const float *m = bonepose + 12 * boneindex;
2029 float relativeorigin[3];
2030 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
2031 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
2032 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
2033 // transform the vertex bone weight into the base mesh
2034 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
2035 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
2036 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
2037 // store the weight as the primary weight on this vertex
2038 loadmodel->surfmesh.blends[j] = boneindex;
2041 // normals and tangents are calculated after elements are loaded
2043 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
2044 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
2045 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
2046 for (i = 0;i < pheader->numverts;i++)
2048 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
2049 // flip T coordinate for OpenGL
2050 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
2053 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
2054 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
2055 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
2057 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
2058 //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)
2059 // byteswap, validate, and swap winding order of tris
2060 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
2061 if (pheader->lump_render.length != count)
2062 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
2063 renderlist = (int *) (pheader->lump_render.start + pbase);
2064 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
2066 for (i = 0;i < loadmodel->num_surfaces;i++)
2068 int firstvertex, lastvertex;
2069 if (renderlist >= renderlistend)
2070 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2071 count = BigLong(*renderlist);renderlist++;
2072 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
2073 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2075 loadmodel->sortedmodelsurfaces[i] = i;
2076 surface = loadmodel->data_surfaces + i;
2077 surface->texture = loadmodel->data_textures + i;
2078 surface->num_firsttriangle = meshtriangles;
2079 surface->num_triangles = count;
2080 meshtriangles += surface->num_triangles;
2082 // load the elements
2083 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2084 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
2086 outelements[j*3+2] = BigLong(renderlist[0]);
2087 outelements[j*3+1] = BigLong(renderlist[1]);
2088 outelements[j*3+0] = BigLong(renderlist[2]);
2090 // validate the elements and find the used vertex range
2091 firstvertex = meshvertices;
2093 for (j = 0;j < surface->num_triangles * 3;j++)
2095 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
2096 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
2097 firstvertex = min(firstvertex, outelements[j]);
2098 lastvertex = max(lastvertex, outelements[j]);
2100 surface->num_firstvertex = firstvertex;
2101 surface->num_vertices = lastvertex + 1 - firstvertex;
2103 // since zym models do not have named sections, reuse their shader
2104 // name as the section name
2105 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
2106 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
2108 Mod_FreeSkinFiles(skinfiles);
2109 Mem_Free(vertbonecounts);
2111 Mod_MakeSortedSurfaces(loadmodel);
2113 // compute all the mesh information that was not loaded from the file
2114 if (loadmodel->surfmesh.data_element3s)
2115 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2116 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2117 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2118 Mod_BuildBaseBonePoses();
2119 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2120 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);
2121 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2123 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2125 if (!loadmodel->surfmesh.isanimated)
2127 Mod_MakeCollisionBIH(loadmodel, true);
2128 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2129 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2130 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2131 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2135 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2137 dpmheader_t *pheader;
2141 unsigned char *pbase;
2142 int i, j, k, meshvertices, meshtriangles;
2143 skinfile_t *skinfiles;
2144 unsigned char *data;
2146 float biggestorigin, tempvec[3], modelscale;
2150 pheader = (dpmheader_t *)buffer;
2151 pbase = (unsigned char *)buffer;
2152 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2153 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2154 if (BigLong(pheader->type) != 2)
2155 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2157 loadmodel->modeldatatypestring = "DPM";
2159 loadmodel->type = mod_alias;
2160 loadmodel->synctype = ST_RAND;
2163 pheader->type = BigLong(pheader->type);
2164 pheader->filesize = BigLong(pheader->filesize);
2165 pheader->mins[0] = BigFloat(pheader->mins[0]);
2166 pheader->mins[1] = BigFloat(pheader->mins[1]);
2167 pheader->mins[2] = BigFloat(pheader->mins[2]);
2168 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2169 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2170 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2171 pheader->yawradius = BigFloat(pheader->yawradius);
2172 pheader->allradius = BigFloat(pheader->allradius);
2173 pheader->num_bones = BigLong(pheader->num_bones);
2174 pheader->num_meshs = BigLong(pheader->num_meshs);
2175 pheader->num_frames = BigLong(pheader->num_frames);
2176 pheader->ofs_bones = BigLong(pheader->ofs_bones);
2177 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2178 pheader->ofs_frames = BigLong(pheader->ofs_frames);
2180 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2182 Con_Printf("%s has no geometry\n", loadmodel->name);
2185 if (pheader->num_frames < 1)
2187 Con_Printf("%s has no frames\n", loadmodel->name);
2191 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2192 loadmodel->DrawSky = NULL;
2193 loadmodel->DrawAddWaterPlanes = NULL;
2194 loadmodel->Draw = R_Q1BSP_Draw;
2195 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2196 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2197 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2198 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2199 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2200 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2201 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2202 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2203 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2204 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2205 loadmodel->PointSuperContents = NULL;
2208 for (i = 0;i < 3;i++)
2210 loadmodel->normalmins[i] = pheader->mins[i];
2211 loadmodel->normalmaxs[i] = pheader->maxs[i];
2212 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2213 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2214 loadmodel->rotatedmins[i] = -pheader->allradius;
2215 loadmodel->rotatedmaxs[i] = pheader->allradius;
2217 loadmodel->radius = pheader->allradius;
2218 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2220 // load external .skin files if present
2221 skinfiles = Mod_LoadSkinFiles();
2222 if (loadmodel->numskins < 1)
2223 loadmodel->numskins = 1;
2228 // gather combined statistics from the meshes
2229 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2230 for (i = 0;i < (int)pheader->num_meshs;i++)
2232 int numverts = BigLong(dpmmesh->num_verts);
2233 meshvertices += numverts;
2234 meshtriangles += BigLong(dpmmesh->num_tris);
2238 loadmodel->numframes = pheader->num_frames;
2239 loadmodel->num_bones = pheader->num_bones;
2240 loadmodel->num_poses = loadmodel->numframes;
2241 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2242 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2243 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2244 // do most allocations as one merged chunk
2245 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(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));
2246 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2247 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2248 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2249 loadmodel->surfmesh.num_vertices = meshvertices;
2250 loadmodel->surfmesh.num_triangles = meshtriangles;
2251 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2252 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2253 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2254 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2255 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2256 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2257 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2258 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2259 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2260 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2261 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2262 loadmodel->surfmesh.num_blends = 0;
2263 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2264 if (meshvertices <= 65536)
2265 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2266 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2267 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
2269 for (i = 0;i < loadmodel->numskins;i++)
2271 loadmodel->skinscenes[i].firstframe = i;
2272 loadmodel->skinscenes[i].framecount = 1;
2273 loadmodel->skinscenes[i].loop = true;
2274 loadmodel->skinscenes[i].framerate = 10;
2277 // load the bone info
2278 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2279 for (i = 0;i < loadmodel->num_bones;i++)
2281 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2282 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2283 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2284 if (loadmodel->data_bones[i].parent >= i)
2285 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2289 frames = (dpmframe_t *) (pbase + pheader->ofs_frames);
2290 // figure out scale of model from root bone, for compatibility with old dpmodel versions
2291 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2292 tempvec[0] = BigFloat(poses[0]);
2293 tempvec[1] = BigFloat(poses[1]);
2294 tempvec[2] = BigFloat(poses[2]);
2295 modelscale = VectorLength(tempvec);
2297 for (i = 0;i < loadmodel->numframes;i++)
2299 memcpy(loadmodel->animscenes[i].name, frames[i].name, sizeof(frames[i].name));
2300 loadmodel->animscenes[i].firstframe = i;
2301 loadmodel->animscenes[i].framecount = 1;
2302 loadmodel->animscenes[i].loop = true;
2303 loadmodel->animscenes[i].framerate = 10;
2304 // load the bone poses for this frame
2305 poses = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2306 for (j = 0;j < loadmodel->num_bones*12;j++)
2308 f = fabs(BigFloat(poses[j]));
2309 biggestorigin = max(biggestorigin, f);
2311 // stuff not processed here: mins, maxs, yawradius, allradius
2313 loadmodel->num_posescale = biggestorigin / 32767.0f;
2314 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2315 for (i = 0;i < loadmodel->numframes;i++)
2317 const float *frameposes = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2318 for (j = 0;j < loadmodel->num_bones;j++)
2321 matrix4x4_t posematrix;
2322 for (k = 0;k < 12;k++)
2323 pose[k] = BigFloat(frameposes[j*12+k]);
2324 // scale child bones to match the root scale
2325 if (loadmodel->data_bones[j].parent >= 0)
2327 pose[3] *= modelscale;
2328 pose[7] *= modelscale;
2329 pose[11] *= modelscale;
2331 // normalize rotation matrix
2332 VectorNormalize(pose + 0);
2333 VectorNormalize(pose + 4);
2334 VectorNormalize(pose + 8);
2335 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2336 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
2340 // load the meshes now
2341 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2344 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2345 // (converting from weight-blending skeletal animation to
2346 // deformation-based skeletal animation)
2347 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2348 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2349 for (i = 0;i < loadmodel->num_bones;i++)
2352 for (k = 0;k < 12;k++)
2353 m[k] = BigFloat(poses[i*12+k]);
2354 if (loadmodel->data_bones[i].parent >= 0)
2355 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2357 for (k = 0;k < 12;k++)
2358 bonepose[12*i+k] = m[k];
2360 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2362 const int *inelements;
2364 const float *intexcoord;
2365 msurface_t *surface;
2367 loadmodel->sortedmodelsurfaces[i] = i;
2368 surface = loadmodel->data_surfaces + i;
2369 surface->texture = loadmodel->data_textures + i;
2370 surface->num_firsttriangle = meshtriangles;
2371 surface->num_triangles = BigLong(dpmmesh->num_tris);
2372 surface->num_firstvertex = meshvertices;
2373 surface->num_vertices = BigLong(dpmmesh->num_verts);
2374 meshvertices += surface->num_vertices;
2375 meshtriangles += surface->num_triangles;
2377 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2378 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2379 for (j = 0;j < surface->num_triangles;j++)
2381 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2382 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2383 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2384 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2389 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2390 for (j = 0;j < surface->num_vertices*2;j++)
2391 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2393 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2394 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2396 int weightindex[4] = { 0, 0, 0, 0 };
2397 float weightinfluence[4] = { 0, 0, 0, 0 };
2399 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2400 data += sizeof(dpmvertex_t);
2401 for (k = 0;k < numweights;k++)
2403 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2404 int boneindex = BigLong(vert->bonenum);
2405 const float *m = bonepose + 12 * boneindex;
2406 float influence = BigFloat(vert->influence);
2407 float relativeorigin[3], relativenormal[3];
2408 relativeorigin[0] = BigFloat(vert->origin[0]);
2409 relativeorigin[1] = BigFloat(vert->origin[1]);
2410 relativeorigin[2] = BigFloat(vert->origin[2]);
2411 relativenormal[0] = BigFloat(vert->normal[0]);
2412 relativenormal[1] = BigFloat(vert->normal[1]);
2413 relativenormal[2] = BigFloat(vert->normal[2]);
2414 // blend the vertex bone weights into the base mesh
2415 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2416 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2417 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2418 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2419 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2420 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2423 // store the first (and often only) weight
2424 weightinfluence[0] = influence;
2425 weightindex[0] = boneindex;
2429 // sort the new weight into this vertex's weight table
2430 // (which only accepts up to 4 bones per vertex)
2431 for (l = 0;l < 4;l++)
2433 if (weightinfluence[l] < influence)
2435 // move weaker influence weights out of the way first
2437 for (l2 = 3;l2 > l;l2--)
2439 weightinfluence[l2] = weightinfluence[l2-1];
2440 weightindex[l2] = weightindex[l2-1];
2442 // store the new weight
2443 weightinfluence[l] = influence;
2444 weightindex[l] = boneindex;
2449 data += sizeof(dpmbonevert_t);
2451 loadmodel->surfmesh.blends[j] = Mod_Skeletal_AddBlend(loadmodel, weightindex, weightinfluence);
2454 // since dpm models do not have named sections, reuse their shader name as the section name
2455 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2457 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2459 if (loadmodel->surfmesh.num_blends < meshvertices)
2460 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2462 Mod_FreeSkinFiles(skinfiles);
2463 Mod_MakeSortedSurfaces(loadmodel);
2465 // compute all the mesh information that was not loaded from the file
2466 if (loadmodel->surfmesh.data_element3s)
2467 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2468 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2469 Mod_BuildBaseBonePoses();
2470 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);
2471 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2473 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2475 if (!loadmodel->surfmesh.isanimated)
2477 Mod_MakeCollisionBIH(loadmodel, true);
2478 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2479 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2480 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2481 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2485 // no idea why PSK/PSA files contain weird quaternions but they do...
2486 #define PSKQUATNEGATIONS
2487 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2489 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2490 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2491 fs_offset_t filesize;
2496 pskboneinfo_t *bones;
2497 pskrawweights_t *rawweights;
2498 //pskboneinfo_t *animbones;
2499 pskaniminfo_t *anims;
2500 pskanimkeys_t *animkeys;
2501 void *animfilebuffer, *animbuffer, *animbufferend;
2502 unsigned char *data;
2504 skinfile_t *skinfiles;
2505 char animname[MAX_QPATH];
2507 float biggestorigin;
2509 pchunk = (pskchunk_t *)buffer;
2510 if (strcmp(pchunk->id, "ACTRHEAD"))
2511 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2513 loadmodel->modeldatatypestring = "PSK";
2515 loadmodel->type = mod_alias;
2516 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2517 loadmodel->DrawSky = NULL;
2518 loadmodel->DrawAddWaterPlanes = NULL;
2519 loadmodel->Draw = R_Q1BSP_Draw;
2520 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2521 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2522 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2523 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2524 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2525 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2526 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2527 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2528 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2529 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2530 loadmodel->PointSuperContents = NULL;
2531 loadmodel->synctype = ST_RAND;
2533 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2534 strlcat(animname, ".psa", sizeof(animname));
2535 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2536 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2537 if (animbuffer == NULL)
2538 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2557 while (buffer < bufferend)
2559 pchunk = (pskchunk_t *)buffer;
2560 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2561 version = LittleLong(pchunk->version);
2562 recordsize = LittleLong(pchunk->recordsize);
2563 numrecords = LittleLong(pchunk->numrecords);
2564 if (developer_extra.integer)
2565 Con_DPrintf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2566 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2567 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);
2568 if (!strcmp(pchunk->id, "ACTRHEAD"))
2572 else if (!strcmp(pchunk->id, "PNTS0000"))
2575 if (recordsize != sizeof(*p))
2576 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2577 // byteswap in place and keep the pointer
2578 numpnts = numrecords;
2579 pnts = (pskpnts_t *)buffer;
2580 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2582 p->origin[0] = LittleFloat(p->origin[0]);
2583 p->origin[1] = LittleFloat(p->origin[1]);
2584 p->origin[2] = LittleFloat(p->origin[2]);
2588 else if (!strcmp(pchunk->id, "VTXW0000"))
2591 if (recordsize != sizeof(*p))
2592 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2593 // byteswap in place and keep the pointer
2594 numvtxw = numrecords;
2595 vtxw = (pskvtxw_t *)buffer;
2596 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2598 p->pntsindex = LittleShort(p->pntsindex);
2599 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2600 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2601 if (p->pntsindex >= numpnts)
2603 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2609 else if (!strcmp(pchunk->id, "FACE0000"))
2612 if (recordsize != sizeof(*p))
2613 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2614 // byteswap in place and keep the pointer
2615 numfaces = numrecords;
2616 faces = (pskface_t *)buffer;
2617 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2619 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2620 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2621 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2622 p->group = LittleLong(p->group);
2623 if (p->vtxwindex[0] >= numvtxw)
2625 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2626 p->vtxwindex[0] = 0;
2628 if (p->vtxwindex[1] >= numvtxw)
2630 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2631 p->vtxwindex[1] = 0;
2633 if (p->vtxwindex[2] >= numvtxw)
2635 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2636 p->vtxwindex[2] = 0;
2641 else if (!strcmp(pchunk->id, "MATT0000"))
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 nummatts = numrecords;
2648 matts = (pskmatt_t *)buffer;
2649 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2655 else if (!strcmp(pchunk->id, "REFSKELT"))
2658 if (recordsize != sizeof(*p))
2659 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2660 // byteswap in place and keep the pointer
2661 numbones = numrecords;
2662 bones = (pskboneinfo_t *)buffer;
2663 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2665 p->numchildren = LittleLong(p->numchildren);
2666 p->parent = LittleLong(p->parent);
2667 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2668 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2669 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2670 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2671 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2672 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2673 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2674 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2675 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2676 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2677 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2678 #ifdef PSKQUATNEGATIONS
2681 p->basepose.quat[0] *= -1;
2682 p->basepose.quat[1] *= -1;
2683 p->basepose.quat[2] *= -1;
2687 p->basepose.quat[0] *= 1;
2688 p->basepose.quat[1] *= -1;
2689 p->basepose.quat[2] *= 1;
2692 if (p->parent < 0 || p->parent >= numbones)
2694 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2700 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2703 if (recordsize != sizeof(*p))
2704 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2705 // byteswap in place and keep the pointer
2706 numrawweights = numrecords;
2707 rawweights = (pskrawweights_t *)buffer;
2708 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2710 p->weight = LittleFloat(p->weight);
2711 p->pntsindex = LittleLong(p->pntsindex);
2712 p->boneindex = LittleLong(p->boneindex);
2713 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2715 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2718 if (p->boneindex < 0 || p->boneindex >= numbones)
2720 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2728 while (animbuffer < animbufferend)
2730 pchunk = (pskchunk_t *)animbuffer;
2731 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2732 version = LittleLong(pchunk->version);
2733 recordsize = LittleLong(pchunk->recordsize);
2734 numrecords = LittleLong(pchunk->numrecords);
2735 if (developer_extra.integer)
2736 Con_DPrintf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2737 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2738 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);
2739 if (!strcmp(pchunk->id, "ANIMHEAD"))
2743 else if (!strcmp(pchunk->id, "BONENAMES"))
2746 if (recordsize != sizeof(*p))
2747 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2748 // byteswap in place and keep the pointer
2749 numanimbones = numrecords;
2750 //animbones = (pskboneinfo_t *)animbuffer;
2751 // NOTE: supposedly psa does not need to match the psk model, the
2752 // bones missing from the psa would simply use their base
2753 // positions from the psk, but this is hard for me to implement
2754 // and people can easily make animations that match.
2755 if (numanimbones != numbones)
2756 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2757 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2759 p->numchildren = LittleLong(p->numchildren);
2760 p->parent = LittleLong(p->parent);
2761 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2762 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2763 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2764 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2765 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2766 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2767 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2768 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2769 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2770 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2771 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2772 #ifdef PSKQUATNEGATIONS
2775 p->basepose.quat[0] *= -1;
2776 p->basepose.quat[1] *= -1;
2777 p->basepose.quat[2] *= -1;
2781 p->basepose.quat[0] *= 1;
2782 p->basepose.quat[1] *= -1;
2783 p->basepose.quat[2] *= 1;
2786 if (p->parent < 0 || p->parent >= numanimbones)
2788 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2791 // check that bones are the same as in the base
2792 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2793 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2797 else if (!strcmp(pchunk->id, "ANIMINFO"))
2800 if (recordsize != sizeof(*p))
2801 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2802 // byteswap in place and keep the pointer
2803 numanims = numrecords;
2804 anims = (pskaniminfo_t *)animbuffer;
2805 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2807 p->numbones = LittleLong(p->numbones);
2808 p->playtime = LittleFloat(p->playtime);
2809 p->fps = LittleFloat(p->fps);
2810 p->firstframe = LittleLong(p->firstframe);
2811 p->numframes = LittleLong(p->numframes);
2812 if (p->numbones != numbones)
2813 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2817 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2820 if (recordsize != sizeof(*p))
2821 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2822 numanimkeys = numrecords;
2823 animkeys = (pskanimkeys_t *)animbuffer;
2824 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2826 p->origin[0] = LittleFloat(p->origin[0]);
2827 p->origin[1] = LittleFloat(p->origin[1]);
2828 p->origin[2] = LittleFloat(p->origin[2]);
2829 p->quat[0] = LittleFloat(p->quat[0]);
2830 p->quat[1] = LittleFloat(p->quat[1]);
2831 p->quat[2] = LittleFloat(p->quat[2]);
2832 p->quat[3] = LittleFloat(p->quat[3]);
2833 p->frametime = LittleFloat(p->frametime);
2834 #ifdef PSKQUATNEGATIONS
2835 if (index % numbones)
2850 // TODO: allocate bonepose stuff
2853 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2856 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2857 Host_Error("%s: missing required chunks", loadmodel->name);
2859 loadmodel->numframes = 0;
2860 for (index = 0;index < numanims;index++)
2861 loadmodel->numframes += anims[index].numframes;
2863 if (numanimkeys != numbones * loadmodel->numframes)
2864 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2866 meshvertices = numvtxw;
2867 meshtriangles = numfaces;
2869 // load external .skin files if present
2870 skinfiles = Mod_LoadSkinFiles();
2871 if (loadmodel->numskins < 1)
2872 loadmodel->numskins = 1;
2873 loadmodel->num_bones = numbones;
2874 loadmodel->num_poses = loadmodel->numframes;
2875 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2876 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2877 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2878 loadmodel->surfmesh.num_vertices = meshvertices;
2879 loadmodel->surfmesh.num_triangles = meshtriangles;
2880 // do most allocations as one merged chunk
2881 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(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);
2882 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2883 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2884 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2885 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2886 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2887 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2888 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2889 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2890 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2891 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2892 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2893 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2894 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2895 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2896 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2897 loadmodel->surfmesh.num_blends = 0;
2898 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2899 if (loadmodel->surfmesh.num_vertices <= 65536)
2900 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2901 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2902 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(blendweights_t));
2904 for (i = 0;i < loadmodel->numskins;i++)
2906 loadmodel->skinscenes[i].firstframe = i;
2907 loadmodel->skinscenes[i].framecount = 1;
2908 loadmodel->skinscenes[i].loop = true;
2909 loadmodel->skinscenes[i].framerate = 10;
2913 for (index = 0, i = 0;index < nummatts;index++)
2915 // since psk models do not have named sections, reuse their shader name as the section name
2916 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2917 loadmodel->sortedmodelsurfaces[index] = index;
2918 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2919 loadmodel->data_surfaces[index].num_firstvertex = 0;
2920 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2923 // copy over the vertex locations and texcoords
2924 for (index = 0;index < numvtxw;index++)
2926 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2927 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2928 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2929 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2930 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2933 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2934 for (index = 0;index < numfaces;index++)
2935 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2936 for (index = 0, i = 0;index < nummatts;index++)
2938 loadmodel->data_surfaces[index].num_firsttriangle = i;
2939 i += loadmodel->data_surfaces[index].num_triangles;
2940 loadmodel->data_surfaces[index].num_triangles = 0;
2942 for (index = 0;index < numfaces;index++)
2944 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2945 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2946 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2947 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2950 // copy over the bones
2951 for (index = 0;index < numbones;index++)
2953 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2954 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2955 if (loadmodel->data_bones[index].parent >= index)
2956 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2959 // sort the psk point weights into the vertex weight tables
2960 // (which only accept up to 4 bones per vertex)
2961 for (index = 0;index < numvtxw;index++)
2963 int weightindex[4] = { 0, 0, 0, 0 };
2964 float weightinfluence[4] = { 0, 0, 0, 0 };
2966 for (j = 0;j < numrawweights;j++)
2968 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2970 int boneindex = rawweights[j].boneindex;
2971 float influence = rawweights[j].weight;
2972 for (l = 0;l < 4;l++)
2974 if (weightinfluence[l] < influence)
2976 // move lower influence weights out of the way first
2978 for (l2 = 3;l2 > l;l2--)
2980 weightinfluence[l2] = weightinfluence[l2-1];
2981 weightindex[l2] = weightindex[l2-1];
2983 // store the new weight
2984 weightinfluence[l] = influence;
2985 weightindex[l] = boneindex;
2991 loadmodel->surfmesh.blends[index] = Mod_Skeletal_AddBlend(loadmodel, weightindex, weightinfluence);
2993 if (loadmodel->surfmesh.num_blends < loadmodel->surfmesh.num_vertices)
2994 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2996 // set up the animscenes based on the anims
2997 for (index = 0, i = 0;index < numanims;index++)
2999 for (j = 0;j < anims[index].numframes;j++, i++)
3001 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
3002 loadmodel->animscenes[i].firstframe = i;
3003 loadmodel->animscenes[i].framecount = 1;
3004 loadmodel->animscenes[i].loop = true;
3005 loadmodel->animscenes[i].framerate = 10;
3009 // calculate the scaling value for bone origins so they can be compressed to short
3011 for (index = 0;index < numanimkeys;index++)
3013 pskanimkeys_t *k = animkeys + index;
3014 biggestorigin = max(biggestorigin, fabs(k->origin[0]));
3015 biggestorigin = max(biggestorigin, fabs(k->origin[1]));
3016 biggestorigin = max(biggestorigin, fabs(k->origin[2]));
3018 loadmodel->num_posescale = biggestorigin / 32767.0f;
3019 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3021 // load the poses from the animkeys
3022 for (index = 0;index < numanimkeys;index++)
3024 pskanimkeys_t *k = animkeys + index;
3026 Vector4Copy(k->quat, quat);
3028 Vector4Negate(quat, quat);
3029 Vector4Normalize2(quat, quat);
3030 // compress poses to the short[6] format for longterm storage
3031 loadmodel->data_poses6s[index*6+0] = k->origin[0] * loadmodel->num_poseinvscale;
3032 loadmodel->data_poses6s[index*6+1] = k->origin[1] * loadmodel->num_poseinvscale;
3033 loadmodel->data_poses6s[index*6+2] = k->origin[2] * loadmodel->num_poseinvscale;
3034 loadmodel->data_poses6s[index*6+3] = quat[0] * 32767.0f;
3035 loadmodel->data_poses6s[index*6+4] = quat[1] * 32767.0f;
3036 loadmodel->data_poses6s[index*6+5] = quat[2] * 32767.0f;
3038 Mod_FreeSkinFiles(skinfiles);
3039 Mem_Free(animfilebuffer);
3040 Mod_MakeSortedSurfaces(loadmodel);
3042 // compute all the mesh information that was not loaded from the file
3043 // TODO: honor smoothing groups somehow?
3044 if (loadmodel->surfmesh.data_element3s)
3045 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3046 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3047 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
3048 Mod_BuildBaseBonePoses();
3049 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
3050 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);
3051 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3052 Mod_Alias_CalculateBoundingBox();
3054 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
3056 if (!loadmodel->surfmesh.isanimated)
3058 Mod_MakeCollisionBIH(loadmodel, true);
3059 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3060 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3061 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3062 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;