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 blendweights_t *newweights)
52 blendweights_t *weights;
53 if(!newweights->influence[1])
54 return newweights->index[0];
55 weights = model->surfmesh.data_blendweights;
56 for (i = 0;i < model->surfmesh.num_blends;i++, weights++)
58 if (!memcmp(weights, newweights, sizeof(blendweights_t)))
59 return model->num_bones + i;
61 model->surfmesh.num_blends++;
62 memcpy(weights, newweights, sizeof(blendweights_t));
63 return model->num_bones + i;
66 int Mod_Skeletal_CompressBlend(dp_model_t *model, const int *newindex, const float *newinfluence)
70 blendweights_t newweights;
75 scale += newinfluence[i];
76 scale = 255.0f / scale;
80 newweights.index[i] = newindex[i];
81 newweights.influence[i] = (unsigned char)(newinfluence[i] * scale);
82 total += newweights.influence[i];
88 if(newweights.influence[i] > 0 && total > 255)
90 newweights.influence[i]--;
97 for (i = 0; i < 4;i++)
99 if(newweights.influence[i] < 255 && total < 255)
101 newweights.influence[i]++;
106 return Mod_Skeletal_AddBlend(model, &newweights);
109 static int maxbonepose = 0;
110 static float (*bonepose)[12] = NULL;
112 void Mod_Skeletal_FreeBuffers(void)
120 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)
122 // vertex weighted skeletal
126 float (*boneposerelative)[12];
127 const blendweights_t * RESTRICT weights;
129 if (maxbonepose < model->num_bones*2 + model->surfmesh.num_blends)
133 maxbonepose = model->num_bones*2 + model->surfmesh.num_blends;
134 bonepose = (float (*)[12])Z_Malloc(maxbonepose * sizeof(float[12]));
137 boneposerelative = bonepose + model->num_bones;
139 if (skeleton && !skeleton->relativetransforms)
142 // interpolate matrices
145 for (i = 0;i < model->num_bones;i++)
147 Matrix4x4_ToArray12FloatD3D(&skeleton->relativetransforms[i], m);
148 if (model->data_bones[i].parent >= 0)
149 R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
151 memcpy(bonepose[i], m, sizeof(m));
153 // create a relative deformation matrix to describe displacement
154 // from the base mesh, which is used by the actual weighting
155 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]);
160 float originscale = model->num_posescale;
162 const short * RESTRICT pose6s;
163 for (i = 0;i < model->num_bones;i++)
165 memset(m, 0, sizeof(m));
166 for (blends = 0;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++)
168 pose6s = model->data_poses6s + 6 * (frameblend[blends].subframe * model->num_bones + i);
169 lerp = frameblend[blends].lerp;
170 x = pose6s[3] * (1.0f / 32767.0f);
171 y = pose6s[4] * (1.0f / 32767.0f);
172 z = pose6s[5] * (1.0f / 32767.0f);
173 w = 1.0f - (x*x+y*y+z*z);
174 w = w > 0.0f ? -sqrt(w) : 0.0f;
175 m[ 0] += (1-2*(y*y+z*z)) * lerp;
176 m[ 1] += ( 2*(x*y-z*w)) * lerp;
177 m[ 2] += ( 2*(x*z+y*w)) * lerp;
178 m[ 3] += (pose6s[0] * originscale) * lerp;
179 m[ 4] += ( 2*(x*y+z*w)) * lerp;
180 m[ 5] += (1-2*(x*x+z*z)) * lerp;
181 m[ 6] += ( 2*(y*z-x*w)) * lerp;
182 m[ 7] += (pose6s[1] * originscale) * lerp;
183 m[ 8] += ( 2*(x*z-y*w)) * lerp;
184 m[ 9] += ( 2*(y*z+x*w)) * lerp;
185 m[10] += (1-2*(x*x+y*y)) * lerp;
186 m[11] += (pose6s[2] * originscale) * lerp;
189 VectorNormalize(m + 4);
190 VectorNormalize(m + 8);
191 if (i == r_skeletal_debugbone.integer)
192 m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
193 m[3] *= r_skeletal_debugtranslatex.value;
194 m[7] *= r_skeletal_debugtranslatey.value;
195 m[11] *= r_skeletal_debugtranslatez.value;
196 if (model->data_bones[i].parent >= 0)
197 R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
199 memcpy(bonepose[i], m, sizeof(m));
200 // create a relative deformation matrix to describe displacement
201 // from the base mesh, which is used by the actual weighting
202 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]);
206 // generate matrices for all blend combinations
207 weights = model->surfmesh.data_blendweights;
208 for (i = 0;i < model->surfmesh.num_blends;i++, weights++)
210 float * RESTRICT b = boneposerelative[model->num_bones + i];
211 const float * RESTRICT m = boneposerelative[weights->index[0]];
212 float f = weights->influence[0] * (1.0f / 255.0f);
213 b[ 0] = f*m[ 0]; b[ 1] = f*m[ 1]; b[ 2] = f*m[ 2]; b[ 3] = f*m[ 3];
214 b[ 4] = f*m[ 4]; b[ 5] = f*m[ 5]; b[ 6] = f*m[ 6]; b[ 7] = f*m[ 7];
215 b[ 8] = f*m[ 8]; b[ 9] = f*m[ 9]; b[10] = f*m[10]; b[11] = f*m[11];
216 for (k = 1;k < 4 && weights->influence[k];k++)
218 m = boneposerelative[weights->index[k]];
219 f = weights->influence[k] * (1.0f / 255.0f);
220 b[ 0] += f*m[ 0]; b[ 1] += f*m[ 1]; b[ 2] += f*m[ 2]; b[ 3] += f*m[ 3];
221 b[ 4] += f*m[ 4]; b[ 5] += f*m[ 5]; b[ 6] += f*m[ 6]; b[ 7] += f*m[ 7];
222 b[ 8] += f*m[ 8]; b[ 9] += f*m[ 9]; b[10] += f*m[10]; b[11] += f*m[11];
226 // transform vertex attributes by blended matrices
229 const float * RESTRICT v = model->surfmesh.data_vertex3f;
230 const unsigned short * RESTRICT b = model->surfmesh.blends;
231 // special case common combinations of attributes to avoid repeated loading of matrices
234 const float * RESTRICT n = model->surfmesh.data_normal3f;
235 if (svector3f && tvector3f)
237 const float * RESTRICT sv = model->surfmesh.data_svector3f;
238 const float * RESTRICT tv = model->surfmesh.data_tvector3f;
239 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)
241 const float * RESTRICT m = boneposerelative[*b];
242 vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
243 vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
244 vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
245 normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
246 normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
247 normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
248 svector3f[0] = (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
249 svector3f[1] = (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
250 svector3f[2] = (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
251 tvector3f[0] = (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
252 tvector3f[1] = (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
253 tvector3f[2] = (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
257 for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, n += 3, b++, vertex3f += 3, normal3f += 3)
259 const float * RESTRICT m = boneposerelative[*b];
260 vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
261 vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
262 vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
263 normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
264 normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
265 normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
270 for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, b++, vertex3f += 3)
272 const float * RESTRICT m = boneposerelative[*b];
273 vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
274 vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
275 vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
281 const float * RESTRICT n = model->surfmesh.data_normal3f;
282 const unsigned short * RESTRICT b = model->surfmesh.blends;
283 for (i = 0;i < model->surfmesh.num_vertices;i++, n += 3, b++, normal3f += 3)
285 const float * RESTRICT m = boneposerelative[*b];
286 normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
287 normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
288 normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
294 const float * RESTRICT sv = model->surfmesh.data_svector3f;
295 const unsigned short * RESTRICT b = model->surfmesh.blends;
296 for (i = 0;i < model->surfmesh.num_vertices;i++, sv += 3, b++, svector3f += 3)
298 const float * RESTRICT m = boneposerelative[*b];
299 svector3f[0] = (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
300 svector3f[1] = (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
301 svector3f[2] = (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
307 const float * RESTRICT tv = model->surfmesh.data_tvector3f;
308 const unsigned short * RESTRICT b = model->surfmesh.blends;
309 for (i = 0;i < model->surfmesh.num_vertices;i++, tv += 3, b++, tvector3f += 3)
311 const float * RESTRICT m = boneposerelative[*b];
312 tvector3f[0] = (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
313 tvector3f[1] = (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
314 tvector3f[2] = (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
319 void Mod_MD3_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)
322 int i, numblends, blendnum;
323 int numverts = model->surfmesh.num_vertices;
325 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
327 //VectorMA(translate, model->surfmesh.num_morphmdlframetranslate, frameblend[blendnum].lerp, translate);
328 if (frameblend[blendnum].lerp > 0)
329 numblends = blendnum + 1;
331 // special case for the first blend because it avoids some adds and the need to memset the arrays first
332 for (blendnum = 0;blendnum < numblends;blendnum++)
334 const md3vertex_t *verts = model->surfmesh.data_morphmd3vertex + numverts * frameblend[blendnum].subframe;
337 float scale = frameblend[blendnum].lerp * (1.0f / 64.0f);
340 for (i = 0;i < numverts;i++)
342 vertex3f[i * 3 + 0] = verts[i].origin[0] * scale;
343 vertex3f[i * 3 + 1] = verts[i].origin[1] * scale;
344 vertex3f[i * 3 + 2] = verts[i].origin[2] * scale;
349 for (i = 0;i < numverts;i++)
351 vertex3f[i * 3 + 0] += verts[i].origin[0] * scale;
352 vertex3f[i * 3 + 1] += verts[i].origin[1] * scale;
353 vertex3f[i * 3 + 2] += verts[i].origin[2] * scale;
357 // the yaw and pitch stored in md3 models are 8bit quantized angles
358 // (0-255), and as such a lookup table is very well suited to
359 // decoding them, and since cosine is equivilant to sine with an
360 // extra 45 degree rotation, this uses one lookup table for both
361 // sine and cosine with a +64 bias to get cosine.
364 float lerp = frameblend[blendnum].lerp;
367 for (i = 0;i < numverts;i++)
369 normal3f[i * 3 + 0] = mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
370 normal3f[i * 3 + 1] = mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
371 normal3f[i * 3 + 2] = mod_md3_sin[verts[i].pitch + 64] * lerp;
376 for (i = 0;i < numverts;i++)
378 normal3f[i * 3 + 0] += mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
379 normal3f[i * 3 + 1] += mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
380 normal3f[i * 3 + 2] += mod_md3_sin[verts[i].pitch + 64] * lerp;
386 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
387 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
390 for (i = 0;i < numverts;i++, texvecvert++)
392 VectorScale(texvecvert->svec, f, svector3f + i*3);
393 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
398 for (i = 0;i < numverts;i++, texvecvert++)
400 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
401 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
408 void Mod_MDL_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)
411 int i, numblends, blendnum;
412 int numverts = model->surfmesh.num_vertices;
414 VectorClear(translate);
416 // blend the frame translates to avoid redundantly doing so on each vertex
417 // (a bit of a brain twister but it works)
418 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
420 if (model->surfmesh.data_morphmd2framesize6f)
421 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6 + 3, translate);
423 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.num_morphmdlframetranslate, translate);
424 if (frameblend[blendnum].lerp > 0)
425 numblends = blendnum + 1;
427 // special case for the first blend because it avoids some adds and the need to memset the arrays first
428 for (blendnum = 0;blendnum < numblends;blendnum++)
430 const trivertx_t *verts = model->surfmesh.data_morphmdlvertex + numverts * frameblend[blendnum].subframe;
434 if (model->surfmesh.data_morphmd2framesize6f)
435 VectorScale(model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6, frameblend[blendnum].lerp, scale);
437 VectorScale(model->surfmesh.num_morphmdlframescale, frameblend[blendnum].lerp, scale);
440 for (i = 0;i < numverts;i++)
442 vertex3f[i * 3 + 0] = translate[0] + verts[i].v[0] * scale[0];
443 vertex3f[i * 3 + 1] = translate[1] + verts[i].v[1] * scale[1];
444 vertex3f[i * 3 + 2] = translate[2] + verts[i].v[2] * scale[2];
449 for (i = 0;i < numverts;i++)
451 vertex3f[i * 3 + 0] += verts[i].v[0] * scale[0];
452 vertex3f[i * 3 + 1] += verts[i].v[1] * scale[1];
453 vertex3f[i * 3 + 2] += verts[i].v[2] * scale[2];
457 // the vertex normals in mdl models are an index into a table of
458 // 162 unique values, this very crude quantization reduces the
459 // vertex normal to only one byte, which saves a lot of space but
460 // also makes lighting pretty coarse
463 float lerp = frameblend[blendnum].lerp;
466 for (i = 0;i < numverts;i++)
468 const float *vn = m_bytenormals[verts[i].lightnormalindex];
469 VectorScale(vn, lerp, normal3f + i*3);
474 for (i = 0;i < numverts;i++)
476 const float *vn = m_bytenormals[verts[i].lightnormalindex];
477 VectorMA(normal3f + i*3, lerp, vn, normal3f + i*3);
483 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
484 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
487 for (i = 0;i < numverts;i++, texvecvert++)
489 VectorScale(texvecvert->svec, f, svector3f + i*3);
490 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
495 for (i = 0;i < numverts;i++, texvecvert++)
497 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
498 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
505 int Mod_Alias_GetTagMatrix(const dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, int tagindex, matrix4x4_t *outmatrix)
508 matrix4x4_t parentbonematrix;
509 matrix4x4_t tempbonematrix;
510 matrix4x4_t bonematrix;
511 matrix4x4_t blendmatrix;
518 *outmatrix = identitymatrix;
519 if (skeleton && skeleton->relativetransforms)
521 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
523 *outmatrix = skeleton->relativetransforms[tagindex];
524 while ((tagindex = model->data_bones[tagindex].parent) >= 0)
527 Matrix4x4_Concat(outmatrix, &skeleton->relativetransforms[tagindex], &temp);
530 else if (model->num_bones)
532 if (tagindex < 0 || tagindex >= model->num_bones)
534 Matrix4x4_Clear(&blendmatrix);
535 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
537 lerp = frameblend[blendindex].lerp;
538 Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
539 parenttagindex = tagindex;
540 while ((parenttagindex = model->data_bones[parenttagindex].parent) >= 0)
542 Matrix4x4_FromBonePose6s(&parentbonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + parenttagindex));
543 tempbonematrix = bonematrix;
544 Matrix4x4_Concat(&bonematrix, &parentbonematrix, &tempbonematrix);
546 Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
548 *outmatrix = blendmatrix;
550 else if (model->num_tags)
552 if (tagindex < 0 || tagindex >= model->num_tags)
554 for (k = 0;k < 12;k++)
556 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
558 lerp = frameblend[blendindex].lerp;
559 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
560 for (k = 0;k < 12;k++)
561 blendtag[k] += input[k] * lerp;
563 Matrix4x4_FromArray12FloatGL(outmatrix, blendtag);
566 if(!mod_alias_supporttagscale.integer)
567 Matrix4x4_Normalize3(outmatrix, outmatrix);
572 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)
577 matrix4x4_t bonematrix;
578 matrix4x4_t blendmatrix;
582 if (skeleton && skeleton->relativetransforms)
584 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
586 *parentindex = skeleton->model->data_bones[tagindex].parent;
587 *tagname = skeleton->model->data_bones[tagindex].name;
588 *tag_localmatrix = skeleton->relativetransforms[tagindex];
591 else if (model->num_bones)
593 if (tagindex < 0 || tagindex >= model->num_bones)
595 *parentindex = model->data_bones[tagindex].parent;
596 *tagname = model->data_bones[tagindex].name;
597 Matrix4x4_Clear(&blendmatrix);
598 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
600 lerp = frameblend[blendindex].lerp;
601 Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
602 Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
604 *tag_localmatrix = blendmatrix;
607 else if (model->num_tags)
609 if (tagindex < 0 || tagindex >= model->num_tags)
612 *tagname = model->data_tags[tagindex].name;
613 for (k = 0;k < 12;k++)
615 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
617 lerp = frameblend[blendindex].lerp;
618 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
619 for (k = 0;k < 12;k++)
620 blendtag[k] += input[k] * lerp;
622 Matrix4x4_FromArray12FloatGL(tag_localmatrix, blendtag);
629 int Mod_Alias_GetTagIndexForName(const dp_model_t *model, unsigned int skin, const char *tagname)
632 if(skin >= (unsigned int)model->numskins)
634 if (model->num_bones)
635 for (i = 0;i < model->num_bones;i++)
636 if (!strcasecmp(tagname, model->data_bones[i].name))
639 for (i = 0;i < model->num_tags;i++)
640 if (!strcasecmp(tagname, model->data_tags[i].name))
645 static void Mod_BuildBaseBonePoses(void)
648 matrix4x4_t *basebonepose;
649 float *outinvmatrix = loadmodel->data_baseboneposeinverse;
650 matrix4x4_t bonematrix;
651 matrix4x4_t tempbonematrix;
652 if (!loadmodel->num_bones)
654 basebonepose = (matrix4x4_t *)Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(matrix4x4_t));
655 for (boneindex = 0;boneindex < loadmodel->num_bones;boneindex++)
657 Matrix4x4_FromBonePose6s(&bonematrix, loadmodel->num_posescale, loadmodel->data_poses6s + 6 * boneindex);
658 if (loadmodel->data_bones[boneindex].parent >= 0)
660 tempbonematrix = bonematrix;
661 Matrix4x4_Concat(&bonematrix, basebonepose + loadmodel->data_bones[boneindex].parent, &tempbonematrix);
663 basebonepose[boneindex] = bonematrix;
664 Matrix4x4_Invert_Simple(&tempbonematrix, basebonepose + boneindex);
665 Matrix4x4_ToArray12FloatD3D(&tempbonematrix, outinvmatrix + 12*boneindex);
667 Mem_Free(basebonepose);
670 static void Mod_Alias_CalculateBoundingBox(void)
673 qboolean firstvertex = true;
674 float dist, yawradius, radius;
677 frameblend_t frameblend[MAX_FRAMEBLENDS];
678 memset(frameblend, 0, sizeof(frameblend));
679 frameblend[0].lerp = 1;
680 vertex3f = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
681 VectorClear(loadmodel->normalmins);
682 VectorClear(loadmodel->normalmaxs);
685 for (frameblend[0].subframe = 0;frameblend[0].subframe < loadmodel->num_poses;frameblend[0].subframe++)
687 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, vertex3f, NULL, NULL, NULL);
688 for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
693 VectorCopy(v, loadmodel->normalmins);
694 VectorCopy(v, loadmodel->normalmaxs);
698 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
699 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
700 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
701 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
702 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
703 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
705 dist = v[0] * v[0] + v[1] * v[1];
706 if (yawradius < dist)
715 radius = sqrt(radius);
716 yawradius = sqrt(yawradius);
717 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
718 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
719 loadmodel->yawmins[2] = loadmodel->normalmins[2];
720 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
721 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
722 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
723 loadmodel->radius = radius;
724 loadmodel->radius2 = radius * radius;
727 static void Mod_Alias_MorphMesh_CompileFrames(void)
730 frameblend_t frameblend[MAX_FRAMEBLENDS];
731 unsigned char *datapointer;
732 memset(frameblend, 0, sizeof(frameblend));
733 frameblend[0].lerp = 1;
734 datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
735 loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
736 loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
737 loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
738 loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
739 loadmodel->surfmesh.data_morphtexvecvertex = (texvecvertex_t *)datapointer;datapointer += loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices * sizeof(texvecvertex_t);
740 // 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)
741 for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
743 frameblend[0].subframe = i;
744 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
745 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);
746 // encode the svector and tvector in 3 byte format for permanent storage
747 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
749 VectorScaleCast(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
750 VectorScaleCast(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
755 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)
758 float segmentmins[3], segmentmaxs[3];
760 static int maxvertices = 0;
761 static float *vertex3f = NULL;
762 memset(trace, 0, sizeof(*trace));
764 trace->realfraction = 1;
765 trace->hitsupercontentsmask = hitsupercontentsmask;
766 if (maxvertices < model->surfmesh.num_vertices)
770 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
771 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
773 segmentmins[0] = min(start[0], end[0]) - 1;
774 segmentmins[1] = min(start[1], end[1]) - 1;
775 segmentmins[2] = min(start[2], end[2]) - 1;
776 segmentmaxs[0] = max(start[0], end[0]) + 1;
777 segmentmaxs[1] = max(start[1], end[1]) + 1;
778 segmentmaxs[2] = max(start[2], end[2]) + 1;
779 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
780 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
781 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);
784 static int maxvertices = 0;
785 static float *vertex3f = NULL;
787 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)
790 vec3_t shiftstart, shiftend;
791 float segmentmins[3], segmentmaxs[3];
793 colboxbrushf_t thisbrush_start, thisbrush_end;
794 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
796 if (VectorCompare(boxmins, boxmaxs))
798 VectorAdd(start, boxmins, shiftstart);
799 VectorAdd(end, boxmins, shiftend);
800 Mod_MDLMD2MD3_TraceLine(model, frameblend, skeleton, trace, shiftstart, shiftend, hitsupercontentsmask);
801 VectorSubtract(trace->endpos, boxmins, trace->endpos);
805 // box trace, performed as brush trace
806 memset(trace, 0, sizeof(*trace));
808 trace->realfraction = 1;
809 trace->hitsupercontentsmask = hitsupercontentsmask;
810 if (maxvertices < model->surfmesh.num_vertices)
814 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
815 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
817 segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
818 segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
819 segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
820 segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
821 segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
822 segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
823 VectorAdd(start, boxmins, boxstartmins);
824 VectorAdd(start, boxmaxs, boxstartmaxs);
825 VectorAdd(end, boxmins, boxendmins);
826 VectorAdd(end, boxmaxs, boxendmaxs);
827 Collision_BrushForBox(&thisbrush_start, boxstartmins, boxstartmaxs, 0, 0, NULL);
828 Collision_BrushForBox(&thisbrush_end, boxendmins, boxendmaxs, 0, 0, NULL);
829 if (maxvertices < model->surfmesh.num_vertices)
833 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
834 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
836 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
837 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
838 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);
841 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
844 for (i = 0;i < inverts;i++)
846 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
848 j = vertremap[i]; // not onseam
851 j = vertremap[i+inverts]; // onseam
857 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
859 int i, f, pose, groupframes;
861 daliasframetype_t *pframetype;
862 daliasframe_t *pinframe;
863 daliasgroup_t *group;
864 daliasinterval_t *intervals;
867 scene = loadmodel->animscenes;
868 for (f = 0;f < loadmodel->numframes;f++)
870 pframetype = (daliasframetype_t *)datapointer;
871 datapointer += sizeof(daliasframetype_t);
872 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
874 // a single frame is still treated as a group
881 group = (daliasgroup_t *)datapointer;
882 datapointer += sizeof(daliasgroup_t);
883 groupframes = LittleLong (group->numframes);
885 // intervals (time per frame)
886 intervals = (daliasinterval_t *)datapointer;
887 datapointer += sizeof(daliasinterval_t) * groupframes;
889 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
890 if (interval < 0.01f)
892 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
897 // get scene name from first frame
898 pinframe = (daliasframe_t *)datapointer;
900 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
901 scene->firstframe = pose;
902 scene->framecount = groupframes;
903 scene->framerate = 1.0f / interval;
908 for (i = 0;i < groupframes;i++)
910 pinframe = (daliasframe_t *)datapointer;
911 datapointer += sizeof(daliasframe_t);
912 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
913 datapointer += sizeof(trivertx_t) * inverts;
919 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
921 if (cls.state == ca_dedicated)
925 skinframe = R_SkinFrame_LoadMissing();
926 memset(texture, 0, sizeof(*texture));
927 texture->currentframe = texture;
928 //texture->animated = false;
929 texture->numskinframes = 1;
930 texture->skinframerate = 1;
931 texture->skinframes[0] = skinframe;
932 texture->currentskinframe = skinframe;
933 //texture->backgroundnumskinframes = 0;
934 //texture->customblendfunc[0] = 0;
935 //texture->customblendfunc[1] = 0;
936 //texture->surfaceflags = 0;
937 //texture->supercontents = 0;
938 //texture->surfaceparms = 0;
939 //texture->textureflags = 0;
941 texture->basematerialflags = MATERIALFLAG_WALL;
942 if (texture->currentskinframe->hasalpha)
943 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
944 texture->currentmaterialflags = texture->basematerialflags;
945 texture->offsetmapping = OFFSETMAPPING_OFF;
946 texture->offsetscale = 1;
947 texture->specularscalemod = 1;
948 texture->specularpowermod = 1;
949 texture->surfaceflags = 0;
950 texture->supercontents = SUPERCONTENTS_SOLID;
951 if (!(texture->basematerialflags & MATERIALFLAG_BLENDED))
952 texture->supercontents |= SUPERCONTENTS_OPAQUE;
955 void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
958 static char stripbuf[MAX_QPATH];
959 skinfileitem_t *skinfileitem;
962 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
963 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
965 memset(skin, 0, sizeof(*skin));
967 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
969 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
970 if (!strcmp(skinfileitem->name, meshname))
972 Image_StripImageExtension(skinfileitem->replacement, stripbuf, sizeof(stripbuf));
973 Mod_LoadTextureFromQ3Shader(skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
979 // don't render unmentioned meshes
980 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
981 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
987 Image_StripImageExtension(shadername, stripbuf, sizeof(stripbuf));
988 Mod_LoadTextureFromQ3Shader(skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
992 #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);
993 #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);
994 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
996 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
997 float scales, scalet, interval;
1001 stvert_t *pinstverts;
1002 dtriangle_t *pintriangles;
1003 daliasskintype_t *pinskintype;
1004 daliasskingroup_t *pinskingroup;
1005 daliasskininterval_t *pinskinintervals;
1006 daliasframetype_t *pinframetype;
1007 daliasgroup_t *pinframegroup;
1008 unsigned char *datapointer, *startframes, *startskins;
1009 char name[MAX_QPATH];
1010 skinframe_t *tempskinframe;
1011 animscene_t *tempskinscenes;
1012 texture_t *tempaliasskins;
1014 int *vertonseam, *vertremap;
1015 skinfile_t *skinfiles;
1017 datapointer = (unsigned char *)buffer;
1018 pinmodel = (mdl_t *)datapointer;
1019 datapointer += sizeof(mdl_t);
1021 version = LittleLong (pinmodel->version);
1022 if (version != ALIAS_VERSION)
1023 Host_Error ("%s has wrong version number (%i should be %i)",
1024 loadmodel->name, version, ALIAS_VERSION);
1026 loadmodel->modeldatatypestring = "MDL";
1028 loadmodel->type = mod_alias;
1029 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1030 loadmodel->DrawSky = NULL;
1031 loadmodel->DrawAddWaterPlanes = NULL;
1032 loadmodel->Draw = R_Q1BSP_Draw;
1033 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1034 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1035 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1036 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1037 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1038 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1039 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1040 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1041 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1042 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1043 loadmodel->PointSuperContents = NULL;
1045 loadmodel->num_surfaces = 1;
1046 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1047 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
1048 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1049 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1050 loadmodel->sortedmodelsurfaces[0] = 0;
1052 loadmodel->numskins = LittleLong(pinmodel->numskins);
1053 BOUNDI(loadmodel->numskins,0,65536);
1054 skinwidth = LittleLong (pinmodel->skinwidth);
1055 BOUNDI(skinwidth,0,65536);
1056 skinheight = LittleLong (pinmodel->skinheight);
1057 BOUNDI(skinheight,0,65536);
1058 numverts = LittleLong(pinmodel->numverts);
1059 BOUNDI(numverts,0,65536);
1060 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
1061 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
1062 loadmodel->numframes = LittleLong(pinmodel->numframes);
1063 BOUNDI(loadmodel->numframes,0,65536);
1064 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
1065 BOUNDI((int)loadmodel->synctype,0,2);
1066 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1067 i = LittleLong (pinmodel->flags);
1068 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1070 for (i = 0;i < 3;i++)
1072 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
1073 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
1076 startskins = datapointer;
1078 for (i = 0;i < loadmodel->numskins;i++)
1080 pinskintype = (daliasskintype_t *)datapointer;
1081 datapointer += sizeof(daliasskintype_t);
1082 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
1086 pinskingroup = (daliasskingroup_t *)datapointer;
1087 datapointer += sizeof(daliasskingroup_t);
1088 groupskins = LittleLong(pinskingroup->numskins);
1089 datapointer += sizeof(daliasskininterval_t) * groupskins;
1092 for (j = 0;j < groupskins;j++)
1094 datapointer += skinwidth * skinheight;
1099 pinstverts = (stvert_t *)datapointer;
1100 datapointer += sizeof(stvert_t) * numverts;
1102 pintriangles = (dtriangle_t *)datapointer;
1103 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
1105 startframes = datapointer;
1106 loadmodel->surfmesh.num_morphframes = 0;
1107 for (i = 0;i < loadmodel->numframes;i++)
1109 pinframetype = (daliasframetype_t *)datapointer;
1110 datapointer += sizeof(daliasframetype_t);
1111 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
1115 pinframegroup = (daliasgroup_t *)datapointer;
1116 datapointer += sizeof(daliasgroup_t);
1117 groupframes = LittleLong(pinframegroup->numframes);
1118 datapointer += sizeof(daliasinterval_t) * groupframes;
1121 for (j = 0;j < groupframes;j++)
1123 datapointer += sizeof(daliasframe_t);
1124 datapointer += sizeof(trivertx_t) * numverts;
1125 loadmodel->surfmesh.num_morphframes++;
1128 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1130 // store texture coordinates into temporary array, they will be stored
1131 // after usage is determined (triangle data)
1132 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
1133 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
1134 vertonseam = vertremap + numverts * 2;
1136 scales = 1.0 / skinwidth;
1137 scalet = 1.0 / skinheight;
1138 for (i = 0;i < numverts;i++)
1140 vertonseam[i] = LittleLong(pinstverts[i].onseam);
1141 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
1142 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
1143 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
1144 vertst[(i+numverts)*2+1] = vertst[i*2+1];
1147 // load triangle data
1148 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1150 // read the triangle elements
1151 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1152 for (j = 0;j < 3;j++)
1153 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1154 // validate (note numverts is used because this is the original data)
1155 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1156 // now butcher the elements according to vertonseam and tri->facesfront
1157 // and then compact the vertex set to remove duplicates
1158 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1159 if (!LittleLong(pintriangles[i].facesfront)) // backface
1160 for (j = 0;j < 3;j++)
1161 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1162 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1164 // (this uses vertremap to count usage to save some memory)
1165 for (i = 0;i < numverts*2;i++)
1167 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1168 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1169 // build remapping table and compact array
1170 loadmodel->surfmesh.num_vertices = 0;
1171 for (i = 0;i < numverts*2;i++)
1175 vertremap[i] = loadmodel->surfmesh.num_vertices;
1176 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1177 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1178 loadmodel->surfmesh.num_vertices++;
1181 vertremap[i] = -1; // not used at all
1183 // remap the elements to the new vertex set
1184 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1185 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1186 // store the texture coordinates
1187 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1188 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1190 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1191 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1194 // generate ushort elements array if possible
1195 if (loadmodel->surfmesh.num_vertices <= 65536)
1196 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1197 if (loadmodel->surfmesh.data_element3s)
1198 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1199 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1202 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1203 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1204 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1205 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1206 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1207 Mod_Alias_CalculateBoundingBox();
1208 Mod_Alias_MorphMesh_CompileFrames();
1211 Mem_Free(vertremap);
1214 skinfiles = Mod_LoadSkinFiles();
1217 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1218 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1219 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1220 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1221 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1222 Mod_FreeSkinFiles(skinfiles);
1223 for (i = 0;i < loadmodel->numskins;i++)
1225 loadmodel->skinscenes[i].firstframe = i;
1226 loadmodel->skinscenes[i].framecount = 1;
1227 loadmodel->skinscenes[i].loop = true;
1228 loadmodel->skinscenes[i].framerate = 10;
1233 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1234 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1235 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1236 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1238 datapointer = startskins;
1239 for (i = 0;i < loadmodel->numskins;i++)
1241 pinskintype = (daliasskintype_t *)datapointer;
1242 datapointer += sizeof(daliasskintype_t);
1244 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1251 pinskingroup = (daliasskingroup_t *)datapointer;
1252 datapointer += sizeof(daliasskingroup_t);
1254 groupskins = LittleLong (pinskingroup->numskins);
1256 pinskinintervals = (daliasskininterval_t *)datapointer;
1257 datapointer += sizeof(daliasskininterval_t) * groupskins;
1259 interval = LittleFloat(pinskinintervals[0].interval);
1260 if (interval < 0.01f)
1262 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1267 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1268 loadmodel->skinscenes[i].firstframe = totalskins;
1269 loadmodel->skinscenes[i].framecount = groupskins;
1270 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1271 loadmodel->skinscenes[i].loop = true;
1273 for (j = 0;j < groupskins;j++)
1276 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1278 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1279 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))
1280 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));
1281 datapointer += skinwidth * skinheight;
1285 // check for skins that don't exist in the model, but do exist as external images
1286 // (this was added because yummyluv kept pestering me about support for it)
1287 // TODO: support shaders here?
1288 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)))
1290 // expand the arrays to make room
1291 tempskinscenes = loadmodel->skinscenes;
1292 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1293 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1294 Mem_Free(tempskinscenes);
1296 tempaliasskins = loadmodel->data_textures;
1297 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1298 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1299 Mem_Free(tempaliasskins);
1301 // store the info about the new skin
1302 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1303 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1304 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1305 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1306 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1307 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1309 //increase skin counts
1310 loadmodel->numskins++;
1313 // fix up the pointers since they are pointing at the old textures array
1314 // FIXME: this is a hack!
1315 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1316 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1320 surface = loadmodel->data_surfaces;
1321 surface->texture = loadmodel->data_textures;
1322 surface->num_firsttriangle = 0;
1323 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1324 surface->num_firstvertex = 0;
1325 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1327 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1329 if (!loadmodel->surfmesh.isanimated)
1331 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1332 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1333 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1334 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1335 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1339 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1341 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1342 float iskinwidth, iskinheight;
1343 unsigned char *data;
1344 msurface_t *surface;
1346 unsigned char *base, *datapointer;
1347 md2frame_t *pinframe;
1349 md2triangle_t *intri;
1350 unsigned short *inst;
1351 struct md2verthash_s
1353 struct md2verthash_s *next;
1357 *hash, **md2verthash, *md2verthashdata;
1358 skinfile_t *skinfiles;
1360 pinmodel = (md2_t *)buffer;
1361 base = (unsigned char *)buffer;
1363 version = LittleLong (pinmodel->version);
1364 if (version != MD2ALIAS_VERSION)
1365 Host_Error ("%s has wrong version number (%i should be %i)",
1366 loadmodel->name, version, MD2ALIAS_VERSION);
1368 loadmodel->modeldatatypestring = "MD2";
1370 loadmodel->type = mod_alias;
1371 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1372 loadmodel->DrawSky = NULL;
1373 loadmodel->DrawAddWaterPlanes = NULL;
1374 loadmodel->Draw = R_Q1BSP_Draw;
1375 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1376 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1377 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1378 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1379 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1380 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1381 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1382 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1383 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1384 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1385 loadmodel->PointSuperContents = NULL;
1387 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1388 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1389 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1390 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1391 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1392 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1393 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1394 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1396 end = LittleLong(pinmodel->ofs_end);
1397 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1398 Host_Error ("%s is not a valid model", loadmodel->name);
1399 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1400 Host_Error ("%s is not a valid model", loadmodel->name);
1401 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1402 Host_Error ("%s is not a valid model", loadmodel->name);
1403 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1404 Host_Error ("%s is not a valid model", loadmodel->name);
1405 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1406 Host_Error ("%s is not a valid model", loadmodel->name);
1408 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1409 numxyz = LittleLong(pinmodel->num_xyz);
1410 numst = LittleLong(pinmodel->num_st);
1411 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1412 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1413 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1414 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1415 skinwidth = LittleLong(pinmodel->skinwidth);
1416 skinheight = LittleLong(pinmodel->skinheight);
1417 iskinwidth = 1.0f / skinwidth;
1418 iskinheight = 1.0f / skinheight;
1420 loadmodel->num_surfaces = 1;
1421 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1422 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]));
1423 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1424 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1425 loadmodel->sortedmodelsurfaces[0] = 0;
1426 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1427 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1428 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1429 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1431 loadmodel->synctype = ST_RAND;
1434 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1435 skinfiles = Mod_LoadSkinFiles();
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 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1442 Mod_FreeSkinFiles(skinfiles);
1444 else if (loadmodel->numskins)
1446 // skins found (most likely not a player model)
1447 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1448 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1449 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1450 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1451 Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
1455 // no skins (most likely a player model)
1456 loadmodel->numskins = 1;
1457 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1458 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1459 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1460 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1463 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1464 for (i = 0;i < loadmodel->numskins;i++)
1466 loadmodel->skinscenes[i].firstframe = i;
1467 loadmodel->skinscenes[i].framecount = 1;
1468 loadmodel->skinscenes[i].loop = true;
1469 loadmodel->skinscenes[i].framerate = 10;
1472 // load the triangles and stvert data
1473 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1474 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1475 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1476 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1477 // swap the triangle list
1478 loadmodel->surfmesh.num_vertices = 0;
1479 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1481 for (j = 0;j < 3;j++)
1483 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1484 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1487 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1492 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1495 hashindex = (xyz * 256 + st) & 65535;
1496 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1497 if (hash->xyz == xyz && hash->st == st)
1501 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1504 hash->next = md2verthash[hashindex];
1505 md2verthash[hashindex] = hash;
1507 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1511 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1512 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));
1513 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1514 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1515 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1518 hash = md2verthashdata + i;
1519 vertremap[i] = hash->xyz;
1520 sts = LittleShort(inst[hash->st*2+0]);
1521 stt = LittleShort(inst[hash->st*2+1]);
1522 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1524 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1528 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1529 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1532 Mem_Free(md2verthash);
1533 Mem_Free(md2verthashdata);
1535 // generate ushort elements array if possible
1536 if (loadmodel->surfmesh.num_vertices <= 65536)
1537 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1538 if (loadmodel->surfmesh.data_element3s)
1539 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1540 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1543 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1544 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1549 pinframe = (md2frame_t *)datapointer;
1550 datapointer += sizeof(md2frame_t);
1551 // store the frame scale/translate into the appropriate array
1552 for (j = 0;j < 3;j++)
1554 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1555 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1557 // convert the vertices
1558 v = (trivertx_t *)datapointer;
1559 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1560 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1561 out[k] = v[vertremap[k]];
1562 datapointer += numxyz * sizeof(trivertx_t);
1564 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1565 loadmodel->animscenes[i].firstframe = i;
1566 loadmodel->animscenes[i].framecount = 1;
1567 loadmodel->animscenes[i].framerate = 10;
1568 loadmodel->animscenes[i].loop = true;
1571 Mem_Free(vertremap);
1573 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1574 Mod_Alias_CalculateBoundingBox();
1575 Mod_Alias_MorphMesh_CompileFrames();
1577 surface = loadmodel->data_surfaces;
1578 surface->texture = loadmodel->data_textures;
1579 surface->num_firsttriangle = 0;
1580 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1581 surface->num_firstvertex = 0;
1582 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1584 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1586 if (!loadmodel->surfmesh.isanimated)
1588 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1589 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1590 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1591 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1592 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1596 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1598 int i, j, k, version, meshvertices, meshtriangles;
1599 unsigned char *data;
1600 msurface_t *surface;
1601 md3modelheader_t *pinmodel;
1602 md3frameinfo_t *pinframe;
1605 skinfile_t *skinfiles;
1607 pinmodel = (md3modelheader_t *)buffer;
1609 if (memcmp(pinmodel->identifier, "IDP3", 4))
1610 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1611 version = LittleLong (pinmodel->version);
1612 if (version != MD3VERSION)
1613 Host_Error ("%s has wrong version number (%i should be %i)",
1614 loadmodel->name, version, MD3VERSION);
1616 skinfiles = Mod_LoadSkinFiles();
1617 if (loadmodel->numskins < 1)
1618 loadmodel->numskins = 1;
1620 loadmodel->modeldatatypestring = "MD3";
1622 loadmodel->type = mod_alias;
1623 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1624 loadmodel->DrawSky = NULL;
1625 loadmodel->DrawAddWaterPlanes = NULL;
1626 loadmodel->Draw = R_Q1BSP_Draw;
1627 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1628 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1629 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1630 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1631 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1632 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1633 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1634 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1635 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1636 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1637 loadmodel->PointSuperContents = NULL;
1638 loadmodel->synctype = ST_RAND;
1639 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1640 i = LittleLong (pinmodel->flags);
1641 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1643 // set up some global info about the model
1644 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1645 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1647 // make skinscenes for the skins (no groups)
1648 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1649 for (i = 0;i < loadmodel->numskins;i++)
1651 loadmodel->skinscenes[i].firstframe = i;
1652 loadmodel->skinscenes[i].framecount = 1;
1653 loadmodel->skinscenes[i].loop = true;
1654 loadmodel->skinscenes[i].framerate = 10;
1658 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1659 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1661 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1662 loadmodel->animscenes[i].firstframe = i;
1663 loadmodel->animscenes[i].framecount = 1;
1664 loadmodel->animscenes[i].framerate = 10;
1665 loadmodel->animscenes[i].loop = true;
1669 loadmodel->num_tagframes = loadmodel->numframes;
1670 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1671 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1672 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1674 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1675 for (j = 0;j < 9;j++)
1676 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1677 for (j = 0;j < 3;j++)
1678 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1679 //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);
1685 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)))
1687 if (memcmp(pinmesh->identifier, "IDP3", 4))
1688 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1689 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1690 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1691 meshvertices += LittleLong(pinmesh->num_vertices);
1692 meshtriangles += LittleLong(pinmesh->num_triangles);
1695 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1696 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1697 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1698 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));
1699 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1700 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1701 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1702 loadmodel->surfmesh.num_vertices = meshvertices;
1703 loadmodel->surfmesh.num_triangles = meshtriangles;
1704 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1705 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1706 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1707 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1708 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1709 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1710 if (meshvertices <= 65536)
1711 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1715 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)))
1717 if (memcmp(pinmesh->identifier, "IDP3", 4))
1718 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1719 loadmodel->sortedmodelsurfaces[i] = i;
1720 surface = loadmodel->data_surfaces + i;
1721 surface->texture = loadmodel->data_textures + i;
1722 surface->num_firsttriangle = meshtriangles;
1723 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1724 surface->num_firstvertex = meshvertices;
1725 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1726 meshvertices += surface->num_vertices;
1727 meshtriangles += surface->num_triangles;
1729 for (j = 0;j < surface->num_triangles * 3;j++)
1730 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1731 for (j = 0;j < surface->num_vertices;j++)
1733 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1734 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1736 for (j = 0;j < loadmodel->numframes;j++)
1738 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1739 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1740 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1742 out->origin[0] = LittleShort(in->origin[0]);
1743 out->origin[1] = LittleShort(in->origin[1]);
1744 out->origin[2] = LittleShort(in->origin[2]);
1745 out->pitch = in->pitch;
1750 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1752 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1754 if (loadmodel->surfmesh.data_element3s)
1755 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1756 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1757 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1758 Mod_Alias_MorphMesh_CompileFrames();
1759 Mod_Alias_CalculateBoundingBox();
1760 Mod_FreeSkinFiles(skinfiles);
1761 Mod_MakeSortedSurfaces(loadmodel);
1763 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1764 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1766 if (!loadmodel->surfmesh.isanimated)
1768 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1769 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1770 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1771 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1772 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1776 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1778 zymtype1header_t *pinmodel, *pheader;
1779 unsigned char *pbase;
1780 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1781 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose, f, biggestorigin, tempvec[3], modelscale;
1782 zymvertex_t *verts, *vertdata;
1786 skinfile_t *skinfiles;
1787 unsigned char *data;
1788 msurface_t *surface;
1790 pinmodel = (zymtype1header_t *)buffer;
1791 pbase = (unsigned char *)buffer;
1792 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1793 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1794 if (BigLong(pinmodel->type) != 1)
1795 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1797 loadmodel->modeldatatypestring = "ZYM";
1799 loadmodel->type = mod_alias;
1800 loadmodel->synctype = ST_RAND;
1804 pheader->type = BigLong(pinmodel->type);
1805 pheader->filesize = BigLong(pinmodel->filesize);
1806 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1807 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1808 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1809 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1810 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1811 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1812 pheader->radius = BigFloat(pinmodel->radius);
1813 pheader->numverts = BigLong(pinmodel->numverts);
1814 pheader->numtris = BigLong(pinmodel->numtris);
1815 pheader->numshaders = BigLong(pinmodel->numshaders);
1816 pheader->numbones = BigLong(pinmodel->numbones);
1817 pheader->numscenes = BigLong(pinmodel->numscenes);
1818 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1819 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1820 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1821 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1822 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1823 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1824 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1825 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1826 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1827 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1828 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1829 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1830 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1831 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1832 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1833 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1834 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1835 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1837 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1839 Con_Printf("%s has no geometry\n", loadmodel->name);
1842 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1844 Con_Printf("%s has no animations\n", loadmodel->name);
1848 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1849 loadmodel->DrawSky = NULL;
1850 loadmodel->DrawAddWaterPlanes = NULL;
1851 loadmodel->Draw = R_Q1BSP_Draw;
1852 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1853 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1854 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1855 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1856 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1857 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1858 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1859 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1860 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1861 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1862 loadmodel->PointSuperContents = NULL;
1864 loadmodel->numframes = pheader->numscenes;
1865 loadmodel->num_surfaces = pheader->numshaders;
1867 skinfiles = Mod_LoadSkinFiles();
1868 if (loadmodel->numskins < 1)
1869 loadmodel->numskins = 1;
1871 // make skinscenes for the skins (no groups)
1872 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1873 for (i = 0;i < loadmodel->numskins;i++)
1875 loadmodel->skinscenes[i].firstframe = i;
1876 loadmodel->skinscenes[i].framecount = 1;
1877 loadmodel->skinscenes[i].loop = true;
1878 loadmodel->skinscenes[i].framerate = 10;
1882 modelradius = pheader->radius;
1883 for (i = 0;i < 3;i++)
1885 loadmodel->normalmins[i] = pheader->mins[i];
1886 loadmodel->normalmaxs[i] = pheader->maxs[i];
1887 loadmodel->rotatedmins[i] = -modelradius;
1888 loadmodel->rotatedmaxs[i] = modelradius;
1890 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1891 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1892 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1893 if (loadmodel->yawmaxs[0] > modelradius)
1894 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1895 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1896 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1897 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1898 loadmodel->radius = modelradius;
1899 loadmodel->radius2 = modelradius * modelradius;
1901 // go through the lumps, swapping things
1903 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1904 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1905 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1906 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1907 for (i = 0;i < pheader->numscenes;i++)
1909 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1910 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1911 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1912 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1913 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1914 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1915 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1916 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1917 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1918 if (loadmodel->animscenes[i].framerate < 0)
1919 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1923 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1924 loadmodel->num_bones = pheader->numbones;
1925 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1926 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1927 for (i = 0;i < pheader->numbones;i++)
1929 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1930 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1931 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1932 if (loadmodel->data_bones[i].parent >= i)
1933 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1936 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1937 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1938 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1939 for (i = 0;i < pheader->numverts;i++)
1941 vertbonecounts[i] = BigLong(bonecount[i]);
1942 if (vertbonecounts[i] != 1)
1943 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1946 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1948 meshvertices = pheader->numverts;
1949 meshtriangles = pheader->numtris;
1951 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1952 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1953 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1954 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]));
1955 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1956 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1957 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1958 loadmodel->surfmesh.num_vertices = meshvertices;
1959 loadmodel->surfmesh.num_triangles = meshtriangles;
1960 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1961 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1962 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1963 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1964 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1965 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1966 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1967 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1968 loadmodel->surfmesh.num_blends = 0;
1969 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
1970 if (loadmodel->surfmesh.num_vertices <= 65536)
1971 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1972 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
1973 loadmodel->surfmesh.data_blendweights = NULL;
1975 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1976 poses = (float *) (pheader->lump_poses.start + pbase);
1977 // figure out scale of model from root bone, for compatibility with old zmodel versions
1978 tempvec[0] = BigFloat(poses[0]);
1979 tempvec[1] = BigFloat(poses[1]);
1980 tempvec[2] = BigFloat(poses[2]);
1981 modelscale = VectorLength(tempvec);
1983 for (i = 0;i < loadmodel->num_bones * numposes * 12;i++)
1985 f = fabs(BigFloat(poses[i]));
1986 biggestorigin = max(biggestorigin, f);
1988 loadmodel->num_posescale = biggestorigin / 32767.0f;
1989 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
1990 for (i = 0;i < numposes;i++)
1992 const float *frameposes = (float *) (pheader->lump_poses.start + pbase) + 12*i*loadmodel->num_bones;
1993 for (j = 0;j < loadmodel->num_bones;j++)
1996 matrix4x4_t posematrix;
1997 for (k = 0;k < 12;k++)
1998 pose[k] = BigFloat(frameposes[j*12+k]);
1999 //if (j < loadmodel->num_bones)
2000 // 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));
2001 // scale child bones to match the root scale
2002 if (loadmodel->data_bones[j].parent >= 0)
2004 pose[3] *= modelscale;
2005 pose[7] *= modelscale;
2006 pose[11] *= modelscale;
2008 // normalize rotation matrix
2009 VectorNormalize(pose + 0);
2010 VectorNormalize(pose + 4);
2011 VectorNormalize(pose + 8);
2012 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2013 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
2017 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
2018 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
2019 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
2020 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2021 // (converting from weight-blending skeletal animation to
2022 // deformation-based skeletal animation)
2023 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2024 for (i = 0;i < loadmodel->num_bones;i++)
2027 for (k = 0;k < 12;k++)
2028 m[k] = BigFloat(poses[i*12+k]);
2029 if (loadmodel->data_bones[i].parent >= 0)
2030 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2032 for (k = 0;k < 12;k++)
2033 bonepose[12*i+k] = m[k];
2035 for (j = 0;j < pheader->numverts;j++)
2037 // this format really should have had a per vertexweight weight value...
2038 // but since it does not, the weighting is completely ignored and
2039 // only one weight is allowed per vertex
2040 int boneindex = BigLong(vertdata[j].bonenum);
2041 const float *m = bonepose + 12 * boneindex;
2042 float relativeorigin[3];
2043 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
2044 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
2045 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
2046 // transform the vertex bone weight into the base mesh
2047 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
2048 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
2049 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
2050 // store the weight as the primary weight on this vertex
2051 loadmodel->surfmesh.blends[j] = boneindex;
2054 // normals and tangents are calculated after elements are loaded
2056 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
2057 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
2058 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
2059 for (i = 0;i < pheader->numverts;i++)
2061 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
2062 // flip T coordinate for OpenGL
2063 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
2066 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
2067 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
2068 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
2070 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
2071 //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)
2072 // byteswap, validate, and swap winding order of tris
2073 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
2074 if (pheader->lump_render.length != count)
2075 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
2076 renderlist = (int *) (pheader->lump_render.start + pbase);
2077 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
2079 for (i = 0;i < loadmodel->num_surfaces;i++)
2081 int firstvertex, lastvertex;
2082 if (renderlist >= renderlistend)
2083 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2084 count = BigLong(*renderlist);renderlist++;
2085 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
2086 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2088 loadmodel->sortedmodelsurfaces[i] = i;
2089 surface = loadmodel->data_surfaces + i;
2090 surface->texture = loadmodel->data_textures + i;
2091 surface->num_firsttriangle = meshtriangles;
2092 surface->num_triangles = count;
2093 meshtriangles += surface->num_triangles;
2095 // load the elements
2096 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2097 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
2099 outelements[j*3+2] = BigLong(renderlist[0]);
2100 outelements[j*3+1] = BigLong(renderlist[1]);
2101 outelements[j*3+0] = BigLong(renderlist[2]);
2103 // validate the elements and find the used vertex range
2104 firstvertex = meshvertices;
2106 for (j = 0;j < surface->num_triangles * 3;j++)
2108 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
2109 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
2110 firstvertex = min(firstvertex, outelements[j]);
2111 lastvertex = max(lastvertex, outelements[j]);
2113 surface->num_firstvertex = firstvertex;
2114 surface->num_vertices = lastvertex + 1 - firstvertex;
2116 // since zym models do not have named sections, reuse their shader
2117 // name as the section name
2118 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
2119 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
2121 Mod_FreeSkinFiles(skinfiles);
2122 Mem_Free(vertbonecounts);
2124 Mod_MakeSortedSurfaces(loadmodel);
2126 // compute all the mesh information that was not loaded from the file
2127 if (loadmodel->surfmesh.data_element3s)
2128 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2129 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2130 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2131 Mod_BuildBaseBonePoses();
2132 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2133 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);
2134 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2136 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2138 if (!loadmodel->surfmesh.isanimated)
2140 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2141 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2142 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2143 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2144 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2148 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2150 dpmheader_t *pheader;
2154 unsigned char *pbase;
2155 int i, j, k, meshvertices, meshtriangles;
2156 skinfile_t *skinfiles;
2157 unsigned char *data;
2159 float biggestorigin, tempvec[3], modelscale;
2163 pheader = (dpmheader_t *)buffer;
2164 pbase = (unsigned char *)buffer;
2165 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2166 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2167 if (BigLong(pheader->type) != 2)
2168 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2170 loadmodel->modeldatatypestring = "DPM";
2172 loadmodel->type = mod_alias;
2173 loadmodel->synctype = ST_RAND;
2176 pheader->type = BigLong(pheader->type);
2177 pheader->filesize = BigLong(pheader->filesize);
2178 pheader->mins[0] = BigFloat(pheader->mins[0]);
2179 pheader->mins[1] = BigFloat(pheader->mins[1]);
2180 pheader->mins[2] = BigFloat(pheader->mins[2]);
2181 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2182 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2183 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2184 pheader->yawradius = BigFloat(pheader->yawradius);
2185 pheader->allradius = BigFloat(pheader->allradius);
2186 pheader->num_bones = BigLong(pheader->num_bones);
2187 pheader->num_meshs = BigLong(pheader->num_meshs);
2188 pheader->num_frames = BigLong(pheader->num_frames);
2189 pheader->ofs_bones = BigLong(pheader->ofs_bones);
2190 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2191 pheader->ofs_frames = BigLong(pheader->ofs_frames);
2193 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2195 Con_Printf("%s has no geometry\n", loadmodel->name);
2198 if (pheader->num_frames < 1)
2200 Con_Printf("%s has no frames\n", loadmodel->name);
2204 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2205 loadmodel->DrawSky = NULL;
2206 loadmodel->DrawAddWaterPlanes = NULL;
2207 loadmodel->Draw = R_Q1BSP_Draw;
2208 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2209 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2210 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2211 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2212 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2213 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2214 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2215 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2216 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2217 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2218 loadmodel->PointSuperContents = NULL;
2221 for (i = 0;i < 3;i++)
2223 loadmodel->normalmins[i] = pheader->mins[i];
2224 loadmodel->normalmaxs[i] = pheader->maxs[i];
2225 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2226 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2227 loadmodel->rotatedmins[i] = -pheader->allradius;
2228 loadmodel->rotatedmaxs[i] = pheader->allradius;
2230 loadmodel->radius = pheader->allradius;
2231 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2233 // load external .skin files if present
2234 skinfiles = Mod_LoadSkinFiles();
2235 if (loadmodel->numskins < 1)
2236 loadmodel->numskins = 1;
2241 // gather combined statistics from the meshes
2242 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2243 for (i = 0;i < (int)pheader->num_meshs;i++)
2245 int numverts = BigLong(dpmmesh->num_verts);
2246 meshvertices += numverts;
2247 meshtriangles += BigLong(dpmmesh->num_tris);
2251 loadmodel->numframes = pheader->num_frames;
2252 loadmodel->num_bones = pheader->num_bones;
2253 loadmodel->num_poses = loadmodel->numframes;
2254 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2255 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2256 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2257 // do most allocations as one merged chunk
2258 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));
2259 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2260 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2261 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2262 loadmodel->surfmesh.num_vertices = meshvertices;
2263 loadmodel->surfmesh.num_triangles = meshtriangles;
2264 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2265 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2266 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2267 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2268 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2269 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2270 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2271 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2272 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2273 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2274 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2275 loadmodel->surfmesh.num_blends = 0;
2276 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2277 if (meshvertices <= 65536)
2278 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2279 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2280 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
2282 for (i = 0;i < loadmodel->numskins;i++)
2284 loadmodel->skinscenes[i].firstframe = i;
2285 loadmodel->skinscenes[i].framecount = 1;
2286 loadmodel->skinscenes[i].loop = true;
2287 loadmodel->skinscenes[i].framerate = 10;
2290 // load the bone info
2291 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2292 for (i = 0;i < loadmodel->num_bones;i++)
2294 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2295 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2296 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2297 if (loadmodel->data_bones[i].parent >= i)
2298 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2302 frames = (dpmframe_t *) (pbase + pheader->ofs_frames);
2303 // figure out scale of model from root bone, for compatibility with old dpmodel versions
2304 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2305 tempvec[0] = BigFloat(poses[0]);
2306 tempvec[1] = BigFloat(poses[1]);
2307 tempvec[2] = BigFloat(poses[2]);
2308 modelscale = VectorLength(tempvec);
2310 for (i = 0;i < loadmodel->numframes;i++)
2312 memcpy(loadmodel->animscenes[i].name, frames[i].name, sizeof(frames[i].name));
2313 loadmodel->animscenes[i].firstframe = i;
2314 loadmodel->animscenes[i].framecount = 1;
2315 loadmodel->animscenes[i].loop = true;
2316 loadmodel->animscenes[i].framerate = 10;
2317 // load the bone poses for this frame
2318 poses = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2319 for (j = 0;j < loadmodel->num_bones*12;j++)
2321 f = fabs(BigFloat(poses[j]));
2322 biggestorigin = max(biggestorigin, f);
2324 // stuff not processed here: mins, maxs, yawradius, allradius
2326 loadmodel->num_posescale = biggestorigin / 32767.0f;
2327 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2328 for (i = 0;i < loadmodel->numframes;i++)
2330 const float *frameposes = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2331 for (j = 0;j < loadmodel->num_bones;j++)
2334 matrix4x4_t posematrix;
2335 for (k = 0;k < 12;k++)
2336 pose[k] = BigFloat(frameposes[j*12+k]);
2337 // scale child bones to match the root scale
2338 if (loadmodel->data_bones[j].parent >= 0)
2340 pose[3] *= modelscale;
2341 pose[7] *= modelscale;
2342 pose[11] *= modelscale;
2344 // normalize rotation matrix
2345 VectorNormalize(pose + 0);
2346 VectorNormalize(pose + 4);
2347 VectorNormalize(pose + 8);
2348 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2349 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
2353 // load the meshes now
2354 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2357 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2358 // (converting from weight-blending skeletal animation to
2359 // deformation-based skeletal animation)
2360 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2361 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2362 for (i = 0;i < loadmodel->num_bones;i++)
2365 for (k = 0;k < 12;k++)
2366 m[k] = BigFloat(poses[i*12+k]);
2367 if (loadmodel->data_bones[i].parent >= 0)
2368 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2370 for (k = 0;k < 12;k++)
2371 bonepose[12*i+k] = m[k];
2373 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2375 const int *inelements;
2377 const float *intexcoord;
2378 msurface_t *surface;
2380 loadmodel->sortedmodelsurfaces[i] = i;
2381 surface = loadmodel->data_surfaces + i;
2382 surface->texture = loadmodel->data_textures + i;
2383 surface->num_firsttriangle = meshtriangles;
2384 surface->num_triangles = BigLong(dpmmesh->num_tris);
2385 surface->num_firstvertex = meshvertices;
2386 surface->num_vertices = BigLong(dpmmesh->num_verts);
2387 meshvertices += surface->num_vertices;
2388 meshtriangles += surface->num_triangles;
2390 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2391 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2392 for (j = 0;j < surface->num_triangles;j++)
2394 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2395 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2396 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2397 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2402 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2403 for (j = 0;j < surface->num_vertices*2;j++)
2404 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2406 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2407 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2409 int weightindex[4] = { 0, 0, 0, 0 };
2410 float weightinfluence[4] = { 0, 0, 0, 0 };
2412 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2413 data += sizeof(dpmvertex_t);
2414 for (k = 0;k < numweights;k++)
2416 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2417 int boneindex = BigLong(vert->bonenum);
2418 const float *m = bonepose + 12 * boneindex;
2419 float influence = BigFloat(vert->influence);
2420 float relativeorigin[3], relativenormal[3];
2421 relativeorigin[0] = BigFloat(vert->origin[0]);
2422 relativeorigin[1] = BigFloat(vert->origin[1]);
2423 relativeorigin[2] = BigFloat(vert->origin[2]);
2424 relativenormal[0] = BigFloat(vert->normal[0]);
2425 relativenormal[1] = BigFloat(vert->normal[1]);
2426 relativenormal[2] = BigFloat(vert->normal[2]);
2427 // blend the vertex bone weights into the base mesh
2428 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2429 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2430 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2431 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2432 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2433 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2436 // store the first (and often only) weight
2437 weightinfluence[0] = influence;
2438 weightindex[0] = boneindex;
2442 // sort the new weight into this vertex's weight table
2443 // (which only accepts up to 4 bones per vertex)
2444 for (l = 0;l < 4;l++)
2446 if (weightinfluence[l] < influence)
2448 // move weaker influence weights out of the way first
2450 for (l2 = 3;l2 > l;l2--)
2452 weightinfluence[l2] = weightinfluence[l2-1];
2453 weightindex[l2] = weightindex[l2-1];
2455 // store the new weight
2456 weightinfluence[l] = influence;
2457 weightindex[l] = boneindex;
2462 data += sizeof(dpmbonevert_t);
2464 loadmodel->surfmesh.blends[j] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
2467 // since dpm models do not have named sections, reuse their shader name as the section name
2468 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2470 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2472 if (loadmodel->surfmesh.num_blends < meshvertices)
2473 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2475 Mod_FreeSkinFiles(skinfiles);
2476 Mod_MakeSortedSurfaces(loadmodel);
2478 // compute all the mesh information that was not loaded from the file
2479 if (loadmodel->surfmesh.data_element3s)
2480 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2481 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2482 Mod_BuildBaseBonePoses();
2483 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);
2484 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2486 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2488 if (!loadmodel->surfmesh.isanimated)
2490 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2491 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2492 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2493 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2494 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2498 // no idea why PSK/PSA files contain weird quaternions but they do...
2499 #define PSKQUATNEGATIONS
2500 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2502 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2503 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2504 fs_offset_t filesize;
2509 pskboneinfo_t *bones;
2510 pskrawweights_t *rawweights;
2511 //pskboneinfo_t *animbones;
2512 pskaniminfo_t *anims;
2513 pskanimkeys_t *animkeys;
2514 void *animfilebuffer, *animbuffer, *animbufferend;
2515 unsigned char *data;
2517 skinfile_t *skinfiles;
2518 char animname[MAX_QPATH];
2520 float biggestorigin;
2522 pchunk = (pskchunk_t *)buffer;
2523 if (strcmp(pchunk->id, "ACTRHEAD"))
2524 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2526 loadmodel->modeldatatypestring = "PSK";
2528 loadmodel->type = mod_alias;
2529 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2530 loadmodel->DrawSky = NULL;
2531 loadmodel->DrawAddWaterPlanes = NULL;
2532 loadmodel->Draw = R_Q1BSP_Draw;
2533 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2534 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2535 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2536 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2537 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2538 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2539 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2540 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2541 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2542 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2543 loadmodel->PointSuperContents = NULL;
2544 loadmodel->synctype = ST_RAND;
2546 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2547 strlcat(animname, ".psa", sizeof(animname));
2548 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2549 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2550 if (animbuffer == NULL)
2551 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2570 while (buffer < bufferend)
2572 pchunk = (pskchunk_t *)buffer;
2573 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2574 version = LittleLong(pchunk->version);
2575 recordsize = LittleLong(pchunk->recordsize);
2576 numrecords = LittleLong(pchunk->numrecords);
2577 if (developer_extra.integer)
2578 Con_DPrintf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2579 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2580 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);
2581 if (!strcmp(pchunk->id, "ACTRHEAD"))
2585 else if (!strcmp(pchunk->id, "PNTS0000"))
2588 if (recordsize != sizeof(*p))
2589 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2590 // byteswap in place and keep the pointer
2591 numpnts = numrecords;
2592 pnts = (pskpnts_t *)buffer;
2593 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2595 p->origin[0] = LittleFloat(p->origin[0]);
2596 p->origin[1] = LittleFloat(p->origin[1]);
2597 p->origin[2] = LittleFloat(p->origin[2]);
2601 else if (!strcmp(pchunk->id, "VTXW0000"))
2604 if (recordsize != sizeof(*p))
2605 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2606 // byteswap in place and keep the pointer
2607 numvtxw = numrecords;
2608 vtxw = (pskvtxw_t *)buffer;
2609 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2611 p->pntsindex = LittleShort(p->pntsindex);
2612 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2613 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2614 if (p->pntsindex >= numpnts)
2616 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2622 else if (!strcmp(pchunk->id, "FACE0000"))
2625 if (recordsize != sizeof(*p))
2626 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2627 // byteswap in place and keep the pointer
2628 numfaces = numrecords;
2629 faces = (pskface_t *)buffer;
2630 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2632 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2633 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2634 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2635 p->group = LittleLong(p->group);
2636 if (p->vtxwindex[0] >= numvtxw)
2638 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2639 p->vtxwindex[0] = 0;
2641 if (p->vtxwindex[1] >= numvtxw)
2643 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2644 p->vtxwindex[1] = 0;
2646 if (p->vtxwindex[2] >= numvtxw)
2648 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2649 p->vtxwindex[2] = 0;
2654 else if (!strcmp(pchunk->id, "MATT0000"))
2657 if (recordsize != sizeof(*p))
2658 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2659 // byteswap in place and keep the pointer
2660 nummatts = numrecords;
2661 matts = (pskmatt_t *)buffer;
2662 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2668 else if (!strcmp(pchunk->id, "REFSKELT"))
2671 if (recordsize != sizeof(*p))
2672 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2673 // byteswap in place and keep the pointer
2674 numbones = numrecords;
2675 bones = (pskboneinfo_t *)buffer;
2676 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2678 p->numchildren = LittleLong(p->numchildren);
2679 p->parent = LittleLong(p->parent);
2680 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2681 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2682 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2683 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2684 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2685 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2686 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2687 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2688 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2689 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2690 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2691 #ifdef PSKQUATNEGATIONS
2694 p->basepose.quat[0] *= -1;
2695 p->basepose.quat[1] *= -1;
2696 p->basepose.quat[2] *= -1;
2700 p->basepose.quat[0] *= 1;
2701 p->basepose.quat[1] *= -1;
2702 p->basepose.quat[2] *= 1;
2705 if (p->parent < 0 || p->parent >= numbones)
2707 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2713 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2716 if (recordsize != sizeof(*p))
2717 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2718 // byteswap in place and keep the pointer
2719 numrawweights = numrecords;
2720 rawweights = (pskrawweights_t *)buffer;
2721 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2723 p->weight = LittleFloat(p->weight);
2724 p->pntsindex = LittleLong(p->pntsindex);
2725 p->boneindex = LittleLong(p->boneindex);
2726 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2728 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2731 if (p->boneindex < 0 || p->boneindex >= numbones)
2733 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2741 while (animbuffer < animbufferend)
2743 pchunk = (pskchunk_t *)animbuffer;
2744 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2745 version = LittleLong(pchunk->version);
2746 recordsize = LittleLong(pchunk->recordsize);
2747 numrecords = LittleLong(pchunk->numrecords);
2748 if (developer_extra.integer)
2749 Con_DPrintf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2750 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2751 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);
2752 if (!strcmp(pchunk->id, "ANIMHEAD"))
2756 else if (!strcmp(pchunk->id, "BONENAMES"))
2759 if (recordsize != sizeof(*p))
2760 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2761 // byteswap in place and keep the pointer
2762 numanimbones = numrecords;
2763 //animbones = (pskboneinfo_t *)animbuffer;
2764 // NOTE: supposedly psa does not need to match the psk model, the
2765 // bones missing from the psa would simply use their base
2766 // positions from the psk, but this is hard for me to implement
2767 // and people can easily make animations that match.
2768 if (numanimbones != numbones)
2769 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2770 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2772 p->numchildren = LittleLong(p->numchildren);
2773 p->parent = LittleLong(p->parent);
2774 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2775 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2776 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2777 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2778 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2779 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2780 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2781 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2782 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2783 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2784 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2785 #ifdef PSKQUATNEGATIONS
2788 p->basepose.quat[0] *= -1;
2789 p->basepose.quat[1] *= -1;
2790 p->basepose.quat[2] *= -1;
2794 p->basepose.quat[0] *= 1;
2795 p->basepose.quat[1] *= -1;
2796 p->basepose.quat[2] *= 1;
2799 if (p->parent < 0 || p->parent >= numanimbones)
2801 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2804 // check that bones are the same as in the base
2805 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2806 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2810 else if (!strcmp(pchunk->id, "ANIMINFO"))
2813 if (recordsize != sizeof(*p))
2814 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2815 // byteswap in place and keep the pointer
2816 numanims = numrecords;
2817 anims = (pskaniminfo_t *)animbuffer;
2818 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2820 p->numbones = LittleLong(p->numbones);
2821 p->playtime = LittleFloat(p->playtime);
2822 p->fps = LittleFloat(p->fps);
2823 p->firstframe = LittleLong(p->firstframe);
2824 p->numframes = LittleLong(p->numframes);
2825 if (p->numbones != numbones)
2826 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2830 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2833 if (recordsize != sizeof(*p))
2834 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2835 numanimkeys = numrecords;
2836 animkeys = (pskanimkeys_t *)animbuffer;
2837 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2839 p->origin[0] = LittleFloat(p->origin[0]);
2840 p->origin[1] = LittleFloat(p->origin[1]);
2841 p->origin[2] = LittleFloat(p->origin[2]);
2842 p->quat[0] = LittleFloat(p->quat[0]);
2843 p->quat[1] = LittleFloat(p->quat[1]);
2844 p->quat[2] = LittleFloat(p->quat[2]);
2845 p->quat[3] = LittleFloat(p->quat[3]);
2846 p->frametime = LittleFloat(p->frametime);
2847 #ifdef PSKQUATNEGATIONS
2848 if (index % numbones)
2863 // TODO: allocate bonepose stuff
2866 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2869 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2870 Host_Error("%s: missing required chunks", loadmodel->name);
2872 loadmodel->numframes = 0;
2873 for (index = 0;index < numanims;index++)
2874 loadmodel->numframes += anims[index].numframes;
2876 if (numanimkeys != numbones * loadmodel->numframes)
2877 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2879 meshvertices = numvtxw;
2880 meshtriangles = numfaces;
2882 // load external .skin files if present
2883 skinfiles = Mod_LoadSkinFiles();
2884 if (loadmodel->numskins < 1)
2885 loadmodel->numskins = 1;
2886 loadmodel->num_bones = numbones;
2887 loadmodel->num_poses = loadmodel->numframes;
2888 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2889 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2890 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2891 loadmodel->surfmesh.num_vertices = meshvertices;
2892 loadmodel->surfmesh.num_triangles = meshtriangles;
2893 // do most allocations as one merged chunk
2894 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);
2895 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2896 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2897 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2898 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2899 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2900 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2901 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2902 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2903 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2904 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2905 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2906 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2907 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2908 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2909 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2910 loadmodel->surfmesh.num_blends = 0;
2911 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2912 if (loadmodel->surfmesh.num_vertices <= 65536)
2913 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2914 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2915 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(blendweights_t));
2917 for (i = 0;i < loadmodel->numskins;i++)
2919 loadmodel->skinscenes[i].firstframe = i;
2920 loadmodel->skinscenes[i].framecount = 1;
2921 loadmodel->skinscenes[i].loop = true;
2922 loadmodel->skinscenes[i].framerate = 10;
2926 for (index = 0, i = 0;index < nummatts;index++)
2928 // since psk models do not have named sections, reuse their shader name as the section name
2929 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2930 loadmodel->sortedmodelsurfaces[index] = index;
2931 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2932 loadmodel->data_surfaces[index].num_firstvertex = 0;
2933 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2936 // copy over the vertex locations and texcoords
2937 for (index = 0;index < numvtxw;index++)
2939 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2940 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2941 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2942 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2943 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2946 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2947 for (index = 0;index < numfaces;index++)
2948 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2949 for (index = 0, i = 0;index < nummatts;index++)
2951 loadmodel->data_surfaces[index].num_firsttriangle = i;
2952 i += loadmodel->data_surfaces[index].num_triangles;
2953 loadmodel->data_surfaces[index].num_triangles = 0;
2955 for (index = 0;index < numfaces;index++)
2957 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2958 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2959 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2960 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2963 // copy over the bones
2964 for (index = 0;index < numbones;index++)
2966 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2967 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2968 if (loadmodel->data_bones[index].parent >= index)
2969 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2972 // sort the psk point weights into the vertex weight tables
2973 // (which only accept up to 4 bones per vertex)
2974 for (index = 0;index < numvtxw;index++)
2976 int weightindex[4] = { 0, 0, 0, 0 };
2977 float weightinfluence[4] = { 0, 0, 0, 0 };
2979 for (j = 0;j < numrawweights;j++)
2981 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2983 int boneindex = rawweights[j].boneindex;
2984 float influence = rawweights[j].weight;
2985 for (l = 0;l < 4;l++)
2987 if (weightinfluence[l] < influence)
2989 // move lower influence weights out of the way first
2991 for (l2 = 3;l2 > l;l2--)
2993 weightinfluence[l2] = weightinfluence[l2-1];
2994 weightindex[l2] = weightindex[l2-1];
2996 // store the new weight
2997 weightinfluence[l] = influence;
2998 weightindex[l] = boneindex;
3004 loadmodel->surfmesh.blends[index] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
3006 if (loadmodel->surfmesh.num_blends < loadmodel->surfmesh.num_vertices)
3007 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
3009 // set up the animscenes based on the anims
3010 for (index = 0, i = 0;index < numanims;index++)
3012 for (j = 0;j < anims[index].numframes;j++, i++)
3014 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
3015 loadmodel->animscenes[i].firstframe = i;
3016 loadmodel->animscenes[i].framecount = 1;
3017 loadmodel->animscenes[i].loop = true;
3018 loadmodel->animscenes[i].framerate = anims[index].fps;
3022 // calculate the scaling value for bone origins so they can be compressed to short
3024 for (index = 0;index < numanimkeys;index++)
3026 pskanimkeys_t *k = animkeys + index;
3027 biggestorigin = max(biggestorigin, fabs(k->origin[0]));
3028 biggestorigin = max(biggestorigin, fabs(k->origin[1]));
3029 biggestorigin = max(biggestorigin, fabs(k->origin[2]));
3031 loadmodel->num_posescale = biggestorigin / 32767.0f;
3032 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3034 // load the poses from the animkeys
3035 for (index = 0;index < numanimkeys;index++)
3037 pskanimkeys_t *k = animkeys + index;
3039 Vector4Copy(k->quat, quat);
3041 Vector4Negate(quat, quat);
3042 Vector4Normalize2(quat, quat);
3043 // compress poses to the short[6] format for longterm storage
3044 loadmodel->data_poses6s[index*6+0] = k->origin[0] * loadmodel->num_poseinvscale;
3045 loadmodel->data_poses6s[index*6+1] = k->origin[1] * loadmodel->num_poseinvscale;
3046 loadmodel->data_poses6s[index*6+2] = k->origin[2] * loadmodel->num_poseinvscale;
3047 loadmodel->data_poses6s[index*6+3] = quat[0] * 32767.0f;
3048 loadmodel->data_poses6s[index*6+4] = quat[1] * 32767.0f;
3049 loadmodel->data_poses6s[index*6+5] = quat[2] * 32767.0f;
3051 Mod_FreeSkinFiles(skinfiles);
3052 Mem_Free(animfilebuffer);
3053 Mod_MakeSortedSurfaces(loadmodel);
3055 // compute all the mesh information that was not loaded from the file
3056 // TODO: honor smoothing groups somehow?
3057 if (loadmodel->surfmesh.data_element3s)
3058 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3059 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3060 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
3061 Mod_BuildBaseBonePoses();
3062 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
3063 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);
3064 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3065 Mod_Alias_CalculateBoundingBox();
3067 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
3069 if (!loadmodel->surfmesh.isanimated)
3071 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3072 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3073 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3074 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3075 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
3079 void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
3081 unsigned char *data;
3083 unsigned char *pbase, *pend;
3084 iqmheader_t *header;
3085 skinfile_t *skinfiles;
3086 int i, j, k, meshvertices, meshtriangles;
3087 float *vposition = NULL, *vtexcoord = NULL, *vnormal = NULL, *vtangent = NULL;
3088 unsigned char *vblendindexes = NULL, *vblendweights = NULL;
3093 iqmbounds_t *bounds;
3094 iqmvertexarray_t *va;
3095 unsigned short *framedata;
3096 float biggestorigin;
3097 const int *inelements;
3099 float *outvertex, *outnormal, *outtexcoord, *outsvector, *outtvector;
3101 pbase = (unsigned char *)buffer;
3102 pend = (unsigned char *)bufferend;
3103 header = (iqmheader_t *)buffer;
3104 if (memcmp(header->id, "INTERQUAKEMODEL", 16))
3105 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model", loadmodel->name);
3106 if (LittleLong(header->version) != 1)
3107 Host_Error ("Mod_INTERQUAKEMODEL_Load: only version 1 models are currently supported (name = %s)", loadmodel->name);
3109 loadmodel->modeldatatypestring = "IQM";
3111 loadmodel->type = mod_alias;
3112 loadmodel->synctype = ST_RAND;
3115 header->version = LittleLong(header->version);
3116 header->filesize = LittleLong(header->filesize);
3117 header->flags = LittleLong(header->flags);
3118 header->num_text = LittleLong(header->num_text);
3119 header->ofs_text = LittleLong(header->ofs_text);
3120 header->num_meshes = LittleLong(header->num_meshes);
3121 header->ofs_meshes = LittleLong(header->ofs_meshes);
3122 header->num_vertexarrays = LittleLong(header->num_vertexarrays);
3123 header->num_vertexes = LittleLong(header->num_vertexes);
3124 header->ofs_vertexarrays = LittleLong(header->ofs_vertexarrays);
3125 header->num_triangles = LittleLong(header->num_triangles);
3126 header->ofs_triangles = LittleLong(header->ofs_triangles);
3127 header->ofs_neighbors = LittleLong(header->ofs_neighbors);
3128 header->num_joints = LittleLong(header->num_joints);
3129 header->ofs_joints = LittleLong(header->ofs_joints);
3130 header->num_poses = LittleLong(header->num_poses);
3131 header->ofs_poses = LittleLong(header->ofs_poses);
3132 header->num_anims = LittleLong(header->num_anims);
3133 header->ofs_anims = LittleLong(header->ofs_anims);
3134 header->num_frames = LittleLong(header->num_frames);
3135 header->num_framechannels = LittleLong(header->num_framechannels);
3136 header->ofs_frames = LittleLong(header->ofs_frames);
3137 header->ofs_bounds = LittleLong(header->ofs_bounds);
3138 header->num_comment = LittleLong(header->num_comment);
3139 header->ofs_comment = LittleLong(header->ofs_comment);
3140 header->num_extensions = LittleLong(header->num_extensions);
3141 header->ofs_extensions = LittleLong(header->ofs_extensions);
3143 if (header->num_triangles < 1 || header->num_vertexes < 3 || header->num_vertexarrays < 1 || header->num_meshes < 1)
3145 Con_Printf("%s has no geometry\n", loadmodel->name);
3148 if (header->num_frames < 1 || header->num_anims < 1)
3150 Con_Printf("%s has no animations\n", loadmodel->name);
3154 if (pbase + header->ofs_text + header->num_text > pend ||
3155 pbase + header->ofs_meshes + header->num_meshes*sizeof(iqmmesh_t) > pend ||
3156 pbase + header->ofs_vertexarrays + header->num_vertexarrays*sizeof(iqmvertexarray_t) > pend ||
3157 pbase + header->ofs_triangles + header->num_triangles*sizeof(int[3]) > pend ||
3158 (header->ofs_neighbors && pbase + header->ofs_neighbors + header->num_triangles*sizeof(int[3]) > pend) ||
3159 pbase + header->ofs_joints + header->num_joints*sizeof(iqmjoint_t) > pend ||
3160 pbase + header->ofs_poses + header->num_poses*sizeof(iqmpose_t) > pend ||
3161 pbase + header->ofs_anims + header->num_anims*sizeof(iqmanim_t) > pend ||
3162 pbase + header->ofs_frames + header->num_frames*header->num_framechannels*sizeof(unsigned short) > pend ||
3163 (header->ofs_bounds && pbase + header->ofs_bounds + header->num_frames*sizeof(iqmbounds_t) > pend) ||
3164 pbase + header->ofs_comment + header->num_comment > pend)
3166 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3170 va = (iqmvertexarray_t *)(pbase + header->ofs_vertexarrays);
3171 for (i = 0;i < (int)header->num_vertexarrays;i++)
3174 va[i].type = LittleLong(va[i].type);
3175 va[i].flags = LittleLong(va[i].flags);
3176 va[i].format = LittleLong(va[i].format);
3177 va[i].size = LittleLong(va[i].size);
3178 va[i].offset = LittleLong(va[i].offset);
3179 vsize = header->num_vertexes*va[i].size;
3180 switch (va[i].format)
3182 case IQM_FLOAT: vsize *= sizeof(float); break;
3183 case IQM_UBYTE: vsize *= sizeof(unsigned char); break;
3186 if (pbase + va[i].offset + vsize > pend)
3191 if (va[i].format == IQM_FLOAT && va[i].size == 3)
3192 vposition = (float *)(pbase + va[i].offset);
3195 if (va[i].format == IQM_FLOAT && va[i].size == 2)
3196 vtexcoord = (float *)(pbase + va[i].offset);
3199 if (va[i].format == IQM_FLOAT && va[i].size == 3)
3200 vnormal = (float *)(pbase + va[i].offset);
3203 if (va[i].format == IQM_FLOAT && va[i].size == 4)
3204 vtangent = (float *)(pbase + va[i].offset);
3206 case IQM_BLENDINDEXES:
3207 if (va[i].format == IQM_UBYTE && va[i].size == 4)
3208 vblendindexes = (unsigned char *)(pbase + va[i].offset);
3210 case IQM_BLENDWEIGHTS:
3211 if (va[i].format == IQM_UBYTE && va[i].size == 4)
3212 vblendweights = (unsigned char *)(pbase + va[i].offset);
3216 if (!vposition || !vtexcoord || !vblendindexes || !vblendweights)
3218 Con_Printf("%s is missing vertex array data\n", loadmodel->name);
3222 text = header->num_text && header->ofs_text ? (const char *)(pbase + header->ofs_text) : "";
3224 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
3225 loadmodel->DrawSky = NULL;
3226 loadmodel->DrawAddWaterPlanes = NULL;
3227 loadmodel->Draw = R_Q1BSP_Draw;
3228 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
3229 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
3230 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
3231 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
3232 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
3233 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
3234 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
3235 loadmodel->DrawLight = R_Q1BSP_DrawLight;
3236 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
3237 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
3238 loadmodel->PointSuperContents = NULL;
3240 // load external .skin files if present
3241 skinfiles = Mod_LoadSkinFiles();
3242 if (loadmodel->numskins < 1)
3243 loadmodel->numskins = 1;
3245 loadmodel->numframes = header->num_anims;
3246 loadmodel->num_bones = header->num_joints;
3247 loadmodel->num_poses = header->num_frames;
3248 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = header->num_meshes;
3249 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3250 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3252 meshvertices = header->num_vertexes;
3253 meshtriangles = header->num_triangles;
3255 // do most allocations as one merged chunk
3256 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));
3257 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
3258 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
3259 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
3260 loadmodel->surfmesh.num_vertices = meshvertices;
3261 loadmodel->surfmesh.num_triangles = meshtriangles;
3262 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3263 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3264 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
3265 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3266 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3267 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
3268 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
3269 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
3270 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
3271 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
3272 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
3273 loadmodel->surfmesh.num_blends = 0;
3274 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
3275 if (meshvertices <= 65536)
3276 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
3277 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
3278 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
3280 for (i = 0;i < loadmodel->numskins;i++)
3282 loadmodel->skinscenes[i].firstframe = i;
3283 loadmodel->skinscenes[i].framecount = 1;
3284 loadmodel->skinscenes[i].loop = true;
3285 loadmodel->skinscenes[i].framerate = 10;
3288 // load the bone info
3289 joint = (iqmjoint_t *) (pbase + header->ofs_joints);
3290 for (i = 0;i < loadmodel->num_bones;i++)
3292 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3293 joint[i].name = LittleLong(joint[i].name);
3294 joint[i].parent = LittleLong(joint[i].parent);
3295 for (j = 0;j < 3;j++)
3297 joint[i].origin[j] = LittleFloat(joint[i].origin[j]);
3298 joint[i].rotation[j] = LittleFloat(joint[i].rotation[j]);
3299 joint[i].scale[j] = LittleFloat(joint[i].scale[j]);
3301 strlcpy(loadmodel->data_bones[i].name, &text[joint[i].name], sizeof(loadmodel->data_bones[i].name));
3302 loadmodel->data_bones[i].parent = joint[i].parent;
3303 if (loadmodel->data_bones[i].parent >= i)
3304 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3305 Matrix4x4_FromDoom3Joint(&relbase, joint[i].origin[0], joint[i].origin[1], joint[i].origin[2], joint[i].rotation[0], joint[i].rotation[1], joint[i].rotation[2]);
3306 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3307 if (loadmodel->data_bones[i].parent >= 0)
3309 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3310 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3311 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3313 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3316 // set up the animscenes based on the anims
3317 anim = (iqmanim_t *) (pbase + header->ofs_anims);
3318 for (i = 0;i < (int)header->num_anims;i++)
3320 anim[i].name = LittleLong(anim[i].name);
3321 anim[i].first_frame = LittleLong(anim[i].first_frame);
3322 anim[i].num_frames = LittleLong(anim[i].num_frames);
3323 anim[i].framerate = LittleFloat(anim[i].framerate);
3324 anim[i].flags = LittleLong(anim[i].flags);
3325 strlcpy(loadmodel->animscenes[i].name, &text[anim[i].name], sizeof(loadmodel->animscenes[i].name));
3326 loadmodel->animscenes[i].firstframe = anim[i].first_frame;
3327 loadmodel->animscenes[i].framecount = anim[i].num_frames;
3328 loadmodel->animscenes[i].loop = ((anim[i].flags & IQM_LOOP) != 0);
3329 loadmodel->animscenes[i].framerate = anim[i].framerate;
3332 pose = (iqmpose_t *) (pbase + header->ofs_poses);
3334 for (i = 0;i < (int)header->num_poses;i++)
3337 pose[i].parent = LittleLong(pose[i].parent);
3338 pose[i].channelmask = LittleLong(pose[i].channelmask);
3339 pose[i].channeloffset[0] = LittleFloat(pose[i].channeloffset[0]);
3340 pose[i].channeloffset[1] = LittleFloat(pose[i].channeloffset[1]);
3341 pose[i].channeloffset[2] = LittleFloat(pose[i].channeloffset[2]);
3342 pose[i].channeloffset[3] = LittleFloat(pose[i].channeloffset[3]);
3343 pose[i].channeloffset[4] = LittleFloat(pose[i].channeloffset[4]);
3344 pose[i].channeloffset[5] = LittleFloat(pose[i].channeloffset[5]);
3345 pose[i].channeloffset[6] = LittleFloat(pose[i].channeloffset[6]);
3346 pose[i].channeloffset[7] = LittleFloat(pose[i].channeloffset[7]);
3347 pose[i].channeloffset[8] = LittleFloat(pose[i].channeloffset[8]);
3348 pose[i].channelscale[0] = LittleFloat(pose[i].channelscale[0]);
3349 pose[i].channelscale[1] = LittleFloat(pose[i].channelscale[1]);
3350 pose[i].channelscale[2] = LittleFloat(pose[i].channelscale[2]);
3351 pose[i].channelscale[3] = LittleFloat(pose[i].channelscale[3]);
3352 pose[i].channelscale[4] = LittleFloat(pose[i].channelscale[4]);
3353 pose[i].channelscale[5] = LittleFloat(pose[i].channelscale[5]);
3354 pose[i].channelscale[6] = LittleFloat(pose[i].channelscale[6]);
3355 pose[i].channelscale[7] = LittleFloat(pose[i].channelscale[7]);
3356 pose[i].channelscale[8] = LittleFloat(pose[i].channelscale[8]);
3357 f = fabs(pose[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3358 f = fabs(pose[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3359 f = fabs(pose[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3360 f = fabs(pose[i].channeloffset[0] + 0xFFFF*pose[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3361 f = fabs(pose[i].channeloffset[1] + 0xFFFF*pose[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3362 f = fabs(pose[i].channeloffset[2] + 0xFFFF*pose[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3364 loadmodel->num_posescale = biggestorigin / 32767.0f;
3365 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3367 // load the pose data
3368 framedata = (unsigned short *) (pbase + header->ofs_frames);
3369 for (i = 0, k = 0;i < (int)header->num_frames;i++)
3371 for (j = 0;j < (int)header->num_poses;j++, k++)
3373 loadmodel->data_poses6s[k*6 + 0] = loadmodel->num_poseinvscale * (pose[j].channeloffset[0] + (pose[j].channelmask&1 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[0] : 0));
3374 loadmodel->data_poses6s[k*6 + 1] = loadmodel->num_poseinvscale * (pose[j].channeloffset[1] + (pose[j].channelmask&2 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[1] : 0));
3375 loadmodel->data_poses6s[k*6 + 2] = loadmodel->num_poseinvscale * (pose[j].channeloffset[2] + (pose[j].channelmask&4 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[2] : 0));
3376 loadmodel->data_poses6s[k*6 + 3] = 32767.0f * (pose[j].channeloffset[3] + (pose[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[3] : 0));
3377 loadmodel->data_poses6s[k*6 + 4] = 32767.0f * (pose[j].channeloffset[4] + (pose[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[4] : 0));
3378 loadmodel->data_poses6s[k*6 + 5] = 32767.0f * (pose[j].channeloffset[5] + (pose[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[5] : 0));
3379 // skip scale data for now
3380 if(pose[j].channelmask&64) framedata++;
3381 if(pose[j].channelmask&128) framedata++;
3382 if(pose[j].channelmask&256) framedata++;
3386 // load bounding box data
3387 if (header->ofs_bounds)
3389 float xyradius = 0, radius = 0;
3390 bounds = (iqmbounds_t *) (pbase + header->ofs_bounds);
3391 VectorClear(loadmodel->normalmins);
3392 VectorClear(loadmodel->normalmaxs);
3393 for (i = 0; i < (int)header->num_frames;i++)
3395 bounds[i].mins[0] = LittleFloat(bounds[i].mins[0]);
3396 bounds[i].mins[1] = LittleFloat(bounds[i].mins[1]);
3397 bounds[i].mins[2] = LittleFloat(bounds[i].mins[2]);
3398 bounds[i].maxs[0] = LittleFloat(bounds[i].maxs[0]);
3399 bounds[i].maxs[1] = LittleFloat(bounds[i].maxs[1]);
3400 bounds[i].maxs[2] = LittleFloat(bounds[i].maxs[2]);
3401 bounds[i].xyradius = LittleFloat(bounds[i].xyradius);
3402 bounds[i].radius = LittleFloat(bounds[i].radius);
3405 VectorCopy(bounds[i].mins, loadmodel->normalmins);
3406 VectorCopy(bounds[i].maxs, loadmodel->normalmaxs);
3410 if (loadmodel->normalmins[0] > bounds[i].mins[0]) loadmodel->normalmins[0] = bounds[i].mins[0];
3411 if (loadmodel->normalmins[1] > bounds[i].mins[1]) loadmodel->normalmins[1] = bounds[i].mins[1];
3412 if (loadmodel->normalmins[2] > bounds[i].mins[2]) loadmodel->normalmins[2] = bounds[i].mins[2];
3413 if (loadmodel->normalmaxs[0] < bounds[i].maxs[0]) loadmodel->normalmaxs[0] = bounds[i].maxs[0];
3414 if (loadmodel->normalmaxs[1] < bounds[i].maxs[1]) loadmodel->normalmaxs[1] = bounds[i].maxs[1];
3415 if (loadmodel->normalmaxs[2] < bounds[i].maxs[2]) loadmodel->normalmaxs[2] = bounds[i].maxs[2];
3417 if (bounds[i].xyradius > xyradius)
3418 xyradius = bounds[i].xyradius;
3419 if (bounds[i].radius > radius)
3420 radius = bounds[i].radius;
3422 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -xyradius;
3423 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = xyradius;
3424 loadmodel->yawmins[2] = loadmodel->normalmins[2];
3425 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
3426 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
3427 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
3428 loadmodel->radius = radius;
3429 loadmodel->radius2 = radius * radius;
3432 // load triangle data
3433 inelements = (const int *) (pbase + header->ofs_triangles);
3434 outelements = loadmodel->surfmesh.data_element3i;
3435 for (i = 0;i < (int)header->num_triangles;i++)
3437 outelements[0] = LittleLong(inelements[0]);
3438 outelements[1] = LittleLong(inelements[1]);
3439 outelements[2] = LittleLong(inelements[2]);
3443 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, header->num_vertexes, __FILE__, __LINE__);
3445 if (header->ofs_neighbors)
3447 inelements = (const int *) (pbase + header->ofs_neighbors);
3448 outelements = loadmodel->surfmesh.data_neighbor3i;
3449 for (i = 0;i < (int)header->num_triangles;i++)
3451 outelements[0] = LittleLong(inelements[0]);
3452 outelements[1] = LittleLong(inelements[1]);
3453 outelements[2] = LittleLong(inelements[2]);
3460 outvertex = loadmodel->surfmesh.data_vertex3f;
3461 for (i = 0;i < (int)header->num_vertexes;i++)
3463 outvertex[0] = LittleFloat(vposition[0]);
3464 outvertex[1] = LittleFloat(vposition[1]);
3465 outvertex[2] = LittleFloat(vposition[2]);
3470 outtexcoord = loadmodel->surfmesh.data_texcoordtexture2f;
3471 for (i = 0;i < (int)header->num_vertexes;i++)
3473 outtexcoord[0] = LittleFloat(vtexcoord[0]);
3474 outtexcoord[1] = LittleFloat(vtexcoord[1]);
3481 outnormal = loadmodel->surfmesh.data_normal3f;
3482 for (i = 0;i < (int)header->num_vertexes;i++)
3484 outnormal[0] = LittleFloat(vnormal[0]);
3485 outnormal[1] = LittleFloat(vnormal[1]);
3486 outnormal[2] = LittleFloat(vnormal[2]);
3492 if(vnormal && vtangent)
3494 outnormal = loadmodel->surfmesh.data_normal3f;
3495 outsvector = loadmodel->surfmesh.data_svector3f;
3496 outtvector = loadmodel->surfmesh.data_tvector3f;
3497 for (i = 0;i < (int)header->num_vertexes;i++)
3499 outsvector[0] = LittleFloat(vtangent[0]);
3500 outsvector[1] = LittleFloat(vtangent[1]);
3501 outsvector[2] = LittleFloat(vtangent[2]);
3502 if(LittleFloat(vtangent[3]) < 0)
3503 CrossProduct(outsvector, outnormal, outtvector);
3505 CrossProduct(outnormal, outsvector, outtvector);
3513 for (i = 0; i < (int)header->num_vertexes;i++)
3515 blendweights_t weights;
3516 memcpy(weights.index, vblendindexes + i*4, 4);
3517 memcpy(weights.influence, vblendweights + i*4, 4);
3518 loadmodel->surfmesh.blends[i] = Mod_Skeletal_AddBlend(loadmodel, &weights);
3522 mesh = (iqmmesh_t *) (pbase + header->ofs_meshes);
3523 for (i = 0;i < (int)header->num_meshes;i++)
3525 msurface_t *surface;
3527 mesh[i].name = LittleLong(mesh[i].name);
3528 mesh[i].material = LittleLong(mesh[i].material);
3529 mesh[i].first_vertex = LittleLong(mesh[i].first_vertex);
3530 mesh[i].num_vertexes = LittleLong(mesh[i].num_vertexes);
3531 mesh[i].first_triangle = LittleLong(mesh[i].first_triangle);
3532 mesh[i].num_triangles = LittleLong(mesh[i].num_triangles);
3534 loadmodel->sortedmodelsurfaces[i] = i;
3535 surface = loadmodel->data_surfaces + i;
3536 surface->texture = loadmodel->data_textures + i;
3537 surface->num_firsttriangle = mesh[i].first_triangle;
3538 surface->num_triangles = mesh[i].num_triangles;
3539 surface->num_firstvertex = mesh[i].first_vertex;
3540 surface->num_vertices = mesh[i].num_vertexes;
3542 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, &text[mesh[i].name], &text[mesh[i].material]);
3545 Mod_FreeSkinFiles(skinfiles);
3546 Mod_MakeSortedSurfaces(loadmodel);
3548 // compute all the mesh information that was not loaded from the file
3549 if (loadmodel->surfmesh.data_element3s)
3550 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3551 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3553 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
3554 if (!vnormal || !vtangent)
3555 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);
3556 if (!header->ofs_neighbors)
3557 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3558 if (!header->ofs_bounds)
3559 Mod_Alias_CalculateBoundingBox();
3561 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
3563 if (!loadmodel->surfmesh.isanimated)
3565 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3566 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3567 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3568 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3569 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;