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])Mem_Alloc(r_main_mempool, 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_TraceBoxBox(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t startboxmins, const vec3_t startboxmaxs, const vec3_t end, const vec3_t endboxmins, const vec3_t endboxmaxs, 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(startboxmins, startboxmaxs) && VectorCompare(startboxmins, endboxmins) && VectorCompare(startboxmaxs, endboxmaxs))
798 VectorAdd(start, startboxmins, shiftstart);
799 VectorAdd(end, startboxmins, shiftend);
800 Mod_MDLMD2MD3_TraceLine(model, frameblend, skeleton, trace, shiftstart, shiftend, hitsupercontentsmask);
801 VectorSubtract(trace->endpos, startboxmins, 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 VectorAdd(start, startboxmins, boxstartmins);
818 VectorAdd(start, startboxmaxs, boxstartmaxs);
819 VectorAdd(end, endboxmins, boxendmins);
820 VectorAdd(end, endboxmaxs, boxendmaxs);
821 segmentmins[0] = min(startboxmins[0], endboxmins[0]) - 1;
822 segmentmins[1] = min(startboxmins[1], endboxmins[1]) - 1;
823 segmentmins[2] = min(startboxmins[2], endboxmins[2]) - 1;
824 segmentmaxs[0] = max(startboxmaxs[0], endboxmaxs[0]) + 1;
825 segmentmaxs[1] = max(startboxmaxs[1], endboxmaxs[1]) + 1;
826 segmentmaxs[2] = max(startboxmaxs[2], endboxmaxs[2]) + 1;
827 Collision_BrushForBox(&thisbrush_start, boxstartmins, boxstartmaxs, 0, 0, NULL);
828 Collision_BrushForBox(&thisbrush_end, boxendmins, boxendmaxs, 0, 0, NULL);
829 if (maxvertices < model->surfmesh.num_vertices)
833 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
834 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
836 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
837 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
838 Collision_TraceBrushTriangleMeshFloat(trace, &thisbrush_start.brush, &thisbrush_end.brush, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs);
841 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
844 for (i = 0;i < inverts;i++)
846 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
848 j = vertremap[i]; // not onseam
851 j = vertremap[i+inverts]; // onseam
857 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
859 int i, f, pose, groupframes;
861 daliasframetype_t *pframetype;
862 daliasframe_t *pinframe;
863 daliasgroup_t *group;
864 daliasinterval_t *intervals;
867 scene = loadmodel->animscenes;
868 for (f = 0;f < loadmodel->numframes;f++)
870 pframetype = (daliasframetype_t *)datapointer;
871 datapointer += sizeof(daliasframetype_t);
872 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
874 // a single frame is still treated as a group
881 group = (daliasgroup_t *)datapointer;
882 datapointer += sizeof(daliasgroup_t);
883 groupframes = LittleLong (group->numframes);
885 // intervals (time per frame)
886 intervals = (daliasinterval_t *)datapointer;
887 datapointer += sizeof(daliasinterval_t) * groupframes;
889 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
890 if (interval < 0.01f)
892 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
897 // get scene name from first frame
898 pinframe = (daliasframe_t *)datapointer;
900 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
901 scene->firstframe = pose;
902 scene->framecount = groupframes;
903 scene->framerate = 1.0f / interval;
908 for (i = 0;i < groupframes;i++)
910 pinframe = (daliasframe_t *)datapointer;
911 datapointer += sizeof(daliasframe_t);
912 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
913 datapointer += sizeof(trivertx_t) * inverts;
919 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
921 if (cls.state == ca_dedicated)
925 skinframe = R_SkinFrame_LoadMissing();
926 memset(texture, 0, sizeof(*texture));
927 texture->currentframe = texture;
928 //texture->animated = false;
929 texture->numskinframes = 1;
930 texture->skinframerate = 1;
931 texture->skinframes[0] = skinframe;
932 texture->currentskinframe = skinframe;
933 //texture->backgroundnumskinframes = 0;
934 //texture->customblendfunc[0] = 0;
935 //texture->customblendfunc[1] = 0;
936 //texture->surfaceflags = 0;
937 //texture->supercontents = 0;
938 //texture->surfaceparms = 0;
939 //texture->textureflags = 0;
941 texture->basematerialflags = MATERIALFLAG_WALL;
942 if (texture->currentskinframe->hasalpha)
943 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
944 texture->currentmaterialflags = texture->basematerialflags;
945 texture->offsetmapping = OFFSETMAPPING_OFF;
946 texture->offsetscale = 1;
947 texture->specularscalemod = 1;
948 texture->specularpowermod = 1;
949 texture->surfaceflags = 0;
950 texture->supercontents = SUPERCONTENTS_SOLID;
951 if (!(texture->basematerialflags & MATERIALFLAG_BLENDED))
952 texture->supercontents |= SUPERCONTENTS_OPAQUE;
955 void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
958 skinfileitem_t *skinfileitem;
961 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
962 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
964 memset(skin, 0, sizeof(*skin));
966 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
968 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
969 if (!strcmp(skinfileitem->name, meshname))
971 Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
977 // don't render unmentioned meshes
978 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
979 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
984 Mod_LoadTextureFromQ3Shader(skin, shadername, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
987 #define BOUNDI(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid ##VALUE (%d exceeds %d - %d)", loadmodel->name, VALUE, MIN, MAX);
988 #define BOUNDF(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid ##VALUE (%f exceeds %f - %f)", loadmodel->name, VALUE, MIN, MAX);
989 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
991 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
992 float scales, scalet, interval;
996 stvert_t *pinstverts;
997 dtriangle_t *pintriangles;
998 daliasskintype_t *pinskintype;
999 daliasskingroup_t *pinskingroup;
1000 daliasskininterval_t *pinskinintervals;
1001 daliasframetype_t *pinframetype;
1002 daliasgroup_t *pinframegroup;
1003 unsigned char *datapointer, *startframes, *startskins;
1004 char name[MAX_QPATH];
1005 skinframe_t *tempskinframe;
1006 animscene_t *tempskinscenes;
1007 texture_t *tempaliasskins;
1009 int *vertonseam, *vertremap;
1010 skinfile_t *skinfiles;
1012 datapointer = (unsigned char *)buffer;
1013 pinmodel = (mdl_t *)datapointer;
1014 datapointer += sizeof(mdl_t);
1016 version = LittleLong (pinmodel->version);
1017 if (version != ALIAS_VERSION)
1018 Host_Error ("%s has wrong version number (%i should be %i)",
1019 loadmodel->name, version, ALIAS_VERSION);
1021 loadmodel->modeldatatypestring = "MDL";
1023 loadmodel->type = mod_alias;
1024 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1025 loadmodel->DrawSky = NULL;
1026 loadmodel->DrawAddWaterPlanes = NULL;
1027 loadmodel->Draw = R_Q1BSP_Draw;
1028 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1029 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1030 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1031 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1032 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1033 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1034 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1035 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1036 loadmodel->TraceBox = Mod_TraceBox_using_TraceBoxBox;
1037 loadmodel->TraceBoxBox = Mod_MDLMD2MD3_TraceBoxBox;
1038 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1039 loadmodel->PointSuperContents = NULL;
1041 loadmodel->num_surfaces = 1;
1042 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1043 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
1044 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1045 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1046 loadmodel->sortedmodelsurfaces[0] = 0;
1048 loadmodel->numskins = LittleLong(pinmodel->numskins);
1049 BOUNDI(loadmodel->numskins,0,65536);
1050 skinwidth = LittleLong (pinmodel->skinwidth);
1051 BOUNDI(skinwidth,0,65536);
1052 skinheight = LittleLong (pinmodel->skinheight);
1053 BOUNDI(skinheight,0,65536);
1054 numverts = LittleLong(pinmodel->numverts);
1055 BOUNDI(numverts,0,65536);
1056 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
1057 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
1058 loadmodel->numframes = LittleLong(pinmodel->numframes);
1059 BOUNDI(loadmodel->numframes,0,65536);
1060 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
1061 BOUNDI((int)loadmodel->synctype,0,2);
1062 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1063 i = LittleLong (pinmodel->flags);
1064 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1066 for (i = 0;i < 3;i++)
1068 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
1069 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
1072 startskins = datapointer;
1074 for (i = 0;i < loadmodel->numskins;i++)
1076 pinskintype = (daliasskintype_t *)datapointer;
1077 datapointer += sizeof(daliasskintype_t);
1078 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
1082 pinskingroup = (daliasskingroup_t *)datapointer;
1083 datapointer += sizeof(daliasskingroup_t);
1084 groupskins = LittleLong(pinskingroup->numskins);
1085 datapointer += sizeof(daliasskininterval_t) * groupskins;
1088 for (j = 0;j < groupskins;j++)
1090 datapointer += skinwidth * skinheight;
1095 pinstverts = (stvert_t *)datapointer;
1096 datapointer += sizeof(stvert_t) * numverts;
1098 pintriangles = (dtriangle_t *)datapointer;
1099 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
1101 startframes = datapointer;
1102 loadmodel->surfmesh.num_morphframes = 0;
1103 for (i = 0;i < loadmodel->numframes;i++)
1105 pinframetype = (daliasframetype_t *)datapointer;
1106 datapointer += sizeof(daliasframetype_t);
1107 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
1111 pinframegroup = (daliasgroup_t *)datapointer;
1112 datapointer += sizeof(daliasgroup_t);
1113 groupframes = LittleLong(pinframegroup->numframes);
1114 datapointer += sizeof(daliasinterval_t) * groupframes;
1117 for (j = 0;j < groupframes;j++)
1119 datapointer += sizeof(daliasframe_t);
1120 datapointer += sizeof(trivertx_t) * numverts;
1121 loadmodel->surfmesh.num_morphframes++;
1124 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1126 // store texture coordinates into temporary array, they will be stored
1127 // after usage is determined (triangle data)
1128 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
1129 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
1130 vertonseam = vertremap + numverts * 2;
1132 scales = 1.0 / skinwidth;
1133 scalet = 1.0 / skinheight;
1134 for (i = 0;i < numverts;i++)
1136 vertonseam[i] = LittleLong(pinstverts[i].onseam);
1137 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
1138 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
1139 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
1140 vertst[(i+numverts)*2+1] = vertst[i*2+1];
1143 // load triangle data
1144 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1146 // read the triangle elements
1147 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1148 for (j = 0;j < 3;j++)
1149 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1150 // validate (note numverts is used because this is the original data)
1151 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1152 // now butcher the elements according to vertonseam and tri->facesfront
1153 // and then compact the vertex set to remove duplicates
1154 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1155 if (!LittleLong(pintriangles[i].facesfront)) // backface
1156 for (j = 0;j < 3;j++)
1157 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1158 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1160 // (this uses vertremap to count usage to save some memory)
1161 for (i = 0;i < numverts*2;i++)
1163 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1164 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1165 // build remapping table and compact array
1166 loadmodel->surfmesh.num_vertices = 0;
1167 for (i = 0;i < numverts*2;i++)
1171 vertremap[i] = loadmodel->surfmesh.num_vertices;
1172 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1173 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1174 loadmodel->surfmesh.num_vertices++;
1177 vertremap[i] = -1; // not used at all
1179 // remap the elements to the new vertex set
1180 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1181 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1182 // store the texture coordinates
1183 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1184 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1186 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1187 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1190 // generate ushort elements array if possible
1191 if (loadmodel->surfmesh.num_vertices <= 65536)
1192 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1193 if (loadmodel->surfmesh.data_element3s)
1194 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1195 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1198 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1199 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1200 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1201 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1202 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1203 Mod_Alias_CalculateBoundingBox();
1204 Mod_Alias_MorphMesh_CompileFrames();
1207 Mem_Free(vertremap);
1210 skinfiles = Mod_LoadSkinFiles();
1213 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1214 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1215 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1216 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1217 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1218 Mod_FreeSkinFiles(skinfiles);
1219 for (i = 0;i < loadmodel->numskins;i++)
1221 loadmodel->skinscenes[i].firstframe = i;
1222 loadmodel->skinscenes[i].framecount = 1;
1223 loadmodel->skinscenes[i].loop = true;
1224 loadmodel->skinscenes[i].framerate = 10;
1229 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1230 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1231 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1232 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1234 datapointer = startskins;
1235 for (i = 0;i < loadmodel->numskins;i++)
1237 pinskintype = (daliasskintype_t *)datapointer;
1238 datapointer += sizeof(daliasskintype_t);
1240 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1247 pinskingroup = (daliasskingroup_t *)datapointer;
1248 datapointer += sizeof(daliasskingroup_t);
1250 groupskins = LittleLong (pinskingroup->numskins);
1252 pinskinintervals = (daliasskininterval_t *)datapointer;
1253 datapointer += sizeof(daliasskininterval_t) * groupskins;
1255 interval = LittleFloat(pinskinintervals[0].interval);
1256 if (interval < 0.01f)
1258 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1263 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1264 loadmodel->skinscenes[i].firstframe = totalskins;
1265 loadmodel->skinscenes[i].framecount = groupskins;
1266 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1267 loadmodel->skinscenes[i].loop = true;
1269 for (j = 0;j < groupskins;j++)
1272 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1274 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1275 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))
1276 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));
1277 datapointer += skinwidth * skinheight;
1281 // check for skins that don't exist in the model, but do exist as external images
1282 // (this was added because yummyluv kept pestering me about support for it)
1283 // TODO: support shaders here?
1284 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)))
1286 // expand the arrays to make room
1287 tempskinscenes = loadmodel->skinscenes;
1288 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1289 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1290 Mem_Free(tempskinscenes);
1292 tempaliasskins = loadmodel->data_textures;
1293 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1294 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1295 Mem_Free(tempaliasskins);
1297 // store the info about the new skin
1298 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1299 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1300 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1301 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1302 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1303 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1305 //increase skin counts
1306 loadmodel->numskins++;
1309 // fix up the pointers since they are pointing at the old textures array
1310 // FIXME: this is a hack!
1311 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1312 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1316 surface = loadmodel->data_surfaces;
1317 surface->texture = loadmodel->data_textures;
1318 surface->num_firsttriangle = 0;
1319 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1320 surface->num_firstvertex = 0;
1321 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1323 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1325 if (!loadmodel->surfmesh.isanimated)
1327 Mod_MakeCollisionBIH(loadmodel, true);
1328 loadmodel->TraceBoxBox = Mod_CollisionBIH_TraceBoxBox;
1329 loadmodel->TraceBox = Mod_TraceBox_using_TraceBoxBox;
1330 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1331 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1332 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1336 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1338 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1339 float iskinwidth, iskinheight;
1340 unsigned char *data;
1341 msurface_t *surface;
1343 unsigned char *base, *datapointer;
1344 md2frame_t *pinframe;
1346 md2triangle_t *intri;
1347 unsigned short *inst;
1348 struct md2verthash_s
1350 struct md2verthash_s *next;
1354 *hash, **md2verthash, *md2verthashdata;
1355 skinfile_t *skinfiles;
1357 pinmodel = (md2_t *)buffer;
1358 base = (unsigned char *)buffer;
1360 version = LittleLong (pinmodel->version);
1361 if (version != MD2ALIAS_VERSION)
1362 Host_Error ("%s has wrong version number (%i should be %i)",
1363 loadmodel->name, version, MD2ALIAS_VERSION);
1365 loadmodel->modeldatatypestring = "MD2";
1367 loadmodel->type = mod_alias;
1368 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1369 loadmodel->DrawSky = NULL;
1370 loadmodel->DrawAddWaterPlanes = NULL;
1371 loadmodel->Draw = R_Q1BSP_Draw;
1372 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1373 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1374 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1375 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1376 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1377 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1378 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1379 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1380 loadmodel->TraceBox = Mod_TraceBox_using_TraceBoxBox;
1381 loadmodel->TraceBoxBox = Mod_MDLMD2MD3_TraceBoxBox;
1382 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1383 loadmodel->PointSuperContents = NULL;
1385 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1386 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1387 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1388 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1389 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1390 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1391 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1392 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1394 end = LittleLong(pinmodel->ofs_end);
1395 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1396 Host_Error ("%s is not a valid model", loadmodel->name);
1397 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1398 Host_Error ("%s is not a valid model", loadmodel->name);
1399 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1400 Host_Error ("%s is not a valid model", loadmodel->name);
1401 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1402 Host_Error ("%s is not a valid model", loadmodel->name);
1403 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1404 Host_Error ("%s is not a valid model", loadmodel->name);
1406 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1407 numxyz = LittleLong(pinmodel->num_xyz);
1408 numst = LittleLong(pinmodel->num_st);
1409 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1410 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1411 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1412 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1413 skinwidth = LittleLong(pinmodel->skinwidth);
1414 skinheight = LittleLong(pinmodel->skinheight);
1415 iskinwidth = 1.0f / skinwidth;
1416 iskinheight = 1.0f / skinheight;
1418 loadmodel->num_surfaces = 1;
1419 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1420 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]));
1421 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1422 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1423 loadmodel->sortedmodelsurfaces[0] = 0;
1424 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1425 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1426 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1427 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1429 loadmodel->synctype = ST_RAND;
1432 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1433 skinfiles = Mod_LoadSkinFiles();
1436 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1437 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1438 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1439 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1440 Mod_FreeSkinFiles(skinfiles);
1442 else if (loadmodel->numskins)
1444 // skins found (most likely not a player model)
1445 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1446 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1447 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1448 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1449 Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
1453 // no skins (most likely a player model)
1454 loadmodel->numskins = 1;
1455 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1456 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1457 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1458 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1461 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1462 for (i = 0;i < loadmodel->numskins;i++)
1464 loadmodel->skinscenes[i].firstframe = i;
1465 loadmodel->skinscenes[i].framecount = 1;
1466 loadmodel->skinscenes[i].loop = true;
1467 loadmodel->skinscenes[i].framerate = 10;
1470 // load the triangles and stvert data
1471 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1472 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1473 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1474 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1475 // swap the triangle list
1476 loadmodel->surfmesh.num_vertices = 0;
1477 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1479 for (j = 0;j < 3;j++)
1481 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1482 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1485 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1490 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1493 hashindex = (xyz * 256 + st) & 65535;
1494 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1495 if (hash->xyz == xyz && hash->st == st)
1499 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1502 hash->next = md2verthash[hashindex];
1503 md2verthash[hashindex] = hash;
1505 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1509 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1510 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));
1511 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1512 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1513 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1516 hash = md2verthashdata + i;
1517 vertremap[i] = hash->xyz;
1518 sts = LittleShort(inst[hash->st*2+0]);
1519 stt = LittleShort(inst[hash->st*2+1]);
1520 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1522 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1526 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1527 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1530 Mem_Free(md2verthash);
1531 Mem_Free(md2verthashdata);
1533 // generate ushort elements array if possible
1534 if (loadmodel->surfmesh.num_vertices <= 65536)
1535 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1536 if (loadmodel->surfmesh.data_element3s)
1537 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1538 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1541 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1542 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1547 pinframe = (md2frame_t *)datapointer;
1548 datapointer += sizeof(md2frame_t);
1549 // store the frame scale/translate into the appropriate array
1550 for (j = 0;j < 3;j++)
1552 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1553 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1555 // convert the vertices
1556 v = (trivertx_t *)datapointer;
1557 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1558 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1559 out[k] = v[vertremap[k]];
1560 datapointer += numxyz * sizeof(trivertx_t);
1562 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1563 loadmodel->animscenes[i].firstframe = i;
1564 loadmodel->animscenes[i].framecount = 1;
1565 loadmodel->animscenes[i].framerate = 10;
1566 loadmodel->animscenes[i].loop = true;
1569 Mem_Free(vertremap);
1571 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1572 Mod_Alias_CalculateBoundingBox();
1573 Mod_Alias_MorphMesh_CompileFrames();
1575 surface = loadmodel->data_surfaces;
1576 surface->texture = loadmodel->data_textures;
1577 surface->num_firsttriangle = 0;
1578 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1579 surface->num_firstvertex = 0;
1580 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1582 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1584 if (!loadmodel->surfmesh.isanimated)
1586 Mod_MakeCollisionBIH(loadmodel, true);
1587 loadmodel->TraceBoxBox = Mod_CollisionBIH_TraceBoxBox;
1588 loadmodel->TraceBox = Mod_TraceBox_using_TraceBoxBox;
1589 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1590 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1591 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1595 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1597 int i, j, k, version, meshvertices, meshtriangles;
1598 unsigned char *data;
1599 msurface_t *surface;
1600 md3modelheader_t *pinmodel;
1601 md3frameinfo_t *pinframe;
1604 skinfile_t *skinfiles;
1606 pinmodel = (md3modelheader_t *)buffer;
1608 if (memcmp(pinmodel->identifier, "IDP3", 4))
1609 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1610 version = LittleLong (pinmodel->version);
1611 if (version != MD3VERSION)
1612 Host_Error ("%s has wrong version number (%i should be %i)",
1613 loadmodel->name, version, MD3VERSION);
1615 skinfiles = Mod_LoadSkinFiles();
1616 if (loadmodel->numskins < 1)
1617 loadmodel->numskins = 1;
1619 loadmodel->modeldatatypestring = "MD3";
1621 loadmodel->type = mod_alias;
1622 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1623 loadmodel->DrawSky = NULL;
1624 loadmodel->DrawAddWaterPlanes = NULL;
1625 loadmodel->Draw = R_Q1BSP_Draw;
1626 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1627 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1628 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1629 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1630 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1631 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1632 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1633 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1634 loadmodel->TraceBox = Mod_TraceBox_using_TraceBoxBox;
1635 loadmodel->TraceBoxBox = Mod_MDLMD2MD3_TraceBoxBox;
1636 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1637 loadmodel->PointSuperContents = NULL;
1638 loadmodel->synctype = ST_RAND;
1639 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1640 i = LittleLong (pinmodel->flags);
1641 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1643 // set up some global info about the model
1644 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1645 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1647 // make skinscenes for the skins (no groups)
1648 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1649 for (i = 0;i < loadmodel->numskins;i++)
1651 loadmodel->skinscenes[i].firstframe = i;
1652 loadmodel->skinscenes[i].framecount = 1;
1653 loadmodel->skinscenes[i].loop = true;
1654 loadmodel->skinscenes[i].framerate = 10;
1658 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1659 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1661 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1662 loadmodel->animscenes[i].firstframe = i;
1663 loadmodel->animscenes[i].framecount = 1;
1664 loadmodel->animscenes[i].framerate = 10;
1665 loadmodel->animscenes[i].loop = true;
1669 loadmodel->num_tagframes = loadmodel->numframes;
1670 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1671 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1672 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1674 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1675 for (j = 0;j < 9;j++)
1676 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1677 for (j = 0;j < 3;j++)
1678 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1679 //Con_Printf("model \"%s\" frame #%i tag #%i \"%s\"\n", loadmodel->name, i / loadmodel->num_tags, i % loadmodel->num_tags, loadmodel->data_tags[i].name);
1685 for (i = 0, pinmesh = (md3mesh_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_meshes));i < loadmodel->num_surfaces;i++, pinmesh = (md3mesh_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_end)))
1687 if (memcmp(pinmesh->identifier, "IDP3", 4))
1688 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1689 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1690 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1691 meshvertices += LittleLong(pinmesh->num_vertices);
1692 meshtriangles += LittleLong(pinmesh->num_triangles);
1695 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1696 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1697 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1698 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshvertices * sizeof(float[2]) + meshvertices * loadmodel->numframes * sizeof(md3vertex_t));
1699 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1700 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1701 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1702 loadmodel->surfmesh.num_vertices = meshvertices;
1703 loadmodel->surfmesh.num_triangles = meshtriangles;
1704 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1705 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1706 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1707 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1708 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1709 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1710 if (meshvertices <= 65536)
1711 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1715 for (i = 0, pinmesh = (md3mesh_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_meshes));i < loadmodel->num_surfaces;i++, pinmesh = (md3mesh_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_end)))
1717 if (memcmp(pinmesh->identifier, "IDP3", 4))
1718 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1719 loadmodel->sortedmodelsurfaces[i] = i;
1720 surface = loadmodel->data_surfaces + i;
1721 surface->texture = loadmodel->data_textures + i;
1722 surface->num_firsttriangle = meshtriangles;
1723 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1724 surface->num_firstvertex = meshvertices;
1725 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1726 meshvertices += surface->num_vertices;
1727 meshtriangles += surface->num_triangles;
1729 for (j = 0;j < surface->num_triangles * 3;j++)
1730 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1731 for (j = 0;j < surface->num_vertices;j++)
1733 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1734 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1736 for (j = 0;j < loadmodel->numframes;j++)
1738 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1739 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1740 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1742 out->origin[0] = LittleShort(in->origin[0]);
1743 out->origin[1] = LittleShort(in->origin[1]);
1744 out->origin[2] = LittleShort(in->origin[2]);
1745 out->pitch = in->pitch;
1750 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1752 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1754 if (loadmodel->surfmesh.data_element3s)
1755 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1756 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1757 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1758 Mod_Alias_MorphMesh_CompileFrames();
1759 Mod_Alias_CalculateBoundingBox();
1760 Mod_FreeSkinFiles(skinfiles);
1761 Mod_MakeSortedSurfaces(loadmodel);
1763 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1764 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1766 if (!loadmodel->surfmesh.isanimated)
1768 Mod_MakeCollisionBIH(loadmodel, true);
1769 loadmodel->TraceBoxBox = Mod_CollisionBIH_TraceBoxBox;
1770 loadmodel->TraceBox = Mod_TraceBox_using_TraceBoxBox;
1771 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1772 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1773 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1777 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1779 zymtype1header_t *pinmodel, *pheader;
1780 unsigned char *pbase;
1781 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1782 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose, f, biggestorigin, tempvec[3], modelscale;
1783 zymvertex_t *verts, *vertdata;
1787 skinfile_t *skinfiles;
1788 unsigned char *data;
1789 msurface_t *surface;
1791 pinmodel = (zymtype1header_t *)buffer;
1792 pbase = (unsigned char *)buffer;
1793 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1794 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1795 if (BigLong(pinmodel->type) != 1)
1796 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1798 loadmodel->modeldatatypestring = "ZYM";
1800 loadmodel->type = mod_alias;
1801 loadmodel->synctype = ST_RAND;
1805 pheader->type = BigLong(pinmodel->type);
1806 pheader->filesize = BigLong(pinmodel->filesize);
1807 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1808 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1809 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1810 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1811 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1812 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1813 pheader->radius = BigFloat(pinmodel->radius);
1814 pheader->numverts = BigLong(pinmodel->numverts);
1815 pheader->numtris = BigLong(pinmodel->numtris);
1816 pheader->numshaders = BigLong(pinmodel->numshaders);
1817 pheader->numbones = BigLong(pinmodel->numbones);
1818 pheader->numscenes = BigLong(pinmodel->numscenes);
1819 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1820 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1821 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1822 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1823 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1824 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1825 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1826 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1827 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1828 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1829 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1830 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1831 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1832 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1833 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1834 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1835 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1836 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1838 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1840 Con_Printf("%s has no geometry\n", loadmodel->name);
1843 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1845 Con_Printf("%s has no animations\n", loadmodel->name);
1849 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1850 loadmodel->DrawSky = NULL;
1851 loadmodel->DrawAddWaterPlanes = NULL;
1852 loadmodel->Draw = R_Q1BSP_Draw;
1853 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1854 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1855 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1856 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1857 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1858 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1859 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1860 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1861 loadmodel->TraceBox = Mod_TraceBox_using_TraceBoxBox;
1862 loadmodel->TraceBoxBox = Mod_MDLMD2MD3_TraceBoxBox;
1863 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1864 loadmodel->PointSuperContents = NULL;
1866 loadmodel->numframes = pheader->numscenes;
1867 loadmodel->num_surfaces = pheader->numshaders;
1869 skinfiles = Mod_LoadSkinFiles();
1870 if (loadmodel->numskins < 1)
1871 loadmodel->numskins = 1;
1873 // make skinscenes for the skins (no groups)
1874 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1875 for (i = 0;i < loadmodel->numskins;i++)
1877 loadmodel->skinscenes[i].firstframe = i;
1878 loadmodel->skinscenes[i].framecount = 1;
1879 loadmodel->skinscenes[i].loop = true;
1880 loadmodel->skinscenes[i].framerate = 10;
1884 modelradius = pheader->radius;
1885 for (i = 0;i < 3;i++)
1887 loadmodel->normalmins[i] = pheader->mins[i];
1888 loadmodel->normalmaxs[i] = pheader->maxs[i];
1889 loadmodel->rotatedmins[i] = -modelradius;
1890 loadmodel->rotatedmaxs[i] = modelradius;
1892 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1893 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1894 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1895 if (loadmodel->yawmaxs[0] > modelradius)
1896 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1897 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1898 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1899 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1900 loadmodel->radius = modelradius;
1901 loadmodel->radius2 = modelradius * modelradius;
1903 // go through the lumps, swapping things
1905 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1906 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1907 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1908 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1909 for (i = 0;i < pheader->numscenes;i++)
1911 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1912 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1913 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1914 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1915 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1916 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1917 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1918 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1919 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1920 if (loadmodel->animscenes[i].framerate < 0)
1921 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1925 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1926 loadmodel->num_bones = pheader->numbones;
1927 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1928 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1929 for (i = 0;i < pheader->numbones;i++)
1931 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1932 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1933 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1934 if (loadmodel->data_bones[i].parent >= i)
1935 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1938 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1939 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1940 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1941 for (i = 0;i < pheader->numverts;i++)
1943 vertbonecounts[i] = BigLong(bonecount[i]);
1944 if (vertbonecounts[i] != 1)
1945 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1948 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1950 meshvertices = pheader->numverts;
1951 meshtriangles = pheader->numtris;
1953 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1954 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1955 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1956 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]));
1957 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1958 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1959 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1960 loadmodel->surfmesh.num_vertices = meshvertices;
1961 loadmodel->surfmesh.num_triangles = meshtriangles;
1962 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1963 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1964 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1965 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1966 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1967 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1968 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1969 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1970 loadmodel->surfmesh.num_blends = 0;
1971 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
1972 if (loadmodel->surfmesh.num_vertices <= 65536)
1973 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1974 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
1975 loadmodel->surfmesh.data_blendweights = NULL;
1977 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1978 poses = (float *) (pheader->lump_poses.start + pbase);
1979 // figure out scale of model from root bone, for compatibility with old zmodel versions
1980 tempvec[0] = BigFloat(poses[0]);
1981 tempvec[1] = BigFloat(poses[1]);
1982 tempvec[2] = BigFloat(poses[2]);
1983 modelscale = VectorLength(tempvec);
1985 for (i = 0;i < loadmodel->num_bones * numposes * 12;i++)
1987 f = fabs(BigFloat(poses[i]));
1988 biggestorigin = max(biggestorigin, f);
1990 loadmodel->num_posescale = biggestorigin / 32767.0f;
1991 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
1992 for (i = 0;i < numposes;i++)
1994 const float *frameposes = (float *) (pheader->lump_poses.start + pbase) + 12*i*loadmodel->num_bones;
1995 for (j = 0;j < loadmodel->num_bones;j++)
1998 matrix4x4_t posematrix;
1999 for (k = 0;k < 12;k++)
2000 pose[k] = BigFloat(frameposes[j*12+k]);
2001 //if (j < loadmodel->num_bones)
2002 // 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));
2003 // scale child bones to match the root scale
2004 if (loadmodel->data_bones[j].parent >= 0)
2006 pose[3] *= modelscale;
2007 pose[7] *= modelscale;
2008 pose[11] *= modelscale;
2010 // normalize rotation matrix
2011 VectorNormalize(pose + 0);
2012 VectorNormalize(pose + 4);
2013 VectorNormalize(pose + 8);
2014 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2015 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
2019 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
2020 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
2021 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
2022 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2023 // (converting from weight-blending skeletal animation to
2024 // deformation-based skeletal animation)
2025 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2026 for (i = 0;i < loadmodel->num_bones;i++)
2029 for (k = 0;k < 12;k++)
2030 m[k] = BigFloat(poses[i*12+k]);
2031 if (loadmodel->data_bones[i].parent >= 0)
2032 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2034 for (k = 0;k < 12;k++)
2035 bonepose[12*i+k] = m[k];
2037 for (j = 0;j < pheader->numverts;j++)
2039 // this format really should have had a per vertexweight weight value...
2040 // but since it does not, the weighting is completely ignored and
2041 // only one weight is allowed per vertex
2042 int boneindex = BigLong(vertdata[j].bonenum);
2043 const float *m = bonepose + 12 * boneindex;
2044 float relativeorigin[3];
2045 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
2046 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
2047 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
2048 // transform the vertex bone weight into the base mesh
2049 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
2050 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
2051 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
2052 // store the weight as the primary weight on this vertex
2053 loadmodel->surfmesh.blends[j] = boneindex;
2056 // normals and tangents are calculated after elements are loaded
2058 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
2059 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
2060 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
2061 for (i = 0;i < pheader->numverts;i++)
2063 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
2064 // flip T coordinate for OpenGL
2065 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
2068 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
2069 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
2070 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
2072 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
2073 //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)
2074 // byteswap, validate, and swap winding order of tris
2075 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
2076 if (pheader->lump_render.length != count)
2077 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
2078 renderlist = (int *) (pheader->lump_render.start + pbase);
2079 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
2081 for (i = 0;i < loadmodel->num_surfaces;i++)
2083 int firstvertex, lastvertex;
2084 if (renderlist >= renderlistend)
2085 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2086 count = BigLong(*renderlist);renderlist++;
2087 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
2088 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2090 loadmodel->sortedmodelsurfaces[i] = i;
2091 surface = loadmodel->data_surfaces + i;
2092 surface->texture = loadmodel->data_textures + i;
2093 surface->num_firsttriangle = meshtriangles;
2094 surface->num_triangles = count;
2095 meshtriangles += surface->num_triangles;
2097 // load the elements
2098 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2099 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
2101 outelements[j*3+2] = BigLong(renderlist[0]);
2102 outelements[j*3+1] = BigLong(renderlist[1]);
2103 outelements[j*3+0] = BigLong(renderlist[2]);
2105 // validate the elements and find the used vertex range
2106 firstvertex = meshvertices;
2108 for (j = 0;j < surface->num_triangles * 3;j++)
2110 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
2111 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
2112 firstvertex = min(firstvertex, outelements[j]);
2113 lastvertex = max(lastvertex, outelements[j]);
2115 surface->num_firstvertex = firstvertex;
2116 surface->num_vertices = lastvertex + 1 - firstvertex;
2118 // since zym models do not have named sections, reuse their shader
2119 // name as the section name
2120 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
2121 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
2123 Mod_FreeSkinFiles(skinfiles);
2124 Mem_Free(vertbonecounts);
2126 Mod_MakeSortedSurfaces(loadmodel);
2128 // compute all the mesh information that was not loaded from the file
2129 if (loadmodel->surfmesh.data_element3s)
2130 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2131 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2132 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2133 Mod_BuildBaseBonePoses();
2134 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2135 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);
2136 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2138 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2140 if (!loadmodel->surfmesh.isanimated)
2142 Mod_MakeCollisionBIH(loadmodel, true);
2143 loadmodel->TraceBoxBox = Mod_CollisionBIH_TraceBoxBox;
2144 loadmodel->TraceBox = Mod_TraceBox_using_TraceBoxBox;
2145 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2146 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2147 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2151 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2153 dpmheader_t *pheader;
2157 unsigned char *pbase;
2158 int i, j, k, meshvertices, meshtriangles;
2159 skinfile_t *skinfiles;
2160 unsigned char *data;
2162 float biggestorigin, tempvec[3], modelscale;
2166 pheader = (dpmheader_t *)buffer;
2167 pbase = (unsigned char *)buffer;
2168 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2169 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2170 if (BigLong(pheader->type) != 2)
2171 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2173 loadmodel->modeldatatypestring = "DPM";
2175 loadmodel->type = mod_alias;
2176 loadmodel->synctype = ST_RAND;
2179 pheader->type = BigLong(pheader->type);
2180 pheader->filesize = BigLong(pheader->filesize);
2181 pheader->mins[0] = BigFloat(pheader->mins[0]);
2182 pheader->mins[1] = BigFloat(pheader->mins[1]);
2183 pheader->mins[2] = BigFloat(pheader->mins[2]);
2184 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2185 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2186 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2187 pheader->yawradius = BigFloat(pheader->yawradius);
2188 pheader->allradius = BigFloat(pheader->allradius);
2189 pheader->num_bones = BigLong(pheader->num_bones);
2190 pheader->num_meshs = BigLong(pheader->num_meshs);
2191 pheader->num_frames = BigLong(pheader->num_frames);
2192 pheader->ofs_bones = BigLong(pheader->ofs_bones);
2193 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2194 pheader->ofs_frames = BigLong(pheader->ofs_frames);
2196 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2198 Con_Printf("%s has no geometry\n", loadmodel->name);
2201 if (pheader->num_frames < 1)
2203 Con_Printf("%s has no frames\n", loadmodel->name);
2207 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2208 loadmodel->DrawSky = NULL;
2209 loadmodel->DrawAddWaterPlanes = NULL;
2210 loadmodel->Draw = R_Q1BSP_Draw;
2211 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2212 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2213 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2214 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2215 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2216 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2217 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2218 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2219 loadmodel->TraceBox = Mod_TraceBox_using_TraceBoxBox;
2220 loadmodel->TraceBoxBox = Mod_MDLMD2MD3_TraceBoxBox;
2221 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2222 loadmodel->PointSuperContents = NULL;
2225 for (i = 0;i < 3;i++)
2227 loadmodel->normalmins[i] = pheader->mins[i];
2228 loadmodel->normalmaxs[i] = pheader->maxs[i];
2229 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2230 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2231 loadmodel->rotatedmins[i] = -pheader->allradius;
2232 loadmodel->rotatedmaxs[i] = pheader->allradius;
2234 loadmodel->radius = pheader->allradius;
2235 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2237 // load external .skin files if present
2238 skinfiles = Mod_LoadSkinFiles();
2239 if (loadmodel->numskins < 1)
2240 loadmodel->numskins = 1;
2245 // gather combined statistics from the meshes
2246 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2247 for (i = 0;i < (int)pheader->num_meshs;i++)
2249 int numverts = BigLong(dpmmesh->num_verts);
2250 meshvertices += numverts;
2251 meshtriangles += BigLong(dpmmesh->num_tris);
2255 loadmodel->numframes = pheader->num_frames;
2256 loadmodel->num_bones = pheader->num_bones;
2257 loadmodel->num_poses = loadmodel->numframes;
2258 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2259 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2260 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2261 // do most allocations as one merged chunk
2262 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));
2263 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2264 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2265 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2266 loadmodel->surfmesh.num_vertices = meshvertices;
2267 loadmodel->surfmesh.num_triangles = meshtriangles;
2268 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2269 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2270 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2271 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2272 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2273 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2274 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2275 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2276 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2277 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2278 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2279 loadmodel->surfmesh.num_blends = 0;
2280 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2281 if (meshvertices <= 65536)
2282 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2283 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2284 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
2286 for (i = 0;i < loadmodel->numskins;i++)
2288 loadmodel->skinscenes[i].firstframe = i;
2289 loadmodel->skinscenes[i].framecount = 1;
2290 loadmodel->skinscenes[i].loop = true;
2291 loadmodel->skinscenes[i].framerate = 10;
2294 // load the bone info
2295 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2296 for (i = 0;i < loadmodel->num_bones;i++)
2298 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2299 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2300 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2301 if (loadmodel->data_bones[i].parent >= i)
2302 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2306 frames = (dpmframe_t *) (pbase + pheader->ofs_frames);
2307 // figure out scale of model from root bone, for compatibility with old dpmodel versions
2308 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2309 tempvec[0] = BigFloat(poses[0]);
2310 tempvec[1] = BigFloat(poses[1]);
2311 tempvec[2] = BigFloat(poses[2]);
2312 modelscale = VectorLength(tempvec);
2314 for (i = 0;i < loadmodel->numframes;i++)
2316 memcpy(loadmodel->animscenes[i].name, frames[i].name, sizeof(frames[i].name));
2317 loadmodel->animscenes[i].firstframe = i;
2318 loadmodel->animscenes[i].framecount = 1;
2319 loadmodel->animscenes[i].loop = true;
2320 loadmodel->animscenes[i].framerate = 10;
2321 // load the bone poses for this frame
2322 poses = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2323 for (j = 0;j < loadmodel->num_bones*12;j++)
2325 f = fabs(BigFloat(poses[j]));
2326 biggestorigin = max(biggestorigin, f);
2328 // stuff not processed here: mins, maxs, yawradius, allradius
2330 loadmodel->num_posescale = biggestorigin / 32767.0f;
2331 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2332 for (i = 0;i < loadmodel->numframes;i++)
2334 const float *frameposes = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2335 for (j = 0;j < loadmodel->num_bones;j++)
2338 matrix4x4_t posematrix;
2339 for (k = 0;k < 12;k++)
2340 pose[k] = BigFloat(frameposes[j*12+k]);
2341 // scale child bones to match the root scale
2342 if (loadmodel->data_bones[j].parent >= 0)
2344 pose[3] *= modelscale;
2345 pose[7] *= modelscale;
2346 pose[11] *= modelscale;
2348 // normalize rotation matrix
2349 VectorNormalize(pose + 0);
2350 VectorNormalize(pose + 4);
2351 VectorNormalize(pose + 8);
2352 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2353 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
2357 // load the meshes now
2358 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2361 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2362 // (converting from weight-blending skeletal animation to
2363 // deformation-based skeletal animation)
2364 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2365 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2366 for (i = 0;i < loadmodel->num_bones;i++)
2369 for (k = 0;k < 12;k++)
2370 m[k] = BigFloat(poses[i*12+k]);
2371 if (loadmodel->data_bones[i].parent >= 0)
2372 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2374 for (k = 0;k < 12;k++)
2375 bonepose[12*i+k] = m[k];
2377 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2379 const int *inelements;
2381 const float *intexcoord;
2382 msurface_t *surface;
2384 loadmodel->sortedmodelsurfaces[i] = i;
2385 surface = loadmodel->data_surfaces + i;
2386 surface->texture = loadmodel->data_textures + i;
2387 surface->num_firsttriangle = meshtriangles;
2388 surface->num_triangles = BigLong(dpmmesh->num_tris);
2389 surface->num_firstvertex = meshvertices;
2390 surface->num_vertices = BigLong(dpmmesh->num_verts);
2391 meshvertices += surface->num_vertices;
2392 meshtriangles += surface->num_triangles;
2394 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2395 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2396 for (j = 0;j < surface->num_triangles;j++)
2398 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2399 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2400 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2401 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2406 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2407 for (j = 0;j < surface->num_vertices*2;j++)
2408 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2410 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2411 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2413 int weightindex[4] = { 0, 0, 0, 0 };
2414 float weightinfluence[4] = { 0, 0, 0, 0 };
2416 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2417 data += sizeof(dpmvertex_t);
2418 for (k = 0;k < numweights;k++)
2420 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2421 int boneindex = BigLong(vert->bonenum);
2422 const float *m = bonepose + 12 * boneindex;
2423 float influence = BigFloat(vert->influence);
2424 float relativeorigin[3], relativenormal[3];
2425 relativeorigin[0] = BigFloat(vert->origin[0]);
2426 relativeorigin[1] = BigFloat(vert->origin[1]);
2427 relativeorigin[2] = BigFloat(vert->origin[2]);
2428 relativenormal[0] = BigFloat(vert->normal[0]);
2429 relativenormal[1] = BigFloat(vert->normal[1]);
2430 relativenormal[2] = BigFloat(vert->normal[2]);
2431 // blend the vertex bone weights into the base mesh
2432 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2433 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2434 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2435 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2436 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2437 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2440 // store the first (and often only) weight
2441 weightinfluence[0] = influence;
2442 weightindex[0] = boneindex;
2446 // sort the new weight into this vertex's weight table
2447 // (which only accepts up to 4 bones per vertex)
2448 for (l = 0;l < 4;l++)
2450 if (weightinfluence[l] < influence)
2452 // move weaker influence weights out of the way first
2454 for (l2 = 3;l2 > l;l2--)
2456 weightinfluence[l2] = weightinfluence[l2-1];
2457 weightindex[l2] = weightindex[l2-1];
2459 // store the new weight
2460 weightinfluence[l] = influence;
2461 weightindex[l] = boneindex;
2466 data += sizeof(dpmbonevert_t);
2468 loadmodel->surfmesh.blends[j] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
2471 // since dpm models do not have named sections, reuse their shader name as the section name
2472 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2474 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2476 if (loadmodel->surfmesh.num_blends < meshvertices)
2477 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2479 Mod_FreeSkinFiles(skinfiles);
2480 Mod_MakeSortedSurfaces(loadmodel);
2482 // compute all the mesh information that was not loaded from the file
2483 if (loadmodel->surfmesh.data_element3s)
2484 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2485 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2486 Mod_BuildBaseBonePoses();
2487 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);
2488 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2490 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2492 if (!loadmodel->surfmesh.isanimated)
2494 Mod_MakeCollisionBIH(loadmodel, true);
2495 loadmodel->TraceBoxBox = Mod_CollisionBIH_TraceBoxBox;
2496 loadmodel->TraceBox = Mod_TraceBox_using_TraceBoxBox;
2497 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2498 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2499 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2503 // no idea why PSK/PSA files contain weird quaternions but they do...
2504 #define PSKQUATNEGATIONS
2505 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2507 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2508 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2509 fs_offset_t filesize;
2514 pskboneinfo_t *bones;
2515 pskrawweights_t *rawweights;
2516 //pskboneinfo_t *animbones;
2517 pskaniminfo_t *anims;
2518 pskanimkeys_t *animkeys;
2519 void *animfilebuffer, *animbuffer, *animbufferend;
2520 unsigned char *data;
2522 skinfile_t *skinfiles;
2523 char animname[MAX_QPATH];
2525 float biggestorigin;
2527 pchunk = (pskchunk_t *)buffer;
2528 if (strcmp(pchunk->id, "ACTRHEAD"))
2529 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2531 loadmodel->modeldatatypestring = "PSK";
2533 loadmodel->type = mod_alias;
2534 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2535 loadmodel->DrawSky = NULL;
2536 loadmodel->DrawAddWaterPlanes = NULL;
2537 loadmodel->Draw = R_Q1BSP_Draw;
2538 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2539 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2540 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2541 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2542 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2543 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2544 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2545 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2546 loadmodel->TraceBox = Mod_TraceBox_using_TraceBoxBox;
2547 loadmodel->TraceBoxBox = Mod_MDLMD2MD3_TraceBoxBox;
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);
3078 loadmodel->TraceBoxBox = Mod_CollisionBIH_TraceBoxBox;
3079 loadmodel->TraceBox = Mod_TraceBox_using_TraceBoxBox;
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;
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 header = (iqmheader_t *)buffer;
3110 if (memcmp(header->id, "INTERQUAKEMODEL", 16))
3111 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model", loadmodel->name);
3112 if (LittleLong(header->version) != 0)
3113 Host_Error ("Mod_INTERQUAKEMODEL_Load: only version 0 models are currently supported (name = %s)", loadmodel->name);
3115 loadmodel->modeldatatypestring = "IQM";
3117 loadmodel->type = mod_alias;
3118 loadmodel->synctype = ST_RAND;
3121 header->version = LittleLong(header->version);
3122 header->filesize = LittleLong(header->filesize);
3123 header->flags = LittleLong(header->flags);
3124 header->num_text = LittleLong(header->num_text);
3125 header->ofs_text = LittleLong(header->ofs_text);
3126 header->num_meshes = LittleLong(header->num_meshes);
3127 header->ofs_meshes = LittleLong(header->ofs_meshes);
3128 header->num_vertexarrays = LittleLong(header->num_vertexarrays);
3129 header->num_vertexes = LittleLong(header->num_vertexes);
3130 header->ofs_vertexarrays = LittleLong(header->ofs_vertexarrays);
3131 header->num_triangles = LittleLong(header->num_triangles);
3132 header->ofs_triangles = LittleLong(header->ofs_triangles);
3133 header->ofs_neighbors = LittleLong(header->ofs_neighbors);
3134 header->num_joints = LittleLong(header->num_joints);
3135 header->ofs_joints = LittleLong(header->ofs_joints);
3136 header->num_poses = LittleLong(header->num_poses);
3137 header->ofs_poses = LittleLong(header->ofs_poses);
3138 header->num_anims = LittleLong(header->num_anims);
3139 header->ofs_anims = LittleLong(header->ofs_anims);
3140 header->num_frames = LittleLong(header->num_frames);
3141 header->num_framechannels = LittleLong(header->num_framechannels);
3142 header->ofs_frames = LittleLong(header->ofs_frames);
3143 header->num_comment = LittleLong(header->num_comment);
3144 header->ofs_comment = LittleLong(header->ofs_comment);
3145 header->num_extensions = LittleLong(header->num_extensions);
3146 header->ofs_extensions = LittleLong(header->ofs_extensions);
3148 if (header->num_triangles < 1 || header->num_vertexes < 3 || header->num_vertexarrays < 1 || header->num_meshes < 1)
3150 Con_Printf("%s has no geometry\n", loadmodel->name);
3153 if (header->num_frames < 1 || header->num_anims < 1)
3155 Con_Printf("%s has no animations\n", loadmodel->name);
3159 va = (iqmvertexarray_t *)(pbase + header->ofs_vertexarrays);
3160 for (i = 0;i < (int)header->num_vertexarrays;i++)
3162 va[i].type = LittleLong(va[i].type);
3163 va[i].flags = LittleLong(va[i].flags);
3164 va[i].format = LittleLong(va[i].format);
3165 va[i].size = LittleLong(va[i].size);
3166 va[i].offset = LittleLong(va[i].offset);
3170 if (va[i].format == IQM_FLOAT && va[i].size == 3)
3171 vposition = (float *)(pbase + va[i].offset);
3174 if (va[i].format == IQM_FLOAT && va[i].size == 2)
3175 vtexcoord = (float *)(pbase + va[i].offset);
3178 if (va[i].format == IQM_FLOAT && va[i].size == 3)
3179 vnormal = (float *)(pbase + va[i].offset);
3182 if (va[i].format == IQM_FLOAT && va[i].size == 4)
3183 vtangent = (float *)(pbase + va[i].offset);
3185 case IQM_BLENDINDEXES:
3186 if (va[i].format == IQM_UBYTE && va[i].size == 4)
3187 vblendindexes = (unsigned char *)(pbase + va[i].offset);
3189 case IQM_BLENDWEIGHTS:
3190 if (va[i].format == IQM_UBYTE && va[i].size == 4)
3191 vblendweights = (unsigned char *)(pbase + va[i].offset);
3195 if (!vposition || !vtexcoord || !vblendindexes || !vblendweights)
3197 Con_Printf("%s is missing vertex array data\n", loadmodel->name);
3201 text = header->num_text && header->ofs_text ? (const char *)(pbase + header->ofs_text) : "";
3203 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
3204 loadmodel->DrawSky = NULL;
3205 loadmodel->DrawAddWaterPlanes = NULL;
3206 loadmodel->Draw = R_Q1BSP_Draw;
3207 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
3208 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
3209 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
3210 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
3211 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
3212 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
3213 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
3214 loadmodel->DrawLight = R_Q1BSP_DrawLight;
3215 loadmodel->TraceBox = Mod_TraceBox_using_TraceBoxBox;
3216 loadmodel->TraceBoxBox = Mod_MDLMD2MD3_TraceBoxBox;
3217 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
3218 loadmodel->PointSuperContents = NULL;
3220 // load external .skin files if present
3221 skinfiles = Mod_LoadSkinFiles();
3222 if (loadmodel->numskins < 1)
3223 loadmodel->numskins = 1;
3225 loadmodel->numframes = header->num_frames;
3226 loadmodel->num_bones = header->num_joints;
3227 loadmodel->num_poses = loadmodel->numframes;
3228 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = header->num_meshes;
3229 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3230 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3232 meshvertices = header->num_vertexes;
3233 meshtriangles = header->num_triangles;
3235 // do most allocations as one merged chunk
3236 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));
3237 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
3238 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
3239 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
3240 loadmodel->surfmesh.num_vertices = meshvertices;
3241 loadmodel->surfmesh.num_triangles = meshtriangles;
3242 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3243 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3244 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
3245 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3246 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3247 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
3248 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
3249 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
3250 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
3251 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
3252 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
3253 loadmodel->surfmesh.num_blends = 0;
3254 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
3255 if (meshvertices <= 65536)
3256 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
3257 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
3258 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
3260 for (i = 0;i < loadmodel->numskins;i++)
3262 loadmodel->skinscenes[i].firstframe = i;
3263 loadmodel->skinscenes[i].framecount = 1;
3264 loadmodel->skinscenes[i].loop = true;
3265 loadmodel->skinscenes[i].framerate = 10;
3268 // load the bone info
3269 joint = (iqmjoint_t *) (pbase + header->ofs_joints);
3270 for (i = 0;i < loadmodel->num_bones;i++)
3272 matrix4x4_t base, invbase;
3273 joint[i].name = LittleLong(joint[i].name);
3274 joint[i].parent = LittleLong(joint[i].parent);
3275 for (j = 0;j < 3;j++)
3277 joint[i].origin[j] = LittleFloat(joint[i].origin[j]);
3278 joint[i].rotation[j] = LittleFloat(joint[i].rotation[j]);
3280 strlcpy(loadmodel->data_bones[i].name, &text[joint[i].name], sizeof(loadmodel->data_bones[i].name));
3281 loadmodel->data_bones[i].parent = joint[i].parent;
3282 if (loadmodel->data_bones[i].parent >= i)
3283 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3284 Matrix4x4_FromDoom3Joint(&base, joint[i].origin[0], joint[i].origin[1], joint[i].origin[2], joint[i].rotation[0], joint[i].rotation[1], joint[i].rotation[2]);
3285 Matrix4x4_Invert_Simple(&invbase, &base);
3286 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3289 // set up the animscenes based on the anims
3290 anim = (iqmanim_t *) (pbase + header->ofs_anims);
3291 for (i = 0;i < (int)header->num_anims;i++)
3293 anim[i].name = LittleLong(anim[i].name);
3294 anim[i].first_frame = LittleLong(anim[i].first_frame);
3295 anim[i].num_frames = LittleLong(anim[i].num_frames);
3296 anim[i].framerate = LittleFloat(anim[i].framerate);
3297 anim[i].flags = LittleLong(anim[i].flags);
3298 for (j = anim[i].first_frame;j < (int)(anim[i].first_frame + anim[i].num_frames);j++)
3300 dpsnprintf(loadmodel->animscenes[j].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", &text[anim[i].name], j - anim[i].first_frame);
3301 loadmodel->animscenes[j].firstframe = j;
3302 loadmodel->animscenes[j].framecount = 1;
3303 loadmodel->animscenes[i].loop = ((anim[i].flags & IQM_LOOP) != 0);
3304 loadmodel->animscenes[j].framerate = anim[i].framerate;
3308 pose = (iqmpose_t *) (pbase + header->ofs_poses);
3310 for (i = 0;i < (int)header->num_poses;i++)
3313 pose[i].parent = LittleLong(pose[i].parent);
3314 pose[i].channelmask = LittleLong(pose[i].channelmask);
3315 pose[i].channeloffset[0] = LittleFloat(pose[i].channeloffset[0]);
3316 pose[i].channeloffset[1] = LittleFloat(pose[i].channeloffset[1]);
3317 pose[i].channeloffset[2] = LittleFloat(pose[i].channeloffset[2]);
3318 pose[i].channeloffset[3] = LittleFloat(pose[i].channeloffset[3]);
3319 pose[i].channeloffset[4] = LittleFloat(pose[i].channeloffset[4]);
3320 pose[i].channeloffset[5] = LittleFloat(pose[i].channeloffset[5]);
3321 pose[i].channelscale[0] = LittleFloat(pose[i].channelscale[0]);
3322 pose[i].channelscale[1] = LittleFloat(pose[i].channelscale[1]);
3323 pose[i].channelscale[2] = LittleFloat(pose[i].channelscale[2]);
3324 pose[i].channelscale[3] = LittleFloat(pose[i].channelscale[3]);
3325 pose[i].channelscale[4] = LittleFloat(pose[i].channelscale[4]);
3326 pose[i].channelscale[5] = LittleFloat(pose[i].channelscale[5]);
3327 f = fabs(pose[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3328 f = fabs(pose[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3329 f = fabs(pose[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3330 f = fabs(pose[i].channeloffset[0] + 0xFFFF*pose[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3331 f = fabs(pose[i].channeloffset[1] + 0xFFFF*pose[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3332 f = fabs(pose[i].channeloffset[2] + 0xFFFF*pose[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3334 loadmodel->num_posescale = biggestorigin / 32767.0f;
3335 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3337 // load the pose data
3338 framedata = (unsigned short *) (pbase + header->ofs_frames);
3339 for (i = 0, k = 0;i < (int)header->num_frames;i++)
3341 for (j = 0;j < (int)header->num_poses;j++, k++)
3343 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));
3344 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));
3345 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));
3346 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));
3347 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));
3348 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));
3352 // load bounding box data
3353 if (header->ofs_bounds)
3355 float xyradius = 0, radius = 0;
3356 bounds = (iqmbounds_t *) (pbase + header->ofs_bounds);
3357 VectorClear(loadmodel->normalmins);
3358 VectorClear(loadmodel->normalmaxs);
3359 for (i = 0; i < (int)header->num_frames;i++)
3361 bounds[i].mins[0] = LittleFloat(bounds[i].mins[0]);
3362 bounds[i].mins[1] = LittleFloat(bounds[i].mins[1]);
3363 bounds[i].mins[2] = LittleFloat(bounds[i].mins[2]);
3364 bounds[i].maxs[0] = LittleFloat(bounds[i].maxs[0]);
3365 bounds[i].maxs[1] = LittleFloat(bounds[i].maxs[1]);
3366 bounds[i].maxs[2] = LittleFloat(bounds[i].maxs[2]);
3367 bounds[i].xyradius = LittleFloat(bounds[i].xyradius);
3368 bounds[i].radius = LittleFloat(bounds[i].radius);
3371 VectorCopy(bounds[i].mins, loadmodel->normalmins);
3372 VectorCopy(bounds[i].maxs, loadmodel->normalmaxs);
3376 if (loadmodel->normalmins[0] > bounds[i].mins[0]) loadmodel->normalmins[0] = bounds[i].mins[0];
3377 if (loadmodel->normalmins[1] > bounds[i].mins[1]) loadmodel->normalmins[1] = bounds[i].mins[1];
3378 if (loadmodel->normalmins[2] > bounds[i].mins[2]) loadmodel->normalmins[2] = bounds[i].mins[2];
3379 if (loadmodel->normalmaxs[0] < bounds[i].maxs[0]) loadmodel->normalmaxs[0] = bounds[i].maxs[0];
3380 if (loadmodel->normalmaxs[1] < bounds[i].maxs[1]) loadmodel->normalmaxs[1] = bounds[i].maxs[1];
3381 if (loadmodel->normalmaxs[2] < bounds[i].maxs[2]) loadmodel->normalmaxs[2] = bounds[i].maxs[2];
3383 if (bounds[i].xyradius > xyradius)
3384 xyradius = bounds[i].xyradius;
3385 if (bounds[i].radius > radius)
3386 radius = bounds[i].radius;
3388 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -xyradius;
3389 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = xyradius;
3390 loadmodel->yawmins[2] = loadmodel->normalmins[2];
3391 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
3392 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
3393 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
3394 loadmodel->radius = radius;
3395 loadmodel->radius2 = radius * radius;
3398 // load triangle data
3399 inelements = (const int *) (pbase + header->ofs_triangles);
3400 outelements = loadmodel->surfmesh.data_element3i;
3401 for (i = 0;i < (int)header->num_triangles;i++)
3403 outelements[0] = LittleLong(inelements[0]);
3404 outelements[1] = LittleLong(inelements[1]);
3405 outelements[2] = LittleLong(inelements[2]);
3409 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, header->num_vertexes, __FILE__, __LINE__);
3411 if (header->ofs_neighbors)
3413 inelements = (const int *) (pbase + header->ofs_neighbors);
3414 outelements = loadmodel->surfmesh.data_neighbor3i;
3415 for (i = 0;i < (int)header->num_triangles;i++)
3417 outelements[0] = LittleLong(inelements[0]);
3418 outelements[1] = LittleLong(inelements[1]);
3419 outelements[2] = LittleLong(inelements[2]);
3426 outvertex = loadmodel->surfmesh.data_vertex3f;
3427 for (i = 0;i < (int)header->num_vertexes;i++)
3429 outvertex[0] = LittleFloat(vposition[0]);
3430 outvertex[1] = LittleFloat(vposition[1]);
3431 outvertex[2] = LittleFloat(vposition[2]);
3436 outtexcoord = loadmodel->surfmesh.data_texcoordtexture2f;
3437 for (i = 0;i < (int)header->num_vertexes;i++)
3439 outtexcoord[0] = LittleFloat(vtexcoord[0]);
3440 outtexcoord[1] = LittleFloat(vtexcoord[1]);
3447 outnormal = loadmodel->surfmesh.data_normal3f;
3448 for (i = 0;i < (int)header->num_vertexes;i++)
3450 outnormal[0] = LittleFloat(vnormal[0]);
3451 outnormal[1] = LittleFloat(vnormal[1]);
3452 outnormal[2] = LittleFloat(vnormal[2]);
3458 if(vnormal && vtangent)
3460 outnormal = loadmodel->surfmesh.data_normal3f;
3461 outsvector = loadmodel->surfmesh.data_svector3f;
3462 outtvector = loadmodel->surfmesh.data_tvector3f;
3463 for (i = 0;i < (int)header->num_vertexes;i++)
3465 outsvector[0] = LittleFloat(vtangent[0]);
3466 outsvector[1] = LittleFloat(vtangent[1]);
3467 outsvector[2] = LittleFloat(vtangent[2]);
3468 if(LittleFloat(vtangent[3]) < 0)
3469 CrossProduct(outsvector, outnormal, outtvector);
3471 CrossProduct(outnormal, outsvector, outtvector);
3479 for (i = 0; i < (int)header->num_vertexes;i++)
3481 blendweights_t weights;
3482 memcpy(weights.index, vblendindexes + i*4, 4);
3483 memcpy(weights.influence, vblendweights + i*4, 4);
3484 loadmodel->surfmesh.blends[i] = Mod_Skeletal_AddBlend(loadmodel, &weights);
3488 mesh = (iqmmesh_t *) (pbase + header->ofs_meshes);
3489 for (i = 0;i < (int)header->num_meshes;i++)
3491 msurface_t *surface;
3493 mesh[i].name = LittleLong(mesh[i].name);
3494 mesh[i].material = LittleLong(mesh[i].material);
3495 mesh[i].first_vertex = LittleLong(mesh[i].first_vertex);
3496 mesh[i].num_vertexes = LittleLong(mesh[i].num_vertexes);
3497 mesh[i].first_triangle = LittleLong(mesh[i].first_triangle);
3498 mesh[i].num_triangles = LittleLong(mesh[i].num_triangles);
3500 loadmodel->sortedmodelsurfaces[i] = i;
3501 surface = loadmodel->data_surfaces + i;
3502 surface->texture = loadmodel->data_textures + i;
3503 surface->num_firsttriangle = mesh[i].first_triangle;
3504 surface->num_triangles = mesh[i].num_triangles;
3505 surface->num_firstvertex = mesh[i].first_vertex;
3506 surface->num_vertices = mesh[i].num_vertexes;
3508 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, &text[mesh[i].name], &text[mesh[i].material]);
3511 Mod_FreeSkinFiles(skinfiles);
3512 Mod_MakeSortedSurfaces(loadmodel);
3514 // compute all the mesh information that was not loaded from the file
3515 if (loadmodel->surfmesh.data_element3s)
3516 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3517 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3519 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
3520 if (!vnormal || !vtangent)
3521 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);
3522 if (!header->ofs_neighbors)
3523 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3524 if (!header->ofs_bounds)
3525 Mod_Alias_CalculateBoundingBox();
3527 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
3529 if (!loadmodel->surfmesh.isanimated)
3531 Mod_MakeCollisionBIH(loadmodel, true);
3532 loadmodel->TraceBoxBox = Mod_CollisionBIH_TraceBoxBox;
3533 loadmodel->TraceBox = Mod_TraceBox_using_TraceBoxBox;
3534 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3535 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3536 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;