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;
945 texture->surfaceflags = 0;
946 texture->supercontents = SUPERCONTENTS_SOLID;
947 if (!(texture->basematerialflags & MATERIALFLAG_BLENDED))
948 texture->supercontents |= SUPERCONTENTS_OPAQUE;
951 void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
954 skinfileitem_t *skinfileitem;
957 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
958 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
960 memset(skin, 0, sizeof(*skin));
962 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
964 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
965 if (!strcmp(skinfileitem->name, meshname))
967 Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
973 // don't render unmentioned meshes
974 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
975 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
980 Mod_LoadTextureFromQ3Shader(skin, shadername, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
983 #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);
984 #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);
985 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
987 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
988 float scales, scalet, interval;
992 stvert_t *pinstverts;
993 dtriangle_t *pintriangles;
994 daliasskintype_t *pinskintype;
995 daliasskingroup_t *pinskingroup;
996 daliasskininterval_t *pinskinintervals;
997 daliasframetype_t *pinframetype;
998 daliasgroup_t *pinframegroup;
999 unsigned char *datapointer, *startframes, *startskins;
1000 char name[MAX_QPATH];
1001 skinframe_t *tempskinframe;
1002 animscene_t *tempskinscenes;
1003 texture_t *tempaliasskins;
1005 int *vertonseam, *vertremap;
1006 skinfile_t *skinfiles;
1008 datapointer = (unsigned char *)buffer;
1009 pinmodel = (mdl_t *)datapointer;
1010 datapointer += sizeof(mdl_t);
1012 version = LittleLong (pinmodel->version);
1013 if (version != ALIAS_VERSION)
1014 Host_Error ("%s has wrong version number (%i should be %i)",
1015 loadmodel->name, version, ALIAS_VERSION);
1017 loadmodel->modeldatatypestring = "MDL";
1019 loadmodel->type = mod_alias;
1020 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1021 loadmodel->DrawSky = NULL;
1022 loadmodel->DrawAddWaterPlanes = NULL;
1023 loadmodel->Draw = R_Q1BSP_Draw;
1024 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1025 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1026 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1027 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1028 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1029 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1030 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1031 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1032 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1033 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1034 loadmodel->PointSuperContents = NULL;
1036 loadmodel->num_surfaces = 1;
1037 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1038 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
1039 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1040 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1041 loadmodel->sortedmodelsurfaces[0] = 0;
1043 loadmodel->numskins = LittleLong(pinmodel->numskins);
1044 BOUNDI(loadmodel->numskins,0,65536);
1045 skinwidth = LittleLong (pinmodel->skinwidth);
1046 BOUNDI(skinwidth,0,65536);
1047 skinheight = LittleLong (pinmodel->skinheight);
1048 BOUNDI(skinheight,0,65536);
1049 numverts = LittleLong(pinmodel->numverts);
1050 BOUNDI(numverts,0,65536);
1051 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
1052 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
1053 loadmodel->numframes = LittleLong(pinmodel->numframes);
1054 BOUNDI(loadmodel->numframes,0,65536);
1055 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
1056 BOUNDI((int)loadmodel->synctype,0,2);
1057 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1058 i = LittleLong (pinmodel->flags);
1059 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1061 for (i = 0;i < 3;i++)
1063 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
1064 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
1067 startskins = datapointer;
1069 for (i = 0;i < loadmodel->numskins;i++)
1071 pinskintype = (daliasskintype_t *)datapointer;
1072 datapointer += sizeof(daliasskintype_t);
1073 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
1077 pinskingroup = (daliasskingroup_t *)datapointer;
1078 datapointer += sizeof(daliasskingroup_t);
1079 groupskins = LittleLong(pinskingroup->numskins);
1080 datapointer += sizeof(daliasskininterval_t) * groupskins;
1083 for (j = 0;j < groupskins;j++)
1085 datapointer += skinwidth * skinheight;
1090 pinstverts = (stvert_t *)datapointer;
1091 datapointer += sizeof(stvert_t) * numverts;
1093 pintriangles = (dtriangle_t *)datapointer;
1094 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
1096 startframes = datapointer;
1097 loadmodel->surfmesh.num_morphframes = 0;
1098 for (i = 0;i < loadmodel->numframes;i++)
1100 pinframetype = (daliasframetype_t *)datapointer;
1101 datapointer += sizeof(daliasframetype_t);
1102 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
1106 pinframegroup = (daliasgroup_t *)datapointer;
1107 datapointer += sizeof(daliasgroup_t);
1108 groupframes = LittleLong(pinframegroup->numframes);
1109 datapointer += sizeof(daliasinterval_t) * groupframes;
1112 for (j = 0;j < groupframes;j++)
1114 datapointer += sizeof(daliasframe_t);
1115 datapointer += sizeof(trivertx_t) * numverts;
1116 loadmodel->surfmesh.num_morphframes++;
1119 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1121 // store texture coordinates into temporary array, they will be stored
1122 // after usage is determined (triangle data)
1123 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
1124 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
1125 vertonseam = vertremap + numverts * 2;
1127 scales = 1.0 / skinwidth;
1128 scalet = 1.0 / skinheight;
1129 for (i = 0;i < numverts;i++)
1131 vertonseam[i] = LittleLong(pinstverts[i].onseam);
1132 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
1133 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
1134 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
1135 vertst[(i+numverts)*2+1] = vertst[i*2+1];
1138 // load triangle data
1139 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1141 // read the triangle elements
1142 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1143 for (j = 0;j < 3;j++)
1144 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1145 // validate (note numverts is used because this is the original data)
1146 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1147 // now butcher the elements according to vertonseam and tri->facesfront
1148 // and then compact the vertex set to remove duplicates
1149 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1150 if (!LittleLong(pintriangles[i].facesfront)) // backface
1151 for (j = 0;j < 3;j++)
1152 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1153 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1155 // (this uses vertremap to count usage to save some memory)
1156 for (i = 0;i < numverts*2;i++)
1158 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1159 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1160 // build remapping table and compact array
1161 loadmodel->surfmesh.num_vertices = 0;
1162 for (i = 0;i < numverts*2;i++)
1166 vertremap[i] = loadmodel->surfmesh.num_vertices;
1167 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1168 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1169 loadmodel->surfmesh.num_vertices++;
1172 vertremap[i] = -1; // not used at all
1174 // remap the elements to the new vertex set
1175 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1176 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1177 // store the texture coordinates
1178 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1179 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1181 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1182 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1185 // generate ushort elements array if possible
1186 if (loadmodel->surfmesh.num_vertices <= 65536)
1187 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1188 if (loadmodel->surfmesh.data_element3s)
1189 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1190 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1193 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1194 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1195 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1196 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1197 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1198 Mod_Alias_CalculateBoundingBox();
1199 Mod_Alias_MorphMesh_CompileFrames();
1202 Mem_Free(vertremap);
1205 skinfiles = Mod_LoadSkinFiles();
1208 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1209 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1210 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1211 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1212 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1213 Mod_FreeSkinFiles(skinfiles);
1214 for (i = 0;i < loadmodel->numskins;i++)
1216 loadmodel->skinscenes[i].firstframe = i;
1217 loadmodel->skinscenes[i].framecount = 1;
1218 loadmodel->skinscenes[i].loop = true;
1219 loadmodel->skinscenes[i].framerate = 10;
1224 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1225 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1226 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1227 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1229 datapointer = startskins;
1230 for (i = 0;i < loadmodel->numskins;i++)
1232 pinskintype = (daliasskintype_t *)datapointer;
1233 datapointer += sizeof(daliasskintype_t);
1235 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1242 pinskingroup = (daliasskingroup_t *)datapointer;
1243 datapointer += sizeof(daliasskingroup_t);
1245 groupskins = LittleLong (pinskingroup->numskins);
1247 pinskinintervals = (daliasskininterval_t *)datapointer;
1248 datapointer += sizeof(daliasskininterval_t) * groupskins;
1250 interval = LittleFloat(pinskinintervals[0].interval);
1251 if (interval < 0.01f)
1253 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1258 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1259 loadmodel->skinscenes[i].firstframe = totalskins;
1260 loadmodel->skinscenes[i].framecount = groupskins;
1261 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1262 loadmodel->skinscenes[i].loop = true;
1264 for (j = 0;j < groupskins;j++)
1267 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1269 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1270 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))
1271 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));
1272 datapointer += skinwidth * skinheight;
1276 // check for skins that don't exist in the model, but do exist as external images
1277 // (this was added because yummyluv kept pestering me about support for it)
1278 // TODO: support shaders here?
1279 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)))
1281 // expand the arrays to make room
1282 tempskinscenes = loadmodel->skinscenes;
1283 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1284 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1285 Mem_Free(tempskinscenes);
1287 tempaliasskins = loadmodel->data_textures;
1288 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1289 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1290 Mem_Free(tempaliasskins);
1292 // store the info about the new skin
1293 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1294 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1295 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1296 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1297 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1298 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1300 //increase skin counts
1301 loadmodel->numskins++;
1304 // fix up the pointers since they are pointing at the old textures array
1305 // FIXME: this is a hack!
1306 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1307 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1311 surface = loadmodel->data_surfaces;
1312 surface->texture = loadmodel->data_textures;
1313 surface->num_firsttriangle = 0;
1314 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1315 surface->num_firstvertex = 0;
1316 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1318 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1320 if (!loadmodel->surfmesh.isanimated)
1322 Mod_MakeCollisionBIH(loadmodel, true);
1323 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1324 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1325 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1326 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1330 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1332 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1333 float iskinwidth, iskinheight;
1334 unsigned char *data;
1335 msurface_t *surface;
1337 unsigned char *base, *datapointer;
1338 md2frame_t *pinframe;
1340 md2triangle_t *intri;
1341 unsigned short *inst;
1342 struct md2verthash_s
1344 struct md2verthash_s *next;
1348 *hash, **md2verthash, *md2verthashdata;
1349 skinfile_t *skinfiles;
1351 pinmodel = (md2_t *)buffer;
1352 base = (unsigned char *)buffer;
1354 version = LittleLong (pinmodel->version);
1355 if (version != MD2ALIAS_VERSION)
1356 Host_Error ("%s has wrong version number (%i should be %i)",
1357 loadmodel->name, version, MD2ALIAS_VERSION);
1359 loadmodel->modeldatatypestring = "MD2";
1361 loadmodel->type = mod_alias;
1362 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1363 loadmodel->DrawSky = NULL;
1364 loadmodel->DrawAddWaterPlanes = NULL;
1365 loadmodel->Draw = R_Q1BSP_Draw;
1366 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1367 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1368 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1369 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1370 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1371 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1372 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1373 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1374 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1375 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1376 loadmodel->PointSuperContents = NULL;
1378 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1379 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1380 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1381 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1382 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1383 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1384 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1385 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1387 end = LittleLong(pinmodel->ofs_end);
1388 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1389 Host_Error ("%s is not a valid model", loadmodel->name);
1390 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1391 Host_Error ("%s is not a valid model", loadmodel->name);
1392 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1393 Host_Error ("%s is not a valid model", loadmodel->name);
1394 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1395 Host_Error ("%s is not a valid model", loadmodel->name);
1396 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1397 Host_Error ("%s is not a valid model", loadmodel->name);
1399 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1400 numxyz = LittleLong(pinmodel->num_xyz);
1401 numst = LittleLong(pinmodel->num_st);
1402 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1403 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1404 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1405 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1406 skinwidth = LittleLong(pinmodel->skinwidth);
1407 skinheight = LittleLong(pinmodel->skinheight);
1408 iskinwidth = 1.0f / skinwidth;
1409 iskinheight = 1.0f / skinheight;
1411 loadmodel->num_surfaces = 1;
1412 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1413 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]));
1414 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1415 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1416 loadmodel->sortedmodelsurfaces[0] = 0;
1417 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1418 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1419 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1420 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1422 loadmodel->synctype = ST_RAND;
1425 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1426 skinfiles = Mod_LoadSkinFiles();
1429 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1430 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1431 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1432 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1433 Mod_FreeSkinFiles(skinfiles);
1435 else if (loadmodel->numskins)
1437 // skins found (most likely not a player model)
1438 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1439 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1440 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1441 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1442 Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
1446 // no skins (most likely a player model)
1447 loadmodel->numskins = 1;
1448 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1449 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1450 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1451 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1454 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1455 for (i = 0;i < loadmodel->numskins;i++)
1457 loadmodel->skinscenes[i].firstframe = i;
1458 loadmodel->skinscenes[i].framecount = 1;
1459 loadmodel->skinscenes[i].loop = true;
1460 loadmodel->skinscenes[i].framerate = 10;
1463 // load the triangles and stvert data
1464 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1465 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1466 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1467 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1468 // swap the triangle list
1469 loadmodel->surfmesh.num_vertices = 0;
1470 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1472 for (j = 0;j < 3;j++)
1474 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1475 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1478 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1483 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1486 hashindex = (xyz * 256 + st) & 65535;
1487 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1488 if (hash->xyz == xyz && hash->st == st)
1492 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1495 hash->next = md2verthash[hashindex];
1496 md2verthash[hashindex] = hash;
1498 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1502 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1503 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));
1504 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1505 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1506 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1509 hash = md2verthashdata + i;
1510 vertremap[i] = hash->xyz;
1511 sts = LittleShort(inst[hash->st*2+0]);
1512 stt = LittleShort(inst[hash->st*2+1]);
1513 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1515 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1519 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1520 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1523 Mem_Free(md2verthash);
1524 Mem_Free(md2verthashdata);
1526 // generate ushort elements array if possible
1527 if (loadmodel->surfmesh.num_vertices <= 65536)
1528 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1529 if (loadmodel->surfmesh.data_element3s)
1530 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1531 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1534 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1535 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1540 pinframe = (md2frame_t *)datapointer;
1541 datapointer += sizeof(md2frame_t);
1542 // store the frame scale/translate into the appropriate array
1543 for (j = 0;j < 3;j++)
1545 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1546 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1548 // convert the vertices
1549 v = (trivertx_t *)datapointer;
1550 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1551 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1552 out[k] = v[vertremap[k]];
1553 datapointer += numxyz * sizeof(trivertx_t);
1555 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1556 loadmodel->animscenes[i].firstframe = i;
1557 loadmodel->animscenes[i].framecount = 1;
1558 loadmodel->animscenes[i].framerate = 10;
1559 loadmodel->animscenes[i].loop = true;
1562 Mem_Free(vertremap);
1564 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1565 Mod_Alias_CalculateBoundingBox();
1566 Mod_Alias_MorphMesh_CompileFrames();
1568 surface = loadmodel->data_surfaces;
1569 surface->texture = loadmodel->data_textures;
1570 surface->num_firsttriangle = 0;
1571 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1572 surface->num_firstvertex = 0;
1573 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1575 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1577 if (!loadmodel->surfmesh.isanimated)
1579 Mod_MakeCollisionBIH(loadmodel, true);
1580 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1581 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1582 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1583 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1587 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1589 int i, j, k, version, meshvertices, meshtriangles;
1590 unsigned char *data;
1591 msurface_t *surface;
1592 md3modelheader_t *pinmodel;
1593 md3frameinfo_t *pinframe;
1596 skinfile_t *skinfiles;
1598 pinmodel = (md3modelheader_t *)buffer;
1600 if (memcmp(pinmodel->identifier, "IDP3", 4))
1601 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1602 version = LittleLong (pinmodel->version);
1603 if (version != MD3VERSION)
1604 Host_Error ("%s has wrong version number (%i should be %i)",
1605 loadmodel->name, version, MD3VERSION);
1607 skinfiles = Mod_LoadSkinFiles();
1608 if (loadmodel->numskins < 1)
1609 loadmodel->numskins = 1;
1611 loadmodel->modeldatatypestring = "MD3";
1613 loadmodel->type = mod_alias;
1614 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1615 loadmodel->DrawSky = NULL;
1616 loadmodel->DrawAddWaterPlanes = NULL;
1617 loadmodel->Draw = R_Q1BSP_Draw;
1618 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1619 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1620 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1621 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1622 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1623 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1624 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1625 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1626 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1627 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1628 loadmodel->PointSuperContents = NULL;
1629 loadmodel->synctype = ST_RAND;
1630 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1631 i = LittleLong (pinmodel->flags);
1632 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1634 // set up some global info about the model
1635 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1636 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1638 // make skinscenes for the skins (no groups)
1639 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1640 for (i = 0;i < loadmodel->numskins;i++)
1642 loadmodel->skinscenes[i].firstframe = i;
1643 loadmodel->skinscenes[i].framecount = 1;
1644 loadmodel->skinscenes[i].loop = true;
1645 loadmodel->skinscenes[i].framerate = 10;
1649 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1650 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1652 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1653 loadmodel->animscenes[i].firstframe = i;
1654 loadmodel->animscenes[i].framecount = 1;
1655 loadmodel->animscenes[i].framerate = 10;
1656 loadmodel->animscenes[i].loop = true;
1660 loadmodel->num_tagframes = loadmodel->numframes;
1661 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1662 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1663 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1665 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1666 for (j = 0;j < 9;j++)
1667 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1668 for (j = 0;j < 3;j++)
1669 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1670 //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);
1676 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)))
1678 if (memcmp(pinmesh->identifier, "IDP3", 4))
1679 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1680 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1681 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1682 meshvertices += LittleLong(pinmesh->num_vertices);
1683 meshtriangles += LittleLong(pinmesh->num_triangles);
1686 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1687 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1688 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1689 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));
1690 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1691 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1692 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1693 loadmodel->surfmesh.num_vertices = meshvertices;
1694 loadmodel->surfmesh.num_triangles = meshtriangles;
1695 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1696 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1697 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1698 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1699 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1700 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1701 if (meshvertices <= 65536)
1702 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1706 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)))
1708 if (memcmp(pinmesh->identifier, "IDP3", 4))
1709 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1710 loadmodel->sortedmodelsurfaces[i] = i;
1711 surface = loadmodel->data_surfaces + i;
1712 surface->texture = loadmodel->data_textures + i;
1713 surface->num_firsttriangle = meshtriangles;
1714 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1715 surface->num_firstvertex = meshvertices;
1716 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1717 meshvertices += surface->num_vertices;
1718 meshtriangles += surface->num_triangles;
1720 for (j = 0;j < surface->num_triangles * 3;j++)
1721 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1722 for (j = 0;j < surface->num_vertices;j++)
1724 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1725 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1727 for (j = 0;j < loadmodel->numframes;j++)
1729 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1730 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1731 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1733 out->origin[0] = LittleShort(in->origin[0]);
1734 out->origin[1] = LittleShort(in->origin[1]);
1735 out->origin[2] = LittleShort(in->origin[2]);
1736 out->pitch = in->pitch;
1741 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1743 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1745 if (loadmodel->surfmesh.data_element3s)
1746 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1747 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1748 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1749 Mod_Alias_MorphMesh_CompileFrames();
1750 Mod_Alias_CalculateBoundingBox();
1751 Mod_FreeSkinFiles(skinfiles);
1752 Mod_MakeSortedSurfaces(loadmodel);
1754 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1755 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1757 if (!loadmodel->surfmesh.isanimated)
1759 Mod_MakeCollisionBIH(loadmodel, true);
1760 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1761 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1762 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1763 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1767 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1769 zymtype1header_t *pinmodel, *pheader;
1770 unsigned char *pbase;
1771 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1772 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose, f, biggestorigin, tempvec[3], modelscale;
1773 zymvertex_t *verts, *vertdata;
1777 skinfile_t *skinfiles;
1778 unsigned char *data;
1779 msurface_t *surface;
1781 pinmodel = (zymtype1header_t *)buffer;
1782 pbase = (unsigned char *)buffer;
1783 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1784 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1785 if (BigLong(pinmodel->type) != 1)
1786 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1788 loadmodel->modeldatatypestring = "ZYM";
1790 loadmodel->type = mod_alias;
1791 loadmodel->synctype = ST_RAND;
1795 pheader->type = BigLong(pinmodel->type);
1796 pheader->filesize = BigLong(pinmodel->filesize);
1797 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1798 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1799 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1800 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1801 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1802 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1803 pheader->radius = BigFloat(pinmodel->radius);
1804 pheader->numverts = BigLong(pinmodel->numverts);
1805 pheader->numtris = BigLong(pinmodel->numtris);
1806 pheader->numshaders = BigLong(pinmodel->numshaders);
1807 pheader->numbones = BigLong(pinmodel->numbones);
1808 pheader->numscenes = BigLong(pinmodel->numscenes);
1809 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1810 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1811 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1812 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1813 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1814 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1815 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1816 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1817 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1818 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1819 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1820 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1821 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1822 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1823 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1824 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1825 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1826 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1828 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1830 Con_Printf("%s has no geometry\n", loadmodel->name);
1833 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1835 Con_Printf("%s has no animations\n", loadmodel->name);
1839 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1840 loadmodel->DrawSky = NULL;
1841 loadmodel->DrawAddWaterPlanes = NULL;
1842 loadmodel->Draw = R_Q1BSP_Draw;
1843 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1844 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1845 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1846 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1847 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1848 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1849 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1850 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1851 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1852 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1853 loadmodel->PointSuperContents = NULL;
1855 loadmodel->numframes = pheader->numscenes;
1856 loadmodel->num_surfaces = pheader->numshaders;
1858 skinfiles = Mod_LoadSkinFiles();
1859 if (loadmodel->numskins < 1)
1860 loadmodel->numskins = 1;
1862 // make skinscenes for the skins (no groups)
1863 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1864 for (i = 0;i < loadmodel->numskins;i++)
1866 loadmodel->skinscenes[i].firstframe = i;
1867 loadmodel->skinscenes[i].framecount = 1;
1868 loadmodel->skinscenes[i].loop = true;
1869 loadmodel->skinscenes[i].framerate = 10;
1873 modelradius = pheader->radius;
1874 for (i = 0;i < 3;i++)
1876 loadmodel->normalmins[i] = pheader->mins[i];
1877 loadmodel->normalmaxs[i] = pheader->maxs[i];
1878 loadmodel->rotatedmins[i] = -modelradius;
1879 loadmodel->rotatedmaxs[i] = modelradius;
1881 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1882 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1883 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1884 if (loadmodel->yawmaxs[0] > modelradius)
1885 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1886 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1887 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1888 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1889 loadmodel->radius = modelradius;
1890 loadmodel->radius2 = modelradius * modelradius;
1892 // go through the lumps, swapping things
1894 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1895 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1896 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1897 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1898 for (i = 0;i < pheader->numscenes;i++)
1900 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1901 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1902 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1903 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1904 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1905 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1906 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1907 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1908 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1909 if (loadmodel->animscenes[i].framerate < 0)
1910 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1914 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1915 loadmodel->num_bones = pheader->numbones;
1916 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1917 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1918 for (i = 0;i < pheader->numbones;i++)
1920 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1921 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1922 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1923 if (loadmodel->data_bones[i].parent >= i)
1924 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1927 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1928 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1929 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1930 for (i = 0;i < pheader->numverts;i++)
1932 vertbonecounts[i] = BigLong(bonecount[i]);
1933 if (vertbonecounts[i] != 1)
1934 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1937 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1939 meshvertices = pheader->numverts;
1940 meshtriangles = pheader->numtris;
1942 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1943 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1944 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1945 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]));
1946 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1947 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1948 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1949 loadmodel->surfmesh.num_vertices = meshvertices;
1950 loadmodel->surfmesh.num_triangles = meshtriangles;
1951 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1952 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1953 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1954 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1955 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1956 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1957 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1958 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1959 loadmodel->surfmesh.num_blends = 0;
1960 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
1961 if (loadmodel->surfmesh.num_vertices <= 65536)
1962 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1963 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
1964 loadmodel->surfmesh.data_blendweights = NULL;
1966 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1967 poses = (float *) (pheader->lump_poses.start + pbase);
1968 // figure out scale of model from root bone, for compatibility with old zmodel versions
1969 tempvec[0] = BigFloat(poses[0]);
1970 tempvec[1] = BigFloat(poses[1]);
1971 tempvec[2] = BigFloat(poses[2]);
1972 modelscale = VectorLength(tempvec);
1974 for (i = 0;i < loadmodel->num_bones * numposes * 12;i++)
1976 f = fabs(BigFloat(poses[i]));
1977 biggestorigin = max(biggestorigin, f);
1979 loadmodel->num_posescale = biggestorigin / 32767.0f;
1980 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
1981 for (i = 0;i < numposes;i++)
1983 const float *frameposes = (float *) (pheader->lump_poses.start + pbase) + 12*i*loadmodel->num_bones;
1984 for (j = 0;j < loadmodel->num_bones;j++)
1987 matrix4x4_t posematrix;
1988 for (k = 0;k < 12;k++)
1989 pose[k] = BigFloat(frameposes[j*12+k]);
1990 //if (j < loadmodel->num_bones)
1991 // 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));
1992 // scale child bones to match the root scale
1993 if (loadmodel->data_bones[j].parent >= 0)
1995 pose[3] *= modelscale;
1996 pose[7] *= modelscale;
1997 pose[11] *= modelscale;
1999 // normalize rotation matrix
2000 VectorNormalize(pose + 0);
2001 VectorNormalize(pose + 4);
2002 VectorNormalize(pose + 8);
2003 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2004 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
2008 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
2009 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
2010 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
2011 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2012 // (converting from weight-blending skeletal animation to
2013 // deformation-based skeletal animation)
2014 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2015 for (i = 0;i < loadmodel->num_bones;i++)
2018 for (k = 0;k < 12;k++)
2019 m[k] = BigFloat(poses[i*12+k]);
2020 if (loadmodel->data_bones[i].parent >= 0)
2021 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2023 for (k = 0;k < 12;k++)
2024 bonepose[12*i+k] = m[k];
2026 for (j = 0;j < pheader->numverts;j++)
2028 // this format really should have had a per vertexweight weight value...
2029 // but since it does not, the weighting is completely ignored and
2030 // only one weight is allowed per vertex
2031 int boneindex = BigLong(vertdata[j].bonenum);
2032 const float *m = bonepose + 12 * boneindex;
2033 float relativeorigin[3];
2034 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
2035 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
2036 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
2037 // transform the vertex bone weight into the base mesh
2038 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
2039 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
2040 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
2041 // store the weight as the primary weight on this vertex
2042 loadmodel->surfmesh.blends[j] = boneindex;
2045 // normals and tangents are calculated after elements are loaded
2047 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
2048 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
2049 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
2050 for (i = 0;i < pheader->numverts;i++)
2052 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
2053 // flip T coordinate for OpenGL
2054 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
2057 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
2058 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
2059 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
2061 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
2062 //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)
2063 // byteswap, validate, and swap winding order of tris
2064 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
2065 if (pheader->lump_render.length != count)
2066 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
2067 renderlist = (int *) (pheader->lump_render.start + pbase);
2068 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
2070 for (i = 0;i < loadmodel->num_surfaces;i++)
2072 int firstvertex, lastvertex;
2073 if (renderlist >= renderlistend)
2074 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2075 count = BigLong(*renderlist);renderlist++;
2076 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
2077 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2079 loadmodel->sortedmodelsurfaces[i] = i;
2080 surface = loadmodel->data_surfaces + i;
2081 surface->texture = loadmodel->data_textures + i;
2082 surface->num_firsttriangle = meshtriangles;
2083 surface->num_triangles = count;
2084 meshtriangles += surface->num_triangles;
2086 // load the elements
2087 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2088 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
2090 outelements[j*3+2] = BigLong(renderlist[0]);
2091 outelements[j*3+1] = BigLong(renderlist[1]);
2092 outelements[j*3+0] = BigLong(renderlist[2]);
2094 // validate the elements and find the used vertex range
2095 firstvertex = meshvertices;
2097 for (j = 0;j < surface->num_triangles * 3;j++)
2099 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
2100 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
2101 firstvertex = min(firstvertex, outelements[j]);
2102 lastvertex = max(lastvertex, outelements[j]);
2104 surface->num_firstvertex = firstvertex;
2105 surface->num_vertices = lastvertex + 1 - firstvertex;
2107 // since zym models do not have named sections, reuse their shader
2108 // name as the section name
2109 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
2110 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
2112 Mod_FreeSkinFiles(skinfiles);
2113 Mem_Free(vertbonecounts);
2115 Mod_MakeSortedSurfaces(loadmodel);
2117 // compute all the mesh information that was not loaded from the file
2118 if (loadmodel->surfmesh.data_element3s)
2119 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2120 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2121 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2122 Mod_BuildBaseBonePoses();
2123 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2124 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);
2125 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2127 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2129 if (!loadmodel->surfmesh.isanimated)
2131 Mod_MakeCollisionBIH(loadmodel, true);
2132 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2133 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2134 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2135 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2139 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2141 dpmheader_t *pheader;
2145 unsigned char *pbase;
2146 int i, j, k, meshvertices, meshtriangles;
2147 skinfile_t *skinfiles;
2148 unsigned char *data;
2150 float biggestorigin, tempvec[3], modelscale;
2154 pheader = (dpmheader_t *)buffer;
2155 pbase = (unsigned char *)buffer;
2156 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2157 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2158 if (BigLong(pheader->type) != 2)
2159 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2161 loadmodel->modeldatatypestring = "DPM";
2163 loadmodel->type = mod_alias;
2164 loadmodel->synctype = ST_RAND;
2167 pheader->type = BigLong(pheader->type);
2168 pheader->filesize = BigLong(pheader->filesize);
2169 pheader->mins[0] = BigFloat(pheader->mins[0]);
2170 pheader->mins[1] = BigFloat(pheader->mins[1]);
2171 pheader->mins[2] = BigFloat(pheader->mins[2]);
2172 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2173 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2174 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2175 pheader->yawradius = BigFloat(pheader->yawradius);
2176 pheader->allradius = BigFloat(pheader->allradius);
2177 pheader->num_bones = BigLong(pheader->num_bones);
2178 pheader->num_meshs = BigLong(pheader->num_meshs);
2179 pheader->num_frames = BigLong(pheader->num_frames);
2180 pheader->ofs_bones = BigLong(pheader->ofs_bones);
2181 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2182 pheader->ofs_frames = BigLong(pheader->ofs_frames);
2184 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2186 Con_Printf("%s has no geometry\n", loadmodel->name);
2189 if (pheader->num_frames < 1)
2191 Con_Printf("%s has no frames\n", loadmodel->name);
2195 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2196 loadmodel->DrawSky = NULL;
2197 loadmodel->DrawAddWaterPlanes = NULL;
2198 loadmodel->Draw = R_Q1BSP_Draw;
2199 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2200 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2201 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2202 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2203 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2204 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2205 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2206 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2207 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2208 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2209 loadmodel->PointSuperContents = NULL;
2212 for (i = 0;i < 3;i++)
2214 loadmodel->normalmins[i] = pheader->mins[i];
2215 loadmodel->normalmaxs[i] = pheader->maxs[i];
2216 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2217 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2218 loadmodel->rotatedmins[i] = -pheader->allradius;
2219 loadmodel->rotatedmaxs[i] = pheader->allradius;
2221 loadmodel->radius = pheader->allradius;
2222 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2224 // load external .skin files if present
2225 skinfiles = Mod_LoadSkinFiles();
2226 if (loadmodel->numskins < 1)
2227 loadmodel->numskins = 1;
2232 // gather combined statistics from the meshes
2233 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2234 for (i = 0;i < (int)pheader->num_meshs;i++)
2236 int numverts = BigLong(dpmmesh->num_verts);
2237 meshvertices += numverts;
2238 meshtriangles += BigLong(dpmmesh->num_tris);
2242 loadmodel->numframes = pheader->num_frames;
2243 loadmodel->num_bones = pheader->num_bones;
2244 loadmodel->num_poses = loadmodel->numframes;
2245 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2246 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2247 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2248 // do most allocations as one merged chunk
2249 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));
2250 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2251 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2252 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2253 loadmodel->surfmesh.num_vertices = meshvertices;
2254 loadmodel->surfmesh.num_triangles = meshtriangles;
2255 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2256 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2257 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2258 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2259 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2260 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2261 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2262 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2263 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2264 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2265 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2266 loadmodel->surfmesh.num_blends = 0;
2267 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2268 if (meshvertices <= 65536)
2269 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2270 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2271 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
2273 for (i = 0;i < loadmodel->numskins;i++)
2275 loadmodel->skinscenes[i].firstframe = i;
2276 loadmodel->skinscenes[i].framecount = 1;
2277 loadmodel->skinscenes[i].loop = true;
2278 loadmodel->skinscenes[i].framerate = 10;
2281 // load the bone info
2282 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2283 for (i = 0;i < loadmodel->num_bones;i++)
2285 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2286 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2287 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2288 if (loadmodel->data_bones[i].parent >= i)
2289 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2293 frames = (dpmframe_t *) (pbase + pheader->ofs_frames);
2294 // figure out scale of model from root bone, for compatibility with old dpmodel versions
2295 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2296 tempvec[0] = BigFloat(poses[0]);
2297 tempvec[1] = BigFloat(poses[1]);
2298 tempvec[2] = BigFloat(poses[2]);
2299 modelscale = VectorLength(tempvec);
2301 for (i = 0;i < loadmodel->numframes;i++)
2303 memcpy(loadmodel->animscenes[i].name, frames[i].name, sizeof(frames[i].name));
2304 loadmodel->animscenes[i].firstframe = i;
2305 loadmodel->animscenes[i].framecount = 1;
2306 loadmodel->animscenes[i].loop = true;
2307 loadmodel->animscenes[i].framerate = 10;
2308 // load the bone poses for this frame
2309 poses = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2310 for (j = 0;j < loadmodel->num_bones*12;j++)
2312 f = fabs(BigFloat(poses[j]));
2313 biggestorigin = max(biggestorigin, f);
2315 // stuff not processed here: mins, maxs, yawradius, allradius
2317 loadmodel->num_posescale = biggestorigin / 32767.0f;
2318 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2319 for (i = 0;i < loadmodel->numframes;i++)
2321 const float *frameposes = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2322 for (j = 0;j < loadmodel->num_bones;j++)
2325 matrix4x4_t posematrix;
2326 for (k = 0;k < 12;k++)
2327 pose[k] = BigFloat(frameposes[j*12+k]);
2328 // scale child bones to match the root scale
2329 if (loadmodel->data_bones[j].parent >= 0)
2331 pose[3] *= modelscale;
2332 pose[7] *= modelscale;
2333 pose[11] *= modelscale;
2335 // normalize rotation matrix
2336 VectorNormalize(pose + 0);
2337 VectorNormalize(pose + 4);
2338 VectorNormalize(pose + 8);
2339 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2340 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
2344 // load the meshes now
2345 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2348 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2349 // (converting from weight-blending skeletal animation to
2350 // deformation-based skeletal animation)
2351 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2352 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2353 for (i = 0;i < loadmodel->num_bones;i++)
2356 for (k = 0;k < 12;k++)
2357 m[k] = BigFloat(poses[i*12+k]);
2358 if (loadmodel->data_bones[i].parent >= 0)
2359 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2361 for (k = 0;k < 12;k++)
2362 bonepose[12*i+k] = m[k];
2364 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2366 const int *inelements;
2368 const float *intexcoord;
2369 msurface_t *surface;
2371 loadmodel->sortedmodelsurfaces[i] = i;
2372 surface = loadmodel->data_surfaces + i;
2373 surface->texture = loadmodel->data_textures + i;
2374 surface->num_firsttriangle = meshtriangles;
2375 surface->num_triangles = BigLong(dpmmesh->num_tris);
2376 surface->num_firstvertex = meshvertices;
2377 surface->num_vertices = BigLong(dpmmesh->num_verts);
2378 meshvertices += surface->num_vertices;
2379 meshtriangles += surface->num_triangles;
2381 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2382 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2383 for (j = 0;j < surface->num_triangles;j++)
2385 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2386 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2387 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2388 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2393 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2394 for (j = 0;j < surface->num_vertices*2;j++)
2395 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2397 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2398 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2400 int weightindex[4] = { 0, 0, 0, 0 };
2401 float weightinfluence[4] = { 0, 0, 0, 0 };
2403 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2404 data += sizeof(dpmvertex_t);
2405 for (k = 0;k < numweights;k++)
2407 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2408 int boneindex = BigLong(vert->bonenum);
2409 const float *m = bonepose + 12 * boneindex;
2410 float influence = BigFloat(vert->influence);
2411 float relativeorigin[3], relativenormal[3];
2412 relativeorigin[0] = BigFloat(vert->origin[0]);
2413 relativeorigin[1] = BigFloat(vert->origin[1]);
2414 relativeorigin[2] = BigFloat(vert->origin[2]);
2415 relativenormal[0] = BigFloat(vert->normal[0]);
2416 relativenormal[1] = BigFloat(vert->normal[1]);
2417 relativenormal[2] = BigFloat(vert->normal[2]);
2418 // blend the vertex bone weights into the base mesh
2419 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2420 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2421 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2422 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2423 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2424 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2427 // store the first (and often only) weight
2428 weightinfluence[0] = influence;
2429 weightindex[0] = boneindex;
2433 // sort the new weight into this vertex's weight table
2434 // (which only accepts up to 4 bones per vertex)
2435 for (l = 0;l < 4;l++)
2437 if (weightinfluence[l] < influence)
2439 // move weaker influence weights out of the way first
2441 for (l2 = 3;l2 > l;l2--)
2443 weightinfluence[l2] = weightinfluence[l2-1];
2444 weightindex[l2] = weightindex[l2-1];
2446 // store the new weight
2447 weightinfluence[l] = influence;
2448 weightindex[l] = boneindex;
2453 data += sizeof(dpmbonevert_t);
2455 loadmodel->surfmesh.blends[j] = Mod_Skeletal_AddBlend(loadmodel, weightindex, weightinfluence);
2458 // since dpm models do not have named sections, reuse their shader name as the section name
2459 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2461 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2463 if (loadmodel->surfmesh.num_blends < meshvertices)
2464 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2466 Mod_FreeSkinFiles(skinfiles);
2467 Mod_MakeSortedSurfaces(loadmodel);
2469 // compute all the mesh information that was not loaded from the file
2470 if (loadmodel->surfmesh.data_element3s)
2471 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2472 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2473 Mod_BuildBaseBonePoses();
2474 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);
2475 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2477 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2479 if (!loadmodel->surfmesh.isanimated)
2481 Mod_MakeCollisionBIH(loadmodel, true);
2482 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2483 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2484 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2485 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2489 // no idea why PSK/PSA files contain weird quaternions but they do...
2490 #define PSKQUATNEGATIONS
2491 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2493 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2494 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2495 fs_offset_t filesize;
2500 pskboneinfo_t *bones;
2501 pskrawweights_t *rawweights;
2502 //pskboneinfo_t *animbones;
2503 pskaniminfo_t *anims;
2504 pskanimkeys_t *animkeys;
2505 void *animfilebuffer, *animbuffer, *animbufferend;
2506 unsigned char *data;
2508 skinfile_t *skinfiles;
2509 char animname[MAX_QPATH];
2511 float biggestorigin;
2513 pchunk = (pskchunk_t *)buffer;
2514 if (strcmp(pchunk->id, "ACTRHEAD"))
2515 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2517 loadmodel->modeldatatypestring = "PSK";
2519 loadmodel->type = mod_alias;
2520 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2521 loadmodel->DrawSky = NULL;
2522 loadmodel->DrawAddWaterPlanes = NULL;
2523 loadmodel->Draw = R_Q1BSP_Draw;
2524 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2525 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2526 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2527 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2528 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2529 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2530 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2531 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2532 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2533 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2534 loadmodel->PointSuperContents = NULL;
2535 loadmodel->synctype = ST_RAND;
2537 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2538 strlcat(animname, ".psa", sizeof(animname));
2539 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2540 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2541 if (animbuffer == NULL)
2542 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2561 while (buffer < bufferend)
2563 pchunk = (pskchunk_t *)buffer;
2564 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2565 version = LittleLong(pchunk->version);
2566 recordsize = LittleLong(pchunk->recordsize);
2567 numrecords = LittleLong(pchunk->numrecords);
2568 if (developer_extra.integer)
2569 Con_DPrintf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2570 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2571 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);
2572 if (!strcmp(pchunk->id, "ACTRHEAD"))
2576 else if (!strcmp(pchunk->id, "PNTS0000"))
2579 if (recordsize != sizeof(*p))
2580 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2581 // byteswap in place and keep the pointer
2582 numpnts = numrecords;
2583 pnts = (pskpnts_t *)buffer;
2584 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2586 p->origin[0] = LittleFloat(p->origin[0]);
2587 p->origin[1] = LittleFloat(p->origin[1]);
2588 p->origin[2] = LittleFloat(p->origin[2]);
2592 else if (!strcmp(pchunk->id, "VTXW0000"))
2595 if (recordsize != sizeof(*p))
2596 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2597 // byteswap in place and keep the pointer
2598 numvtxw = numrecords;
2599 vtxw = (pskvtxw_t *)buffer;
2600 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2602 p->pntsindex = LittleShort(p->pntsindex);
2603 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2604 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2605 if (p->pntsindex >= numpnts)
2607 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2613 else if (!strcmp(pchunk->id, "FACE0000"))
2616 if (recordsize != sizeof(*p))
2617 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2618 // byteswap in place and keep the pointer
2619 numfaces = numrecords;
2620 faces = (pskface_t *)buffer;
2621 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2623 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2624 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2625 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2626 p->group = LittleLong(p->group);
2627 if (p->vtxwindex[0] >= numvtxw)
2629 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2630 p->vtxwindex[0] = 0;
2632 if (p->vtxwindex[1] >= numvtxw)
2634 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2635 p->vtxwindex[1] = 0;
2637 if (p->vtxwindex[2] >= numvtxw)
2639 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2640 p->vtxwindex[2] = 0;
2645 else if (!strcmp(pchunk->id, "MATT0000"))
2648 if (recordsize != sizeof(*p))
2649 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2650 // byteswap in place and keep the pointer
2651 nummatts = numrecords;
2652 matts = (pskmatt_t *)buffer;
2653 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2659 else if (!strcmp(pchunk->id, "REFSKELT"))
2662 if (recordsize != sizeof(*p))
2663 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2664 // byteswap in place and keep the pointer
2665 numbones = numrecords;
2666 bones = (pskboneinfo_t *)buffer;
2667 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2669 p->numchildren = LittleLong(p->numchildren);
2670 p->parent = LittleLong(p->parent);
2671 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2672 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2673 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2674 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2675 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2676 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2677 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2678 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2679 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2680 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2681 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2682 #ifdef PSKQUATNEGATIONS
2685 p->basepose.quat[0] *= -1;
2686 p->basepose.quat[1] *= -1;
2687 p->basepose.quat[2] *= -1;
2691 p->basepose.quat[0] *= 1;
2692 p->basepose.quat[1] *= -1;
2693 p->basepose.quat[2] *= 1;
2696 if (p->parent < 0 || p->parent >= numbones)
2698 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2704 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2707 if (recordsize != sizeof(*p))
2708 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2709 // byteswap in place and keep the pointer
2710 numrawweights = numrecords;
2711 rawweights = (pskrawweights_t *)buffer;
2712 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2714 p->weight = LittleFloat(p->weight);
2715 p->pntsindex = LittleLong(p->pntsindex);
2716 p->boneindex = LittleLong(p->boneindex);
2717 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2719 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2722 if (p->boneindex < 0 || p->boneindex >= numbones)
2724 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2732 while (animbuffer < animbufferend)
2734 pchunk = (pskchunk_t *)animbuffer;
2735 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2736 version = LittleLong(pchunk->version);
2737 recordsize = LittleLong(pchunk->recordsize);
2738 numrecords = LittleLong(pchunk->numrecords);
2739 if (developer_extra.integer)
2740 Con_DPrintf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2741 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2742 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);
2743 if (!strcmp(pchunk->id, "ANIMHEAD"))
2747 else if (!strcmp(pchunk->id, "BONENAMES"))
2750 if (recordsize != sizeof(*p))
2751 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2752 // byteswap in place and keep the pointer
2753 numanimbones = numrecords;
2754 //animbones = (pskboneinfo_t *)animbuffer;
2755 // NOTE: supposedly psa does not need to match the psk model, the
2756 // bones missing from the psa would simply use their base
2757 // positions from the psk, but this is hard for me to implement
2758 // and people can easily make animations that match.
2759 if (numanimbones != numbones)
2760 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2761 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2763 p->numchildren = LittleLong(p->numchildren);
2764 p->parent = LittleLong(p->parent);
2765 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2766 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2767 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2768 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2769 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2770 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2771 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2772 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2773 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2774 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2775 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2776 #ifdef PSKQUATNEGATIONS
2779 p->basepose.quat[0] *= -1;
2780 p->basepose.quat[1] *= -1;
2781 p->basepose.quat[2] *= -1;
2785 p->basepose.quat[0] *= 1;
2786 p->basepose.quat[1] *= -1;
2787 p->basepose.quat[2] *= 1;
2790 if (p->parent < 0 || p->parent >= numanimbones)
2792 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2795 // check that bones are the same as in the base
2796 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2797 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2801 else if (!strcmp(pchunk->id, "ANIMINFO"))
2804 if (recordsize != sizeof(*p))
2805 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2806 // byteswap in place and keep the pointer
2807 numanims = numrecords;
2808 anims = (pskaniminfo_t *)animbuffer;
2809 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2811 p->numbones = LittleLong(p->numbones);
2812 p->playtime = LittleFloat(p->playtime);
2813 p->fps = LittleFloat(p->fps);
2814 p->firstframe = LittleLong(p->firstframe);
2815 p->numframes = LittleLong(p->numframes);
2816 if (p->numbones != numbones)
2817 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2821 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2824 if (recordsize != sizeof(*p))
2825 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2826 numanimkeys = numrecords;
2827 animkeys = (pskanimkeys_t *)animbuffer;
2828 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2830 p->origin[0] = LittleFloat(p->origin[0]);
2831 p->origin[1] = LittleFloat(p->origin[1]);
2832 p->origin[2] = LittleFloat(p->origin[2]);
2833 p->quat[0] = LittleFloat(p->quat[0]);
2834 p->quat[1] = LittleFloat(p->quat[1]);
2835 p->quat[2] = LittleFloat(p->quat[2]);
2836 p->quat[3] = LittleFloat(p->quat[3]);
2837 p->frametime = LittleFloat(p->frametime);
2838 #ifdef PSKQUATNEGATIONS
2839 if (index % numbones)
2854 // TODO: allocate bonepose stuff
2857 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2860 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2861 Host_Error("%s: missing required chunks", loadmodel->name);
2863 loadmodel->numframes = 0;
2864 for (index = 0;index < numanims;index++)
2865 loadmodel->numframes += anims[index].numframes;
2867 if (numanimkeys != numbones * loadmodel->numframes)
2868 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2870 meshvertices = numvtxw;
2871 meshtriangles = numfaces;
2873 // load external .skin files if present
2874 skinfiles = Mod_LoadSkinFiles();
2875 if (loadmodel->numskins < 1)
2876 loadmodel->numskins = 1;
2877 loadmodel->num_bones = numbones;
2878 loadmodel->num_poses = loadmodel->numframes;
2879 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2880 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2881 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2882 loadmodel->surfmesh.num_vertices = meshvertices;
2883 loadmodel->surfmesh.num_triangles = meshtriangles;
2884 // do most allocations as one merged chunk
2885 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);
2886 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2887 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2888 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2889 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2890 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2891 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2892 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2893 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2894 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2895 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2896 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2897 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2898 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2899 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2900 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2901 loadmodel->surfmesh.num_blends = 0;
2902 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2903 if (loadmodel->surfmesh.num_vertices <= 65536)
2904 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2905 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2906 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(blendweights_t));
2908 for (i = 0;i < loadmodel->numskins;i++)
2910 loadmodel->skinscenes[i].firstframe = i;
2911 loadmodel->skinscenes[i].framecount = 1;
2912 loadmodel->skinscenes[i].loop = true;
2913 loadmodel->skinscenes[i].framerate = 10;
2917 for (index = 0, i = 0;index < nummatts;index++)
2919 // since psk models do not have named sections, reuse their shader name as the section name
2920 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2921 loadmodel->sortedmodelsurfaces[index] = index;
2922 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2923 loadmodel->data_surfaces[index].num_firstvertex = 0;
2924 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2927 // copy over the vertex locations and texcoords
2928 for (index = 0;index < numvtxw;index++)
2930 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2931 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2932 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2933 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2934 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2937 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2938 for (index = 0;index < numfaces;index++)
2939 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2940 for (index = 0, i = 0;index < nummatts;index++)
2942 loadmodel->data_surfaces[index].num_firsttriangle = i;
2943 i += loadmodel->data_surfaces[index].num_triangles;
2944 loadmodel->data_surfaces[index].num_triangles = 0;
2946 for (index = 0;index < numfaces;index++)
2948 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2949 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2950 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2951 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2954 // copy over the bones
2955 for (index = 0;index < numbones;index++)
2957 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2958 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2959 if (loadmodel->data_bones[index].parent >= index)
2960 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2963 // sort the psk point weights into the vertex weight tables
2964 // (which only accept up to 4 bones per vertex)
2965 for (index = 0;index < numvtxw;index++)
2967 int weightindex[4] = { 0, 0, 0, 0 };
2968 float weightinfluence[4] = { 0, 0, 0, 0 };
2970 for (j = 0;j < numrawweights;j++)
2972 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2974 int boneindex = rawweights[j].boneindex;
2975 float influence = rawweights[j].weight;
2976 for (l = 0;l < 4;l++)
2978 if (weightinfluence[l] < influence)
2980 // move lower influence weights out of the way first
2982 for (l2 = 3;l2 > l;l2--)
2984 weightinfluence[l2] = weightinfluence[l2-1];
2985 weightindex[l2] = weightindex[l2-1];
2987 // store the new weight
2988 weightinfluence[l] = influence;
2989 weightindex[l] = boneindex;
2995 loadmodel->surfmesh.blends[index] = Mod_Skeletal_AddBlend(loadmodel, weightindex, weightinfluence);
2997 if (loadmodel->surfmesh.num_blends < loadmodel->surfmesh.num_vertices)
2998 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
3000 // set up the animscenes based on the anims
3001 for (index = 0, i = 0;index < numanims;index++)
3003 for (j = 0;j < anims[index].numframes;j++, i++)
3005 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
3006 loadmodel->animscenes[i].firstframe = i;
3007 loadmodel->animscenes[i].framecount = 1;
3008 loadmodel->animscenes[i].loop = true;
3009 loadmodel->animscenes[i].framerate = 10;
3013 // calculate the scaling value for bone origins so they can be compressed to short
3015 for (index = 0;index < numanimkeys;index++)
3017 pskanimkeys_t *k = animkeys + index;
3018 biggestorigin = max(biggestorigin, fabs(k->origin[0]));
3019 biggestorigin = max(biggestorigin, fabs(k->origin[1]));
3020 biggestorigin = max(biggestorigin, fabs(k->origin[2]));
3022 loadmodel->num_posescale = biggestorigin / 32767.0f;
3023 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3025 // load the poses from the animkeys
3026 for (index = 0;index < numanimkeys;index++)
3028 pskanimkeys_t *k = animkeys + index;
3030 Vector4Copy(k->quat, quat);
3032 Vector4Negate(quat, quat);
3033 Vector4Normalize2(quat, quat);
3034 // compress poses to the short[6] format for longterm storage
3035 loadmodel->data_poses6s[index*6+0] = k->origin[0] * loadmodel->num_poseinvscale;
3036 loadmodel->data_poses6s[index*6+1] = k->origin[1] * loadmodel->num_poseinvscale;
3037 loadmodel->data_poses6s[index*6+2] = k->origin[2] * loadmodel->num_poseinvscale;
3038 loadmodel->data_poses6s[index*6+3] = quat[0] * 32767.0f;
3039 loadmodel->data_poses6s[index*6+4] = quat[1] * 32767.0f;
3040 loadmodel->data_poses6s[index*6+5] = quat[2] * 32767.0f;
3042 Mod_FreeSkinFiles(skinfiles);
3043 Mem_Free(animfilebuffer);
3044 Mod_MakeSortedSurfaces(loadmodel);
3046 // compute all the mesh information that was not loaded from the file
3047 // TODO: honor smoothing groups somehow?
3048 if (loadmodel->surfmesh.data_element3s)
3049 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3050 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3051 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
3052 Mod_BuildBaseBonePoses();
3053 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
3054 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);
3055 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3056 Mod_Alias_CalculateBoundingBox();
3058 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
3060 if (!loadmodel->surfmesh.isanimated)
3062 Mod_MakeCollisionBIH(loadmodel, true);
3063 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3064 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3065 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3066 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;