2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 cvar_t r_skeletal_debugbone = {0, "r_skeletal_debugbone", "-1", "development cvar for testing skeletal model code"};
26 cvar_t r_skeletal_debugbonecomponent = {0, "r_skeletal_debugbonecomponent", "3", "development cvar for testing skeletal model code"};
27 cvar_t r_skeletal_debugbonevalue = {0, "r_skeletal_debugbonevalue", "100", "development cvar for testing skeletal model code"};
28 cvar_t r_skeletal_debugtranslatex = {0, "r_skeletal_debugtranslatex", "1", "development cvar for testing skeletal model code"};
29 cvar_t r_skeletal_debugtranslatey = {0, "r_skeletal_debugtranslatey", "1", "development cvar for testing skeletal model code"};
30 cvar_t r_skeletal_debugtranslatez = {0, "r_skeletal_debugtranslatez", "1", "development cvar for testing skeletal model code"};
31 cvar_t mod_alias_supporttagscale = {0, "mod_alias_supporttagscale", "1", "support scaling factors in bone/tag attachment matrices as supported by MD3"};
33 float mod_md3_sin[320];
35 void Mod_AliasInit (void)
38 Cvar_RegisterVariable(&r_skeletal_debugbone);
39 Cvar_RegisterVariable(&r_skeletal_debugbonecomponent);
40 Cvar_RegisterVariable(&r_skeletal_debugbonevalue);
41 Cvar_RegisterVariable(&r_skeletal_debugtranslatex);
42 Cvar_RegisterVariable(&r_skeletal_debugtranslatey);
43 Cvar_RegisterVariable(&r_skeletal_debugtranslatez);
44 Cvar_RegisterVariable(&mod_alias_supporttagscale);
45 for (i = 0;i < 320;i++)
46 mod_md3_sin[i] = sin(i * M_PI * 2.0f / 256.0);
49 int Mod_Skeletal_AddBlend(dp_model_t *model, const blendweights_t *newweights)
52 blendweights_t *weights;
53 if(!newweights->influence[1])
54 return newweights->index[0];
55 weights = model->surfmesh.data_blendweights;
56 for (i = 0;i < model->surfmesh.num_blends;i++, weights++)
58 if (!memcmp(weights, newweights, sizeof(blendweights_t)))
59 return model->num_bones + i;
61 model->surfmesh.num_blends++;
62 memcpy(weights, newweights, sizeof(blendweights_t));
63 return model->num_bones + i;
66 int Mod_Skeletal_CompressBlend(dp_model_t *model, const int *newindex, const float *newinfluence)
70 blendweights_t newweights;
75 scale += newinfluence[i];
76 scale = 255.0f / scale;
80 newweights.index[i] = newindex[i];
81 newweights.influence[i] = (unsigned char)(newinfluence[i] * scale);
82 total += newweights.influence[i];
88 if(newweights.influence[i] > 0 && total > 255)
90 newweights.influence[i]--;
97 for (i = 0; i < 4;i++)
99 if(newweights.influence[i] < 255 && total < 255)
101 newweights.influence[i]++;
106 return Mod_Skeletal_AddBlend(model, &newweights);
109 static int maxbonepose = 0;
110 static float (*bonepose)[12] = NULL;
112 void Mod_Skeletal_FreeBuffers(void)
120 void Mod_Skeletal_AnimateVertices(const dp_model_t * RESTRICT model, const frameblend_t * RESTRICT frameblend, const skeleton_t *skeleton, float * RESTRICT vertex3f, float * RESTRICT normal3f, float * RESTRICT svector3f, float * RESTRICT tvector3f)
122 // vertex weighted skeletal
126 float (*boneposerelative)[12];
127 const blendweights_t * RESTRICT weights;
129 if (maxbonepose < model->num_bones*2 + model->surfmesh.num_blends)
133 maxbonepose = model->num_bones*2 + model->surfmesh.num_blends;
134 bonepose = (float (*)[12])Z_Malloc(maxbonepose * sizeof(float[12]));
137 boneposerelative = bonepose + model->num_bones;
139 if (skeleton && !skeleton->relativetransforms)
142 // interpolate matrices
145 for (i = 0;i < model->num_bones;i++)
147 Matrix4x4_ToArray12FloatD3D(&skeleton->relativetransforms[i], m);
148 if (model->data_bones[i].parent >= 0)
149 R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
151 memcpy(bonepose[i], m, sizeof(m));
153 // create a relative deformation matrix to describe displacement
154 // from the base mesh, which is used by the actual weighting
155 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]);
160 float originscale = model->num_posescale;
162 const short * RESTRICT pose6s;
163 for (i = 0;i < model->num_bones;i++)
165 memset(m, 0, sizeof(m));
166 for (blends = 0;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++)
168 pose6s = model->data_poses6s + 6 * (frameblend[blends].subframe * model->num_bones + i);
169 lerp = frameblend[blends].lerp;
170 x = pose6s[3] * (1.0f / 32767.0f);
171 y = pose6s[4] * (1.0f / 32767.0f);
172 z = pose6s[5] * (1.0f / 32767.0f);
173 w = 1.0f - (x*x+y*y+z*z);
174 w = w > 0.0f ? -sqrt(w) : 0.0f;
175 m[ 0] += (1-2*(y*y+z*z)) * lerp;
176 m[ 1] += ( 2*(x*y-z*w)) * lerp;
177 m[ 2] += ( 2*(x*z+y*w)) * lerp;
178 m[ 3] += (pose6s[0] * originscale) * lerp;
179 m[ 4] += ( 2*(x*y+z*w)) * lerp;
180 m[ 5] += (1-2*(x*x+z*z)) * lerp;
181 m[ 6] += ( 2*(y*z-x*w)) * lerp;
182 m[ 7] += (pose6s[1] * originscale) * lerp;
183 m[ 8] += ( 2*(x*z-y*w)) * lerp;
184 m[ 9] += ( 2*(y*z+x*w)) * lerp;
185 m[10] += (1-2*(x*x+y*y)) * lerp;
186 m[11] += (pose6s[2] * originscale) * lerp;
189 VectorNormalize(m + 4);
190 VectorNormalize(m + 8);
191 if (i == r_skeletal_debugbone.integer)
192 m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
193 m[3] *= r_skeletal_debugtranslatex.value;
194 m[7] *= r_skeletal_debugtranslatey.value;
195 m[11] *= r_skeletal_debugtranslatez.value;
196 if (model->data_bones[i].parent >= 0)
197 R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
199 memcpy(bonepose[i], m, sizeof(m));
200 // create a relative deformation matrix to describe displacement
201 // from the base mesh, which is used by the actual weighting
202 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]);
206 // generate matrices for all blend combinations
207 weights = model->surfmesh.data_blendweights;
208 for (i = 0;i < model->surfmesh.num_blends;i++, weights++)
210 float * RESTRICT b = boneposerelative[model->num_bones + i];
211 const float * RESTRICT m = boneposerelative[weights->index[0]];
212 float f = weights->influence[0] * (1.0f / 255.0f);
213 b[ 0] = f*m[ 0]; b[ 1] = f*m[ 1]; b[ 2] = f*m[ 2]; b[ 3] = f*m[ 3];
214 b[ 4] = f*m[ 4]; b[ 5] = f*m[ 5]; b[ 6] = f*m[ 6]; b[ 7] = f*m[ 7];
215 b[ 8] = f*m[ 8]; b[ 9] = f*m[ 9]; b[10] = f*m[10]; b[11] = f*m[11];
216 for (k = 1;k < 4 && weights->influence[k];k++)
218 m = boneposerelative[weights->index[k]];
219 f = weights->influence[k] * (1.0f / 255.0f);
220 b[ 0] += f*m[ 0]; b[ 1] += f*m[ 1]; b[ 2] += f*m[ 2]; b[ 3] += f*m[ 3];
221 b[ 4] += f*m[ 4]; b[ 5] += f*m[ 5]; b[ 6] += f*m[ 6]; b[ 7] += f*m[ 7];
222 b[ 8] += f*m[ 8]; b[ 9] += f*m[ 9]; b[10] += f*m[10]; b[11] += f*m[11];
226 // transform vertex attributes by blended matrices
229 const float * RESTRICT v = model->surfmesh.data_vertex3f;
230 const unsigned short * RESTRICT b = model->surfmesh.blends;
231 // special case common combinations of attributes to avoid repeated loading of matrices
234 const float * RESTRICT n = model->surfmesh.data_normal3f;
235 if (svector3f && tvector3f)
237 const float * RESTRICT sv = model->surfmesh.data_svector3f;
238 const float * RESTRICT tv = model->surfmesh.data_tvector3f;
239 for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, n += 3, sv += 3, tv += 3, b++, vertex3f += 3, normal3f += 3, svector3f += 3, tvector3f += 3)
241 const float * RESTRICT m = boneposerelative[*b];
242 vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
243 vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
244 vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
245 normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
246 normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
247 normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
248 svector3f[0] = (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
249 svector3f[1] = (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
250 svector3f[2] = (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
251 tvector3f[0] = (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
252 tvector3f[1] = (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
253 tvector3f[2] = (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
257 for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, n += 3, b++, vertex3f += 3, normal3f += 3)
259 const float * RESTRICT m = boneposerelative[*b];
260 vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
261 vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
262 vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
263 normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
264 normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
265 normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
270 for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, b++, vertex3f += 3)
272 const float * RESTRICT m = boneposerelative[*b];
273 vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
274 vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
275 vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
281 const float * RESTRICT n = model->surfmesh.data_normal3f;
282 const unsigned short * RESTRICT b = model->surfmesh.blends;
283 for (i = 0;i < model->surfmesh.num_vertices;i++, n += 3, b++, normal3f += 3)
285 const float * RESTRICT m = boneposerelative[*b];
286 normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
287 normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
288 normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
294 const float * RESTRICT sv = model->surfmesh.data_svector3f;
295 const unsigned short * RESTRICT b = model->surfmesh.blends;
296 for (i = 0;i < model->surfmesh.num_vertices;i++, sv += 3, b++, svector3f += 3)
298 const float * RESTRICT m = boneposerelative[*b];
299 svector3f[0] = (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
300 svector3f[1] = (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
301 svector3f[2] = (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
307 const float * RESTRICT tv = model->surfmesh.data_tvector3f;
308 const unsigned short * RESTRICT b = model->surfmesh.blends;
309 for (i = 0;i < model->surfmesh.num_vertices;i++, tv += 3, b++, tvector3f += 3)
311 const float * RESTRICT m = boneposerelative[*b];
312 tvector3f[0] = (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
313 tvector3f[1] = (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
314 tvector3f[2] = (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
319 void Mod_MD3_AnimateVertices(const dp_model_t * RESTRICT model, const frameblend_t * RESTRICT frameblend, const skeleton_t *skeleton, float * RESTRICT vertex3f, float * RESTRICT normal3f, float * RESTRICT svector3f, float * RESTRICT tvector3f)
322 int i, numblends, blendnum;
323 int numverts = model->surfmesh.num_vertices;
325 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
327 //VectorMA(translate, model->surfmesh.num_morphmdlframetranslate, frameblend[blendnum].lerp, translate);
328 if (frameblend[blendnum].lerp > 0)
329 numblends = blendnum + 1;
331 // special case for the first blend because it avoids some adds and the need to memset the arrays first
332 for (blendnum = 0;blendnum < numblends;blendnum++)
334 const md3vertex_t *verts = model->surfmesh.data_morphmd3vertex + numverts * frameblend[blendnum].subframe;
337 float scale = frameblend[blendnum].lerp * (1.0f / 64.0f);
340 for (i = 0;i < numverts;i++)
342 vertex3f[i * 3 + 0] = verts[i].origin[0] * scale;
343 vertex3f[i * 3 + 1] = verts[i].origin[1] * scale;
344 vertex3f[i * 3 + 2] = verts[i].origin[2] * scale;
349 for (i = 0;i < numverts;i++)
351 vertex3f[i * 3 + 0] += verts[i].origin[0] * scale;
352 vertex3f[i * 3 + 1] += verts[i].origin[1] * scale;
353 vertex3f[i * 3 + 2] += verts[i].origin[2] * scale;
357 // the yaw and pitch stored in md3 models are 8bit quantized angles
358 // (0-255), and as such a lookup table is very well suited to
359 // decoding them, and since cosine is equivilant to sine with an
360 // extra 45 degree rotation, this uses one lookup table for both
361 // sine and cosine with a +64 bias to get cosine.
364 float lerp = frameblend[blendnum].lerp;
367 for (i = 0;i < numverts;i++)
369 normal3f[i * 3 + 0] = mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
370 normal3f[i * 3 + 1] = mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
371 normal3f[i * 3 + 2] = mod_md3_sin[verts[i].pitch + 64] * lerp;
376 for (i = 0;i < numverts;i++)
378 normal3f[i * 3 + 0] += mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
379 normal3f[i * 3 + 1] += mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
380 normal3f[i * 3 + 2] += mod_md3_sin[verts[i].pitch + 64] * lerp;
386 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
387 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
390 for (i = 0;i < numverts;i++, texvecvert++)
392 VectorScale(texvecvert->svec, f, svector3f + i*3);
393 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
398 for (i = 0;i < numverts;i++, texvecvert++)
400 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
401 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
408 void Mod_MDL_AnimateVertices(const dp_model_t * RESTRICT model, const frameblend_t * RESTRICT frameblend, const skeleton_t *skeleton, float * RESTRICT vertex3f, float * RESTRICT normal3f, float * RESTRICT svector3f, float * RESTRICT tvector3f)
411 int i, numblends, blendnum;
412 int numverts = model->surfmesh.num_vertices;
414 VectorClear(translate);
416 // blend the frame translates to avoid redundantly doing so on each vertex
417 // (a bit of a brain twister but it works)
418 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
420 if (model->surfmesh.data_morphmd2framesize6f)
421 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6 + 3, translate);
423 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.num_morphmdlframetranslate, translate);
424 if (frameblend[blendnum].lerp > 0)
425 numblends = blendnum + 1;
427 // special case for the first blend because it avoids some adds and the need to memset the arrays first
428 for (blendnum = 0;blendnum < numblends;blendnum++)
430 const trivertx_t *verts = model->surfmesh.data_morphmdlvertex + numverts * frameblend[blendnum].subframe;
434 if (model->surfmesh.data_morphmd2framesize6f)
435 VectorScale(model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6, frameblend[blendnum].lerp, scale);
437 VectorScale(model->surfmesh.num_morphmdlframescale, frameblend[blendnum].lerp, scale);
440 for (i = 0;i < numverts;i++)
442 vertex3f[i * 3 + 0] = translate[0] + verts[i].v[0] * scale[0];
443 vertex3f[i * 3 + 1] = translate[1] + verts[i].v[1] * scale[1];
444 vertex3f[i * 3 + 2] = translate[2] + verts[i].v[2] * scale[2];
449 for (i = 0;i < numverts;i++)
451 vertex3f[i * 3 + 0] += verts[i].v[0] * scale[0];
452 vertex3f[i * 3 + 1] += verts[i].v[1] * scale[1];
453 vertex3f[i * 3 + 2] += verts[i].v[2] * scale[2];
457 // the vertex normals in mdl models are an index into a table of
458 // 162 unique values, this very crude quantization reduces the
459 // vertex normal to only one byte, which saves a lot of space but
460 // also makes lighting pretty coarse
463 float lerp = frameblend[blendnum].lerp;
466 for (i = 0;i < numverts;i++)
468 const float *vn = m_bytenormals[verts[i].lightnormalindex];
469 VectorScale(vn, lerp, normal3f + i*3);
474 for (i = 0;i < numverts;i++)
476 const float *vn = m_bytenormals[verts[i].lightnormalindex];
477 VectorMA(normal3f + i*3, lerp, vn, normal3f + i*3);
483 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
484 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
487 for (i = 0;i < numverts;i++, texvecvert++)
489 VectorScale(texvecvert->svec, f, svector3f + i*3);
490 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
495 for (i = 0;i < numverts;i++, texvecvert++)
497 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
498 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
505 int Mod_Alias_GetTagMatrix(const dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, int tagindex, matrix4x4_t *outmatrix)
508 matrix4x4_t parentbonematrix;
509 matrix4x4_t tempbonematrix;
510 matrix4x4_t bonematrix;
511 matrix4x4_t blendmatrix;
518 *outmatrix = identitymatrix;
519 if (skeleton && skeleton->relativetransforms)
521 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
523 *outmatrix = skeleton->relativetransforms[tagindex];
524 while ((tagindex = model->data_bones[tagindex].parent) >= 0)
527 Matrix4x4_Concat(outmatrix, &skeleton->relativetransforms[tagindex], &temp);
530 else if (model->num_bones)
532 if (tagindex < 0 || tagindex >= model->num_bones)
534 Matrix4x4_Clear(&blendmatrix);
535 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
537 lerp = frameblend[blendindex].lerp;
538 Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
539 parenttagindex = tagindex;
540 while ((parenttagindex = model->data_bones[parenttagindex].parent) >= 0)
542 Matrix4x4_FromBonePose6s(&parentbonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + parenttagindex));
543 tempbonematrix = bonematrix;
544 Matrix4x4_Concat(&bonematrix, &parentbonematrix, &tempbonematrix);
546 Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
548 *outmatrix = blendmatrix;
550 else if (model->num_tags)
552 if (tagindex < 0 || tagindex >= model->num_tags)
554 for (k = 0;k < 12;k++)
556 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
558 lerp = frameblend[blendindex].lerp;
559 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
560 for (k = 0;k < 12;k++)
561 blendtag[k] += input[k] * lerp;
563 Matrix4x4_FromArray12FloatGL(outmatrix, blendtag);
566 if(!mod_alias_supporttagscale.integer)
567 Matrix4x4_Normalize3(outmatrix, outmatrix);
572 int Mod_Alias_GetExtendedTagInfoForIndex(const dp_model_t *model, unsigned int skin, const frameblend_t *frameblend, const skeleton_t *skeleton, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
577 matrix4x4_t bonematrix;
578 matrix4x4_t blendmatrix;
582 if (skeleton && skeleton->relativetransforms)
584 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
586 *parentindex = skeleton->model->data_bones[tagindex].parent;
587 *tagname = skeleton->model->data_bones[tagindex].name;
588 *tag_localmatrix = skeleton->relativetransforms[tagindex];
591 else if (model->num_bones)
593 if (tagindex < 0 || tagindex >= model->num_bones)
595 *parentindex = model->data_bones[tagindex].parent;
596 *tagname = model->data_bones[tagindex].name;
597 Matrix4x4_Clear(&blendmatrix);
598 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
600 lerp = frameblend[blendindex].lerp;
601 Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
602 Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
604 *tag_localmatrix = blendmatrix;
607 else if (model->num_tags)
609 if (tagindex < 0 || tagindex >= model->num_tags)
612 *tagname = model->data_tags[tagindex].name;
613 for (k = 0;k < 12;k++)
615 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
617 lerp = frameblend[blendindex].lerp;
618 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
619 for (k = 0;k < 12;k++)
620 blendtag[k] += input[k] * lerp;
622 Matrix4x4_FromArray12FloatGL(tag_localmatrix, blendtag);
629 int Mod_Alias_GetTagIndexForName(const dp_model_t *model, unsigned int skin, const char *tagname)
632 if(skin >= (unsigned int)model->numskins)
634 if (model->num_bones)
635 for (i = 0;i < model->num_bones;i++)
636 if (!strcasecmp(tagname, model->data_bones[i].name))
639 for (i = 0;i < model->num_tags;i++)
640 if (!strcasecmp(tagname, model->data_tags[i].name))
645 static void Mod_BuildBaseBonePoses(void)
648 matrix4x4_t *basebonepose;
649 float *outinvmatrix = loadmodel->data_baseboneposeinverse;
650 matrix4x4_t bonematrix;
651 matrix4x4_t tempbonematrix;
652 if (!loadmodel->num_bones)
654 basebonepose = (matrix4x4_t *)Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(matrix4x4_t));
655 for (boneindex = 0;boneindex < loadmodel->num_bones;boneindex++)
657 Matrix4x4_FromBonePose6s(&bonematrix, loadmodel->num_posescale, loadmodel->data_poses6s + 6 * boneindex);
658 if (loadmodel->data_bones[boneindex].parent >= 0)
660 tempbonematrix = bonematrix;
661 Matrix4x4_Concat(&bonematrix, basebonepose + loadmodel->data_bones[boneindex].parent, &tempbonematrix);
663 basebonepose[boneindex] = bonematrix;
664 Matrix4x4_Invert_Simple(&tempbonematrix, basebonepose + boneindex);
665 Matrix4x4_ToArray12FloatD3D(&tempbonematrix, outinvmatrix + 12*boneindex);
667 Mem_Free(basebonepose);
670 static void Mod_Alias_CalculateBoundingBox(void)
673 qboolean firstvertex = true;
674 float dist, yawradius, radius;
677 frameblend_t frameblend[MAX_FRAMEBLENDS];
678 memset(frameblend, 0, sizeof(frameblend));
679 frameblend[0].lerp = 1;
680 vertex3f = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
681 VectorClear(loadmodel->normalmins);
682 VectorClear(loadmodel->normalmaxs);
685 for (frameblend[0].subframe = 0;frameblend[0].subframe < loadmodel->num_poses;frameblend[0].subframe++)
687 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, vertex3f, NULL, NULL, NULL);
688 for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
693 VectorCopy(v, loadmodel->normalmins);
694 VectorCopy(v, loadmodel->normalmaxs);
698 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
699 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
700 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
701 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
702 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
703 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
705 dist = v[0] * v[0] + v[1] * v[1];
706 if (yawradius < dist)
715 radius = sqrt(radius);
716 yawradius = sqrt(yawradius);
717 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
718 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
719 loadmodel->yawmins[2] = loadmodel->normalmins[2];
720 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
721 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
722 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
723 loadmodel->radius = radius;
724 loadmodel->radius2 = radius * radius;
727 static void Mod_Alias_MorphMesh_CompileFrames(void)
730 frameblend_t frameblend[MAX_FRAMEBLENDS];
731 unsigned char *datapointer;
732 memset(frameblend, 0, sizeof(frameblend));
733 frameblend[0].lerp = 1;
734 datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
735 loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
736 loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
737 loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
738 loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
739 loadmodel->surfmesh.data_morphtexvecvertex = (texvecvertex_t *)datapointer;datapointer += loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices * sizeof(texvecvertex_t);
740 // this counts down from the last frame to the first so that the final data in surfmesh is for frame zero (which is what the renderer expects to be there)
741 for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
743 frameblend[0].subframe = i;
744 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
745 Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, r_smoothnormals_areaweighting.integer != 0);
746 // encode the svector and tvector in 3 byte format for permanent storage
747 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
749 VectorScaleCast(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
750 VectorScaleCast(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
755 static void Mod_MDLMD2MD3_TraceLine(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask)
758 float segmentmins[3], segmentmaxs[3];
760 static int maxvertices = 0;
761 static float *vertex3f = NULL;
762 memset(trace, 0, sizeof(*trace));
764 trace->realfraction = 1;
765 trace->hitsupercontentsmask = hitsupercontentsmask;
766 if (maxvertices < model->surfmesh.num_vertices)
770 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
771 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
773 segmentmins[0] = min(start[0], end[0]) - 1;
774 segmentmins[1] = min(start[1], end[1]) - 1;
775 segmentmins[2] = min(start[2], end[2]) - 1;
776 segmentmaxs[0] = max(start[0], end[0]) + 1;
777 segmentmaxs[1] = max(start[1], end[1]) + 1;
778 segmentmaxs[2] = max(start[2], end[2]) + 1;
779 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
780 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
781 Collision_TraceLineTriangleMeshFloat(trace, start, end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs);
784 static int maxvertices = 0;
785 static float *vertex3f = NULL;
787 static void Mod_MDLMD2MD3_TraceBox(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask)
790 vec3_t shiftstart, shiftend;
791 float segmentmins[3], segmentmaxs[3];
793 colboxbrushf_t thisbrush_start, thisbrush_end;
794 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
796 if (VectorCompare(boxmins, boxmaxs))
798 VectorAdd(start, boxmins, shiftstart);
799 VectorAdd(end, boxmins, shiftend);
800 Mod_MDLMD2MD3_TraceLine(model, frameblend, skeleton, trace, shiftstart, shiftend, hitsupercontentsmask);
801 VectorSubtract(trace->endpos, boxmins, trace->endpos);
805 // box trace, performed as brush trace
806 memset(trace, 0, sizeof(*trace));
808 trace->realfraction = 1;
809 trace->hitsupercontentsmask = hitsupercontentsmask;
810 if (maxvertices < model->surfmesh.num_vertices)
814 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
815 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
817 segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
818 segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
819 segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
820 segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
821 segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
822 segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
823 VectorAdd(start, boxmins, boxstartmins);
824 VectorAdd(start, boxmaxs, boxstartmaxs);
825 VectorAdd(end, boxmins, boxendmins);
826 VectorAdd(end, boxmaxs, boxendmaxs);
827 Collision_BrushForBox(&thisbrush_start, boxstartmins, boxstartmaxs, 0, 0, NULL);
828 Collision_BrushForBox(&thisbrush_end, boxendmins, boxendmaxs, 0, 0, NULL);
829 if (maxvertices < model->surfmesh.num_vertices)
833 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
834 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
836 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
837 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
838 Collision_TraceBrushTriangleMeshFloat(trace, &thisbrush_start.brush, &thisbrush_end.brush, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs);
841 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
844 for (i = 0;i < inverts;i++)
846 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
848 j = vertremap[i]; // not onseam
851 j = vertremap[i+inverts]; // onseam
857 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
859 int i, f, pose, groupframes;
861 daliasframetype_t *pframetype;
862 daliasframe_t *pinframe;
863 daliasgroup_t *group;
864 daliasinterval_t *intervals;
867 scene = loadmodel->animscenes;
868 for (f = 0;f < loadmodel->numframes;f++)
870 pframetype = (daliasframetype_t *)datapointer;
871 datapointer += sizeof(daliasframetype_t);
872 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
874 // a single frame is still treated as a group
881 group = (daliasgroup_t *)datapointer;
882 datapointer += sizeof(daliasgroup_t);
883 groupframes = LittleLong (group->numframes);
885 // intervals (time per frame)
886 intervals = (daliasinterval_t *)datapointer;
887 datapointer += sizeof(daliasinterval_t) * groupframes;
889 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
890 if (interval < 0.01f)
892 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
897 // get scene name from first frame
898 pinframe = (daliasframe_t *)datapointer;
900 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
901 scene->firstframe = pose;
902 scene->framecount = groupframes;
903 scene->framerate = 1.0f / interval;
908 for (i = 0;i < groupframes;i++)
910 pinframe = (daliasframe_t *)datapointer;
911 datapointer += sizeof(daliasframe_t);
912 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
913 datapointer += sizeof(trivertx_t) * inverts;
919 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
921 if (cls.state == ca_dedicated)
925 skinframe = R_SkinFrame_LoadMissing();
926 memset(texture, 0, sizeof(*texture));
927 texture->currentframe = texture;
928 //texture->animated = false;
929 texture->numskinframes = 1;
930 texture->skinframerate = 1;
931 texture->skinframes[0] = skinframe;
932 texture->currentskinframe = skinframe;
933 //texture->backgroundnumskinframes = 0;
934 //texture->customblendfunc[0] = 0;
935 //texture->customblendfunc[1] = 0;
936 //texture->surfaceflags = 0;
937 //texture->supercontents = 0;
938 //texture->surfaceparms = 0;
939 //texture->textureflags = 0;
941 texture->basematerialflags = MATERIALFLAG_WALL;
942 if (texture->currentskinframe->hasalpha)
943 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
944 texture->currentmaterialflags = texture->basematerialflags;
945 texture->offsetmapping = OFFSETMAPPING_OFF;
946 texture->offsetscale = 1;
947 texture->specularscalemod = 1;
948 texture->specularpowermod = 1;
949 texture->surfaceflags = 0;
950 texture->supercontents = SUPERCONTENTS_SOLID;
951 if (!(texture->basematerialflags & MATERIALFLAG_BLENDED))
952 texture->supercontents |= SUPERCONTENTS_OPAQUE;
955 void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
958 static char stripbuf[MAX_QPATH];
959 skinfileitem_t *skinfileitem;
962 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
963 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
965 memset(skin, 0, sizeof(*skin));
967 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
969 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
970 if (!strcmp(skinfileitem->name, meshname))
972 Image_StripImageExtension(skinfileitem->replacement, stripbuf, sizeof(stripbuf));
973 Mod_LoadTextureFromQ3Shader(skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
979 // don't render unmentioned meshes
980 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
981 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
987 Image_StripImageExtension(shadername, stripbuf, sizeof(stripbuf));
988 Mod_LoadTextureFromQ3Shader(skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
992 #define BOUNDI(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid ##VALUE (%d exceeds %d - %d)", loadmodel->name, VALUE, MIN, MAX);
993 #define BOUNDF(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid ##VALUE (%f exceeds %f - %f)", loadmodel->name, VALUE, MIN, MAX);
994 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
996 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
997 float scales, scalet, interval;
1001 stvert_t *pinstverts;
1002 dtriangle_t *pintriangles;
1003 daliasskintype_t *pinskintype;
1004 daliasskingroup_t *pinskingroup;
1005 daliasskininterval_t *pinskinintervals;
1006 daliasframetype_t *pinframetype;
1007 daliasgroup_t *pinframegroup;
1008 unsigned char *datapointer, *startframes, *startskins;
1009 char name[MAX_QPATH];
1010 skinframe_t *tempskinframe;
1011 animscene_t *tempskinscenes;
1012 texture_t *tempaliasskins;
1014 int *vertonseam, *vertremap;
1015 skinfile_t *skinfiles;
1017 datapointer = (unsigned char *)buffer;
1018 pinmodel = (mdl_t *)datapointer;
1019 datapointer += sizeof(mdl_t);
1021 version = LittleLong (pinmodel->version);
1022 if (version != ALIAS_VERSION)
1023 Host_Error ("%s has wrong version number (%i should be %i)",
1024 loadmodel->name, version, ALIAS_VERSION);
1026 loadmodel->modeldatatypestring = "MDL";
1028 loadmodel->type = mod_alias;
1029 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1030 loadmodel->DrawSky = NULL;
1031 loadmodel->DrawAddWaterPlanes = NULL;
1032 loadmodel->Draw = R_Q1BSP_Draw;
1033 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1034 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1035 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1036 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1037 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1038 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1039 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1040 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1041 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1042 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1043 // FIXME add TraceBrush!
1044 loadmodel->PointSuperContents = NULL;
1046 loadmodel->num_surfaces = 1;
1047 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1048 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
1049 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1050 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1051 loadmodel->sortedmodelsurfaces[0] = 0;
1053 loadmodel->numskins = LittleLong(pinmodel->numskins);
1054 BOUNDI(loadmodel->numskins,0,65536);
1055 skinwidth = LittleLong (pinmodel->skinwidth);
1056 BOUNDI(skinwidth,0,65536);
1057 skinheight = LittleLong (pinmodel->skinheight);
1058 BOUNDI(skinheight,0,65536);
1059 numverts = LittleLong(pinmodel->numverts);
1060 BOUNDI(numverts,0,65536);
1061 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
1062 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
1063 loadmodel->numframes = LittleLong(pinmodel->numframes);
1064 BOUNDI(loadmodel->numframes,0,65536);
1065 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
1066 BOUNDI((int)loadmodel->synctype,0,2);
1067 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1068 i = LittleLong (pinmodel->flags);
1069 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1071 for (i = 0;i < 3;i++)
1073 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
1074 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
1077 startskins = datapointer;
1079 for (i = 0;i < loadmodel->numskins;i++)
1081 pinskintype = (daliasskintype_t *)datapointer;
1082 datapointer += sizeof(daliasskintype_t);
1083 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
1087 pinskingroup = (daliasskingroup_t *)datapointer;
1088 datapointer += sizeof(daliasskingroup_t);
1089 groupskins = LittleLong(pinskingroup->numskins);
1090 datapointer += sizeof(daliasskininterval_t) * groupskins;
1093 for (j = 0;j < groupskins;j++)
1095 datapointer += skinwidth * skinheight;
1100 pinstverts = (stvert_t *)datapointer;
1101 datapointer += sizeof(stvert_t) * numverts;
1103 pintriangles = (dtriangle_t *)datapointer;
1104 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
1106 startframes = datapointer;
1107 loadmodel->surfmesh.num_morphframes = 0;
1108 for (i = 0;i < loadmodel->numframes;i++)
1110 pinframetype = (daliasframetype_t *)datapointer;
1111 datapointer += sizeof(daliasframetype_t);
1112 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
1116 pinframegroup = (daliasgroup_t *)datapointer;
1117 datapointer += sizeof(daliasgroup_t);
1118 groupframes = LittleLong(pinframegroup->numframes);
1119 datapointer += sizeof(daliasinterval_t) * groupframes;
1122 for (j = 0;j < groupframes;j++)
1124 datapointer += sizeof(daliasframe_t);
1125 datapointer += sizeof(trivertx_t) * numverts;
1126 loadmodel->surfmesh.num_morphframes++;
1129 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1131 // store texture coordinates into temporary array, they will be stored
1132 // after usage is determined (triangle data)
1133 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
1134 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
1135 vertonseam = vertremap + numverts * 2;
1137 scales = 1.0 / skinwidth;
1138 scalet = 1.0 / skinheight;
1139 for (i = 0;i < numverts;i++)
1141 vertonseam[i] = LittleLong(pinstverts[i].onseam);
1142 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
1143 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
1144 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
1145 vertst[(i+numverts)*2+1] = vertst[i*2+1];
1148 // load triangle data
1149 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1151 // read the triangle elements
1152 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1153 for (j = 0;j < 3;j++)
1154 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1155 // validate (note numverts is used because this is the original data)
1156 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1157 // now butcher the elements according to vertonseam and tri->facesfront
1158 // and then compact the vertex set to remove duplicates
1159 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1160 if (!LittleLong(pintriangles[i].facesfront)) // backface
1161 for (j = 0;j < 3;j++)
1162 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1163 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1165 // (this uses vertremap to count usage to save some memory)
1166 for (i = 0;i < numverts*2;i++)
1168 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1169 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1170 // build remapping table and compact array
1171 loadmodel->surfmesh.num_vertices = 0;
1172 for (i = 0;i < numverts*2;i++)
1176 vertremap[i] = loadmodel->surfmesh.num_vertices;
1177 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1178 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1179 loadmodel->surfmesh.num_vertices++;
1182 vertremap[i] = -1; // not used at all
1184 // remap the elements to the new vertex set
1185 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1186 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1187 // store the texture coordinates
1188 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1189 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1191 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1192 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1195 // generate ushort elements array if possible
1196 if (loadmodel->surfmesh.num_vertices <= 65536)
1197 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1198 if (loadmodel->surfmesh.data_element3s)
1199 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1200 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1203 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1204 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1205 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1206 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1207 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1208 Mod_Alias_CalculateBoundingBox();
1209 Mod_Alias_MorphMesh_CompileFrames();
1212 Mem_Free(vertremap);
1215 skinfiles = Mod_LoadSkinFiles();
1218 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1219 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1220 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1221 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1222 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1223 Mod_FreeSkinFiles(skinfiles);
1224 for (i = 0;i < loadmodel->numskins;i++)
1226 loadmodel->skinscenes[i].firstframe = i;
1227 loadmodel->skinscenes[i].framecount = 1;
1228 loadmodel->skinscenes[i].loop = true;
1229 loadmodel->skinscenes[i].framerate = 10;
1234 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1235 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1236 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1237 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1239 datapointer = startskins;
1240 for (i = 0;i < loadmodel->numskins;i++)
1242 pinskintype = (daliasskintype_t *)datapointer;
1243 datapointer += sizeof(daliasskintype_t);
1245 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1252 pinskingroup = (daliasskingroup_t *)datapointer;
1253 datapointer += sizeof(daliasskingroup_t);
1255 groupskins = LittleLong (pinskingroup->numskins);
1257 pinskinintervals = (daliasskininterval_t *)datapointer;
1258 datapointer += sizeof(daliasskininterval_t) * groupskins;
1260 interval = LittleFloat(pinskinintervals[0].interval);
1261 if (interval < 0.01f)
1263 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1268 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1269 loadmodel->skinscenes[i].firstframe = totalskins;
1270 loadmodel->skinscenes[i].framecount = groupskins;
1271 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1272 loadmodel->skinscenes[i].loop = true;
1274 for (j = 0;j < groupskins;j++)
1277 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1279 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1280 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))
1281 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));
1282 datapointer += skinwidth * skinheight;
1286 // check for skins that don't exist in the model, but do exist as external images
1287 // (this was added because yummyluv kept pestering me about support for it)
1288 // TODO: support shaders here?
1289 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)))
1291 // expand the arrays to make room
1292 tempskinscenes = loadmodel->skinscenes;
1293 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1294 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1295 Mem_Free(tempskinscenes);
1297 tempaliasskins = loadmodel->data_textures;
1298 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1299 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1300 Mem_Free(tempaliasskins);
1302 // store the info about the new skin
1303 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1304 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1305 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1306 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1307 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1308 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1310 //increase skin counts
1311 loadmodel->numskins++;
1314 // fix up the pointers since they are pointing at the old textures array
1315 // FIXME: this is a hack!
1316 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1317 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1321 surface = loadmodel->data_surfaces;
1322 surface->texture = loadmodel->data_textures;
1323 surface->num_firsttriangle = 0;
1324 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1325 surface->num_firstvertex = 0;
1326 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1328 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1330 if (!loadmodel->surfmesh.isanimated)
1332 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1333 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1334 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1335 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1336 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1337 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1341 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1343 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1344 float iskinwidth, iskinheight;
1345 unsigned char *data;
1346 msurface_t *surface;
1348 unsigned char *base, *datapointer;
1349 md2frame_t *pinframe;
1351 md2triangle_t *intri;
1352 unsigned short *inst;
1353 struct md2verthash_s
1355 struct md2verthash_s *next;
1359 *hash, **md2verthash, *md2verthashdata;
1360 skinfile_t *skinfiles;
1362 pinmodel = (md2_t *)buffer;
1363 base = (unsigned char *)buffer;
1365 version = LittleLong (pinmodel->version);
1366 if (version != MD2ALIAS_VERSION)
1367 Host_Error ("%s has wrong version number (%i should be %i)",
1368 loadmodel->name, version, MD2ALIAS_VERSION);
1370 loadmodel->modeldatatypestring = "MD2";
1372 loadmodel->type = mod_alias;
1373 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1374 loadmodel->DrawSky = NULL;
1375 loadmodel->DrawAddWaterPlanes = NULL;
1376 loadmodel->Draw = R_Q1BSP_Draw;
1377 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1378 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1379 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1380 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1381 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1382 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1383 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1384 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1385 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1386 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1387 loadmodel->PointSuperContents = NULL;
1389 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1390 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1391 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1392 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1393 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1394 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1395 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1396 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1398 end = LittleLong(pinmodel->ofs_end);
1399 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1400 Host_Error ("%s is not a valid model", loadmodel->name);
1401 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1402 Host_Error ("%s is not a valid model", loadmodel->name);
1403 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1404 Host_Error ("%s is not a valid model", loadmodel->name);
1405 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1406 Host_Error ("%s is not a valid model", loadmodel->name);
1407 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1408 Host_Error ("%s is not a valid model", loadmodel->name);
1410 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1411 numxyz = LittleLong(pinmodel->num_xyz);
1412 numst = LittleLong(pinmodel->num_st);
1413 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1414 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1415 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1416 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1417 skinwidth = LittleLong(pinmodel->skinwidth);
1418 skinheight = LittleLong(pinmodel->skinheight);
1419 iskinwidth = 1.0f / skinwidth;
1420 iskinheight = 1.0f / skinheight;
1422 loadmodel->num_surfaces = 1;
1423 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1424 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]));
1425 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1426 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1427 loadmodel->sortedmodelsurfaces[0] = 0;
1428 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1429 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1430 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1431 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1433 loadmodel->synctype = ST_RAND;
1436 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1437 skinfiles = Mod_LoadSkinFiles();
1440 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1441 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1442 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1443 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1444 Mod_FreeSkinFiles(skinfiles);
1446 else if (loadmodel->numskins)
1448 // skins found (most likely not a player model)
1449 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1450 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1451 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1452 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1453 Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
1457 // no skins (most likely a player model)
1458 loadmodel->numskins = 1;
1459 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1460 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1461 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1462 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1465 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1466 for (i = 0;i < loadmodel->numskins;i++)
1468 loadmodel->skinscenes[i].firstframe = i;
1469 loadmodel->skinscenes[i].framecount = 1;
1470 loadmodel->skinscenes[i].loop = true;
1471 loadmodel->skinscenes[i].framerate = 10;
1474 // load the triangles and stvert data
1475 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1476 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1477 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1478 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1479 // swap the triangle list
1480 loadmodel->surfmesh.num_vertices = 0;
1481 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1483 for (j = 0;j < 3;j++)
1485 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1486 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1489 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1494 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1497 hashindex = (xyz * 256 + st) & 65535;
1498 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1499 if (hash->xyz == xyz && hash->st == st)
1503 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1506 hash->next = md2verthash[hashindex];
1507 md2verthash[hashindex] = hash;
1509 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1513 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1514 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));
1515 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1516 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1517 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1520 hash = md2verthashdata + i;
1521 vertremap[i] = hash->xyz;
1522 sts = LittleShort(inst[hash->st*2+0]);
1523 stt = LittleShort(inst[hash->st*2+1]);
1524 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1526 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1530 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1531 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1534 Mem_Free(md2verthash);
1535 Mem_Free(md2verthashdata);
1537 // generate ushort elements array if possible
1538 if (loadmodel->surfmesh.num_vertices <= 65536)
1539 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1540 if (loadmodel->surfmesh.data_element3s)
1541 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1542 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1545 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1546 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1551 pinframe = (md2frame_t *)datapointer;
1552 datapointer += sizeof(md2frame_t);
1553 // store the frame scale/translate into the appropriate array
1554 for (j = 0;j < 3;j++)
1556 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1557 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1559 // convert the vertices
1560 v = (trivertx_t *)datapointer;
1561 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1562 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1563 out[k] = v[vertremap[k]];
1564 datapointer += numxyz * sizeof(trivertx_t);
1566 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1567 loadmodel->animscenes[i].firstframe = i;
1568 loadmodel->animscenes[i].framecount = 1;
1569 loadmodel->animscenes[i].framerate = 10;
1570 loadmodel->animscenes[i].loop = true;
1573 Mem_Free(vertremap);
1575 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1576 Mod_Alias_CalculateBoundingBox();
1577 Mod_Alias_MorphMesh_CompileFrames();
1579 surface = loadmodel->data_surfaces;
1580 surface->texture = loadmodel->data_textures;
1581 surface->num_firsttriangle = 0;
1582 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1583 surface->num_firstvertex = 0;
1584 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1586 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1588 if (!loadmodel->surfmesh.isanimated)
1590 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1591 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1592 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1593 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1594 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1595 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1599 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1601 int i, j, k, version, meshvertices, meshtriangles;
1602 unsigned char *data;
1603 msurface_t *surface;
1604 md3modelheader_t *pinmodel;
1605 md3frameinfo_t *pinframe;
1608 skinfile_t *skinfiles;
1610 pinmodel = (md3modelheader_t *)buffer;
1612 if (memcmp(pinmodel->identifier, "IDP3", 4))
1613 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1614 version = LittleLong (pinmodel->version);
1615 if (version != MD3VERSION)
1616 Host_Error ("%s has wrong version number (%i should be %i)",
1617 loadmodel->name, version, MD3VERSION);
1619 skinfiles = Mod_LoadSkinFiles();
1620 if (loadmodel->numskins < 1)
1621 loadmodel->numskins = 1;
1623 loadmodel->modeldatatypestring = "MD3";
1625 loadmodel->type = mod_alias;
1626 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1627 loadmodel->DrawSky = NULL;
1628 loadmodel->DrawAddWaterPlanes = NULL;
1629 loadmodel->Draw = R_Q1BSP_Draw;
1630 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1631 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1632 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1633 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1634 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1635 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1636 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1637 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1638 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1639 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1640 loadmodel->PointSuperContents = NULL;
1641 loadmodel->synctype = ST_RAND;
1642 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1643 i = LittleLong (pinmodel->flags);
1644 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1646 // set up some global info about the model
1647 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1648 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1650 // make skinscenes for the skins (no groups)
1651 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1652 for (i = 0;i < loadmodel->numskins;i++)
1654 loadmodel->skinscenes[i].firstframe = i;
1655 loadmodel->skinscenes[i].framecount = 1;
1656 loadmodel->skinscenes[i].loop = true;
1657 loadmodel->skinscenes[i].framerate = 10;
1661 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1662 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1664 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1665 loadmodel->animscenes[i].firstframe = i;
1666 loadmodel->animscenes[i].framecount = 1;
1667 loadmodel->animscenes[i].framerate = 10;
1668 loadmodel->animscenes[i].loop = true;
1672 loadmodel->num_tagframes = loadmodel->numframes;
1673 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1674 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1675 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1677 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1678 for (j = 0;j < 9;j++)
1679 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1680 for (j = 0;j < 3;j++)
1681 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1682 //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);
1688 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)))
1690 if (memcmp(pinmesh->identifier, "IDP3", 4))
1691 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1692 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1693 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1694 meshvertices += LittleLong(pinmesh->num_vertices);
1695 meshtriangles += LittleLong(pinmesh->num_triangles);
1698 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1699 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1700 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1701 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));
1702 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1703 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1704 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1705 loadmodel->surfmesh.num_vertices = meshvertices;
1706 loadmodel->surfmesh.num_triangles = meshtriangles;
1707 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1708 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1709 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1710 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1711 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1712 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1713 if (meshvertices <= 65536)
1714 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1718 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)))
1720 if (memcmp(pinmesh->identifier, "IDP3", 4))
1721 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1722 loadmodel->sortedmodelsurfaces[i] = i;
1723 surface = loadmodel->data_surfaces + i;
1724 surface->texture = loadmodel->data_textures + i;
1725 surface->num_firsttriangle = meshtriangles;
1726 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1727 surface->num_firstvertex = meshvertices;
1728 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1729 meshvertices += surface->num_vertices;
1730 meshtriangles += surface->num_triangles;
1732 for (j = 0;j < surface->num_triangles * 3;j++)
1733 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1734 for (j = 0;j < surface->num_vertices;j++)
1736 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1737 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1739 for (j = 0;j < loadmodel->numframes;j++)
1741 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1742 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1743 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1745 out->origin[0] = LittleShort(in->origin[0]);
1746 out->origin[1] = LittleShort(in->origin[1]);
1747 out->origin[2] = LittleShort(in->origin[2]);
1748 out->pitch = in->pitch;
1753 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1755 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1757 if (loadmodel->surfmesh.data_element3s)
1758 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1759 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1760 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1761 Mod_Alias_MorphMesh_CompileFrames();
1762 Mod_Alias_CalculateBoundingBox();
1763 Mod_FreeSkinFiles(skinfiles);
1764 Mod_MakeSortedSurfaces(loadmodel);
1766 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1767 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1769 if (!loadmodel->surfmesh.isanimated)
1771 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1772 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1773 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1774 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1775 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1776 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1780 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1782 zymtype1header_t *pinmodel, *pheader;
1783 unsigned char *pbase;
1784 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1785 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose, f, biggestorigin, tempvec[3], modelscale;
1786 zymvertex_t *verts, *vertdata;
1790 skinfile_t *skinfiles;
1791 unsigned char *data;
1792 msurface_t *surface;
1794 pinmodel = (zymtype1header_t *)buffer;
1795 pbase = (unsigned char *)buffer;
1796 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1797 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1798 if (BigLong(pinmodel->type) != 1)
1799 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1801 loadmodel->modeldatatypestring = "ZYM";
1803 loadmodel->type = mod_alias;
1804 loadmodel->synctype = ST_RAND;
1808 pheader->type = BigLong(pinmodel->type);
1809 pheader->filesize = BigLong(pinmodel->filesize);
1810 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1811 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1812 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1813 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1814 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1815 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1816 pheader->radius = BigFloat(pinmodel->radius);
1817 pheader->numverts = BigLong(pinmodel->numverts);
1818 pheader->numtris = BigLong(pinmodel->numtris);
1819 pheader->numshaders = BigLong(pinmodel->numshaders);
1820 pheader->numbones = BigLong(pinmodel->numbones);
1821 pheader->numscenes = BigLong(pinmodel->numscenes);
1822 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1823 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1824 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1825 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1826 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1827 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1828 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1829 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1830 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1831 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1832 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1833 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1834 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1835 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1836 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1837 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1838 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1839 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1841 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1843 Con_Printf("%s has no geometry\n", loadmodel->name);
1846 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1848 Con_Printf("%s has no animations\n", loadmodel->name);
1852 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1853 loadmodel->DrawSky = NULL;
1854 loadmodel->DrawAddWaterPlanes = NULL;
1855 loadmodel->Draw = R_Q1BSP_Draw;
1856 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1857 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1858 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1859 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1860 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1861 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1862 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1863 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1864 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1865 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1866 loadmodel->PointSuperContents = NULL;
1868 loadmodel->numframes = pheader->numscenes;
1869 loadmodel->num_surfaces = pheader->numshaders;
1871 skinfiles = Mod_LoadSkinFiles();
1872 if (loadmodel->numskins < 1)
1873 loadmodel->numskins = 1;
1875 // make skinscenes for the skins (no groups)
1876 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1877 for (i = 0;i < loadmodel->numskins;i++)
1879 loadmodel->skinscenes[i].firstframe = i;
1880 loadmodel->skinscenes[i].framecount = 1;
1881 loadmodel->skinscenes[i].loop = true;
1882 loadmodel->skinscenes[i].framerate = 10;
1886 modelradius = pheader->radius;
1887 for (i = 0;i < 3;i++)
1889 loadmodel->normalmins[i] = pheader->mins[i];
1890 loadmodel->normalmaxs[i] = pheader->maxs[i];
1891 loadmodel->rotatedmins[i] = -modelradius;
1892 loadmodel->rotatedmaxs[i] = modelradius;
1894 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1895 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1896 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1897 if (loadmodel->yawmaxs[0] > modelradius)
1898 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1899 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1900 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1901 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1902 loadmodel->radius = modelradius;
1903 loadmodel->radius2 = modelradius * modelradius;
1905 // go through the lumps, swapping things
1907 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1908 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1909 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1910 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1911 for (i = 0;i < pheader->numscenes;i++)
1913 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1914 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1915 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1916 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1917 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1918 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1919 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1920 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1921 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1922 if (loadmodel->animscenes[i].framerate < 0)
1923 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1927 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1928 loadmodel->num_bones = pheader->numbones;
1929 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1930 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1931 for (i = 0;i < pheader->numbones;i++)
1933 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1934 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1935 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1936 if (loadmodel->data_bones[i].parent >= i)
1937 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1940 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1941 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1942 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1943 for (i = 0;i < pheader->numverts;i++)
1945 vertbonecounts[i] = BigLong(bonecount[i]);
1946 if (vertbonecounts[i] != 1)
1947 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1950 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1952 meshvertices = pheader->numverts;
1953 meshtriangles = pheader->numtris;
1955 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1956 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1957 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1958 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]));
1959 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1960 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1961 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1962 loadmodel->surfmesh.num_vertices = meshvertices;
1963 loadmodel->surfmesh.num_triangles = meshtriangles;
1964 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1965 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1966 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1967 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1968 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1969 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1970 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1971 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1972 loadmodel->surfmesh.num_blends = 0;
1973 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
1974 if (loadmodel->surfmesh.num_vertices <= 65536)
1975 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1976 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
1977 loadmodel->surfmesh.data_blendweights = NULL;
1979 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1980 poses = (float *) (pheader->lump_poses.start + pbase);
1981 // figure out scale of model from root bone, for compatibility with old zmodel versions
1982 tempvec[0] = BigFloat(poses[0]);
1983 tempvec[1] = BigFloat(poses[1]);
1984 tempvec[2] = BigFloat(poses[2]);
1985 modelscale = VectorLength(tempvec);
1987 for (i = 0;i < loadmodel->num_bones * numposes * 12;i++)
1989 f = fabs(BigFloat(poses[i]));
1990 biggestorigin = max(biggestorigin, f);
1992 loadmodel->num_posescale = biggestorigin / 32767.0f;
1993 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
1994 for (i = 0;i < numposes;i++)
1996 const float *frameposes = (float *) (pheader->lump_poses.start + pbase) + 12*i*loadmodel->num_bones;
1997 for (j = 0;j < loadmodel->num_bones;j++)
2000 matrix4x4_t posematrix;
2001 for (k = 0;k < 12;k++)
2002 pose[k] = BigFloat(frameposes[j*12+k]);
2003 //if (j < loadmodel->num_bones)
2004 // 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));
2005 // scale child bones to match the root scale
2006 if (loadmodel->data_bones[j].parent >= 0)
2008 pose[3] *= modelscale;
2009 pose[7] *= modelscale;
2010 pose[11] *= modelscale;
2012 // normalize rotation matrix
2013 VectorNormalize(pose + 0);
2014 VectorNormalize(pose + 4);
2015 VectorNormalize(pose + 8);
2016 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2017 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
2021 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
2022 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
2023 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
2024 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2025 // (converting from weight-blending skeletal animation to
2026 // deformation-based skeletal animation)
2027 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2028 for (i = 0;i < loadmodel->num_bones;i++)
2031 for (k = 0;k < 12;k++)
2032 m[k] = BigFloat(poses[i*12+k]);
2033 if (loadmodel->data_bones[i].parent >= 0)
2034 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2036 for (k = 0;k < 12;k++)
2037 bonepose[12*i+k] = m[k];
2039 for (j = 0;j < pheader->numverts;j++)
2041 // this format really should have had a per vertexweight weight value...
2042 // but since it does not, the weighting is completely ignored and
2043 // only one weight is allowed per vertex
2044 int boneindex = BigLong(vertdata[j].bonenum);
2045 const float *m = bonepose + 12 * boneindex;
2046 float relativeorigin[3];
2047 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
2048 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
2049 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
2050 // transform the vertex bone weight into the base mesh
2051 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
2052 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
2053 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
2054 // store the weight as the primary weight on this vertex
2055 loadmodel->surfmesh.blends[j] = boneindex;
2058 // normals and tangents are calculated after elements are loaded
2060 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
2061 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
2062 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
2063 for (i = 0;i < pheader->numverts;i++)
2065 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
2066 // flip T coordinate for OpenGL
2067 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
2070 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
2071 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
2072 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
2074 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
2075 //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)
2076 // byteswap, validate, and swap winding order of tris
2077 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
2078 if (pheader->lump_render.length != count)
2079 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
2080 renderlist = (int *) (pheader->lump_render.start + pbase);
2081 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
2083 for (i = 0;i < loadmodel->num_surfaces;i++)
2085 int firstvertex, lastvertex;
2086 if (renderlist >= renderlistend)
2087 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2088 count = BigLong(*renderlist);renderlist++;
2089 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
2090 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2092 loadmodel->sortedmodelsurfaces[i] = i;
2093 surface = loadmodel->data_surfaces + i;
2094 surface->texture = loadmodel->data_textures + i;
2095 surface->num_firsttriangle = meshtriangles;
2096 surface->num_triangles = count;
2097 meshtriangles += surface->num_triangles;
2099 // load the elements
2100 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2101 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
2103 outelements[j*3+2] = BigLong(renderlist[0]);
2104 outelements[j*3+1] = BigLong(renderlist[1]);
2105 outelements[j*3+0] = BigLong(renderlist[2]);
2107 // validate the elements and find the used vertex range
2108 firstvertex = meshvertices;
2110 for (j = 0;j < surface->num_triangles * 3;j++)
2112 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
2113 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
2114 firstvertex = min(firstvertex, outelements[j]);
2115 lastvertex = max(lastvertex, outelements[j]);
2117 surface->num_firstvertex = firstvertex;
2118 surface->num_vertices = lastvertex + 1 - firstvertex;
2120 // since zym models do not have named sections, reuse their shader
2121 // name as the section name
2122 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
2123 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
2125 Mod_FreeSkinFiles(skinfiles);
2126 Mem_Free(vertbonecounts);
2128 Mod_MakeSortedSurfaces(loadmodel);
2130 // compute all the mesh information that was not loaded from the file
2131 if (loadmodel->surfmesh.data_element3s)
2132 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2133 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2134 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2135 Mod_BuildBaseBonePoses();
2136 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2137 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);
2138 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2140 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2142 if (!loadmodel->surfmesh.isanimated)
2144 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2145 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2146 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2147 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2148 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2149 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2153 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2155 dpmheader_t *pheader;
2159 unsigned char *pbase;
2160 int i, j, k, meshvertices, meshtriangles;
2161 skinfile_t *skinfiles;
2162 unsigned char *data;
2164 float biggestorigin, tempvec[3], modelscale;
2168 pheader = (dpmheader_t *)buffer;
2169 pbase = (unsigned char *)buffer;
2170 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2171 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2172 if (BigLong(pheader->type) != 2)
2173 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2175 loadmodel->modeldatatypestring = "DPM";
2177 loadmodel->type = mod_alias;
2178 loadmodel->synctype = ST_RAND;
2181 pheader->type = BigLong(pheader->type);
2182 pheader->filesize = BigLong(pheader->filesize);
2183 pheader->mins[0] = BigFloat(pheader->mins[0]);
2184 pheader->mins[1] = BigFloat(pheader->mins[1]);
2185 pheader->mins[2] = BigFloat(pheader->mins[2]);
2186 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2187 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2188 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2189 pheader->yawradius = BigFloat(pheader->yawradius);
2190 pheader->allradius = BigFloat(pheader->allradius);
2191 pheader->num_bones = BigLong(pheader->num_bones);
2192 pheader->num_meshs = BigLong(pheader->num_meshs);
2193 pheader->num_frames = BigLong(pheader->num_frames);
2194 pheader->ofs_bones = BigLong(pheader->ofs_bones);
2195 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2196 pheader->ofs_frames = BigLong(pheader->ofs_frames);
2198 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2200 Con_Printf("%s has no geometry\n", loadmodel->name);
2203 if (pheader->num_frames < 1)
2205 Con_Printf("%s has no frames\n", loadmodel->name);
2209 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2210 loadmodel->DrawSky = NULL;
2211 loadmodel->DrawAddWaterPlanes = NULL;
2212 loadmodel->Draw = R_Q1BSP_Draw;
2213 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2214 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2215 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2216 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2217 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2218 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2219 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2220 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2221 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2222 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2223 loadmodel->PointSuperContents = NULL;
2226 for (i = 0;i < 3;i++)
2228 loadmodel->normalmins[i] = pheader->mins[i];
2229 loadmodel->normalmaxs[i] = pheader->maxs[i];
2230 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2231 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2232 loadmodel->rotatedmins[i] = -pheader->allradius;
2233 loadmodel->rotatedmaxs[i] = pheader->allradius;
2235 loadmodel->radius = pheader->allradius;
2236 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2238 // load external .skin files if present
2239 skinfiles = Mod_LoadSkinFiles();
2240 if (loadmodel->numskins < 1)
2241 loadmodel->numskins = 1;
2246 // gather combined statistics from the meshes
2247 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2248 for (i = 0;i < (int)pheader->num_meshs;i++)
2250 int numverts = BigLong(dpmmesh->num_verts);
2251 meshvertices += numverts;
2252 meshtriangles += BigLong(dpmmesh->num_tris);
2256 loadmodel->numframes = pheader->num_frames;
2257 loadmodel->num_bones = pheader->num_bones;
2258 loadmodel->num_poses = loadmodel->numframes;
2259 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2260 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2261 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2262 // do most allocations as one merged chunk
2263 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));
2264 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2265 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2266 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2267 loadmodel->surfmesh.num_vertices = meshvertices;
2268 loadmodel->surfmesh.num_triangles = meshtriangles;
2269 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2270 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2271 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2272 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2273 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2274 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2275 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2276 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2277 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2278 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2279 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2280 loadmodel->surfmesh.num_blends = 0;
2281 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2282 if (meshvertices <= 65536)
2283 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2284 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2285 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
2287 for (i = 0;i < loadmodel->numskins;i++)
2289 loadmodel->skinscenes[i].firstframe = i;
2290 loadmodel->skinscenes[i].framecount = 1;
2291 loadmodel->skinscenes[i].loop = true;
2292 loadmodel->skinscenes[i].framerate = 10;
2295 // load the bone info
2296 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2297 for (i = 0;i < loadmodel->num_bones;i++)
2299 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2300 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2301 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2302 if (loadmodel->data_bones[i].parent >= i)
2303 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2307 frames = (dpmframe_t *) (pbase + pheader->ofs_frames);
2308 // figure out scale of model from root bone, for compatibility with old dpmodel versions
2309 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2310 tempvec[0] = BigFloat(poses[0]);
2311 tempvec[1] = BigFloat(poses[1]);
2312 tempvec[2] = BigFloat(poses[2]);
2313 modelscale = VectorLength(tempvec);
2315 for (i = 0;i < loadmodel->numframes;i++)
2317 memcpy(loadmodel->animscenes[i].name, frames[i].name, sizeof(frames[i].name));
2318 loadmodel->animscenes[i].firstframe = i;
2319 loadmodel->animscenes[i].framecount = 1;
2320 loadmodel->animscenes[i].loop = true;
2321 loadmodel->animscenes[i].framerate = 10;
2322 // load the bone poses for this frame
2323 poses = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2324 for (j = 0;j < loadmodel->num_bones*12;j++)
2326 f = fabs(BigFloat(poses[j]));
2327 biggestorigin = max(biggestorigin, f);
2329 // stuff not processed here: mins, maxs, yawradius, allradius
2331 loadmodel->num_posescale = biggestorigin / 32767.0f;
2332 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2333 for (i = 0;i < loadmodel->numframes;i++)
2335 const float *frameposes = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2336 for (j = 0;j < loadmodel->num_bones;j++)
2339 matrix4x4_t posematrix;
2340 for (k = 0;k < 12;k++)
2341 pose[k] = BigFloat(frameposes[j*12+k]);
2342 // scale child bones to match the root scale
2343 if (loadmodel->data_bones[j].parent >= 0)
2345 pose[3] *= modelscale;
2346 pose[7] *= modelscale;
2347 pose[11] *= modelscale;
2349 // normalize rotation matrix
2350 VectorNormalize(pose + 0);
2351 VectorNormalize(pose + 4);
2352 VectorNormalize(pose + 8);
2353 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2354 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
2358 // load the meshes now
2359 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2362 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2363 // (converting from weight-blending skeletal animation to
2364 // deformation-based skeletal animation)
2365 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2366 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2367 for (i = 0;i < loadmodel->num_bones;i++)
2370 for (k = 0;k < 12;k++)
2371 m[k] = BigFloat(poses[i*12+k]);
2372 if (loadmodel->data_bones[i].parent >= 0)
2373 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2375 for (k = 0;k < 12;k++)
2376 bonepose[12*i+k] = m[k];
2378 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2380 const int *inelements;
2382 const float *intexcoord;
2383 msurface_t *surface;
2385 loadmodel->sortedmodelsurfaces[i] = i;
2386 surface = loadmodel->data_surfaces + i;
2387 surface->texture = loadmodel->data_textures + i;
2388 surface->num_firsttriangle = meshtriangles;
2389 surface->num_triangles = BigLong(dpmmesh->num_tris);
2390 surface->num_firstvertex = meshvertices;
2391 surface->num_vertices = BigLong(dpmmesh->num_verts);
2392 meshvertices += surface->num_vertices;
2393 meshtriangles += surface->num_triangles;
2395 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2396 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2397 for (j = 0;j < surface->num_triangles;j++)
2399 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2400 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2401 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2402 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2407 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2408 for (j = 0;j < surface->num_vertices*2;j++)
2409 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2411 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2412 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2414 int weightindex[4] = { 0, 0, 0, 0 };
2415 float weightinfluence[4] = { 0, 0, 0, 0 };
2417 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2418 data += sizeof(dpmvertex_t);
2419 for (k = 0;k < numweights;k++)
2421 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2422 int boneindex = BigLong(vert->bonenum);
2423 const float *m = bonepose + 12 * boneindex;
2424 float influence = BigFloat(vert->influence);
2425 float relativeorigin[3], relativenormal[3];
2426 relativeorigin[0] = BigFloat(vert->origin[0]);
2427 relativeorigin[1] = BigFloat(vert->origin[1]);
2428 relativeorigin[2] = BigFloat(vert->origin[2]);
2429 relativenormal[0] = BigFloat(vert->normal[0]);
2430 relativenormal[1] = BigFloat(vert->normal[1]);
2431 relativenormal[2] = BigFloat(vert->normal[2]);
2432 // blend the vertex bone weights into the base mesh
2433 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2434 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2435 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2436 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2437 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2438 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2441 // store the first (and often only) weight
2442 weightinfluence[0] = influence;
2443 weightindex[0] = boneindex;
2447 // sort the new weight into this vertex's weight table
2448 // (which only accepts up to 4 bones per vertex)
2449 for (l = 0;l < 4;l++)
2451 if (weightinfluence[l] < influence)
2453 // move weaker influence weights out of the way first
2455 for (l2 = 3;l2 > l;l2--)
2457 weightinfluence[l2] = weightinfluence[l2-1];
2458 weightindex[l2] = weightindex[l2-1];
2460 // store the new weight
2461 weightinfluence[l] = influence;
2462 weightindex[l] = boneindex;
2467 data += sizeof(dpmbonevert_t);
2469 loadmodel->surfmesh.blends[j] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
2472 // since dpm models do not have named sections, reuse their shader name as the section name
2473 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2475 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2477 if (loadmodel->surfmesh.num_blends < meshvertices)
2478 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2480 Mod_FreeSkinFiles(skinfiles);
2481 Mod_MakeSortedSurfaces(loadmodel);
2483 // compute all the mesh information that was not loaded from the file
2484 if (loadmodel->surfmesh.data_element3s)
2485 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2486 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2487 Mod_BuildBaseBonePoses();
2488 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);
2489 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2491 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2493 if (!loadmodel->surfmesh.isanimated)
2495 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2496 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2497 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2498 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2499 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2500 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2504 // no idea why PSK/PSA files contain weird quaternions but they do...
2505 #define PSKQUATNEGATIONS
2506 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2508 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2509 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2510 fs_offset_t filesize;
2515 pskboneinfo_t *bones;
2516 pskrawweights_t *rawweights;
2517 //pskboneinfo_t *animbones;
2518 pskaniminfo_t *anims;
2519 pskanimkeys_t *animkeys;
2520 void *animfilebuffer, *animbuffer, *animbufferend;
2521 unsigned char *data;
2523 skinfile_t *skinfiles;
2524 char animname[MAX_QPATH];
2526 float biggestorigin;
2528 pchunk = (pskchunk_t *)buffer;
2529 if (strcmp(pchunk->id, "ACTRHEAD"))
2530 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2532 loadmodel->modeldatatypestring = "PSK";
2534 loadmodel->type = mod_alias;
2535 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2536 loadmodel->DrawSky = NULL;
2537 loadmodel->DrawAddWaterPlanes = NULL;
2538 loadmodel->Draw = R_Q1BSP_Draw;
2539 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2540 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2541 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2542 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2543 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2544 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2545 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2546 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2547 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2548 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2549 loadmodel->PointSuperContents = NULL;
2550 loadmodel->synctype = ST_RAND;
2552 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2553 strlcat(animname, ".psa", sizeof(animname));
2554 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2555 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2556 if (animbuffer == NULL)
2557 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2576 while (buffer < bufferend)
2578 pchunk = (pskchunk_t *)buffer;
2579 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2580 version = LittleLong(pchunk->version);
2581 recordsize = LittleLong(pchunk->recordsize);
2582 numrecords = LittleLong(pchunk->numrecords);
2583 if (developer_extra.integer)
2584 Con_DPrintf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2585 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2586 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);
2587 if (!strcmp(pchunk->id, "ACTRHEAD"))
2591 else if (!strcmp(pchunk->id, "PNTS0000"))
2594 if (recordsize != sizeof(*p))
2595 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2596 // byteswap in place and keep the pointer
2597 numpnts = numrecords;
2598 pnts = (pskpnts_t *)buffer;
2599 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2601 p->origin[0] = LittleFloat(p->origin[0]);
2602 p->origin[1] = LittleFloat(p->origin[1]);
2603 p->origin[2] = LittleFloat(p->origin[2]);
2607 else if (!strcmp(pchunk->id, "VTXW0000"))
2610 if (recordsize != sizeof(*p))
2611 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2612 // byteswap in place and keep the pointer
2613 numvtxw = numrecords;
2614 vtxw = (pskvtxw_t *)buffer;
2615 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2617 p->pntsindex = LittleShort(p->pntsindex);
2618 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2619 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2620 if (p->pntsindex >= numpnts)
2622 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2628 else if (!strcmp(pchunk->id, "FACE0000"))
2631 if (recordsize != sizeof(*p))
2632 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2633 // byteswap in place and keep the pointer
2634 numfaces = numrecords;
2635 faces = (pskface_t *)buffer;
2636 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2638 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2639 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2640 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2641 p->group = LittleLong(p->group);
2642 if (p->vtxwindex[0] >= numvtxw)
2644 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2645 p->vtxwindex[0] = 0;
2647 if (p->vtxwindex[1] >= numvtxw)
2649 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2650 p->vtxwindex[1] = 0;
2652 if (p->vtxwindex[2] >= numvtxw)
2654 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2655 p->vtxwindex[2] = 0;
2660 else if (!strcmp(pchunk->id, "MATT0000"))
2663 if (recordsize != sizeof(*p))
2664 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2665 // byteswap in place and keep the pointer
2666 nummatts = numrecords;
2667 matts = (pskmatt_t *)buffer;
2668 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2674 else if (!strcmp(pchunk->id, "REFSKELT"))
2677 if (recordsize != sizeof(*p))
2678 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2679 // byteswap in place and keep the pointer
2680 numbones = numrecords;
2681 bones = (pskboneinfo_t *)buffer;
2682 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2684 p->numchildren = LittleLong(p->numchildren);
2685 p->parent = LittleLong(p->parent);
2686 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2687 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2688 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2689 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2690 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2691 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2692 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2693 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2694 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2695 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2696 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2697 #ifdef PSKQUATNEGATIONS
2700 p->basepose.quat[0] *= -1;
2701 p->basepose.quat[1] *= -1;
2702 p->basepose.quat[2] *= -1;
2706 p->basepose.quat[0] *= 1;
2707 p->basepose.quat[1] *= -1;
2708 p->basepose.quat[2] *= 1;
2711 if (p->parent < 0 || p->parent >= numbones)
2713 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2719 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2722 if (recordsize != sizeof(*p))
2723 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2724 // byteswap in place and keep the pointer
2725 numrawweights = numrecords;
2726 rawweights = (pskrawweights_t *)buffer;
2727 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2729 p->weight = LittleFloat(p->weight);
2730 p->pntsindex = LittleLong(p->pntsindex);
2731 p->boneindex = LittleLong(p->boneindex);
2732 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2734 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2737 if (p->boneindex < 0 || p->boneindex >= numbones)
2739 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2747 while (animbuffer < animbufferend)
2749 pchunk = (pskchunk_t *)animbuffer;
2750 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2751 version = LittleLong(pchunk->version);
2752 recordsize = LittleLong(pchunk->recordsize);
2753 numrecords = LittleLong(pchunk->numrecords);
2754 if (developer_extra.integer)
2755 Con_DPrintf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2756 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2757 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);
2758 if (!strcmp(pchunk->id, "ANIMHEAD"))
2762 else if (!strcmp(pchunk->id, "BONENAMES"))
2765 if (recordsize != sizeof(*p))
2766 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2767 // byteswap in place and keep the pointer
2768 numanimbones = numrecords;
2769 //animbones = (pskboneinfo_t *)animbuffer;
2770 // NOTE: supposedly psa does not need to match the psk model, the
2771 // bones missing from the psa would simply use their base
2772 // positions from the psk, but this is hard for me to implement
2773 // and people can easily make animations that match.
2774 if (numanimbones != numbones)
2775 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2776 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2778 p->numchildren = LittleLong(p->numchildren);
2779 p->parent = LittleLong(p->parent);
2780 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2781 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2782 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2783 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2784 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2785 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2786 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2787 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2788 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2789 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2790 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2791 #ifdef PSKQUATNEGATIONS
2794 p->basepose.quat[0] *= -1;
2795 p->basepose.quat[1] *= -1;
2796 p->basepose.quat[2] *= -1;
2800 p->basepose.quat[0] *= 1;
2801 p->basepose.quat[1] *= -1;
2802 p->basepose.quat[2] *= 1;
2805 if (p->parent < 0 || p->parent >= numanimbones)
2807 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2810 // check that bones are the same as in the base
2811 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2812 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2816 else if (!strcmp(pchunk->id, "ANIMINFO"))
2819 if (recordsize != sizeof(*p))
2820 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2821 // byteswap in place and keep the pointer
2822 numanims = numrecords;
2823 anims = (pskaniminfo_t *)animbuffer;
2824 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2826 p->numbones = LittleLong(p->numbones);
2827 p->playtime = LittleFloat(p->playtime);
2828 p->fps = LittleFloat(p->fps);
2829 p->firstframe = LittleLong(p->firstframe);
2830 p->numframes = LittleLong(p->numframes);
2831 if (p->numbones != numbones)
2832 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2836 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2839 if (recordsize != sizeof(*p))
2840 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2841 numanimkeys = numrecords;
2842 animkeys = (pskanimkeys_t *)animbuffer;
2843 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2845 p->origin[0] = LittleFloat(p->origin[0]);
2846 p->origin[1] = LittleFloat(p->origin[1]);
2847 p->origin[2] = LittleFloat(p->origin[2]);
2848 p->quat[0] = LittleFloat(p->quat[0]);
2849 p->quat[1] = LittleFloat(p->quat[1]);
2850 p->quat[2] = LittleFloat(p->quat[2]);
2851 p->quat[3] = LittleFloat(p->quat[3]);
2852 p->frametime = LittleFloat(p->frametime);
2853 #ifdef PSKQUATNEGATIONS
2854 if (index % numbones)
2869 // TODO: allocate bonepose stuff
2872 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2875 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2876 Host_Error("%s: missing required chunks", loadmodel->name);
2878 loadmodel->numframes = 0;
2879 for (index = 0;index < numanims;index++)
2880 loadmodel->numframes += anims[index].numframes;
2882 if (numanimkeys != numbones * loadmodel->numframes)
2883 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2885 meshvertices = numvtxw;
2886 meshtriangles = numfaces;
2888 // load external .skin files if present
2889 skinfiles = Mod_LoadSkinFiles();
2890 if (loadmodel->numskins < 1)
2891 loadmodel->numskins = 1;
2892 loadmodel->num_bones = numbones;
2893 loadmodel->num_poses = loadmodel->numframes;
2894 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2895 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2896 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2897 loadmodel->surfmesh.num_vertices = meshvertices;
2898 loadmodel->surfmesh.num_triangles = meshtriangles;
2899 // do most allocations as one merged chunk
2900 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);
2901 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2902 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2903 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2904 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2905 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2906 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2907 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2908 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2909 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2910 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2911 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2912 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2913 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2914 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2915 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2916 loadmodel->surfmesh.num_blends = 0;
2917 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2918 if (loadmodel->surfmesh.num_vertices <= 65536)
2919 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2920 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2921 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(blendweights_t));
2923 for (i = 0;i < loadmodel->numskins;i++)
2925 loadmodel->skinscenes[i].firstframe = i;
2926 loadmodel->skinscenes[i].framecount = 1;
2927 loadmodel->skinscenes[i].loop = true;
2928 loadmodel->skinscenes[i].framerate = 10;
2932 for (index = 0, i = 0;index < nummatts;index++)
2934 // since psk models do not have named sections, reuse their shader name as the section name
2935 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2936 loadmodel->sortedmodelsurfaces[index] = index;
2937 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2938 loadmodel->data_surfaces[index].num_firstvertex = 0;
2939 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2942 // copy over the vertex locations and texcoords
2943 for (index = 0;index < numvtxw;index++)
2945 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2946 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2947 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2948 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2949 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2952 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2953 for (index = 0;index < numfaces;index++)
2954 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2955 for (index = 0, i = 0;index < nummatts;index++)
2957 loadmodel->data_surfaces[index].num_firsttriangle = i;
2958 i += loadmodel->data_surfaces[index].num_triangles;
2959 loadmodel->data_surfaces[index].num_triangles = 0;
2961 for (index = 0;index < numfaces;index++)
2963 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2964 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2965 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2966 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2969 // copy over the bones
2970 for (index = 0;index < numbones;index++)
2972 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2973 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2974 if (loadmodel->data_bones[index].parent >= index)
2975 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2978 // sort the psk point weights into the vertex weight tables
2979 // (which only accept up to 4 bones per vertex)
2980 for (index = 0;index < numvtxw;index++)
2982 int weightindex[4] = { 0, 0, 0, 0 };
2983 float weightinfluence[4] = { 0, 0, 0, 0 };
2985 for (j = 0;j < numrawweights;j++)
2987 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2989 int boneindex = rawweights[j].boneindex;
2990 float influence = rawweights[j].weight;
2991 for (l = 0;l < 4;l++)
2993 if (weightinfluence[l] < influence)
2995 // move lower influence weights out of the way first
2997 for (l2 = 3;l2 > l;l2--)
2999 weightinfluence[l2] = weightinfluence[l2-1];
3000 weightindex[l2] = weightindex[l2-1];
3002 // store the new weight
3003 weightinfluence[l] = influence;
3004 weightindex[l] = boneindex;
3010 loadmodel->surfmesh.blends[index] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
3012 if (loadmodel->surfmesh.num_blends < loadmodel->surfmesh.num_vertices)
3013 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
3015 // set up the animscenes based on the anims
3016 for (index = 0, i = 0;index < numanims;index++)
3018 for (j = 0;j < anims[index].numframes;j++, i++)
3020 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
3021 loadmodel->animscenes[i].firstframe = i;
3022 loadmodel->animscenes[i].framecount = 1;
3023 loadmodel->animscenes[i].loop = true;
3024 loadmodel->animscenes[i].framerate = anims[index].fps;
3028 // calculate the scaling value for bone origins so they can be compressed to short
3030 for (index = 0;index < numanimkeys;index++)
3032 pskanimkeys_t *k = animkeys + index;
3033 biggestorigin = max(biggestorigin, fabs(k->origin[0]));
3034 biggestorigin = max(biggestorigin, fabs(k->origin[1]));
3035 biggestorigin = max(biggestorigin, fabs(k->origin[2]));
3037 loadmodel->num_posescale = biggestorigin / 32767.0f;
3038 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3040 // load the poses from the animkeys
3041 for (index = 0;index < numanimkeys;index++)
3043 pskanimkeys_t *k = animkeys + index;
3045 Vector4Copy(k->quat, quat);
3047 Vector4Negate(quat, quat);
3048 Vector4Normalize2(quat, quat);
3049 // compress poses to the short[6] format for longterm storage
3050 loadmodel->data_poses6s[index*6+0] = k->origin[0] * loadmodel->num_poseinvscale;
3051 loadmodel->data_poses6s[index*6+1] = k->origin[1] * loadmodel->num_poseinvscale;
3052 loadmodel->data_poses6s[index*6+2] = k->origin[2] * loadmodel->num_poseinvscale;
3053 loadmodel->data_poses6s[index*6+3] = quat[0] * 32767.0f;
3054 loadmodel->data_poses6s[index*6+4] = quat[1] * 32767.0f;
3055 loadmodel->data_poses6s[index*6+5] = quat[2] * 32767.0f;
3057 Mod_FreeSkinFiles(skinfiles);
3058 Mem_Free(animfilebuffer);
3059 Mod_MakeSortedSurfaces(loadmodel);
3061 // compute all the mesh information that was not loaded from the file
3062 // TODO: honor smoothing groups somehow?
3063 if (loadmodel->surfmesh.data_element3s)
3064 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3065 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3066 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
3067 Mod_BuildBaseBonePoses();
3068 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
3069 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);
3070 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3071 Mod_Alias_CalculateBoundingBox();
3073 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
3075 if (!loadmodel->surfmesh.isanimated)
3077 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3078 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3079 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3080 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3081 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3082 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
3086 void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
3088 unsigned char *data;
3090 unsigned char *pbase, *pend;
3091 iqmheader_t *header;
3092 skinfile_t *skinfiles;
3093 int i, j, k, meshvertices, meshtriangles;
3094 float *vposition = NULL, *vtexcoord = NULL, *vnormal = NULL, *vtangent = NULL;
3095 unsigned char *vblendindexes = NULL, *vblendweights = NULL;
3100 iqmbounds_t *bounds;
3101 iqmvertexarray_t *va;
3102 unsigned short *framedata;
3103 float biggestorigin;
3104 const int *inelements;
3106 float *outvertex, *outnormal, *outtexcoord, *outsvector, *outtvector;
3108 pbase = (unsigned char *)buffer;
3109 pend = (unsigned char *)bufferend;
3110 header = (iqmheader_t *)buffer;
3111 if (memcmp(header->id, "INTERQUAKEMODEL", 16))
3112 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model", loadmodel->name);
3113 if (LittleLong(header->version) != 1)
3114 Host_Error ("Mod_INTERQUAKEMODEL_Load: only version 1 models are currently supported (name = %s)", loadmodel->name);
3116 loadmodel->modeldatatypestring = "IQM";
3118 loadmodel->type = mod_alias;
3119 loadmodel->synctype = ST_RAND;
3122 header->version = LittleLong(header->version);
3123 header->filesize = LittleLong(header->filesize);
3124 header->flags = LittleLong(header->flags);
3125 header->num_text = LittleLong(header->num_text);
3126 header->ofs_text = LittleLong(header->ofs_text);
3127 header->num_meshes = LittleLong(header->num_meshes);
3128 header->ofs_meshes = LittleLong(header->ofs_meshes);
3129 header->num_vertexarrays = LittleLong(header->num_vertexarrays);
3130 header->num_vertexes = LittleLong(header->num_vertexes);
3131 header->ofs_vertexarrays = LittleLong(header->ofs_vertexarrays);
3132 header->num_triangles = LittleLong(header->num_triangles);
3133 header->ofs_triangles = LittleLong(header->ofs_triangles);
3134 header->ofs_neighbors = LittleLong(header->ofs_neighbors);
3135 header->num_joints = LittleLong(header->num_joints);
3136 header->ofs_joints = LittleLong(header->ofs_joints);
3137 header->num_poses = LittleLong(header->num_poses);
3138 header->ofs_poses = LittleLong(header->ofs_poses);
3139 header->num_anims = LittleLong(header->num_anims);
3140 header->ofs_anims = LittleLong(header->ofs_anims);
3141 header->num_frames = LittleLong(header->num_frames);
3142 header->num_framechannels = LittleLong(header->num_framechannels);
3143 header->ofs_frames = LittleLong(header->ofs_frames);
3144 header->ofs_bounds = LittleLong(header->ofs_bounds);
3145 header->num_comment = LittleLong(header->num_comment);
3146 header->ofs_comment = LittleLong(header->ofs_comment);
3147 header->num_extensions = LittleLong(header->num_extensions);
3148 header->ofs_extensions = LittleLong(header->ofs_extensions);
3150 if (header->num_triangles < 1 || header->num_vertexes < 3 || header->num_vertexarrays < 1 || header->num_meshes < 1)
3152 Con_Printf("%s has no geometry\n", loadmodel->name);
3155 if (header->num_frames < 1 || header->num_anims < 1)
3157 Con_Printf("%s has no animations\n", loadmodel->name);
3161 if (pbase + header->ofs_text + header->num_text > pend ||
3162 pbase + header->ofs_meshes + header->num_meshes*sizeof(iqmmesh_t) > pend ||
3163 pbase + header->ofs_vertexarrays + header->num_vertexarrays*sizeof(iqmvertexarray_t) > pend ||
3164 pbase + header->ofs_triangles + header->num_triangles*sizeof(int[3]) > pend ||
3165 (header->ofs_neighbors && pbase + header->ofs_neighbors + header->num_triangles*sizeof(int[3]) > pend) ||
3166 pbase + header->ofs_joints + header->num_joints*sizeof(iqmjoint_t) > pend ||
3167 pbase + header->ofs_poses + header->num_poses*sizeof(iqmpose_t) > pend ||
3168 pbase + header->ofs_anims + header->num_anims*sizeof(iqmanim_t) > pend ||
3169 pbase + header->ofs_frames + header->num_frames*header->num_framechannels*sizeof(unsigned short) > pend ||
3170 (header->ofs_bounds && pbase + header->ofs_bounds + header->num_frames*sizeof(iqmbounds_t) > pend) ||
3171 pbase + header->ofs_comment + header->num_comment > pend)
3173 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3177 va = (iqmvertexarray_t *)(pbase + header->ofs_vertexarrays);
3178 for (i = 0;i < (int)header->num_vertexarrays;i++)
3181 va[i].type = LittleLong(va[i].type);
3182 va[i].flags = LittleLong(va[i].flags);
3183 va[i].format = LittleLong(va[i].format);
3184 va[i].size = LittleLong(va[i].size);
3185 va[i].offset = LittleLong(va[i].offset);
3186 vsize = header->num_vertexes*va[i].size;
3187 switch (va[i].format)
3189 case IQM_FLOAT: vsize *= sizeof(float); break;
3190 case IQM_UBYTE: vsize *= sizeof(unsigned char); break;
3193 if (pbase + va[i].offset + vsize > pend)
3198 if (va[i].format == IQM_FLOAT && va[i].size == 3)
3199 vposition = (float *)(pbase + va[i].offset);
3202 if (va[i].format == IQM_FLOAT && va[i].size == 2)
3203 vtexcoord = (float *)(pbase + va[i].offset);
3206 if (va[i].format == IQM_FLOAT && va[i].size == 3)
3207 vnormal = (float *)(pbase + va[i].offset);
3210 if (va[i].format == IQM_FLOAT && va[i].size == 4)
3211 vtangent = (float *)(pbase + va[i].offset);
3213 case IQM_BLENDINDEXES:
3214 if (va[i].format == IQM_UBYTE && va[i].size == 4)
3215 vblendindexes = (unsigned char *)(pbase + va[i].offset);
3217 case IQM_BLENDWEIGHTS:
3218 if (va[i].format == IQM_UBYTE && va[i].size == 4)
3219 vblendweights = (unsigned char *)(pbase + va[i].offset);
3223 if (!vposition || !vtexcoord || !vblendindexes || !vblendweights)
3225 Con_Printf("%s is missing vertex array data\n", loadmodel->name);
3229 text = header->num_text && header->ofs_text ? (const char *)(pbase + header->ofs_text) : "";
3231 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
3232 loadmodel->DrawSky = NULL;
3233 loadmodel->DrawAddWaterPlanes = NULL;
3234 loadmodel->Draw = R_Q1BSP_Draw;
3235 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
3236 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
3237 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
3238 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
3239 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
3240 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
3241 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
3242 loadmodel->DrawLight = R_Q1BSP_DrawLight;
3243 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
3244 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
3245 loadmodel->PointSuperContents = NULL;
3247 // load external .skin files if present
3248 skinfiles = Mod_LoadSkinFiles();
3249 if (loadmodel->numskins < 1)
3250 loadmodel->numskins = 1;
3252 loadmodel->numframes = header->num_anims;
3253 loadmodel->num_bones = header->num_joints;
3254 loadmodel->num_poses = header->num_frames;
3255 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = header->num_meshes;
3256 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3257 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3259 meshvertices = header->num_vertexes;
3260 meshtriangles = header->num_triangles;
3262 // do most allocations as one merged chunk
3263 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));
3264 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
3265 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
3266 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
3267 loadmodel->surfmesh.num_vertices = meshvertices;
3268 loadmodel->surfmesh.num_triangles = meshtriangles;
3269 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3270 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3271 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
3272 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3273 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3274 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
3275 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
3276 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
3277 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
3278 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
3279 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
3280 loadmodel->surfmesh.num_blends = 0;
3281 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
3282 if (meshvertices <= 65536)
3283 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
3284 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
3285 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
3287 for (i = 0;i < loadmodel->numskins;i++)
3289 loadmodel->skinscenes[i].firstframe = i;
3290 loadmodel->skinscenes[i].framecount = 1;
3291 loadmodel->skinscenes[i].loop = true;
3292 loadmodel->skinscenes[i].framerate = 10;
3295 // load the bone info
3296 joint = (iqmjoint_t *) (pbase + header->ofs_joints);
3297 for (i = 0;i < loadmodel->num_bones;i++)
3299 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3300 joint[i].name = LittleLong(joint[i].name);
3301 joint[i].parent = LittleLong(joint[i].parent);
3302 for (j = 0;j < 3;j++)
3304 joint[i].origin[j] = LittleFloat(joint[i].origin[j]);
3305 joint[i].rotation[j] = LittleFloat(joint[i].rotation[j]);
3306 joint[i].scale[j] = LittleFloat(joint[i].scale[j]);
3308 strlcpy(loadmodel->data_bones[i].name, &text[joint[i].name], sizeof(loadmodel->data_bones[i].name));
3309 loadmodel->data_bones[i].parent = joint[i].parent;
3310 if (loadmodel->data_bones[i].parent >= i)
3311 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3312 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]);
3313 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3314 if (loadmodel->data_bones[i].parent >= 0)
3316 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3317 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3318 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3320 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3323 // set up the animscenes based on the anims
3324 anim = (iqmanim_t *) (pbase + header->ofs_anims);
3325 for (i = 0;i < (int)header->num_anims;i++)
3327 anim[i].name = LittleLong(anim[i].name);
3328 anim[i].first_frame = LittleLong(anim[i].first_frame);
3329 anim[i].num_frames = LittleLong(anim[i].num_frames);
3330 anim[i].framerate = LittleFloat(anim[i].framerate);
3331 anim[i].flags = LittleLong(anim[i].flags);
3332 strlcpy(loadmodel->animscenes[i].name, &text[anim[i].name], sizeof(loadmodel->animscenes[i].name));
3333 loadmodel->animscenes[i].firstframe = anim[i].first_frame;
3334 loadmodel->animscenes[i].framecount = anim[i].num_frames;
3335 loadmodel->animscenes[i].loop = ((anim[i].flags & IQM_LOOP) != 0);
3336 loadmodel->animscenes[i].framerate = anim[i].framerate;
3339 pose = (iqmpose_t *) (pbase + header->ofs_poses);
3341 for (i = 0;i < (int)header->num_poses;i++)
3344 pose[i].parent = LittleLong(pose[i].parent);
3345 pose[i].channelmask = LittleLong(pose[i].channelmask);
3346 pose[i].channeloffset[0] = LittleFloat(pose[i].channeloffset[0]);
3347 pose[i].channeloffset[1] = LittleFloat(pose[i].channeloffset[1]);
3348 pose[i].channeloffset[2] = LittleFloat(pose[i].channeloffset[2]);
3349 pose[i].channeloffset[3] = LittleFloat(pose[i].channeloffset[3]);
3350 pose[i].channeloffset[4] = LittleFloat(pose[i].channeloffset[4]);
3351 pose[i].channeloffset[5] = LittleFloat(pose[i].channeloffset[5]);
3352 pose[i].channeloffset[6] = LittleFloat(pose[i].channeloffset[6]);
3353 pose[i].channeloffset[7] = LittleFloat(pose[i].channeloffset[7]);
3354 pose[i].channeloffset[8] = LittleFloat(pose[i].channeloffset[8]);
3355 pose[i].channelscale[0] = LittleFloat(pose[i].channelscale[0]);
3356 pose[i].channelscale[1] = LittleFloat(pose[i].channelscale[1]);
3357 pose[i].channelscale[2] = LittleFloat(pose[i].channelscale[2]);
3358 pose[i].channelscale[3] = LittleFloat(pose[i].channelscale[3]);
3359 pose[i].channelscale[4] = LittleFloat(pose[i].channelscale[4]);
3360 pose[i].channelscale[5] = LittleFloat(pose[i].channelscale[5]);
3361 pose[i].channelscale[6] = LittleFloat(pose[i].channelscale[6]);
3362 pose[i].channelscale[7] = LittleFloat(pose[i].channelscale[7]);
3363 pose[i].channelscale[8] = LittleFloat(pose[i].channelscale[8]);
3364 f = fabs(pose[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3365 f = fabs(pose[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3366 f = fabs(pose[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3367 f = fabs(pose[i].channeloffset[0] + 0xFFFF*pose[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3368 f = fabs(pose[i].channeloffset[1] + 0xFFFF*pose[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3369 f = fabs(pose[i].channeloffset[2] + 0xFFFF*pose[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3371 loadmodel->num_posescale = biggestorigin / 32767.0f;
3372 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3374 // load the pose data
3375 framedata = (unsigned short *) (pbase + header->ofs_frames);
3376 for (i = 0, k = 0;i < (int)header->num_frames;i++)
3378 for (j = 0;j < (int)header->num_poses;j++, k++)
3380 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));
3381 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));
3382 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));
3383 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));
3384 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));
3385 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));
3386 // skip scale data for now
3387 if(pose[j].channelmask&64) framedata++;
3388 if(pose[j].channelmask&128) framedata++;
3389 if(pose[j].channelmask&256) framedata++;
3393 // load bounding box data
3394 if (header->ofs_bounds)
3396 float xyradius = 0, radius = 0;
3397 bounds = (iqmbounds_t *) (pbase + header->ofs_bounds);
3398 VectorClear(loadmodel->normalmins);
3399 VectorClear(loadmodel->normalmaxs);
3400 for (i = 0; i < (int)header->num_frames;i++)
3402 bounds[i].mins[0] = LittleFloat(bounds[i].mins[0]);
3403 bounds[i].mins[1] = LittleFloat(bounds[i].mins[1]);
3404 bounds[i].mins[2] = LittleFloat(bounds[i].mins[2]);
3405 bounds[i].maxs[0] = LittleFloat(bounds[i].maxs[0]);
3406 bounds[i].maxs[1] = LittleFloat(bounds[i].maxs[1]);
3407 bounds[i].maxs[2] = LittleFloat(bounds[i].maxs[2]);
3408 bounds[i].xyradius = LittleFloat(bounds[i].xyradius);
3409 bounds[i].radius = LittleFloat(bounds[i].radius);
3412 VectorCopy(bounds[i].mins, loadmodel->normalmins);
3413 VectorCopy(bounds[i].maxs, loadmodel->normalmaxs);
3417 if (loadmodel->normalmins[0] > bounds[i].mins[0]) loadmodel->normalmins[0] = bounds[i].mins[0];
3418 if (loadmodel->normalmins[1] > bounds[i].mins[1]) loadmodel->normalmins[1] = bounds[i].mins[1];
3419 if (loadmodel->normalmins[2] > bounds[i].mins[2]) loadmodel->normalmins[2] = bounds[i].mins[2];
3420 if (loadmodel->normalmaxs[0] < bounds[i].maxs[0]) loadmodel->normalmaxs[0] = bounds[i].maxs[0];
3421 if (loadmodel->normalmaxs[1] < bounds[i].maxs[1]) loadmodel->normalmaxs[1] = bounds[i].maxs[1];
3422 if (loadmodel->normalmaxs[2] < bounds[i].maxs[2]) loadmodel->normalmaxs[2] = bounds[i].maxs[2];
3424 if (bounds[i].xyradius > xyradius)
3425 xyradius = bounds[i].xyradius;
3426 if (bounds[i].radius > radius)
3427 radius = bounds[i].radius;
3429 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -xyradius;
3430 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = xyradius;
3431 loadmodel->yawmins[2] = loadmodel->normalmins[2];
3432 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
3433 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
3434 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
3435 loadmodel->radius = radius;
3436 loadmodel->radius2 = radius * radius;
3439 // load triangle data
3440 inelements = (const int *) (pbase + header->ofs_triangles);
3441 outelements = loadmodel->surfmesh.data_element3i;
3442 for (i = 0;i < (int)header->num_triangles;i++)
3444 outelements[0] = LittleLong(inelements[0]);
3445 outelements[1] = LittleLong(inelements[1]);
3446 outelements[2] = LittleLong(inelements[2]);
3450 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, header->num_vertexes, __FILE__, __LINE__);
3452 if (header->ofs_neighbors)
3454 inelements = (const int *) (pbase + header->ofs_neighbors);
3455 outelements = loadmodel->surfmesh.data_neighbor3i;
3456 for (i = 0;i < (int)header->num_triangles;i++)
3458 outelements[0] = LittleLong(inelements[0]);
3459 outelements[1] = LittleLong(inelements[1]);
3460 outelements[2] = LittleLong(inelements[2]);
3467 outvertex = loadmodel->surfmesh.data_vertex3f;
3468 for (i = 0;i < (int)header->num_vertexes;i++)
3470 outvertex[0] = LittleFloat(vposition[0]);
3471 outvertex[1] = LittleFloat(vposition[1]);
3472 outvertex[2] = LittleFloat(vposition[2]);
3477 outtexcoord = loadmodel->surfmesh.data_texcoordtexture2f;
3478 for (i = 0;i < (int)header->num_vertexes;i++)
3480 outtexcoord[0] = LittleFloat(vtexcoord[0]);
3481 outtexcoord[1] = LittleFloat(vtexcoord[1]);
3488 outnormal = loadmodel->surfmesh.data_normal3f;
3489 for (i = 0;i < (int)header->num_vertexes;i++)
3491 outnormal[0] = LittleFloat(vnormal[0]);
3492 outnormal[1] = LittleFloat(vnormal[1]);
3493 outnormal[2] = LittleFloat(vnormal[2]);
3499 if(vnormal && vtangent)
3501 outnormal = loadmodel->surfmesh.data_normal3f;
3502 outsvector = loadmodel->surfmesh.data_svector3f;
3503 outtvector = loadmodel->surfmesh.data_tvector3f;
3504 for (i = 0;i < (int)header->num_vertexes;i++)
3506 outsvector[0] = LittleFloat(vtangent[0]);
3507 outsvector[1] = LittleFloat(vtangent[1]);
3508 outsvector[2] = LittleFloat(vtangent[2]);
3509 if(LittleFloat(vtangent[3]) < 0)
3510 CrossProduct(outsvector, outnormal, outtvector);
3512 CrossProduct(outnormal, outsvector, outtvector);
3520 for (i = 0; i < (int)header->num_vertexes;i++)
3522 blendweights_t weights;
3523 memcpy(weights.index, vblendindexes + i*4, 4);
3524 memcpy(weights.influence, vblendweights + i*4, 4);
3525 loadmodel->surfmesh.blends[i] = Mod_Skeletal_AddBlend(loadmodel, &weights);
3529 mesh = (iqmmesh_t *) (pbase + header->ofs_meshes);
3530 for (i = 0;i < (int)header->num_meshes;i++)
3532 msurface_t *surface;
3534 mesh[i].name = LittleLong(mesh[i].name);
3535 mesh[i].material = LittleLong(mesh[i].material);
3536 mesh[i].first_vertex = LittleLong(mesh[i].first_vertex);
3537 mesh[i].num_vertexes = LittleLong(mesh[i].num_vertexes);
3538 mesh[i].first_triangle = LittleLong(mesh[i].first_triangle);
3539 mesh[i].num_triangles = LittleLong(mesh[i].num_triangles);
3541 loadmodel->sortedmodelsurfaces[i] = i;
3542 surface = loadmodel->data_surfaces + i;
3543 surface->texture = loadmodel->data_textures + i;
3544 surface->num_firsttriangle = mesh[i].first_triangle;
3545 surface->num_triangles = mesh[i].num_triangles;
3546 surface->num_firstvertex = mesh[i].first_vertex;
3547 surface->num_vertices = mesh[i].num_vertexes;
3549 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, &text[mesh[i].name], &text[mesh[i].material]);
3552 Mod_FreeSkinFiles(skinfiles);
3553 Mod_MakeSortedSurfaces(loadmodel);
3555 // compute all the mesh information that was not loaded from the file
3556 if (loadmodel->surfmesh.data_element3s)
3557 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3558 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3560 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
3561 if (!vnormal || !vtangent)
3562 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);
3563 if (!header->ofs_neighbors)
3564 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3565 if (!header->ofs_bounds)
3566 Mod_Alias_CalculateBoundingBox();
3568 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
3570 if (!loadmodel->surfmesh.isanimated)
3572 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3573 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3574 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3575 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3576 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3577 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;