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 skinfileitem_t *skinfileitem;
961 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
962 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
964 memset(skin, 0, sizeof(*skin));
966 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
968 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
969 if (!strcmp(skinfileitem->name, meshname))
971 Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
977 // don't render unmentioned meshes
978 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
979 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
984 Mod_LoadTextureFromQ3Shader(skin, shadername, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
987 #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);
988 #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);
989 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
991 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
992 float scales, scalet, interval;
996 stvert_t *pinstverts;
997 dtriangle_t *pintriangles;
998 daliasskintype_t *pinskintype;
999 daliasskingroup_t *pinskingroup;
1000 daliasskininterval_t *pinskinintervals;
1001 daliasframetype_t *pinframetype;
1002 daliasgroup_t *pinframegroup;
1003 unsigned char *datapointer, *startframes, *startskins;
1004 char name[MAX_QPATH];
1005 skinframe_t *tempskinframe;
1006 animscene_t *tempskinscenes;
1007 texture_t *tempaliasskins;
1009 int *vertonseam, *vertremap;
1010 skinfile_t *skinfiles;
1012 datapointer = (unsigned char *)buffer;
1013 pinmodel = (mdl_t *)datapointer;
1014 datapointer += sizeof(mdl_t);
1016 version = LittleLong (pinmodel->version);
1017 if (version != ALIAS_VERSION)
1018 Host_Error ("%s has wrong version number (%i should be %i)",
1019 loadmodel->name, version, ALIAS_VERSION);
1021 loadmodel->modeldatatypestring = "MDL";
1023 loadmodel->type = mod_alias;
1024 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1025 loadmodel->DrawSky = NULL;
1026 loadmodel->DrawAddWaterPlanes = NULL;
1027 loadmodel->Draw = R_Q1BSP_Draw;
1028 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1029 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1030 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1031 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1032 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1033 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1034 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1035 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1036 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1037 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1038 loadmodel->PointSuperContents = NULL;
1040 loadmodel->num_surfaces = 1;
1041 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1042 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
1043 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1044 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1045 loadmodel->sortedmodelsurfaces[0] = 0;
1047 loadmodel->numskins = LittleLong(pinmodel->numskins);
1048 BOUNDI(loadmodel->numskins,0,65536);
1049 skinwidth = LittleLong (pinmodel->skinwidth);
1050 BOUNDI(skinwidth,0,65536);
1051 skinheight = LittleLong (pinmodel->skinheight);
1052 BOUNDI(skinheight,0,65536);
1053 numverts = LittleLong(pinmodel->numverts);
1054 BOUNDI(numverts,0,65536);
1055 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
1056 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
1057 loadmodel->numframes = LittleLong(pinmodel->numframes);
1058 BOUNDI(loadmodel->numframes,0,65536);
1059 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
1060 BOUNDI((int)loadmodel->synctype,0,2);
1061 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1062 i = LittleLong (pinmodel->flags);
1063 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1065 for (i = 0;i < 3;i++)
1067 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
1068 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
1071 startskins = datapointer;
1073 for (i = 0;i < loadmodel->numskins;i++)
1075 pinskintype = (daliasskintype_t *)datapointer;
1076 datapointer += sizeof(daliasskintype_t);
1077 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
1081 pinskingroup = (daliasskingroup_t *)datapointer;
1082 datapointer += sizeof(daliasskingroup_t);
1083 groupskins = LittleLong(pinskingroup->numskins);
1084 datapointer += sizeof(daliasskininterval_t) * groupskins;
1087 for (j = 0;j < groupskins;j++)
1089 datapointer += skinwidth * skinheight;
1094 pinstverts = (stvert_t *)datapointer;
1095 datapointer += sizeof(stvert_t) * numverts;
1097 pintriangles = (dtriangle_t *)datapointer;
1098 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
1100 startframes = datapointer;
1101 loadmodel->surfmesh.num_morphframes = 0;
1102 for (i = 0;i < loadmodel->numframes;i++)
1104 pinframetype = (daliasframetype_t *)datapointer;
1105 datapointer += sizeof(daliasframetype_t);
1106 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
1110 pinframegroup = (daliasgroup_t *)datapointer;
1111 datapointer += sizeof(daliasgroup_t);
1112 groupframes = LittleLong(pinframegroup->numframes);
1113 datapointer += sizeof(daliasinterval_t) * groupframes;
1116 for (j = 0;j < groupframes;j++)
1118 datapointer += sizeof(daliasframe_t);
1119 datapointer += sizeof(trivertx_t) * numverts;
1120 loadmodel->surfmesh.num_morphframes++;
1123 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1125 // store texture coordinates into temporary array, they will be stored
1126 // after usage is determined (triangle data)
1127 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
1128 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
1129 vertonseam = vertremap + numverts * 2;
1131 scales = 1.0 / skinwidth;
1132 scalet = 1.0 / skinheight;
1133 for (i = 0;i < numverts;i++)
1135 vertonseam[i] = LittleLong(pinstverts[i].onseam);
1136 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
1137 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
1138 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
1139 vertst[(i+numverts)*2+1] = vertst[i*2+1];
1142 // load triangle data
1143 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1145 // read the triangle elements
1146 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1147 for (j = 0;j < 3;j++)
1148 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1149 // validate (note numverts is used because this is the original data)
1150 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1151 // now butcher the elements according to vertonseam and tri->facesfront
1152 // and then compact the vertex set to remove duplicates
1153 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1154 if (!LittleLong(pintriangles[i].facesfront)) // backface
1155 for (j = 0;j < 3;j++)
1156 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1157 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1159 // (this uses vertremap to count usage to save some memory)
1160 for (i = 0;i < numverts*2;i++)
1162 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1163 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1164 // build remapping table and compact array
1165 loadmodel->surfmesh.num_vertices = 0;
1166 for (i = 0;i < numverts*2;i++)
1170 vertremap[i] = loadmodel->surfmesh.num_vertices;
1171 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1172 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1173 loadmodel->surfmesh.num_vertices++;
1176 vertremap[i] = -1; // not used at all
1178 // remap the elements to the new vertex set
1179 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1180 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1181 // store the texture coordinates
1182 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1183 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1185 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1186 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1189 // generate ushort elements array if possible
1190 if (loadmodel->surfmesh.num_vertices <= 65536)
1191 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1192 if (loadmodel->surfmesh.data_element3s)
1193 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1194 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1197 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1198 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1199 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1200 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1201 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1202 Mod_Alias_CalculateBoundingBox();
1203 Mod_Alias_MorphMesh_CompileFrames();
1206 Mem_Free(vertremap);
1209 skinfiles = Mod_LoadSkinFiles();
1212 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1213 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1214 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1215 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1216 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1217 Mod_FreeSkinFiles(skinfiles);
1218 for (i = 0;i < loadmodel->numskins;i++)
1220 loadmodel->skinscenes[i].firstframe = i;
1221 loadmodel->skinscenes[i].framecount = 1;
1222 loadmodel->skinscenes[i].loop = true;
1223 loadmodel->skinscenes[i].framerate = 10;
1228 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1229 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1230 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1231 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1233 datapointer = startskins;
1234 for (i = 0;i < loadmodel->numskins;i++)
1236 pinskintype = (daliasskintype_t *)datapointer;
1237 datapointer += sizeof(daliasskintype_t);
1239 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1246 pinskingroup = (daliasskingroup_t *)datapointer;
1247 datapointer += sizeof(daliasskingroup_t);
1249 groupskins = LittleLong (pinskingroup->numskins);
1251 pinskinintervals = (daliasskininterval_t *)datapointer;
1252 datapointer += sizeof(daliasskininterval_t) * groupskins;
1254 interval = LittleFloat(pinskinintervals[0].interval);
1255 if (interval < 0.01f)
1257 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1262 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1263 loadmodel->skinscenes[i].firstframe = totalskins;
1264 loadmodel->skinscenes[i].framecount = groupskins;
1265 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1266 loadmodel->skinscenes[i].loop = true;
1268 for (j = 0;j < groupskins;j++)
1271 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1273 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1274 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))
1275 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));
1276 datapointer += skinwidth * skinheight;
1280 // check for skins that don't exist in the model, but do exist as external images
1281 // (this was added because yummyluv kept pestering me about support for it)
1282 // TODO: support shaders here?
1283 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)))
1285 // expand the arrays to make room
1286 tempskinscenes = loadmodel->skinscenes;
1287 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1288 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1289 Mem_Free(tempskinscenes);
1291 tempaliasskins = loadmodel->data_textures;
1292 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1293 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1294 Mem_Free(tempaliasskins);
1296 // store the info about the new skin
1297 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1298 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1299 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1300 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1301 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1302 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1304 //increase skin counts
1305 loadmodel->numskins++;
1308 // fix up the pointers since they are pointing at the old textures array
1309 // FIXME: this is a hack!
1310 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1311 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1315 surface = loadmodel->data_surfaces;
1316 surface->texture = loadmodel->data_textures;
1317 surface->num_firsttriangle = 0;
1318 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1319 surface->num_firstvertex = 0;
1320 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1322 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1324 if (!loadmodel->surfmesh.isanimated)
1326 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1327 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1328 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1329 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1330 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1334 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1336 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1337 float iskinwidth, iskinheight;
1338 unsigned char *data;
1339 msurface_t *surface;
1341 unsigned char *base, *datapointer;
1342 md2frame_t *pinframe;
1344 md2triangle_t *intri;
1345 unsigned short *inst;
1346 struct md2verthash_s
1348 struct md2verthash_s *next;
1352 *hash, **md2verthash, *md2verthashdata;
1353 skinfile_t *skinfiles;
1355 pinmodel = (md2_t *)buffer;
1356 base = (unsigned char *)buffer;
1358 version = LittleLong (pinmodel->version);
1359 if (version != MD2ALIAS_VERSION)
1360 Host_Error ("%s has wrong version number (%i should be %i)",
1361 loadmodel->name, version, MD2ALIAS_VERSION);
1363 loadmodel->modeldatatypestring = "MD2";
1365 loadmodel->type = mod_alias;
1366 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1367 loadmodel->DrawSky = NULL;
1368 loadmodel->DrawAddWaterPlanes = NULL;
1369 loadmodel->Draw = R_Q1BSP_Draw;
1370 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1371 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1372 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1373 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1374 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1375 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1376 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1377 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1378 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1379 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1380 loadmodel->PointSuperContents = NULL;
1382 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1383 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1384 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1385 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1386 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1387 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1388 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1389 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1391 end = LittleLong(pinmodel->ofs_end);
1392 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1393 Host_Error ("%s is not a valid model", loadmodel->name);
1394 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1395 Host_Error ("%s is not a valid model", loadmodel->name);
1396 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1397 Host_Error ("%s is not a valid model", loadmodel->name);
1398 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1399 Host_Error ("%s is not a valid model", loadmodel->name);
1400 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1401 Host_Error ("%s is not a valid model", loadmodel->name);
1403 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1404 numxyz = LittleLong(pinmodel->num_xyz);
1405 numst = LittleLong(pinmodel->num_st);
1406 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1407 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1408 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1409 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1410 skinwidth = LittleLong(pinmodel->skinwidth);
1411 skinheight = LittleLong(pinmodel->skinheight);
1412 iskinwidth = 1.0f / skinwidth;
1413 iskinheight = 1.0f / skinheight;
1415 loadmodel->num_surfaces = 1;
1416 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1417 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]));
1418 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1419 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1420 loadmodel->sortedmodelsurfaces[0] = 0;
1421 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1422 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1423 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1424 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1426 loadmodel->synctype = ST_RAND;
1429 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1430 skinfiles = Mod_LoadSkinFiles();
1433 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1434 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1435 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1436 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1437 Mod_FreeSkinFiles(skinfiles);
1439 else if (loadmodel->numskins)
1441 // skins found (most likely not a player model)
1442 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1443 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1444 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1445 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1446 Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
1450 // no skins (most likely a player model)
1451 loadmodel->numskins = 1;
1452 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1453 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1454 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1455 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1458 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1459 for (i = 0;i < loadmodel->numskins;i++)
1461 loadmodel->skinscenes[i].firstframe = i;
1462 loadmodel->skinscenes[i].framecount = 1;
1463 loadmodel->skinscenes[i].loop = true;
1464 loadmodel->skinscenes[i].framerate = 10;
1467 // load the triangles and stvert data
1468 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1469 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1470 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1471 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1472 // swap the triangle list
1473 loadmodel->surfmesh.num_vertices = 0;
1474 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1476 for (j = 0;j < 3;j++)
1478 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1479 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1482 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1487 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1490 hashindex = (xyz * 256 + st) & 65535;
1491 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1492 if (hash->xyz == xyz && hash->st == st)
1496 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1499 hash->next = md2verthash[hashindex];
1500 md2verthash[hashindex] = hash;
1502 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1506 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1507 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));
1508 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1509 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1510 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1513 hash = md2verthashdata + i;
1514 vertremap[i] = hash->xyz;
1515 sts = LittleShort(inst[hash->st*2+0]);
1516 stt = LittleShort(inst[hash->st*2+1]);
1517 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1519 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1523 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1524 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1527 Mem_Free(md2verthash);
1528 Mem_Free(md2verthashdata);
1530 // generate ushort elements array if possible
1531 if (loadmodel->surfmesh.num_vertices <= 65536)
1532 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1533 if (loadmodel->surfmesh.data_element3s)
1534 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1535 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1538 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1539 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1544 pinframe = (md2frame_t *)datapointer;
1545 datapointer += sizeof(md2frame_t);
1546 // store the frame scale/translate into the appropriate array
1547 for (j = 0;j < 3;j++)
1549 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1550 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1552 // convert the vertices
1553 v = (trivertx_t *)datapointer;
1554 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1555 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1556 out[k] = v[vertremap[k]];
1557 datapointer += numxyz * sizeof(trivertx_t);
1559 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1560 loadmodel->animscenes[i].firstframe = i;
1561 loadmodel->animscenes[i].framecount = 1;
1562 loadmodel->animscenes[i].framerate = 10;
1563 loadmodel->animscenes[i].loop = true;
1566 Mem_Free(vertremap);
1568 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1569 Mod_Alias_CalculateBoundingBox();
1570 Mod_Alias_MorphMesh_CompileFrames();
1572 surface = loadmodel->data_surfaces;
1573 surface->texture = loadmodel->data_textures;
1574 surface->num_firsttriangle = 0;
1575 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1576 surface->num_firstvertex = 0;
1577 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1579 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1581 if (!loadmodel->surfmesh.isanimated)
1583 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1584 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1585 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1586 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1587 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1591 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1593 int i, j, k, version, meshvertices, meshtriangles;
1594 unsigned char *data;
1595 msurface_t *surface;
1596 md3modelheader_t *pinmodel;
1597 md3frameinfo_t *pinframe;
1600 skinfile_t *skinfiles;
1602 pinmodel = (md3modelheader_t *)buffer;
1604 if (memcmp(pinmodel->identifier, "IDP3", 4))
1605 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1606 version = LittleLong (pinmodel->version);
1607 if (version != MD3VERSION)
1608 Host_Error ("%s has wrong version number (%i should be %i)",
1609 loadmodel->name, version, MD3VERSION);
1611 skinfiles = Mod_LoadSkinFiles();
1612 if (loadmodel->numskins < 1)
1613 loadmodel->numskins = 1;
1615 loadmodel->modeldatatypestring = "MD3";
1617 loadmodel->type = mod_alias;
1618 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1619 loadmodel->DrawSky = NULL;
1620 loadmodel->DrawAddWaterPlanes = NULL;
1621 loadmodel->Draw = R_Q1BSP_Draw;
1622 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1623 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1624 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1625 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1626 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1627 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1628 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1629 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1630 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1631 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1632 loadmodel->PointSuperContents = NULL;
1633 loadmodel->synctype = ST_RAND;
1634 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1635 i = LittleLong (pinmodel->flags);
1636 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1638 // set up some global info about the model
1639 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1640 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1642 // make skinscenes for the skins (no groups)
1643 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1644 for (i = 0;i < loadmodel->numskins;i++)
1646 loadmodel->skinscenes[i].firstframe = i;
1647 loadmodel->skinscenes[i].framecount = 1;
1648 loadmodel->skinscenes[i].loop = true;
1649 loadmodel->skinscenes[i].framerate = 10;
1653 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1654 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1656 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1657 loadmodel->animscenes[i].firstframe = i;
1658 loadmodel->animscenes[i].framecount = 1;
1659 loadmodel->animscenes[i].framerate = 10;
1660 loadmodel->animscenes[i].loop = true;
1664 loadmodel->num_tagframes = loadmodel->numframes;
1665 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1666 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1667 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1669 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1670 for (j = 0;j < 9;j++)
1671 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1672 for (j = 0;j < 3;j++)
1673 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1674 //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);
1680 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)))
1682 if (memcmp(pinmesh->identifier, "IDP3", 4))
1683 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1684 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1685 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1686 meshvertices += LittleLong(pinmesh->num_vertices);
1687 meshtriangles += LittleLong(pinmesh->num_triangles);
1690 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1691 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1692 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1693 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));
1694 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1695 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1696 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1697 loadmodel->surfmesh.num_vertices = meshvertices;
1698 loadmodel->surfmesh.num_triangles = meshtriangles;
1699 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1700 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1701 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1702 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1703 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1704 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1705 if (meshvertices <= 65536)
1706 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1710 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)))
1712 if (memcmp(pinmesh->identifier, "IDP3", 4))
1713 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1714 loadmodel->sortedmodelsurfaces[i] = i;
1715 surface = loadmodel->data_surfaces + i;
1716 surface->texture = loadmodel->data_textures + i;
1717 surface->num_firsttriangle = meshtriangles;
1718 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1719 surface->num_firstvertex = meshvertices;
1720 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1721 meshvertices += surface->num_vertices;
1722 meshtriangles += surface->num_triangles;
1724 for (j = 0;j < surface->num_triangles * 3;j++)
1725 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1726 for (j = 0;j < surface->num_vertices;j++)
1728 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1729 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1731 for (j = 0;j < loadmodel->numframes;j++)
1733 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1734 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1735 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1737 out->origin[0] = LittleShort(in->origin[0]);
1738 out->origin[1] = LittleShort(in->origin[1]);
1739 out->origin[2] = LittleShort(in->origin[2]);
1740 out->pitch = in->pitch;
1745 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1747 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1749 if (loadmodel->surfmesh.data_element3s)
1750 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1751 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1752 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1753 Mod_Alias_MorphMesh_CompileFrames();
1754 Mod_Alias_CalculateBoundingBox();
1755 Mod_FreeSkinFiles(skinfiles);
1756 Mod_MakeSortedSurfaces(loadmodel);
1758 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1759 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1761 if (!loadmodel->surfmesh.isanimated)
1763 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1764 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1765 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1766 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1767 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1771 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1773 zymtype1header_t *pinmodel, *pheader;
1774 unsigned char *pbase;
1775 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1776 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose, f, biggestorigin, tempvec[3], modelscale;
1777 zymvertex_t *verts, *vertdata;
1781 skinfile_t *skinfiles;
1782 unsigned char *data;
1783 msurface_t *surface;
1785 pinmodel = (zymtype1header_t *)buffer;
1786 pbase = (unsigned char *)buffer;
1787 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1788 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1789 if (BigLong(pinmodel->type) != 1)
1790 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1792 loadmodel->modeldatatypestring = "ZYM";
1794 loadmodel->type = mod_alias;
1795 loadmodel->synctype = ST_RAND;
1799 pheader->type = BigLong(pinmodel->type);
1800 pheader->filesize = BigLong(pinmodel->filesize);
1801 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1802 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1803 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1804 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1805 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1806 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1807 pheader->radius = BigFloat(pinmodel->radius);
1808 pheader->numverts = BigLong(pinmodel->numverts);
1809 pheader->numtris = BigLong(pinmodel->numtris);
1810 pheader->numshaders = BigLong(pinmodel->numshaders);
1811 pheader->numbones = BigLong(pinmodel->numbones);
1812 pheader->numscenes = BigLong(pinmodel->numscenes);
1813 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1814 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1815 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1816 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1817 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1818 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1819 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1820 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1821 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1822 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1823 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1824 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1825 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1826 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1827 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1828 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1829 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1830 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1832 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1834 Con_Printf("%s has no geometry\n", loadmodel->name);
1837 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1839 Con_Printf("%s has no animations\n", loadmodel->name);
1843 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1844 loadmodel->DrawSky = NULL;
1845 loadmodel->DrawAddWaterPlanes = NULL;
1846 loadmodel->Draw = R_Q1BSP_Draw;
1847 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1848 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1849 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1850 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1851 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1852 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1853 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1854 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1855 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1856 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1857 loadmodel->PointSuperContents = NULL;
1859 loadmodel->numframes = pheader->numscenes;
1860 loadmodel->num_surfaces = pheader->numshaders;
1862 skinfiles = Mod_LoadSkinFiles();
1863 if (loadmodel->numskins < 1)
1864 loadmodel->numskins = 1;
1866 // make skinscenes for the skins (no groups)
1867 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1868 for (i = 0;i < loadmodel->numskins;i++)
1870 loadmodel->skinscenes[i].firstframe = i;
1871 loadmodel->skinscenes[i].framecount = 1;
1872 loadmodel->skinscenes[i].loop = true;
1873 loadmodel->skinscenes[i].framerate = 10;
1877 modelradius = pheader->radius;
1878 for (i = 0;i < 3;i++)
1880 loadmodel->normalmins[i] = pheader->mins[i];
1881 loadmodel->normalmaxs[i] = pheader->maxs[i];
1882 loadmodel->rotatedmins[i] = -modelradius;
1883 loadmodel->rotatedmaxs[i] = modelradius;
1885 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1886 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1887 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1888 if (loadmodel->yawmaxs[0] > modelradius)
1889 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1890 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1891 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1892 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1893 loadmodel->radius = modelradius;
1894 loadmodel->radius2 = modelradius * modelradius;
1896 // go through the lumps, swapping things
1898 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1899 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1900 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1901 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1902 for (i = 0;i < pheader->numscenes;i++)
1904 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1905 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1906 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1907 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1908 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1909 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1910 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1911 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1912 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1913 if (loadmodel->animscenes[i].framerate < 0)
1914 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1918 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1919 loadmodel->num_bones = pheader->numbones;
1920 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1921 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1922 for (i = 0;i < pheader->numbones;i++)
1924 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1925 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1926 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1927 if (loadmodel->data_bones[i].parent >= i)
1928 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1931 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1932 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1933 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1934 for (i = 0;i < pheader->numverts;i++)
1936 vertbonecounts[i] = BigLong(bonecount[i]);
1937 if (vertbonecounts[i] != 1)
1938 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1941 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1943 meshvertices = pheader->numverts;
1944 meshtriangles = pheader->numtris;
1946 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1947 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1948 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1949 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]));
1950 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1951 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1952 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1953 loadmodel->surfmesh.num_vertices = meshvertices;
1954 loadmodel->surfmesh.num_triangles = meshtriangles;
1955 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1956 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1957 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1958 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1959 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1960 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1961 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1962 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1963 loadmodel->surfmesh.num_blends = 0;
1964 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
1965 if (loadmodel->surfmesh.num_vertices <= 65536)
1966 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1967 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
1968 loadmodel->surfmesh.data_blendweights = NULL;
1970 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1971 poses = (float *) (pheader->lump_poses.start + pbase);
1972 // figure out scale of model from root bone, for compatibility with old zmodel versions
1973 tempvec[0] = BigFloat(poses[0]);
1974 tempvec[1] = BigFloat(poses[1]);
1975 tempvec[2] = BigFloat(poses[2]);
1976 modelscale = VectorLength(tempvec);
1978 for (i = 0;i < loadmodel->num_bones * numposes * 12;i++)
1980 f = fabs(BigFloat(poses[i]));
1981 biggestorigin = max(biggestorigin, f);
1983 loadmodel->num_posescale = biggestorigin / 32767.0f;
1984 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
1985 for (i = 0;i < numposes;i++)
1987 const float *frameposes = (float *) (pheader->lump_poses.start + pbase) + 12*i*loadmodel->num_bones;
1988 for (j = 0;j < loadmodel->num_bones;j++)
1991 matrix4x4_t posematrix;
1992 for (k = 0;k < 12;k++)
1993 pose[k] = BigFloat(frameposes[j*12+k]);
1994 //if (j < loadmodel->num_bones)
1995 // 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));
1996 // scale child bones to match the root scale
1997 if (loadmodel->data_bones[j].parent >= 0)
1999 pose[3] *= modelscale;
2000 pose[7] *= modelscale;
2001 pose[11] *= modelscale;
2003 // normalize rotation matrix
2004 VectorNormalize(pose + 0);
2005 VectorNormalize(pose + 4);
2006 VectorNormalize(pose + 8);
2007 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2008 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
2012 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
2013 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
2014 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
2015 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2016 // (converting from weight-blending skeletal animation to
2017 // deformation-based skeletal animation)
2018 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2019 for (i = 0;i < loadmodel->num_bones;i++)
2022 for (k = 0;k < 12;k++)
2023 m[k] = BigFloat(poses[i*12+k]);
2024 if (loadmodel->data_bones[i].parent >= 0)
2025 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2027 for (k = 0;k < 12;k++)
2028 bonepose[12*i+k] = m[k];
2030 for (j = 0;j < pheader->numverts;j++)
2032 // this format really should have had a per vertexweight weight value...
2033 // but since it does not, the weighting is completely ignored and
2034 // only one weight is allowed per vertex
2035 int boneindex = BigLong(vertdata[j].bonenum);
2036 const float *m = bonepose + 12 * boneindex;
2037 float relativeorigin[3];
2038 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
2039 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
2040 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
2041 // transform the vertex bone weight into the base mesh
2042 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
2043 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
2044 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
2045 // store the weight as the primary weight on this vertex
2046 loadmodel->surfmesh.blends[j] = boneindex;
2049 // normals and tangents are calculated after elements are loaded
2051 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
2052 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
2053 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
2054 for (i = 0;i < pheader->numverts;i++)
2056 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
2057 // flip T coordinate for OpenGL
2058 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
2061 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
2062 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
2063 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
2065 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
2066 //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)
2067 // byteswap, validate, and swap winding order of tris
2068 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
2069 if (pheader->lump_render.length != count)
2070 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
2071 renderlist = (int *) (pheader->lump_render.start + pbase);
2072 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
2074 for (i = 0;i < loadmodel->num_surfaces;i++)
2076 int firstvertex, lastvertex;
2077 if (renderlist >= renderlistend)
2078 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2079 count = BigLong(*renderlist);renderlist++;
2080 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
2081 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2083 loadmodel->sortedmodelsurfaces[i] = i;
2084 surface = loadmodel->data_surfaces + i;
2085 surface->texture = loadmodel->data_textures + i;
2086 surface->num_firsttriangle = meshtriangles;
2087 surface->num_triangles = count;
2088 meshtriangles += surface->num_triangles;
2090 // load the elements
2091 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2092 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
2094 outelements[j*3+2] = BigLong(renderlist[0]);
2095 outelements[j*3+1] = BigLong(renderlist[1]);
2096 outelements[j*3+0] = BigLong(renderlist[2]);
2098 // validate the elements and find the used vertex range
2099 firstvertex = meshvertices;
2101 for (j = 0;j < surface->num_triangles * 3;j++)
2103 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
2104 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
2105 firstvertex = min(firstvertex, outelements[j]);
2106 lastvertex = max(lastvertex, outelements[j]);
2108 surface->num_firstvertex = firstvertex;
2109 surface->num_vertices = lastvertex + 1 - firstvertex;
2111 // since zym models do not have named sections, reuse their shader
2112 // name as the section name
2113 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
2114 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
2116 Mod_FreeSkinFiles(skinfiles);
2117 Mem_Free(vertbonecounts);
2119 Mod_MakeSortedSurfaces(loadmodel);
2121 // compute all the mesh information that was not loaded from the file
2122 if (loadmodel->surfmesh.data_element3s)
2123 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2124 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2125 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2126 Mod_BuildBaseBonePoses();
2127 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2128 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);
2129 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2131 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2133 if (!loadmodel->surfmesh.isanimated)
2135 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2136 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2137 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2138 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2139 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2143 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2145 dpmheader_t *pheader;
2149 unsigned char *pbase;
2150 int i, j, k, meshvertices, meshtriangles;
2151 skinfile_t *skinfiles;
2152 unsigned char *data;
2154 float biggestorigin, tempvec[3], modelscale;
2158 pheader = (dpmheader_t *)buffer;
2159 pbase = (unsigned char *)buffer;
2160 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2161 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2162 if (BigLong(pheader->type) != 2)
2163 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2165 loadmodel->modeldatatypestring = "DPM";
2167 loadmodel->type = mod_alias;
2168 loadmodel->synctype = ST_RAND;
2171 pheader->type = BigLong(pheader->type);
2172 pheader->filesize = BigLong(pheader->filesize);
2173 pheader->mins[0] = BigFloat(pheader->mins[0]);
2174 pheader->mins[1] = BigFloat(pheader->mins[1]);
2175 pheader->mins[2] = BigFloat(pheader->mins[2]);
2176 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2177 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2178 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2179 pheader->yawradius = BigFloat(pheader->yawradius);
2180 pheader->allradius = BigFloat(pheader->allradius);
2181 pheader->num_bones = BigLong(pheader->num_bones);
2182 pheader->num_meshs = BigLong(pheader->num_meshs);
2183 pheader->num_frames = BigLong(pheader->num_frames);
2184 pheader->ofs_bones = BigLong(pheader->ofs_bones);
2185 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2186 pheader->ofs_frames = BigLong(pheader->ofs_frames);
2188 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2190 Con_Printf("%s has no geometry\n", loadmodel->name);
2193 if (pheader->num_frames < 1)
2195 Con_Printf("%s has no frames\n", loadmodel->name);
2199 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2200 loadmodel->DrawSky = NULL;
2201 loadmodel->DrawAddWaterPlanes = NULL;
2202 loadmodel->Draw = R_Q1BSP_Draw;
2203 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2204 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2205 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2206 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2207 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2208 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2209 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2210 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2211 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2212 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2213 loadmodel->PointSuperContents = NULL;
2216 for (i = 0;i < 3;i++)
2218 loadmodel->normalmins[i] = pheader->mins[i];
2219 loadmodel->normalmaxs[i] = pheader->maxs[i];
2220 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2221 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2222 loadmodel->rotatedmins[i] = -pheader->allradius;
2223 loadmodel->rotatedmaxs[i] = pheader->allradius;
2225 loadmodel->radius = pheader->allradius;
2226 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2228 // load external .skin files if present
2229 skinfiles = Mod_LoadSkinFiles();
2230 if (loadmodel->numskins < 1)
2231 loadmodel->numskins = 1;
2236 // gather combined statistics from the meshes
2237 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2238 for (i = 0;i < (int)pheader->num_meshs;i++)
2240 int numverts = BigLong(dpmmesh->num_verts);
2241 meshvertices += numverts;
2242 meshtriangles += BigLong(dpmmesh->num_tris);
2246 loadmodel->numframes = pheader->num_frames;
2247 loadmodel->num_bones = pheader->num_bones;
2248 loadmodel->num_poses = loadmodel->numframes;
2249 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2250 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2251 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2252 // do most allocations as one merged chunk
2253 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));
2254 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2255 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2256 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2257 loadmodel->surfmesh.num_vertices = meshvertices;
2258 loadmodel->surfmesh.num_triangles = meshtriangles;
2259 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2260 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2261 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2262 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2263 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2264 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2265 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2266 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2267 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2268 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2269 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2270 loadmodel->surfmesh.num_blends = 0;
2271 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2272 if (meshvertices <= 65536)
2273 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2274 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2275 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
2277 for (i = 0;i < loadmodel->numskins;i++)
2279 loadmodel->skinscenes[i].firstframe = i;
2280 loadmodel->skinscenes[i].framecount = 1;
2281 loadmodel->skinscenes[i].loop = true;
2282 loadmodel->skinscenes[i].framerate = 10;
2285 // load the bone info
2286 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2287 for (i = 0;i < loadmodel->num_bones;i++)
2289 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2290 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2291 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2292 if (loadmodel->data_bones[i].parent >= i)
2293 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2297 frames = (dpmframe_t *) (pbase + pheader->ofs_frames);
2298 // figure out scale of model from root bone, for compatibility with old dpmodel versions
2299 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2300 tempvec[0] = BigFloat(poses[0]);
2301 tempvec[1] = BigFloat(poses[1]);
2302 tempvec[2] = BigFloat(poses[2]);
2303 modelscale = VectorLength(tempvec);
2305 for (i = 0;i < loadmodel->numframes;i++)
2307 memcpy(loadmodel->animscenes[i].name, frames[i].name, sizeof(frames[i].name));
2308 loadmodel->animscenes[i].firstframe = i;
2309 loadmodel->animscenes[i].framecount = 1;
2310 loadmodel->animscenes[i].loop = true;
2311 loadmodel->animscenes[i].framerate = 10;
2312 // load the bone poses for this frame
2313 poses = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2314 for (j = 0;j < loadmodel->num_bones*12;j++)
2316 f = fabs(BigFloat(poses[j]));
2317 biggestorigin = max(biggestorigin, f);
2319 // stuff not processed here: mins, maxs, yawradius, allradius
2321 loadmodel->num_posescale = biggestorigin / 32767.0f;
2322 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2323 for (i = 0;i < loadmodel->numframes;i++)
2325 const float *frameposes = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2326 for (j = 0;j < loadmodel->num_bones;j++)
2329 matrix4x4_t posematrix;
2330 for (k = 0;k < 12;k++)
2331 pose[k] = BigFloat(frameposes[j*12+k]);
2332 // scale child bones to match the root scale
2333 if (loadmodel->data_bones[j].parent >= 0)
2335 pose[3] *= modelscale;
2336 pose[7] *= modelscale;
2337 pose[11] *= modelscale;
2339 // normalize rotation matrix
2340 VectorNormalize(pose + 0);
2341 VectorNormalize(pose + 4);
2342 VectorNormalize(pose + 8);
2343 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2344 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
2348 // load the meshes now
2349 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2352 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2353 // (converting from weight-blending skeletal animation to
2354 // deformation-based skeletal animation)
2355 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2356 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2357 for (i = 0;i < loadmodel->num_bones;i++)
2360 for (k = 0;k < 12;k++)
2361 m[k] = BigFloat(poses[i*12+k]);
2362 if (loadmodel->data_bones[i].parent >= 0)
2363 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2365 for (k = 0;k < 12;k++)
2366 bonepose[12*i+k] = m[k];
2368 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2370 const int *inelements;
2372 const float *intexcoord;
2373 msurface_t *surface;
2375 loadmodel->sortedmodelsurfaces[i] = i;
2376 surface = loadmodel->data_surfaces + i;
2377 surface->texture = loadmodel->data_textures + i;
2378 surface->num_firsttriangle = meshtriangles;
2379 surface->num_triangles = BigLong(dpmmesh->num_tris);
2380 surface->num_firstvertex = meshvertices;
2381 surface->num_vertices = BigLong(dpmmesh->num_verts);
2382 meshvertices += surface->num_vertices;
2383 meshtriangles += surface->num_triangles;
2385 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2386 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2387 for (j = 0;j < surface->num_triangles;j++)
2389 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2390 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2391 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2392 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2397 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2398 for (j = 0;j < surface->num_vertices*2;j++)
2399 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2401 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2402 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2404 int weightindex[4] = { 0, 0, 0, 0 };
2405 float weightinfluence[4] = { 0, 0, 0, 0 };
2407 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2408 data += sizeof(dpmvertex_t);
2409 for (k = 0;k < numweights;k++)
2411 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2412 int boneindex = BigLong(vert->bonenum);
2413 const float *m = bonepose + 12 * boneindex;
2414 float influence = BigFloat(vert->influence);
2415 float relativeorigin[3], relativenormal[3];
2416 relativeorigin[0] = BigFloat(vert->origin[0]);
2417 relativeorigin[1] = BigFloat(vert->origin[1]);
2418 relativeorigin[2] = BigFloat(vert->origin[2]);
2419 relativenormal[0] = BigFloat(vert->normal[0]);
2420 relativenormal[1] = BigFloat(vert->normal[1]);
2421 relativenormal[2] = BigFloat(vert->normal[2]);
2422 // blend the vertex bone weights into the base mesh
2423 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2424 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2425 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2426 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2427 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2428 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2431 // store the first (and often only) weight
2432 weightinfluence[0] = influence;
2433 weightindex[0] = boneindex;
2437 // sort the new weight into this vertex's weight table
2438 // (which only accepts up to 4 bones per vertex)
2439 for (l = 0;l < 4;l++)
2441 if (weightinfluence[l] < influence)
2443 // move weaker influence weights out of the way first
2445 for (l2 = 3;l2 > l;l2--)
2447 weightinfluence[l2] = weightinfluence[l2-1];
2448 weightindex[l2] = weightindex[l2-1];
2450 // store the new weight
2451 weightinfluence[l] = influence;
2452 weightindex[l] = boneindex;
2457 data += sizeof(dpmbonevert_t);
2459 loadmodel->surfmesh.blends[j] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
2462 // since dpm models do not have named sections, reuse their shader name as the section name
2463 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2465 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2467 if (loadmodel->surfmesh.num_blends < meshvertices)
2468 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2470 Mod_FreeSkinFiles(skinfiles);
2471 Mod_MakeSortedSurfaces(loadmodel);
2473 // compute all the mesh information that was not loaded from the file
2474 if (loadmodel->surfmesh.data_element3s)
2475 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2476 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2477 Mod_BuildBaseBonePoses();
2478 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);
2479 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2481 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2483 if (!loadmodel->surfmesh.isanimated)
2485 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2486 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2487 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2488 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2489 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2493 // no idea why PSK/PSA files contain weird quaternions but they do...
2494 #define PSKQUATNEGATIONS
2495 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2497 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2498 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2499 fs_offset_t filesize;
2504 pskboneinfo_t *bones;
2505 pskrawweights_t *rawweights;
2506 //pskboneinfo_t *animbones;
2507 pskaniminfo_t *anims;
2508 pskanimkeys_t *animkeys;
2509 void *animfilebuffer, *animbuffer, *animbufferend;
2510 unsigned char *data;
2512 skinfile_t *skinfiles;
2513 char animname[MAX_QPATH];
2515 float biggestorigin;
2517 pchunk = (pskchunk_t *)buffer;
2518 if (strcmp(pchunk->id, "ACTRHEAD"))
2519 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2521 loadmodel->modeldatatypestring = "PSK";
2523 loadmodel->type = mod_alias;
2524 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2525 loadmodel->DrawSky = NULL;
2526 loadmodel->DrawAddWaterPlanes = NULL;
2527 loadmodel->Draw = R_Q1BSP_Draw;
2528 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2529 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2530 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2531 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2532 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2533 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2534 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2535 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2536 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2537 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2538 loadmodel->PointSuperContents = NULL;
2539 loadmodel->synctype = ST_RAND;
2541 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2542 strlcat(animname, ".psa", sizeof(animname));
2543 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2544 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2545 if (animbuffer == NULL)
2546 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2565 while (buffer < bufferend)
2567 pchunk = (pskchunk_t *)buffer;
2568 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2569 version = LittleLong(pchunk->version);
2570 recordsize = LittleLong(pchunk->recordsize);
2571 numrecords = LittleLong(pchunk->numrecords);
2572 if (developer_extra.integer)
2573 Con_DPrintf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2574 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2575 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);
2576 if (!strcmp(pchunk->id, "ACTRHEAD"))
2580 else if (!strcmp(pchunk->id, "PNTS0000"))
2583 if (recordsize != sizeof(*p))
2584 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2585 // byteswap in place and keep the pointer
2586 numpnts = numrecords;
2587 pnts = (pskpnts_t *)buffer;
2588 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2590 p->origin[0] = LittleFloat(p->origin[0]);
2591 p->origin[1] = LittleFloat(p->origin[1]);
2592 p->origin[2] = LittleFloat(p->origin[2]);
2596 else if (!strcmp(pchunk->id, "VTXW0000"))
2599 if (recordsize != sizeof(*p))
2600 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2601 // byteswap in place and keep the pointer
2602 numvtxw = numrecords;
2603 vtxw = (pskvtxw_t *)buffer;
2604 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2606 p->pntsindex = LittleShort(p->pntsindex);
2607 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2608 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2609 if (p->pntsindex >= numpnts)
2611 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2617 else if (!strcmp(pchunk->id, "FACE0000"))
2620 if (recordsize != sizeof(*p))
2621 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2622 // byteswap in place and keep the pointer
2623 numfaces = numrecords;
2624 faces = (pskface_t *)buffer;
2625 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2627 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2628 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2629 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2630 p->group = LittleLong(p->group);
2631 if (p->vtxwindex[0] >= numvtxw)
2633 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2634 p->vtxwindex[0] = 0;
2636 if (p->vtxwindex[1] >= numvtxw)
2638 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2639 p->vtxwindex[1] = 0;
2641 if (p->vtxwindex[2] >= numvtxw)
2643 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2644 p->vtxwindex[2] = 0;
2649 else if (!strcmp(pchunk->id, "MATT0000"))
2652 if (recordsize != sizeof(*p))
2653 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2654 // byteswap in place and keep the pointer
2655 nummatts = numrecords;
2656 matts = (pskmatt_t *)buffer;
2657 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2663 else if (!strcmp(pchunk->id, "REFSKELT"))
2666 if (recordsize != sizeof(*p))
2667 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2668 // byteswap in place and keep the pointer
2669 numbones = numrecords;
2670 bones = (pskboneinfo_t *)buffer;
2671 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2673 p->numchildren = LittleLong(p->numchildren);
2674 p->parent = LittleLong(p->parent);
2675 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2676 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2677 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2678 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2679 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2680 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2681 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2682 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2683 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2684 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2685 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2686 #ifdef PSKQUATNEGATIONS
2689 p->basepose.quat[0] *= -1;
2690 p->basepose.quat[1] *= -1;
2691 p->basepose.quat[2] *= -1;
2695 p->basepose.quat[0] *= 1;
2696 p->basepose.quat[1] *= -1;
2697 p->basepose.quat[2] *= 1;
2700 if (p->parent < 0 || p->parent >= numbones)
2702 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2708 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2711 if (recordsize != sizeof(*p))
2712 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2713 // byteswap in place and keep the pointer
2714 numrawweights = numrecords;
2715 rawweights = (pskrawweights_t *)buffer;
2716 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2718 p->weight = LittleFloat(p->weight);
2719 p->pntsindex = LittleLong(p->pntsindex);
2720 p->boneindex = LittleLong(p->boneindex);
2721 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2723 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2726 if (p->boneindex < 0 || p->boneindex >= numbones)
2728 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2736 while (animbuffer < animbufferend)
2738 pchunk = (pskchunk_t *)animbuffer;
2739 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2740 version = LittleLong(pchunk->version);
2741 recordsize = LittleLong(pchunk->recordsize);
2742 numrecords = LittleLong(pchunk->numrecords);
2743 if (developer_extra.integer)
2744 Con_DPrintf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2745 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2746 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);
2747 if (!strcmp(pchunk->id, "ANIMHEAD"))
2751 else if (!strcmp(pchunk->id, "BONENAMES"))
2754 if (recordsize != sizeof(*p))
2755 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2756 // byteswap in place and keep the pointer
2757 numanimbones = numrecords;
2758 //animbones = (pskboneinfo_t *)animbuffer;
2759 // NOTE: supposedly psa does not need to match the psk model, the
2760 // bones missing from the psa would simply use their base
2761 // positions from the psk, but this is hard for me to implement
2762 // and people can easily make animations that match.
2763 if (numanimbones != numbones)
2764 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2765 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2767 p->numchildren = LittleLong(p->numchildren);
2768 p->parent = LittleLong(p->parent);
2769 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2770 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2771 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2772 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2773 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2774 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2775 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2776 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2777 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2778 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2779 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2780 #ifdef PSKQUATNEGATIONS
2783 p->basepose.quat[0] *= -1;
2784 p->basepose.quat[1] *= -1;
2785 p->basepose.quat[2] *= -1;
2789 p->basepose.quat[0] *= 1;
2790 p->basepose.quat[1] *= -1;
2791 p->basepose.quat[2] *= 1;
2794 if (p->parent < 0 || p->parent >= numanimbones)
2796 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2799 // check that bones are the same as in the base
2800 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2801 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2805 else if (!strcmp(pchunk->id, "ANIMINFO"))
2808 if (recordsize != sizeof(*p))
2809 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2810 // byteswap in place and keep the pointer
2811 numanims = numrecords;
2812 anims = (pskaniminfo_t *)animbuffer;
2813 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2815 p->numbones = LittleLong(p->numbones);
2816 p->playtime = LittleFloat(p->playtime);
2817 p->fps = LittleFloat(p->fps);
2818 p->firstframe = LittleLong(p->firstframe);
2819 p->numframes = LittleLong(p->numframes);
2820 if (p->numbones != numbones)
2821 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2825 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2828 if (recordsize != sizeof(*p))
2829 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2830 numanimkeys = numrecords;
2831 animkeys = (pskanimkeys_t *)animbuffer;
2832 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2834 p->origin[0] = LittleFloat(p->origin[0]);
2835 p->origin[1] = LittleFloat(p->origin[1]);
2836 p->origin[2] = LittleFloat(p->origin[2]);
2837 p->quat[0] = LittleFloat(p->quat[0]);
2838 p->quat[1] = LittleFloat(p->quat[1]);
2839 p->quat[2] = LittleFloat(p->quat[2]);
2840 p->quat[3] = LittleFloat(p->quat[3]);
2841 p->frametime = LittleFloat(p->frametime);
2842 #ifdef PSKQUATNEGATIONS
2843 if (index % numbones)
2858 // TODO: allocate bonepose stuff
2861 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2864 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2865 Host_Error("%s: missing required chunks", loadmodel->name);
2867 loadmodel->numframes = 0;
2868 for (index = 0;index < numanims;index++)
2869 loadmodel->numframes += anims[index].numframes;
2871 if (numanimkeys != numbones * loadmodel->numframes)
2872 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2874 meshvertices = numvtxw;
2875 meshtriangles = numfaces;
2877 // load external .skin files if present
2878 skinfiles = Mod_LoadSkinFiles();
2879 if (loadmodel->numskins < 1)
2880 loadmodel->numskins = 1;
2881 loadmodel->num_bones = numbones;
2882 loadmodel->num_poses = loadmodel->numframes;
2883 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2884 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2885 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2886 loadmodel->surfmesh.num_vertices = meshvertices;
2887 loadmodel->surfmesh.num_triangles = meshtriangles;
2888 // do most allocations as one merged chunk
2889 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);
2890 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2891 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2892 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2893 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2894 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2895 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2896 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2897 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2898 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2899 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2900 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2901 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2902 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2903 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2904 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2905 loadmodel->surfmesh.num_blends = 0;
2906 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2907 if (loadmodel->surfmesh.num_vertices <= 65536)
2908 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2909 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2910 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(blendweights_t));
2912 for (i = 0;i < loadmodel->numskins;i++)
2914 loadmodel->skinscenes[i].firstframe = i;
2915 loadmodel->skinscenes[i].framecount = 1;
2916 loadmodel->skinscenes[i].loop = true;
2917 loadmodel->skinscenes[i].framerate = 10;
2921 for (index = 0, i = 0;index < nummatts;index++)
2923 // since psk models do not have named sections, reuse their shader name as the section name
2924 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2925 loadmodel->sortedmodelsurfaces[index] = index;
2926 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2927 loadmodel->data_surfaces[index].num_firstvertex = 0;
2928 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2931 // copy over the vertex locations and texcoords
2932 for (index = 0;index < numvtxw;index++)
2934 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2935 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2936 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2937 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2938 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2941 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2942 for (index = 0;index < numfaces;index++)
2943 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2944 for (index = 0, i = 0;index < nummatts;index++)
2946 loadmodel->data_surfaces[index].num_firsttriangle = i;
2947 i += loadmodel->data_surfaces[index].num_triangles;
2948 loadmodel->data_surfaces[index].num_triangles = 0;
2950 for (index = 0;index < numfaces;index++)
2952 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2953 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2954 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2955 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2958 // copy over the bones
2959 for (index = 0;index < numbones;index++)
2961 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2962 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2963 if (loadmodel->data_bones[index].parent >= index)
2964 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2967 // sort the psk point weights into the vertex weight tables
2968 // (which only accept up to 4 bones per vertex)
2969 for (index = 0;index < numvtxw;index++)
2971 int weightindex[4] = { 0, 0, 0, 0 };
2972 float weightinfluence[4] = { 0, 0, 0, 0 };
2974 for (j = 0;j < numrawweights;j++)
2976 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2978 int boneindex = rawweights[j].boneindex;
2979 float influence = rawweights[j].weight;
2980 for (l = 0;l < 4;l++)
2982 if (weightinfluence[l] < influence)
2984 // move lower influence weights out of the way first
2986 for (l2 = 3;l2 > l;l2--)
2988 weightinfluence[l2] = weightinfluence[l2-1];
2989 weightindex[l2] = weightindex[l2-1];
2991 // store the new weight
2992 weightinfluence[l] = influence;
2993 weightindex[l] = boneindex;
2999 loadmodel->surfmesh.blends[index] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
3001 if (loadmodel->surfmesh.num_blends < loadmodel->surfmesh.num_vertices)
3002 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
3004 // set up the animscenes based on the anims
3005 for (index = 0, i = 0;index < numanims;index++)
3007 for (j = 0;j < anims[index].numframes;j++, i++)
3009 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
3010 loadmodel->animscenes[i].firstframe = i;
3011 loadmodel->animscenes[i].framecount = 1;
3012 loadmodel->animscenes[i].loop = true;
3013 loadmodel->animscenes[i].framerate = anims[index].fps;
3017 // calculate the scaling value for bone origins so they can be compressed to short
3019 for (index = 0;index < numanimkeys;index++)
3021 pskanimkeys_t *k = animkeys + index;
3022 biggestorigin = max(biggestorigin, fabs(k->origin[0]));
3023 biggestorigin = max(biggestorigin, fabs(k->origin[1]));
3024 biggestorigin = max(biggestorigin, fabs(k->origin[2]));
3026 loadmodel->num_posescale = biggestorigin / 32767.0f;
3027 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3029 // load the poses from the animkeys
3030 for (index = 0;index < numanimkeys;index++)
3032 pskanimkeys_t *k = animkeys + index;
3034 Vector4Copy(k->quat, quat);
3036 Vector4Negate(quat, quat);
3037 Vector4Normalize2(quat, quat);
3038 // compress poses to the short[6] format for longterm storage
3039 loadmodel->data_poses6s[index*6+0] = k->origin[0] * loadmodel->num_poseinvscale;
3040 loadmodel->data_poses6s[index*6+1] = k->origin[1] * loadmodel->num_poseinvscale;
3041 loadmodel->data_poses6s[index*6+2] = k->origin[2] * loadmodel->num_poseinvscale;
3042 loadmodel->data_poses6s[index*6+3] = quat[0] * 32767.0f;
3043 loadmodel->data_poses6s[index*6+4] = quat[1] * 32767.0f;
3044 loadmodel->data_poses6s[index*6+5] = quat[2] * 32767.0f;
3046 Mod_FreeSkinFiles(skinfiles);
3047 Mem_Free(animfilebuffer);
3048 Mod_MakeSortedSurfaces(loadmodel);
3050 // compute all the mesh information that was not loaded from the file
3051 // TODO: honor smoothing groups somehow?
3052 if (loadmodel->surfmesh.data_element3s)
3053 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3054 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3055 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
3056 Mod_BuildBaseBonePoses();
3057 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
3058 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);
3059 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3060 Mod_Alias_CalculateBoundingBox();
3062 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
3064 if (!loadmodel->surfmesh.isanimated)
3066 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3067 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3068 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3069 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3070 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
3074 void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
3076 unsigned char *data;
3078 unsigned char *pbase, *pend;
3079 iqmheader_t *header;
3080 skinfile_t *skinfiles;
3081 int i, j, k, meshvertices, meshtriangles;
3082 float *vposition = NULL, *vtexcoord = NULL, *vnormal = NULL, *vtangent = NULL;
3083 unsigned char *vblendindexes = NULL, *vblendweights = NULL;
3088 iqmbounds_t *bounds;
3089 iqmvertexarray_t *va;
3090 unsigned short *framedata;
3091 float biggestorigin;
3092 const int *inelements;
3094 float *outvertex, *outnormal, *outtexcoord, *outsvector, *outtvector;
3096 pbase = (unsigned char *)buffer;
3097 pend = (unsigned char *)bufferend;
3098 header = (iqmheader_t *)buffer;
3099 if (memcmp(header->id, "INTERQUAKEMODEL", 16))
3100 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model", loadmodel->name);
3101 if (LittleLong(header->version) != 1)
3102 Host_Error ("Mod_INTERQUAKEMODEL_Load: only version 1 models are currently supported (name = %s)", loadmodel->name);
3104 loadmodel->modeldatatypestring = "IQM";
3106 loadmodel->type = mod_alias;
3107 loadmodel->synctype = ST_RAND;
3110 header->version = LittleLong(header->version);
3111 header->filesize = LittleLong(header->filesize);
3112 header->flags = LittleLong(header->flags);
3113 header->num_text = LittleLong(header->num_text);
3114 header->ofs_text = LittleLong(header->ofs_text);
3115 header->num_meshes = LittleLong(header->num_meshes);
3116 header->ofs_meshes = LittleLong(header->ofs_meshes);
3117 header->num_vertexarrays = LittleLong(header->num_vertexarrays);
3118 header->num_vertexes = LittleLong(header->num_vertexes);
3119 header->ofs_vertexarrays = LittleLong(header->ofs_vertexarrays);
3120 header->num_triangles = LittleLong(header->num_triangles);
3121 header->ofs_triangles = LittleLong(header->ofs_triangles);
3122 header->ofs_neighbors = LittleLong(header->ofs_neighbors);
3123 header->num_joints = LittleLong(header->num_joints);
3124 header->ofs_joints = LittleLong(header->ofs_joints);
3125 header->num_poses = LittleLong(header->num_poses);
3126 header->ofs_poses = LittleLong(header->ofs_poses);
3127 header->num_anims = LittleLong(header->num_anims);
3128 header->ofs_anims = LittleLong(header->ofs_anims);
3129 header->num_frames = LittleLong(header->num_frames);
3130 header->num_framechannels = LittleLong(header->num_framechannels);
3131 header->ofs_frames = LittleLong(header->ofs_frames);
3132 header->ofs_bounds = LittleLong(header->ofs_bounds);
3133 header->num_comment = LittleLong(header->num_comment);
3134 header->ofs_comment = LittleLong(header->ofs_comment);
3135 header->num_extensions = LittleLong(header->num_extensions);
3136 header->ofs_extensions = LittleLong(header->ofs_extensions);
3138 if (header->num_triangles < 1 || header->num_vertexes < 3 || header->num_vertexarrays < 1 || header->num_meshes < 1)
3140 Con_Printf("%s has no geometry\n", loadmodel->name);
3143 if (header->num_frames < 1 || header->num_anims < 1)
3145 Con_Printf("%s has no animations\n", loadmodel->name);
3149 if (pbase + header->ofs_text + header->num_text > pend ||
3150 pbase + header->ofs_meshes + header->num_meshes*sizeof(iqmmesh_t) > pend ||
3151 pbase + header->ofs_vertexarrays + header->num_vertexarrays*sizeof(iqmvertexarray_t) > pend ||
3152 pbase + header->ofs_triangles + header->num_triangles*sizeof(int[3]) > pend ||
3153 (header->ofs_neighbors && pbase + header->ofs_neighbors + header->num_triangles*sizeof(int[3]) > pend) ||
3154 pbase + header->ofs_joints + header->num_joints*sizeof(iqmjoint_t) > pend ||
3155 pbase + header->ofs_poses + header->num_poses*sizeof(iqmpose_t) > pend ||
3156 pbase + header->ofs_anims + header->num_anims*sizeof(iqmanim_t) > pend ||
3157 pbase + header->ofs_frames + header->num_frames*header->num_framechannels*sizeof(unsigned short) > pend ||
3158 (header->ofs_bounds && pbase + header->ofs_bounds + header->num_frames*sizeof(iqmbounds_t) > pend) ||
3159 pbase + header->ofs_comment + header->num_comment > pend)
3161 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3165 va = (iqmvertexarray_t *)(pbase + header->ofs_vertexarrays);
3166 for (i = 0;i < (int)header->num_vertexarrays;i++)
3169 va[i].type = LittleLong(va[i].type);
3170 va[i].flags = LittleLong(va[i].flags);
3171 va[i].format = LittleLong(va[i].format);
3172 va[i].size = LittleLong(va[i].size);
3173 va[i].offset = LittleLong(va[i].offset);
3174 vsize = header->num_vertexes*va[i].size;
3175 switch (va[i].format)
3177 case IQM_FLOAT: vsize *= sizeof(float); break;
3178 case IQM_UBYTE: vsize *= sizeof(unsigned char); break;
3181 if (pbase + va[i].offset + vsize > pend)
3186 if (va[i].format == IQM_FLOAT && va[i].size == 3)
3187 vposition = (float *)(pbase + va[i].offset);
3190 if (va[i].format == IQM_FLOAT && va[i].size == 2)
3191 vtexcoord = (float *)(pbase + va[i].offset);
3194 if (va[i].format == IQM_FLOAT && va[i].size == 3)
3195 vnormal = (float *)(pbase + va[i].offset);
3198 if (va[i].format == IQM_FLOAT && va[i].size == 4)
3199 vtangent = (float *)(pbase + va[i].offset);
3201 case IQM_BLENDINDEXES:
3202 if (va[i].format == IQM_UBYTE && va[i].size == 4)
3203 vblendindexes = (unsigned char *)(pbase + va[i].offset);
3205 case IQM_BLENDWEIGHTS:
3206 if (va[i].format == IQM_UBYTE && va[i].size == 4)
3207 vblendweights = (unsigned char *)(pbase + va[i].offset);
3211 if (!vposition || !vtexcoord || !vblendindexes || !vblendweights)
3213 Con_Printf("%s is missing vertex array data\n", loadmodel->name);
3217 text = header->num_text && header->ofs_text ? (const char *)(pbase + header->ofs_text) : "";
3219 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
3220 loadmodel->DrawSky = NULL;
3221 loadmodel->DrawAddWaterPlanes = NULL;
3222 loadmodel->Draw = R_Q1BSP_Draw;
3223 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
3224 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
3225 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
3226 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
3227 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
3228 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
3229 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
3230 loadmodel->DrawLight = R_Q1BSP_DrawLight;
3231 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
3232 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
3233 loadmodel->PointSuperContents = NULL;
3235 // load external .skin files if present
3236 skinfiles = Mod_LoadSkinFiles();
3237 if (loadmodel->numskins < 1)
3238 loadmodel->numskins = 1;
3240 loadmodel->numframes = header->num_anims;
3241 loadmodel->num_bones = header->num_joints;
3242 loadmodel->num_poses = header->num_frames;
3243 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = header->num_meshes;
3244 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3245 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3247 meshvertices = header->num_vertexes;
3248 meshtriangles = header->num_triangles;
3250 // do most allocations as one merged chunk
3251 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));
3252 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
3253 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
3254 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
3255 loadmodel->surfmesh.num_vertices = meshvertices;
3256 loadmodel->surfmesh.num_triangles = meshtriangles;
3257 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3258 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3259 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
3260 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3261 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3262 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
3263 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
3264 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
3265 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
3266 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
3267 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
3268 loadmodel->surfmesh.num_blends = 0;
3269 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
3270 if (meshvertices <= 65536)
3271 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
3272 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
3273 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
3275 for (i = 0;i < loadmodel->numskins;i++)
3277 loadmodel->skinscenes[i].firstframe = i;
3278 loadmodel->skinscenes[i].framecount = 1;
3279 loadmodel->skinscenes[i].loop = true;
3280 loadmodel->skinscenes[i].framerate = 10;
3283 // load the bone info
3284 joint = (iqmjoint_t *) (pbase + header->ofs_joints);
3285 for (i = 0;i < loadmodel->num_bones;i++)
3287 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3288 joint[i].name = LittleLong(joint[i].name);
3289 joint[i].parent = LittleLong(joint[i].parent);
3290 for (j = 0;j < 3;j++)
3292 joint[i].origin[j] = LittleFloat(joint[i].origin[j]);
3293 joint[i].rotation[j] = LittleFloat(joint[i].rotation[j]);
3294 joint[i].scale[j] = LittleFloat(joint[i].scale[j]);
3296 strlcpy(loadmodel->data_bones[i].name, &text[joint[i].name], sizeof(loadmodel->data_bones[i].name));
3297 loadmodel->data_bones[i].parent = joint[i].parent;
3298 if (loadmodel->data_bones[i].parent >= i)
3299 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3300 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]);
3301 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3302 if (loadmodel->data_bones[i].parent >= 0)
3304 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3305 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3306 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3308 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3311 // set up the animscenes based on the anims
3312 anim = (iqmanim_t *) (pbase + header->ofs_anims);
3313 for (i = 0;i < (int)header->num_anims;i++)
3315 anim[i].name = LittleLong(anim[i].name);
3316 anim[i].first_frame = LittleLong(anim[i].first_frame);
3317 anim[i].num_frames = LittleLong(anim[i].num_frames);
3318 anim[i].framerate = LittleFloat(anim[i].framerate);
3319 anim[i].flags = LittleLong(anim[i].flags);
3320 strlcpy(loadmodel->animscenes[i].name, &text[anim[i].name], sizeof(loadmodel->animscenes[i].name));
3321 loadmodel->animscenes[i].firstframe = anim[i].first_frame;
3322 loadmodel->animscenes[i].framecount = anim[i].num_frames;
3323 loadmodel->animscenes[i].loop = ((anim[i].flags & IQM_LOOP) != 0);
3324 loadmodel->animscenes[i].framerate = anim[i].framerate;
3327 pose = (iqmpose_t *) (pbase + header->ofs_poses);
3329 for (i = 0;i < (int)header->num_poses;i++)
3332 pose[i].parent = LittleLong(pose[i].parent);
3333 pose[i].channelmask = LittleLong(pose[i].channelmask);
3334 pose[i].channeloffset[0] = LittleFloat(pose[i].channeloffset[0]);
3335 pose[i].channeloffset[1] = LittleFloat(pose[i].channeloffset[1]);
3336 pose[i].channeloffset[2] = LittleFloat(pose[i].channeloffset[2]);
3337 pose[i].channeloffset[3] = LittleFloat(pose[i].channeloffset[3]);
3338 pose[i].channeloffset[4] = LittleFloat(pose[i].channeloffset[4]);
3339 pose[i].channeloffset[5] = LittleFloat(pose[i].channeloffset[5]);
3340 pose[i].channeloffset[6] = LittleFloat(pose[i].channeloffset[6]);
3341 pose[i].channeloffset[7] = LittleFloat(pose[i].channeloffset[7]);
3342 pose[i].channeloffset[8] = LittleFloat(pose[i].channeloffset[8]);
3343 pose[i].channelscale[0] = LittleFloat(pose[i].channelscale[0]);
3344 pose[i].channelscale[1] = LittleFloat(pose[i].channelscale[1]);
3345 pose[i].channelscale[2] = LittleFloat(pose[i].channelscale[2]);
3346 pose[i].channelscale[3] = LittleFloat(pose[i].channelscale[3]);
3347 pose[i].channelscale[4] = LittleFloat(pose[i].channelscale[4]);
3348 pose[i].channelscale[5] = LittleFloat(pose[i].channelscale[5]);
3349 pose[i].channelscale[6] = LittleFloat(pose[i].channelscale[6]);
3350 pose[i].channelscale[7] = LittleFloat(pose[i].channelscale[7]);
3351 pose[i].channelscale[8] = LittleFloat(pose[i].channelscale[8]);
3352 f = fabs(pose[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3353 f = fabs(pose[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3354 f = fabs(pose[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3355 f = fabs(pose[i].channeloffset[0] + 0xFFFF*pose[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3356 f = fabs(pose[i].channeloffset[1] + 0xFFFF*pose[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3357 f = fabs(pose[i].channeloffset[2] + 0xFFFF*pose[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3359 loadmodel->num_posescale = biggestorigin / 32767.0f;
3360 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3362 // load the pose data
3363 framedata = (unsigned short *) (pbase + header->ofs_frames);
3364 for (i = 0, k = 0;i < (int)header->num_frames;i++)
3366 for (j = 0;j < (int)header->num_poses;j++, k++)
3368 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));
3369 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));
3370 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));
3371 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));
3372 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));
3373 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));
3374 // skip scale data for now
3375 if(pose[j].channelmask&64) framedata++;
3376 if(pose[j].channelmask&128) framedata++;
3377 if(pose[j].channelmask&256) framedata++;
3381 // load bounding box data
3382 if (header->ofs_bounds)
3384 float xyradius = 0, radius = 0;
3385 bounds = (iqmbounds_t *) (pbase + header->ofs_bounds);
3386 VectorClear(loadmodel->normalmins);
3387 VectorClear(loadmodel->normalmaxs);
3388 for (i = 0; i < (int)header->num_frames;i++)
3390 bounds[i].mins[0] = LittleFloat(bounds[i].mins[0]);
3391 bounds[i].mins[1] = LittleFloat(bounds[i].mins[1]);
3392 bounds[i].mins[2] = LittleFloat(bounds[i].mins[2]);
3393 bounds[i].maxs[0] = LittleFloat(bounds[i].maxs[0]);
3394 bounds[i].maxs[1] = LittleFloat(bounds[i].maxs[1]);
3395 bounds[i].maxs[2] = LittleFloat(bounds[i].maxs[2]);
3396 bounds[i].xyradius = LittleFloat(bounds[i].xyradius);
3397 bounds[i].radius = LittleFloat(bounds[i].radius);
3400 VectorCopy(bounds[i].mins, loadmodel->normalmins);
3401 VectorCopy(bounds[i].maxs, loadmodel->normalmaxs);
3405 if (loadmodel->normalmins[0] > bounds[i].mins[0]) loadmodel->normalmins[0] = bounds[i].mins[0];
3406 if (loadmodel->normalmins[1] > bounds[i].mins[1]) loadmodel->normalmins[1] = bounds[i].mins[1];
3407 if (loadmodel->normalmins[2] > bounds[i].mins[2]) loadmodel->normalmins[2] = bounds[i].mins[2];
3408 if (loadmodel->normalmaxs[0] < bounds[i].maxs[0]) loadmodel->normalmaxs[0] = bounds[i].maxs[0];
3409 if (loadmodel->normalmaxs[1] < bounds[i].maxs[1]) loadmodel->normalmaxs[1] = bounds[i].maxs[1];
3410 if (loadmodel->normalmaxs[2] < bounds[i].maxs[2]) loadmodel->normalmaxs[2] = bounds[i].maxs[2];
3412 if (bounds[i].xyradius > xyradius)
3413 xyradius = bounds[i].xyradius;
3414 if (bounds[i].radius > radius)
3415 radius = bounds[i].radius;
3417 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -xyradius;
3418 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = xyradius;
3419 loadmodel->yawmins[2] = loadmodel->normalmins[2];
3420 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
3421 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
3422 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
3423 loadmodel->radius = radius;
3424 loadmodel->radius2 = radius * radius;
3427 // load triangle data
3428 inelements = (const int *) (pbase + header->ofs_triangles);
3429 outelements = loadmodel->surfmesh.data_element3i;
3430 for (i = 0;i < (int)header->num_triangles;i++)
3432 outelements[0] = LittleLong(inelements[0]);
3433 outelements[1] = LittleLong(inelements[1]);
3434 outelements[2] = LittleLong(inelements[2]);
3438 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, header->num_vertexes, __FILE__, __LINE__);
3440 if (header->ofs_neighbors)
3442 inelements = (const int *) (pbase + header->ofs_neighbors);
3443 outelements = loadmodel->surfmesh.data_neighbor3i;
3444 for (i = 0;i < (int)header->num_triangles;i++)
3446 outelements[0] = LittleLong(inelements[0]);
3447 outelements[1] = LittleLong(inelements[1]);
3448 outelements[2] = LittleLong(inelements[2]);
3455 outvertex = loadmodel->surfmesh.data_vertex3f;
3456 for (i = 0;i < (int)header->num_vertexes;i++)
3458 outvertex[0] = LittleFloat(vposition[0]);
3459 outvertex[1] = LittleFloat(vposition[1]);
3460 outvertex[2] = LittleFloat(vposition[2]);
3465 outtexcoord = loadmodel->surfmesh.data_texcoordtexture2f;
3466 for (i = 0;i < (int)header->num_vertexes;i++)
3468 outtexcoord[0] = LittleFloat(vtexcoord[0]);
3469 outtexcoord[1] = LittleFloat(vtexcoord[1]);
3476 outnormal = loadmodel->surfmesh.data_normal3f;
3477 for (i = 0;i < (int)header->num_vertexes;i++)
3479 outnormal[0] = LittleFloat(vnormal[0]);
3480 outnormal[1] = LittleFloat(vnormal[1]);
3481 outnormal[2] = LittleFloat(vnormal[2]);
3487 if(vnormal && vtangent)
3489 outnormal = loadmodel->surfmesh.data_normal3f;
3490 outsvector = loadmodel->surfmesh.data_svector3f;
3491 outtvector = loadmodel->surfmesh.data_tvector3f;
3492 for (i = 0;i < (int)header->num_vertexes;i++)
3494 outsvector[0] = LittleFloat(vtangent[0]);
3495 outsvector[1] = LittleFloat(vtangent[1]);
3496 outsvector[2] = LittleFloat(vtangent[2]);
3497 if(LittleFloat(vtangent[3]) < 0)
3498 CrossProduct(outsvector, outnormal, outtvector);
3500 CrossProduct(outnormal, outsvector, outtvector);
3508 for (i = 0; i < (int)header->num_vertexes;i++)
3510 blendweights_t weights;
3511 memcpy(weights.index, vblendindexes + i*4, 4);
3512 memcpy(weights.influence, vblendweights + i*4, 4);
3513 loadmodel->surfmesh.blends[i] = Mod_Skeletal_AddBlend(loadmodel, &weights);
3517 mesh = (iqmmesh_t *) (pbase + header->ofs_meshes);
3518 for (i = 0;i < (int)header->num_meshes;i++)
3520 msurface_t *surface;
3522 mesh[i].name = LittleLong(mesh[i].name);
3523 mesh[i].material = LittleLong(mesh[i].material);
3524 mesh[i].first_vertex = LittleLong(mesh[i].first_vertex);
3525 mesh[i].num_vertexes = LittleLong(mesh[i].num_vertexes);
3526 mesh[i].first_triangle = LittleLong(mesh[i].first_triangle);
3527 mesh[i].num_triangles = LittleLong(mesh[i].num_triangles);
3529 loadmodel->sortedmodelsurfaces[i] = i;
3530 surface = loadmodel->data_surfaces + i;
3531 surface->texture = loadmodel->data_textures + i;
3532 surface->num_firsttriangle = mesh[i].first_triangle;
3533 surface->num_triangles = mesh[i].num_triangles;
3534 surface->num_firstvertex = mesh[i].first_vertex;
3535 surface->num_vertices = mesh[i].num_vertexes;
3537 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, &text[mesh[i].name], &text[mesh[i].material]);
3540 Mod_FreeSkinFiles(skinfiles);
3541 Mod_MakeSortedSurfaces(loadmodel);
3543 // compute all the mesh information that was not loaded from the file
3544 if (loadmodel->surfmesh.data_element3s)
3545 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3546 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3548 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
3549 if (!vnormal || !vtangent)
3550 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);
3551 if (!header->ofs_neighbors)
3552 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3553 if (!header->ofs_bounds)
3554 Mod_Alias_CalculateBoundingBox();
3556 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
3558 if (!loadmodel->surfmesh.isanimated)
3560 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3561 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3562 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3563 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3564 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;