2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 cvar_t r_skeletal_debugbone = {0, "r_skeletal_debugbone", "-1", "development cvar for testing skeletal model code"};
26 cvar_t r_skeletal_debugbonecomponent = {0, "r_skeletal_debugbonecomponent", "3", "development cvar for testing skeletal model code"};
27 cvar_t r_skeletal_debugbonevalue = {0, "r_skeletal_debugbonevalue", "100", "development cvar for testing skeletal model code"};
28 cvar_t r_skeletal_debugtranslatex = {0, "r_skeletal_debugtranslatex", "1", "development cvar for testing skeletal model code"};
29 cvar_t r_skeletal_debugtranslatey = {0, "r_skeletal_debugtranslatey", "1", "development cvar for testing skeletal model code"};
30 cvar_t r_skeletal_debugtranslatez = {0, "r_skeletal_debugtranslatez", "1", "development cvar for testing skeletal model code"};
31 cvar_t mod_alias_supporttagscale = {0, "mod_alias_supporttagscale", "1", "support scaling factors in bone/tag attachment matrices as supported by MD3"};
33 float mod_md3_sin[320];
35 void Mod_AliasInit (void)
38 Cvar_RegisterVariable(&r_skeletal_debugbone);
39 Cvar_RegisterVariable(&r_skeletal_debugbonecomponent);
40 Cvar_RegisterVariable(&r_skeletal_debugbonevalue);
41 Cvar_RegisterVariable(&r_skeletal_debugtranslatex);
42 Cvar_RegisterVariable(&r_skeletal_debugtranslatey);
43 Cvar_RegisterVariable(&r_skeletal_debugtranslatez);
44 Cvar_RegisterVariable(&mod_alias_supporttagscale);
45 for (i = 0;i < 320;i++)
46 mod_md3_sin[i] = sin(i * M_PI * 2.0f / 256.0);
49 int Mod_Skeletal_AddBlend(dp_model_t *model, const int *newindex, const float *newinfluence)
53 blendweights_t *weights;
54 blendweights_t newweights;
59 scale += newinfluence[i];
60 scale = 255.0f / scale;
64 newweights.index[i] = newindex[i];
65 newweights.influence[i] = (unsigned char)(newinfluence[i] * scale);
66 total += newweights.influence[i];
72 if(newweights.influence[i] > 0 && total > 255)
74 newweights.influence[i]--;
81 for (i = 0; i < 4;i++)
83 if(newweights.influence[i] < 255 && total < 255)
85 newweights.influence[i]++;
90 weights = model->surfmesh.data_blendweights;
91 for (i = 0;i < model->surfmesh.num_blends;i++, weights++)
93 if (!memcmp(weights, &newweights, sizeof(blendweights_t)))
94 return model->num_bones + i;
96 model->surfmesh.num_blends++;
97 memcpy(weights, &newweights, sizeof(blendweights_t));
98 return model->num_bones + i;
101 static int maxbonepose = 0;
102 static float (*bonepose)[12] = NULL;
104 void Mod_Skeletal_FreeBuffers(void)
112 #if defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1400)
113 #define RESTRICT __restrict
118 void Mod_Skeletal_AnimateVertices(const dp_model_t * RESTRICT model, const frameblend_t * RESTRICT frameblend, const skeleton_t *skeleton, float * RESTRICT vertex3f, float * RESTRICT normal3f, float * RESTRICT svector3f, float * RESTRICT tvector3f)
120 // vertex weighted skeletal
124 float (*boneposerelative)[12];
125 const blendweights_t * RESTRICT weights;
127 if (maxbonepose < model->num_bones*2 + model->surfmesh.num_blends)
131 maxbonepose = model->num_bones*2 + model->surfmesh.num_blends;
132 bonepose = (float (*)[12])Mem_Alloc(r_main_mempool, maxbonepose * sizeof(float[12]));
135 boneposerelative = bonepose + model->num_bones;
137 if (skeleton && !skeleton->relativetransforms)
140 // interpolate matrices
143 for (i = 0;i < model->num_bones;i++)
145 Matrix4x4_ToArray12FloatD3D(&skeleton->relativetransforms[i], m);
146 if (model->data_bones[i].parent >= 0)
147 R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
149 memcpy(bonepose[i], m, sizeof(m));
151 // create a relative deformation matrix to describe displacement
152 // from the base mesh, which is used by the actual weighting
153 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]);
158 float originscale = model->num_posescale;
160 const short * RESTRICT pose6s;
161 for (i = 0;i < model->num_bones;i++)
163 memset(m, 0, sizeof(m));
164 for (blends = 0;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++)
166 pose6s = model->data_poses6s + 6 * (frameblend[blends].subframe * model->num_bones + i);
167 lerp = frameblend[blends].lerp;
168 x = pose6s[3] * (1.0f / 32767.0f);
169 y = pose6s[4] * (1.0f / 32767.0f);
170 z = pose6s[5] * (1.0f / 32767.0f);
171 w = 1.0f - (x*x+y*y+z*z);
172 w = w > 0.0f ? -sqrt(w) : 0.0f;
173 m[ 0] += (1-2*(y*y+z*z)) * lerp;
174 m[ 1] += ( 2*(x*y-z*w)) * lerp;
175 m[ 2] += ( 2*(x*z+y*w)) * lerp;
176 m[ 3] += (pose6s[0] * originscale) * lerp;
177 m[ 4] += ( 2*(x*y+z*w)) * lerp;
178 m[ 5] += (1-2*(x*x+z*z)) * lerp;
179 m[ 6] += ( 2*(y*z-x*w)) * lerp;
180 m[ 7] += (pose6s[1] * originscale) * lerp;
181 m[ 8] += ( 2*(x*z-y*w)) * lerp;
182 m[ 9] += ( 2*(y*z+x*w)) * lerp;
183 m[10] += (1-2*(x*x+y*y)) * lerp;
184 m[11] += (pose6s[2] * originscale) * lerp;
187 VectorNormalize(m + 4);
188 VectorNormalize(m + 8);
189 if (i == r_skeletal_debugbone.integer)
190 m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
191 m[3] *= r_skeletal_debugtranslatex.value;
192 m[7] *= r_skeletal_debugtranslatey.value;
193 m[11] *= r_skeletal_debugtranslatez.value;
194 if (model->data_bones[i].parent >= 0)
195 R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
197 memcpy(bonepose[i], m, sizeof(m));
198 // create a relative deformation matrix to describe displacement
199 // from the base mesh, which is used by the actual weighting
200 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]);
204 // generate matrices for all blend combinations
205 weights = model->surfmesh.data_blendweights;
206 for (i = 0;i < model->surfmesh.num_blends;i++, weights++)
208 float * RESTRICT b = boneposerelative[model->num_bones + i];
209 const float * RESTRICT m = boneposerelative[weights->index[0]];
210 float f = weights->influence[0] * (1.0f / 255.0f);
211 b[ 0] = f*m[ 0]; b[ 1] = f*m[ 1]; b[ 2] = f*m[ 2]; b[ 3] = f*m[ 3];
212 b[ 4] = f*m[ 4]; b[ 5] = f*m[ 5]; b[ 6] = f*m[ 6]; b[ 7] = f*m[ 7];
213 b[ 8] = f*m[ 8]; b[ 9] = f*m[ 9]; b[10] = f*m[10]; b[11] = f*m[11];
214 for (k = 1;k < 4 && weights->influence[k];k++)
216 m = boneposerelative[weights->index[k]];
217 f = weights->influence[k] * (1.0f / 255.0f);
218 b[ 0] += f*m[ 0]; b[ 1] += f*m[ 1]; b[ 2] += f*m[ 2]; b[ 3] += f*m[ 3];
219 b[ 4] += f*m[ 4]; b[ 5] += f*m[ 5]; b[ 6] += f*m[ 6]; b[ 7] += f*m[ 7];
220 b[ 8] += f*m[ 8]; b[ 9] += f*m[ 9]; b[10] += f*m[10]; b[11] += f*m[11];
224 // transform vertex attributes by blended matrices
227 const float * RESTRICT v = model->surfmesh.data_vertex3f;
228 const unsigned short * RESTRICT b = model->surfmesh.blends;
229 // special case common combinations of attributes to avoid repeated loading of matrices
232 const float * RESTRICT n = model->surfmesh.data_normal3f;
233 if (svector3f && tvector3f)
235 const float * RESTRICT sv = model->surfmesh.data_svector3f;
236 const float * RESTRICT tv = model->surfmesh.data_tvector3f;
237 for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, n += 3, sv += 3, tv += 3, b++, vertex3f += 3, normal3f += 3, svector3f += 3, tvector3f += 3)
239 const float * RESTRICT m = boneposerelative[*b];
240 vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
241 vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
242 vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
243 normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
244 normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
245 normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
246 svector3f[0] = (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
247 svector3f[1] = (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
248 svector3f[2] = (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
249 tvector3f[0] = (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
250 tvector3f[1] = (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
251 tvector3f[2] = (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
255 for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, n += 3, b++, vertex3f += 3, normal3f += 3)
257 const float * RESTRICT m = boneposerelative[*b];
258 vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
259 vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
260 vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
261 normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
262 normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
263 normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
268 for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, b++, vertex3f += 3)
270 const float * RESTRICT m = boneposerelative[*b];
271 vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
272 vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
273 vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
279 const float * RESTRICT n = model->surfmesh.data_normal3f;
280 const unsigned short * RESTRICT b = model->surfmesh.blends;
281 for (i = 0;i < model->surfmesh.num_vertices;i++, n += 3, b++, normal3f += 3)
283 const float * RESTRICT m = boneposerelative[*b];
284 normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
285 normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
286 normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
292 const float * RESTRICT sv = model->surfmesh.data_svector3f;
293 const unsigned short * RESTRICT b = model->surfmesh.blends;
294 for (i = 0;i < model->surfmesh.num_vertices;i++, sv += 3, b++, svector3f += 3)
296 const float * RESTRICT m = boneposerelative[*b];
297 svector3f[0] = (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
298 svector3f[1] = (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
299 svector3f[2] = (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
305 const float * RESTRICT tv = model->surfmesh.data_tvector3f;
306 const unsigned short * RESTRICT b = model->surfmesh.blends;
307 for (i = 0;i < model->surfmesh.num_vertices;i++, tv += 3, b++, tvector3f += 3)
309 const float * RESTRICT m = boneposerelative[*b];
310 tvector3f[0] = (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
311 tvector3f[1] = (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
312 tvector3f[2] = (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
317 void Mod_MD3_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
320 int i, numblends, blendnum;
321 int numverts = model->surfmesh.num_vertices;
323 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
325 //VectorMA(translate, model->surfmesh.num_morphmdlframetranslate, frameblend[blendnum].lerp, translate);
326 if (frameblend[blendnum].lerp > 0)
327 numblends = blendnum + 1;
329 // special case for the first blend because it avoids some adds and the need to memset the arrays first
330 for (blendnum = 0;blendnum < numblends;blendnum++)
332 const md3vertex_t *verts = model->surfmesh.data_morphmd3vertex + numverts * frameblend[blendnum].subframe;
335 float scale = frameblend[blendnum].lerp * (1.0f / 64.0f);
338 for (i = 0;i < numverts;i++)
340 vertex3f[i * 3 + 0] = verts[i].origin[0] * scale;
341 vertex3f[i * 3 + 1] = verts[i].origin[1] * scale;
342 vertex3f[i * 3 + 2] = verts[i].origin[2] * scale;
347 for (i = 0;i < numverts;i++)
349 vertex3f[i * 3 + 0] += verts[i].origin[0] * scale;
350 vertex3f[i * 3 + 1] += verts[i].origin[1] * scale;
351 vertex3f[i * 3 + 2] += verts[i].origin[2] * scale;
355 // the yaw and pitch stored in md3 models are 8bit quantized angles
356 // (0-255), and as such a lookup table is very well suited to
357 // decoding them, and since cosine is equivilant to sine with an
358 // extra 45 degree rotation, this uses one lookup table for both
359 // sine and cosine with a +64 bias to get cosine.
362 float lerp = frameblend[blendnum].lerp;
365 for (i = 0;i < numverts;i++)
367 normal3f[i * 3 + 0] = mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
368 normal3f[i * 3 + 1] = mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
369 normal3f[i * 3 + 2] = mod_md3_sin[verts[i].pitch + 64] * lerp;
374 for (i = 0;i < numverts;i++)
376 normal3f[i * 3 + 0] += mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
377 normal3f[i * 3 + 1] += mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
378 normal3f[i * 3 + 2] += mod_md3_sin[verts[i].pitch + 64] * lerp;
384 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
385 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
388 for (i = 0;i < numverts;i++, texvecvert++)
390 VectorScale(texvecvert->svec, f, svector3f + i*3);
391 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
396 for (i = 0;i < numverts;i++, texvecvert++)
398 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
399 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
406 void Mod_MDL_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
409 int i, numblends, blendnum;
410 int numverts = model->surfmesh.num_vertices;
412 VectorClear(translate);
414 // blend the frame translates to avoid redundantly doing so on each vertex
415 // (a bit of a brain twister but it works)
416 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
418 if (model->surfmesh.data_morphmd2framesize6f)
419 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6 + 3, translate);
421 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.num_morphmdlframetranslate, translate);
422 if (frameblend[blendnum].lerp > 0)
423 numblends = blendnum + 1;
425 // special case for the first blend because it avoids some adds and the need to memset the arrays first
426 for (blendnum = 0;blendnum < numblends;blendnum++)
428 const trivertx_t *verts = model->surfmesh.data_morphmdlvertex + numverts * frameblend[blendnum].subframe;
432 if (model->surfmesh.data_morphmd2framesize6f)
433 VectorScale(model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6, frameblend[blendnum].lerp, scale);
435 VectorScale(model->surfmesh.num_morphmdlframescale, frameblend[blendnum].lerp, scale);
438 for (i = 0;i < numverts;i++)
440 vertex3f[i * 3 + 0] = translate[0] + verts[i].v[0] * scale[0];
441 vertex3f[i * 3 + 1] = translate[1] + verts[i].v[1] * scale[1];
442 vertex3f[i * 3 + 2] = translate[2] + verts[i].v[2] * scale[2];
447 for (i = 0;i < numverts;i++)
449 vertex3f[i * 3 + 0] += verts[i].v[0] * scale[0];
450 vertex3f[i * 3 + 1] += verts[i].v[1] * scale[1];
451 vertex3f[i * 3 + 2] += verts[i].v[2] * scale[2];
455 // the vertex normals in mdl models are an index into a table of
456 // 162 unique values, this very crude quantization reduces the
457 // vertex normal to only one byte, which saves a lot of space but
458 // also makes lighting pretty coarse
461 float lerp = frameblend[blendnum].lerp;
464 for (i = 0;i < numverts;i++)
466 const float *vn = m_bytenormals[verts[i].lightnormalindex];
467 VectorScale(vn, lerp, normal3f + i*3);
472 for (i = 0;i < numverts;i++)
474 const float *vn = m_bytenormals[verts[i].lightnormalindex];
475 VectorMA(normal3f + i*3, lerp, vn, normal3f + i*3);
481 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
482 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
485 for (i = 0;i < numverts;i++, texvecvert++)
487 VectorScale(texvecvert->svec, f, svector3f + i*3);
488 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
493 for (i = 0;i < numverts;i++, texvecvert++)
495 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
496 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
503 int Mod_Alias_GetTagMatrix(const dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, int tagindex, matrix4x4_t *outmatrix)
506 matrix4x4_t parentbonematrix;
507 matrix4x4_t tempbonematrix;
508 matrix4x4_t bonematrix;
509 matrix4x4_t blendmatrix;
516 *outmatrix = identitymatrix;
517 if (skeleton && skeleton->relativetransforms)
519 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
521 *outmatrix = skeleton->relativetransforms[tagindex];
522 while ((tagindex = model->data_bones[tagindex].parent) >= 0)
525 Matrix4x4_Concat(outmatrix, &skeleton->relativetransforms[tagindex], &temp);
528 else if (model->num_bones)
530 if (tagindex < 0 || tagindex >= model->num_bones)
532 Matrix4x4_Clear(&blendmatrix);
533 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
535 lerp = frameblend[blendindex].lerp;
536 Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
537 parenttagindex = tagindex;
538 while ((parenttagindex = model->data_bones[parenttagindex].parent) >= 0)
540 Matrix4x4_FromBonePose6s(&parentbonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + parenttagindex));
541 tempbonematrix = bonematrix;
542 Matrix4x4_Concat(&bonematrix, &parentbonematrix, &tempbonematrix);
544 Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
546 *outmatrix = blendmatrix;
548 else if (model->num_tags)
550 if (tagindex < 0 || tagindex >= model->num_tags)
552 for (k = 0;k < 12;k++)
554 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
556 lerp = frameblend[blendindex].lerp;
557 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
558 for (k = 0;k < 12;k++)
559 blendtag[k] += input[k] * lerp;
561 Matrix4x4_FromArray12FloatGL(outmatrix, blendtag);
564 if(!mod_alias_supporttagscale.integer)
565 Matrix4x4_Normalize3(outmatrix, outmatrix);
570 int Mod_Alias_GetExtendedTagInfoForIndex(const dp_model_t *model, unsigned int skin, const frameblend_t *frameblend, const skeleton_t *skeleton, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
575 matrix4x4_t bonematrix;
576 matrix4x4_t blendmatrix;
580 if (skeleton && skeleton->relativetransforms)
582 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
584 *parentindex = skeleton->model->data_bones[tagindex].parent;
585 *tagname = skeleton->model->data_bones[tagindex].name;
586 *tag_localmatrix = skeleton->relativetransforms[tagindex];
589 else if (model->num_bones)
591 if (tagindex < 0 || tagindex >= model->num_bones)
593 *parentindex = model->data_bones[tagindex].parent;
594 *tagname = model->data_bones[tagindex].name;
595 Matrix4x4_Clear(&blendmatrix);
596 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
598 lerp = frameblend[blendindex].lerp;
599 Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
600 Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
602 *tag_localmatrix = blendmatrix;
605 else if (model->num_tags)
607 if (tagindex < 0 || tagindex >= model->num_tags)
610 *tagname = model->data_tags[tagindex].name;
611 for (k = 0;k < 12;k++)
613 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
615 lerp = frameblend[blendindex].lerp;
616 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
617 for (k = 0;k < 12;k++)
618 blendtag[k] += input[k] * lerp;
620 Matrix4x4_FromArray12FloatGL(tag_localmatrix, blendtag);
627 int Mod_Alias_GetTagIndexForName(const dp_model_t *model, unsigned int skin, const char *tagname)
630 if(skin >= (unsigned int)model->numskins)
632 if (model->num_bones)
633 for (i = 0;i < model->num_bones;i++)
634 if (!strcasecmp(tagname, model->data_bones[i].name))
637 for (i = 0;i < model->num_tags;i++)
638 if (!strcasecmp(tagname, model->data_tags[i].name))
643 static void Mod_BuildBaseBonePoses(void)
646 matrix4x4_t *basebonepose;
647 float *outinvmatrix = loadmodel->data_baseboneposeinverse;
648 matrix4x4_t bonematrix;
649 matrix4x4_t tempbonematrix;
650 if (!loadmodel->num_bones)
652 basebonepose = (matrix4x4_t *)Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(matrix4x4_t));
653 for (boneindex = 0;boneindex < loadmodel->num_bones;boneindex++)
655 Matrix4x4_FromBonePose6s(&bonematrix, loadmodel->num_posescale, loadmodel->data_poses6s + 6 * boneindex);
656 if (loadmodel->data_bones[boneindex].parent >= 0)
658 tempbonematrix = bonematrix;
659 Matrix4x4_Concat(&bonematrix, basebonepose + loadmodel->data_bones[boneindex].parent, &tempbonematrix);
661 basebonepose[boneindex] = bonematrix;
662 Matrix4x4_Invert_Simple(&tempbonematrix, basebonepose + boneindex);
663 Matrix4x4_ToArray12FloatD3D(&tempbonematrix, outinvmatrix + 12*boneindex);
665 Mem_Free(basebonepose);
668 static void Mod_Alias_CalculateBoundingBox(void)
671 qboolean firstvertex = true;
672 float dist, yawradius, radius;
675 frameblend_t frameblend[MAX_FRAMEBLENDS];
676 memset(frameblend, 0, sizeof(frameblend));
677 frameblend[0].lerp = 1;
678 vertex3f = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
679 VectorClear(loadmodel->normalmins);
680 VectorClear(loadmodel->normalmaxs);
683 for (frameblend[0].subframe = 0;frameblend[0].subframe < loadmodel->num_poses;frameblend[0].subframe++)
685 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, vertex3f, NULL, NULL, NULL);
686 for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
691 VectorCopy(v, loadmodel->normalmins);
692 VectorCopy(v, loadmodel->normalmaxs);
696 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
697 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
698 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
699 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
700 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
701 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
703 dist = v[0] * v[0] + v[1] * v[1];
704 if (yawradius < dist)
713 radius = sqrt(radius);
714 yawradius = sqrt(yawradius);
715 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
716 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
717 loadmodel->yawmins[2] = loadmodel->normalmins[2];
718 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
719 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
720 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
721 loadmodel->radius = radius;
722 loadmodel->radius2 = radius * radius;
725 static void Mod_Alias_MorphMesh_CompileFrames(void)
728 frameblend_t frameblend[MAX_FRAMEBLENDS];
729 unsigned char *datapointer;
730 memset(frameblend, 0, sizeof(frameblend));
731 frameblend[0].lerp = 1;
732 datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
733 loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
734 loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
735 loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
736 loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
737 loadmodel->surfmesh.data_morphtexvecvertex = (texvecvertex_t *)datapointer;datapointer += loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices * sizeof(texvecvertex_t);
738 // this counts down from the last frame to the first so that the final data in surfmesh is for frame zero (which is what the renderer expects to be there)
739 for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
741 frameblend[0].subframe = i;
742 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
743 Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, r_smoothnormals_areaweighting.integer != 0);
744 // encode the svector and tvector in 3 byte format for permanent storage
745 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
747 VectorScaleCast(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
748 VectorScaleCast(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
753 static void Mod_MDLMD2MD3_TraceLine(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask)
756 float segmentmins[3], segmentmaxs[3];
758 static int maxvertices = 0;
759 static float *vertex3f = NULL;
760 memset(trace, 0, sizeof(*trace));
762 trace->realfraction = 1;
763 trace->hitsupercontentsmask = hitsupercontentsmask;
764 if (maxvertices < model->surfmesh.num_vertices)
768 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
769 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
771 segmentmins[0] = min(start[0], end[0]) - 1;
772 segmentmins[1] = min(start[1], end[1]) - 1;
773 segmentmins[2] = min(start[2], end[2]) - 1;
774 segmentmaxs[0] = max(start[0], end[0]) + 1;
775 segmentmaxs[1] = max(start[1], end[1]) + 1;
776 segmentmaxs[2] = max(start[2], end[2]) + 1;
777 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
778 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
779 Collision_TraceLineTriangleMeshFloat(trace, start, end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs);
782 static int maxvertices = 0;
783 static float *vertex3f = NULL;
785 static void Mod_MDLMD2MD3_TraceBox(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask)
788 vec3_t shiftstart, shiftend;
789 float segmentmins[3], segmentmaxs[3];
791 colboxbrushf_t thisbrush_start, thisbrush_end;
792 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
794 if (VectorCompare(boxmins, boxmaxs))
796 VectorAdd(start, boxmins, shiftstart);
797 VectorAdd(end, boxmins, shiftend);
798 Mod_MDLMD2MD3_TraceLine(model, frameblend, skeleton, trace, shiftstart, shiftend, hitsupercontentsmask);
799 VectorSubtract(trace->endpos, boxmins, trace->endpos);
803 // box trace, performed as brush trace
804 memset(trace, 0, sizeof(*trace));
806 trace->realfraction = 1;
807 trace->hitsupercontentsmask = hitsupercontentsmask;
808 if (maxvertices < model->surfmesh.num_vertices)
812 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
813 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
815 segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
816 segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
817 segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
818 segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
819 segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
820 segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
821 VectorAdd(start, boxmins, boxstartmins);
822 VectorAdd(start, boxmaxs, boxstartmaxs);
823 VectorAdd(end, boxmins, boxendmins);
824 VectorAdd(end, boxmaxs, boxendmaxs);
825 Collision_BrushForBox(&thisbrush_start, boxstartmins, boxstartmaxs, 0, 0, NULL);
826 Collision_BrushForBox(&thisbrush_end, boxendmins, boxendmaxs, 0, 0, NULL);
827 if (maxvertices < model->surfmesh.num_vertices)
831 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
832 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
834 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
835 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
836 Collision_TraceBrushTriangleMeshFloat(trace, &thisbrush_start.brush, &thisbrush_end.brush, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs);
839 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
842 for (i = 0;i < inverts;i++)
844 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
846 j = vertremap[i]; // not onseam
849 j = vertremap[i+inverts]; // onseam
855 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
857 int i, f, pose, groupframes;
859 daliasframetype_t *pframetype;
860 daliasframe_t *pinframe;
861 daliasgroup_t *group;
862 daliasinterval_t *intervals;
865 scene = loadmodel->animscenes;
866 for (f = 0;f < loadmodel->numframes;f++)
868 pframetype = (daliasframetype_t *)datapointer;
869 datapointer += sizeof(daliasframetype_t);
870 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
872 // a single frame is still treated as a group
879 group = (daliasgroup_t *)datapointer;
880 datapointer += sizeof(daliasgroup_t);
881 groupframes = LittleLong (group->numframes);
883 // intervals (time per frame)
884 intervals = (daliasinterval_t *)datapointer;
885 datapointer += sizeof(daliasinterval_t) * groupframes;
887 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
888 if (interval < 0.01f)
890 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
895 // get scene name from first frame
896 pinframe = (daliasframe_t *)datapointer;
898 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
899 scene->firstframe = pose;
900 scene->framecount = groupframes;
901 scene->framerate = 1.0f / interval;
906 for (i = 0;i < groupframes;i++)
908 pinframe = (daliasframe_t *)datapointer;
909 datapointer += sizeof(daliasframe_t);
910 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
911 datapointer += sizeof(trivertx_t) * inverts;
917 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
919 if (cls.state == ca_dedicated)
923 skinframe = R_SkinFrame_LoadMissing();
924 memset(texture, 0, sizeof(*texture));
925 texture->currentframe = texture;
926 //texture->animated = false;
927 texture->numskinframes = 1;
928 texture->skinframerate = 1;
929 texture->skinframes[0] = skinframe;
930 texture->currentskinframe = skinframe;
931 //texture->backgroundnumskinframes = 0;
932 //texture->customblendfunc[0] = 0;
933 //texture->customblendfunc[1] = 0;
934 //texture->surfaceflags = 0;
935 //texture->supercontents = 0;
936 //texture->surfaceparms = 0;
937 //texture->textureflags = 0;
939 texture->basematerialflags = MATERIALFLAG_WALL;
940 if (texture->currentskinframe->hasalpha)
941 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
942 texture->currentmaterialflags = texture->basematerialflags;
943 texture->specularscalemod = 1;
944 texture->specularpowermod = 1;
947 void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
950 skinfileitem_t *skinfileitem;
953 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
954 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
956 memset(skin, 0, sizeof(*skin));
958 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
960 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
961 if (!strcmp(skinfileitem->name, meshname))
963 Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
969 // don't render unmentioned meshes
970 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
971 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
976 Mod_LoadTextureFromQ3Shader(skin, shadername, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
979 #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);
980 #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);
981 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
983 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
984 float scales, scalet, interval;
988 stvert_t *pinstverts;
989 dtriangle_t *pintriangles;
990 daliasskintype_t *pinskintype;
991 daliasskingroup_t *pinskingroup;
992 daliasskininterval_t *pinskinintervals;
993 daliasframetype_t *pinframetype;
994 daliasgroup_t *pinframegroup;
995 unsigned char *datapointer, *startframes, *startskins;
996 char name[MAX_QPATH];
997 skinframe_t *tempskinframe;
998 animscene_t *tempskinscenes;
999 texture_t *tempaliasskins;
1001 int *vertonseam, *vertremap;
1002 skinfile_t *skinfiles;
1004 datapointer = (unsigned char *)buffer;
1005 pinmodel = (mdl_t *)datapointer;
1006 datapointer += sizeof(mdl_t);
1008 version = LittleLong (pinmodel->version);
1009 if (version != ALIAS_VERSION)
1010 Host_Error ("%s has wrong version number (%i should be %i)",
1011 loadmodel->name, version, ALIAS_VERSION);
1013 loadmodel->modeldatatypestring = "MDL";
1015 loadmodel->type = mod_alias;
1016 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1017 loadmodel->DrawSky = NULL;
1018 loadmodel->DrawAddWaterPlanes = NULL;
1019 loadmodel->Draw = R_Q1BSP_Draw;
1020 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1021 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1022 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1023 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1024 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1025 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1026 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1027 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1028 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1029 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1030 loadmodel->PointSuperContents = NULL;
1032 loadmodel->num_surfaces = 1;
1033 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1034 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
1035 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1036 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1037 loadmodel->sortedmodelsurfaces[0] = 0;
1039 loadmodel->numskins = LittleLong(pinmodel->numskins);
1040 BOUNDI(loadmodel->numskins,0,65536);
1041 skinwidth = LittleLong (pinmodel->skinwidth);
1042 BOUNDI(skinwidth,0,65536);
1043 skinheight = LittleLong (pinmodel->skinheight);
1044 BOUNDI(skinheight,0,65536);
1045 numverts = LittleLong(pinmodel->numverts);
1046 BOUNDI(numverts,0,65536);
1047 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
1048 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
1049 loadmodel->numframes = LittleLong(pinmodel->numframes);
1050 BOUNDI(loadmodel->numframes,0,65536);
1051 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
1052 BOUNDI((int)loadmodel->synctype,0,2);
1053 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1054 i = LittleLong (pinmodel->flags);
1055 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1057 for (i = 0;i < 3;i++)
1059 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
1060 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
1063 startskins = datapointer;
1065 for (i = 0;i < loadmodel->numskins;i++)
1067 pinskintype = (daliasskintype_t *)datapointer;
1068 datapointer += sizeof(daliasskintype_t);
1069 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
1073 pinskingroup = (daliasskingroup_t *)datapointer;
1074 datapointer += sizeof(daliasskingroup_t);
1075 groupskins = LittleLong(pinskingroup->numskins);
1076 datapointer += sizeof(daliasskininterval_t) * groupskins;
1079 for (j = 0;j < groupskins;j++)
1081 datapointer += skinwidth * skinheight;
1086 pinstverts = (stvert_t *)datapointer;
1087 datapointer += sizeof(stvert_t) * numverts;
1089 pintriangles = (dtriangle_t *)datapointer;
1090 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
1092 startframes = datapointer;
1093 loadmodel->surfmesh.num_morphframes = 0;
1094 for (i = 0;i < loadmodel->numframes;i++)
1096 pinframetype = (daliasframetype_t *)datapointer;
1097 datapointer += sizeof(daliasframetype_t);
1098 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
1102 pinframegroup = (daliasgroup_t *)datapointer;
1103 datapointer += sizeof(daliasgroup_t);
1104 groupframes = LittleLong(pinframegroup->numframes);
1105 datapointer += sizeof(daliasinterval_t) * groupframes;
1108 for (j = 0;j < groupframes;j++)
1110 datapointer += sizeof(daliasframe_t);
1111 datapointer += sizeof(trivertx_t) * numverts;
1112 loadmodel->surfmesh.num_morphframes++;
1115 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1117 // store texture coordinates into temporary array, they will be stored
1118 // after usage is determined (triangle data)
1119 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
1120 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
1121 vertonseam = vertremap + numverts * 2;
1123 scales = 1.0 / skinwidth;
1124 scalet = 1.0 / skinheight;
1125 for (i = 0;i < numverts;i++)
1127 vertonseam[i] = LittleLong(pinstverts[i].onseam);
1128 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
1129 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
1130 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
1131 vertst[(i+numverts)*2+1] = vertst[i*2+1];
1134 // load triangle data
1135 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1137 // read the triangle elements
1138 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1139 for (j = 0;j < 3;j++)
1140 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1141 // validate (note numverts is used because this is the original data)
1142 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1143 // now butcher the elements according to vertonseam and tri->facesfront
1144 // and then compact the vertex set to remove duplicates
1145 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1146 if (!LittleLong(pintriangles[i].facesfront)) // backface
1147 for (j = 0;j < 3;j++)
1148 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1149 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1151 // (this uses vertremap to count usage to save some memory)
1152 for (i = 0;i < numverts*2;i++)
1154 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1155 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1156 // build remapping table and compact array
1157 loadmodel->surfmesh.num_vertices = 0;
1158 for (i = 0;i < numverts*2;i++)
1162 vertremap[i] = loadmodel->surfmesh.num_vertices;
1163 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1164 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1165 loadmodel->surfmesh.num_vertices++;
1168 vertremap[i] = -1; // not used at all
1170 // remap the elements to the new vertex set
1171 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1172 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1173 // store the texture coordinates
1174 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1175 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1177 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1178 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1181 // generate ushort elements array if possible
1182 if (loadmodel->surfmesh.num_vertices <= 65536)
1183 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1184 if (loadmodel->surfmesh.data_element3s)
1185 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1186 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1189 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1190 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1191 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1192 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1193 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1194 Mod_Alias_CalculateBoundingBox();
1195 Mod_Alias_MorphMesh_CompileFrames();
1198 Mem_Free(vertremap);
1201 skinfiles = Mod_LoadSkinFiles();
1204 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1205 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1206 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1207 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1208 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1209 Mod_FreeSkinFiles(skinfiles);
1210 for (i = 0;i < loadmodel->numskins;i++)
1212 loadmodel->skinscenes[i].firstframe = i;
1213 loadmodel->skinscenes[i].framecount = 1;
1214 loadmodel->skinscenes[i].loop = true;
1215 loadmodel->skinscenes[i].framerate = 10;
1220 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1221 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1222 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1223 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1225 datapointer = startskins;
1226 for (i = 0;i < loadmodel->numskins;i++)
1228 pinskintype = (daliasskintype_t *)datapointer;
1229 datapointer += sizeof(daliasskintype_t);
1231 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1238 pinskingroup = (daliasskingroup_t *)datapointer;
1239 datapointer += sizeof(daliasskingroup_t);
1241 groupskins = LittleLong (pinskingroup->numskins);
1243 pinskinintervals = (daliasskininterval_t *)datapointer;
1244 datapointer += sizeof(daliasskininterval_t) * groupskins;
1246 interval = LittleFloat(pinskinintervals[0].interval);
1247 if (interval < 0.01f)
1249 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1254 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1255 loadmodel->skinscenes[i].firstframe = totalskins;
1256 loadmodel->skinscenes[i].framecount = groupskins;
1257 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1258 loadmodel->skinscenes[i].loop = true;
1260 for (j = 0;j < groupskins;j++)
1263 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1265 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1266 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))
1267 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));
1268 datapointer += skinwidth * skinheight;
1272 // check for skins that don't exist in the model, but do exist as external images
1273 // (this was added because yummyluv kept pestering me about support for it)
1274 // TODO: support shaders here?
1275 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)))
1277 // expand the arrays to make room
1278 tempskinscenes = loadmodel->skinscenes;
1279 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1280 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1281 Mem_Free(tempskinscenes);
1283 tempaliasskins = loadmodel->data_textures;
1284 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1285 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1286 Mem_Free(tempaliasskins);
1288 // store the info about the new skin
1289 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1290 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1291 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1292 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1293 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1294 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1296 //increase skin counts
1297 loadmodel->numskins++;
1300 // fix up the pointers since they are pointing at the old textures array
1301 // FIXME: this is a hack!
1302 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1303 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1307 surface = loadmodel->data_surfaces;
1308 surface->texture = loadmodel->data_textures;
1309 surface->num_firsttriangle = 0;
1310 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1311 surface->num_firstvertex = 0;
1312 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1314 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1317 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1319 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1320 float iskinwidth, iskinheight;
1321 unsigned char *data;
1322 msurface_t *surface;
1324 unsigned char *base, *datapointer;
1325 md2frame_t *pinframe;
1327 md2triangle_t *intri;
1328 unsigned short *inst;
1329 struct md2verthash_s
1331 struct md2verthash_s *next;
1335 *hash, **md2verthash, *md2verthashdata;
1336 skinfile_t *skinfiles;
1338 pinmodel = (md2_t *)buffer;
1339 base = (unsigned char *)buffer;
1341 version = LittleLong (pinmodel->version);
1342 if (version != MD2ALIAS_VERSION)
1343 Host_Error ("%s has wrong version number (%i should be %i)",
1344 loadmodel->name, version, MD2ALIAS_VERSION);
1346 loadmodel->modeldatatypestring = "MD2";
1348 loadmodel->type = mod_alias;
1349 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1350 loadmodel->DrawSky = NULL;
1351 loadmodel->DrawAddWaterPlanes = NULL;
1352 loadmodel->Draw = R_Q1BSP_Draw;
1353 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1354 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1355 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1356 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1357 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1358 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1359 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1360 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1361 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1362 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1363 loadmodel->PointSuperContents = NULL;
1365 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1366 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1367 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1368 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1369 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1370 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1371 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1372 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1374 end = LittleLong(pinmodel->ofs_end);
1375 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1376 Host_Error ("%s is not a valid model", loadmodel->name);
1377 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1378 Host_Error ("%s is not a valid model", loadmodel->name);
1379 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1380 Host_Error ("%s is not a valid model", loadmodel->name);
1381 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1382 Host_Error ("%s is not a valid model", loadmodel->name);
1383 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1384 Host_Error ("%s is not a valid model", loadmodel->name);
1386 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1387 numxyz = LittleLong(pinmodel->num_xyz);
1388 numst = LittleLong(pinmodel->num_st);
1389 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1390 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1391 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1392 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1393 skinwidth = LittleLong(pinmodel->skinwidth);
1394 skinheight = LittleLong(pinmodel->skinheight);
1395 iskinwidth = 1.0f / skinwidth;
1396 iskinheight = 1.0f / skinheight;
1398 loadmodel->num_surfaces = 1;
1399 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1400 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]));
1401 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1402 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1403 loadmodel->sortedmodelsurfaces[0] = 0;
1404 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1405 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1406 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1407 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1409 loadmodel->synctype = ST_RAND;
1412 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1413 skinfiles = Mod_LoadSkinFiles();
1416 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1417 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1418 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1419 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1420 Mod_FreeSkinFiles(skinfiles);
1422 else if (loadmodel->numskins)
1424 // skins found (most likely not a player model)
1425 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1426 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1427 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1428 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1429 Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
1433 // no skins (most likely a player model)
1434 loadmodel->numskins = 1;
1435 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1436 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1437 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1438 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1441 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1442 for (i = 0;i < loadmodel->numskins;i++)
1444 loadmodel->skinscenes[i].firstframe = i;
1445 loadmodel->skinscenes[i].framecount = 1;
1446 loadmodel->skinscenes[i].loop = true;
1447 loadmodel->skinscenes[i].framerate = 10;
1450 // load the triangles and stvert data
1451 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1452 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1453 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1454 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1455 // swap the triangle list
1456 loadmodel->surfmesh.num_vertices = 0;
1457 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1459 for (j = 0;j < 3;j++)
1461 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1462 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1465 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1470 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1473 hashindex = (xyz * 256 + st) & 65535;
1474 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1475 if (hash->xyz == xyz && hash->st == st)
1479 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1482 hash->next = md2verthash[hashindex];
1483 md2verthash[hashindex] = hash;
1485 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1489 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1490 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));
1491 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1492 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1493 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1496 hash = md2verthashdata + i;
1497 vertremap[i] = hash->xyz;
1498 sts = LittleShort(inst[hash->st*2+0]);
1499 stt = LittleShort(inst[hash->st*2+1]);
1500 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1502 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1506 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1507 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1510 Mem_Free(md2verthash);
1511 Mem_Free(md2verthashdata);
1513 // generate ushort elements array if possible
1514 if (loadmodel->surfmesh.num_vertices <= 65536)
1515 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1516 if (loadmodel->surfmesh.data_element3s)
1517 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1518 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1521 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1522 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1527 pinframe = (md2frame_t *)datapointer;
1528 datapointer += sizeof(md2frame_t);
1529 // store the frame scale/translate into the appropriate array
1530 for (j = 0;j < 3;j++)
1532 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1533 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1535 // convert the vertices
1536 v = (trivertx_t *)datapointer;
1537 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1538 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1539 out[k] = v[vertremap[k]];
1540 datapointer += numxyz * sizeof(trivertx_t);
1542 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1543 loadmodel->animscenes[i].firstframe = i;
1544 loadmodel->animscenes[i].framecount = 1;
1545 loadmodel->animscenes[i].framerate = 10;
1546 loadmodel->animscenes[i].loop = true;
1549 Mem_Free(vertremap);
1551 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1552 Mod_Alias_CalculateBoundingBox();
1553 Mod_Alias_MorphMesh_CompileFrames();
1555 surface = loadmodel->data_surfaces;
1556 surface->texture = loadmodel->data_textures;
1557 surface->num_firsttriangle = 0;
1558 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1559 surface->num_firstvertex = 0;
1560 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1562 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1565 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1567 int i, j, k, version, meshvertices, meshtriangles;
1568 unsigned char *data;
1569 msurface_t *surface;
1570 md3modelheader_t *pinmodel;
1571 md3frameinfo_t *pinframe;
1574 skinfile_t *skinfiles;
1576 pinmodel = (md3modelheader_t *)buffer;
1578 if (memcmp(pinmodel->identifier, "IDP3", 4))
1579 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1580 version = LittleLong (pinmodel->version);
1581 if (version != MD3VERSION)
1582 Host_Error ("%s has wrong version number (%i should be %i)",
1583 loadmodel->name, version, MD3VERSION);
1585 skinfiles = Mod_LoadSkinFiles();
1586 if (loadmodel->numskins < 1)
1587 loadmodel->numskins = 1;
1589 loadmodel->modeldatatypestring = "MD3";
1591 loadmodel->type = mod_alias;
1592 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1593 loadmodel->DrawSky = NULL;
1594 loadmodel->DrawAddWaterPlanes = NULL;
1595 loadmodel->Draw = R_Q1BSP_Draw;
1596 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1597 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1598 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1599 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1600 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1601 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1602 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1603 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1604 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1605 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1606 loadmodel->PointSuperContents = NULL;
1607 loadmodel->synctype = ST_RAND;
1608 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1609 i = LittleLong (pinmodel->flags);
1610 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1612 // set up some global info about the model
1613 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1614 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1616 // make skinscenes for the skins (no groups)
1617 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1618 for (i = 0;i < loadmodel->numskins;i++)
1620 loadmodel->skinscenes[i].firstframe = i;
1621 loadmodel->skinscenes[i].framecount = 1;
1622 loadmodel->skinscenes[i].loop = true;
1623 loadmodel->skinscenes[i].framerate = 10;
1627 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1628 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1630 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1631 loadmodel->animscenes[i].firstframe = i;
1632 loadmodel->animscenes[i].framecount = 1;
1633 loadmodel->animscenes[i].framerate = 10;
1634 loadmodel->animscenes[i].loop = true;
1638 loadmodel->num_tagframes = loadmodel->numframes;
1639 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1640 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1641 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1643 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1644 for (j = 0;j < 9;j++)
1645 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1646 for (j = 0;j < 3;j++)
1647 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1648 //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);
1654 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)))
1656 if (memcmp(pinmesh->identifier, "IDP3", 4))
1657 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1658 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1659 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1660 meshvertices += LittleLong(pinmesh->num_vertices);
1661 meshtriangles += LittleLong(pinmesh->num_triangles);
1664 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1665 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1666 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1667 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));
1668 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1669 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1670 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1671 loadmodel->surfmesh.num_vertices = meshvertices;
1672 loadmodel->surfmesh.num_triangles = meshtriangles;
1673 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1674 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1675 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1676 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1677 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1678 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1679 if (meshvertices <= 65536)
1680 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1684 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)))
1686 if (memcmp(pinmesh->identifier, "IDP3", 4))
1687 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1688 loadmodel->sortedmodelsurfaces[i] = i;
1689 surface = loadmodel->data_surfaces + i;
1690 surface->texture = loadmodel->data_textures + i;
1691 surface->num_firsttriangle = meshtriangles;
1692 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1693 surface->num_firstvertex = meshvertices;
1694 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1695 meshvertices += surface->num_vertices;
1696 meshtriangles += surface->num_triangles;
1698 for (j = 0;j < surface->num_triangles * 3;j++)
1699 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1700 for (j = 0;j < surface->num_vertices;j++)
1702 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1703 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1705 for (j = 0;j < loadmodel->numframes;j++)
1707 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1708 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1709 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1711 out->origin[0] = LittleShort(in->origin[0]);
1712 out->origin[1] = LittleShort(in->origin[1]);
1713 out->origin[2] = LittleShort(in->origin[2]);
1714 out->pitch = in->pitch;
1719 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1721 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1723 if (loadmodel->surfmesh.data_element3s)
1724 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1725 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1726 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1727 Mod_Alias_MorphMesh_CompileFrames();
1728 Mod_Alias_CalculateBoundingBox();
1729 Mod_FreeSkinFiles(skinfiles);
1730 Mod_MakeSortedSurfaces(loadmodel);
1732 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1733 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1736 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1738 zymtype1header_t *pinmodel, *pheader;
1739 unsigned char *pbase;
1740 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1741 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose, f, biggestorigin, tempvec[3], modelscale;
1742 zymvertex_t *verts, *vertdata;
1746 skinfile_t *skinfiles;
1747 unsigned char *data;
1748 msurface_t *surface;
1750 pinmodel = (zymtype1header_t *)buffer;
1751 pbase = (unsigned char *)buffer;
1752 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1753 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1754 if (BigLong(pinmodel->type) != 1)
1755 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1757 loadmodel->modeldatatypestring = "ZYM";
1759 loadmodel->type = mod_alias;
1760 loadmodel->synctype = ST_RAND;
1764 pheader->type = BigLong(pinmodel->type);
1765 pheader->filesize = BigLong(pinmodel->filesize);
1766 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1767 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1768 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1769 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1770 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1771 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1772 pheader->radius = BigFloat(pinmodel->radius);
1773 pheader->numverts = BigLong(pinmodel->numverts);
1774 pheader->numtris = BigLong(pinmodel->numtris);
1775 pheader->numshaders = BigLong(pinmodel->numshaders);
1776 pheader->numbones = BigLong(pinmodel->numbones);
1777 pheader->numscenes = BigLong(pinmodel->numscenes);
1778 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1779 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1780 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1781 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1782 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1783 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1784 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1785 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1786 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1787 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1788 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1789 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1790 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1791 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1792 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1793 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1794 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1795 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1797 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1799 Con_Printf("%s has no geometry\n", loadmodel->name);
1802 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1804 Con_Printf("%s has no animations\n", loadmodel->name);
1808 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1809 loadmodel->DrawSky = NULL;
1810 loadmodel->DrawAddWaterPlanes = NULL;
1811 loadmodel->Draw = R_Q1BSP_Draw;
1812 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1813 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1814 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1815 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1816 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1817 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1818 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1819 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1820 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1821 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1822 loadmodel->PointSuperContents = NULL;
1824 loadmodel->numframes = pheader->numscenes;
1825 loadmodel->num_surfaces = pheader->numshaders;
1827 skinfiles = Mod_LoadSkinFiles();
1828 if (loadmodel->numskins < 1)
1829 loadmodel->numskins = 1;
1831 // make skinscenes for the skins (no groups)
1832 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1833 for (i = 0;i < loadmodel->numskins;i++)
1835 loadmodel->skinscenes[i].firstframe = i;
1836 loadmodel->skinscenes[i].framecount = 1;
1837 loadmodel->skinscenes[i].loop = true;
1838 loadmodel->skinscenes[i].framerate = 10;
1842 modelradius = pheader->radius;
1843 for (i = 0;i < 3;i++)
1845 loadmodel->normalmins[i] = pheader->mins[i];
1846 loadmodel->normalmaxs[i] = pheader->maxs[i];
1847 loadmodel->rotatedmins[i] = -modelradius;
1848 loadmodel->rotatedmaxs[i] = modelradius;
1850 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1851 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1852 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1853 if (loadmodel->yawmaxs[0] > modelradius)
1854 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1855 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1856 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1857 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1858 loadmodel->radius = modelradius;
1859 loadmodel->radius2 = modelradius * modelradius;
1861 // go through the lumps, swapping things
1863 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1864 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1865 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1866 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1867 for (i = 0;i < pheader->numscenes;i++)
1869 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1870 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1871 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1872 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1873 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1874 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1875 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1876 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1877 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1878 if (loadmodel->animscenes[i].framerate < 0)
1879 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1883 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1884 loadmodel->num_bones = pheader->numbones;
1885 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1886 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1887 for (i = 0;i < pheader->numbones;i++)
1889 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1890 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1891 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1892 if (loadmodel->data_bones[i].parent >= i)
1893 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1896 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1897 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1898 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1899 for (i = 0;i < pheader->numverts;i++)
1901 vertbonecounts[i] = BigLong(bonecount[i]);
1902 if (vertbonecounts[i] != 1)
1903 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1906 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1908 meshvertices = pheader->numverts;
1909 meshtriangles = pheader->numtris;
1911 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1912 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1913 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1914 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]));
1915 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1916 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1917 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1918 loadmodel->surfmesh.num_vertices = meshvertices;
1919 loadmodel->surfmesh.num_triangles = meshtriangles;
1920 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1921 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1922 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1923 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1924 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1925 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1926 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1927 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1928 loadmodel->surfmesh.num_blends = 0;
1929 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
1930 if (loadmodel->surfmesh.num_vertices <= 65536)
1931 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1932 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
1933 loadmodel->surfmesh.data_blendweights = NULL;
1935 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1936 poses = (float *) (pheader->lump_poses.start + pbase);
1937 // figure out scale of model from root bone, for compatibility with old zmodel versions
1938 tempvec[0] = BigFloat(poses[0]);
1939 tempvec[1] = BigFloat(poses[1]);
1940 tempvec[2] = BigFloat(poses[2]);
1941 modelscale = VectorLength(tempvec);
1943 for (i = 0;i < loadmodel->num_bones * numposes * 12;i++)
1945 f = fabs(BigFloat(poses[i]));
1946 biggestorigin = max(biggestorigin, f);
1948 loadmodel->num_posescale = biggestorigin / 32767.0f;
1949 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
1950 for (i = 0;i < numposes;i++)
1952 const float *frameposes = (float *) (pheader->lump_poses.start + pbase) + 12*i*loadmodel->num_bones;
1953 for (j = 0;j < loadmodel->num_bones;j++)
1956 matrix4x4_t posematrix;
1957 for (k = 0;k < 12;k++)
1958 pose[k] = BigFloat(frameposes[j*12+k]);
1959 //if (j < loadmodel->num_bones)
1960 // 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));
1961 // scale child bones to match the root scale
1962 if (loadmodel->data_bones[j].parent >= 0)
1964 pose[3] *= modelscale;
1965 pose[7] *= modelscale;
1966 pose[11] *= modelscale;
1968 // normalize rotation matrix
1969 VectorNormalize(pose + 0);
1970 VectorNormalize(pose + 4);
1971 VectorNormalize(pose + 8);
1972 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
1973 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
1977 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1978 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1979 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1980 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1981 // (converting from weight-blending skeletal animation to
1982 // deformation-based skeletal animation)
1983 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1984 for (i = 0;i < loadmodel->num_bones;i++)
1987 for (k = 0;k < 12;k++)
1988 m[k] = BigFloat(poses[i*12+k]);
1989 if (loadmodel->data_bones[i].parent >= 0)
1990 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1992 for (k = 0;k < 12;k++)
1993 bonepose[12*i+k] = m[k];
1995 for (j = 0;j < pheader->numverts;j++)
1997 // this format really should have had a per vertexweight weight value...
1998 // but since it does not, the weighting is completely ignored and
1999 // only one weight is allowed per vertex
2000 int boneindex = BigLong(vertdata[j].bonenum);
2001 const float *m = bonepose + 12 * boneindex;
2002 float relativeorigin[3];
2003 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
2004 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
2005 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
2006 // transform the vertex bone weight into the base mesh
2007 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
2008 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
2009 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
2010 // store the weight as the primary weight on this vertex
2011 loadmodel->surfmesh.blends[j] = boneindex;
2014 // normals and tangents are calculated after elements are loaded
2016 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
2017 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
2018 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
2019 for (i = 0;i < pheader->numverts;i++)
2021 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
2022 // flip T coordinate for OpenGL
2023 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
2026 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
2027 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
2028 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
2030 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
2031 //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)
2032 // byteswap, validate, and swap winding order of tris
2033 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
2034 if (pheader->lump_render.length != count)
2035 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
2036 renderlist = (int *) (pheader->lump_render.start + pbase);
2037 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
2039 for (i = 0;i < loadmodel->num_surfaces;i++)
2041 int firstvertex, lastvertex;
2042 if (renderlist >= renderlistend)
2043 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2044 count = BigLong(*renderlist);renderlist++;
2045 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
2046 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2048 loadmodel->sortedmodelsurfaces[i] = i;
2049 surface = loadmodel->data_surfaces + i;
2050 surface->texture = loadmodel->data_textures + i;
2051 surface->num_firsttriangle = meshtriangles;
2052 surface->num_triangles = count;
2053 meshtriangles += surface->num_triangles;
2055 // load the elements
2056 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2057 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
2059 outelements[j*3+2] = BigLong(renderlist[0]);
2060 outelements[j*3+1] = BigLong(renderlist[1]);
2061 outelements[j*3+0] = BigLong(renderlist[2]);
2063 // validate the elements and find the used vertex range
2064 firstvertex = meshvertices;
2066 for (j = 0;j < surface->num_triangles * 3;j++)
2068 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
2069 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
2070 firstvertex = min(firstvertex, outelements[j]);
2071 lastvertex = max(lastvertex, outelements[j]);
2073 surface->num_firstvertex = firstvertex;
2074 surface->num_vertices = lastvertex + 1 - firstvertex;
2076 // since zym models do not have named sections, reuse their shader
2077 // name as the section name
2078 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
2079 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
2081 Mod_FreeSkinFiles(skinfiles);
2082 Mem_Free(vertbonecounts);
2084 Mod_MakeSortedSurfaces(loadmodel);
2086 // compute all the mesh information that was not loaded from the file
2087 if (loadmodel->surfmesh.data_element3s)
2088 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2089 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2090 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2091 Mod_BuildBaseBonePoses();
2092 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2093 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);
2094 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2096 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2099 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2101 dpmheader_t *pheader;
2105 unsigned char *pbase;
2106 int i, j, k, meshvertices, meshtriangles;
2107 skinfile_t *skinfiles;
2108 unsigned char *data;
2110 float biggestorigin, tempvec[3], modelscale;
2114 pheader = (dpmheader_t *)buffer;
2115 pbase = (unsigned char *)buffer;
2116 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2117 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2118 if (BigLong(pheader->type) != 2)
2119 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2121 loadmodel->modeldatatypestring = "DPM";
2123 loadmodel->type = mod_alias;
2124 loadmodel->synctype = ST_RAND;
2127 pheader->type = BigLong(pheader->type);
2128 pheader->filesize = BigLong(pheader->filesize);
2129 pheader->mins[0] = BigFloat(pheader->mins[0]);
2130 pheader->mins[1] = BigFloat(pheader->mins[1]);
2131 pheader->mins[2] = BigFloat(pheader->mins[2]);
2132 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2133 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2134 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2135 pheader->yawradius = BigFloat(pheader->yawradius);
2136 pheader->allradius = BigFloat(pheader->allradius);
2137 pheader->num_bones = BigLong(pheader->num_bones);
2138 pheader->num_meshs = BigLong(pheader->num_meshs);
2139 pheader->num_frames = BigLong(pheader->num_frames);
2140 pheader->ofs_bones = BigLong(pheader->ofs_bones);
2141 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2142 pheader->ofs_frames = BigLong(pheader->ofs_frames);
2144 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2146 Con_Printf("%s has no geometry\n", loadmodel->name);
2149 if (pheader->num_frames < 1)
2151 Con_Printf("%s has no frames\n", loadmodel->name);
2155 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2156 loadmodel->DrawSky = NULL;
2157 loadmodel->DrawAddWaterPlanes = NULL;
2158 loadmodel->Draw = R_Q1BSP_Draw;
2159 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2160 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2161 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2162 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2163 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2164 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2165 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2166 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2167 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2168 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2169 loadmodel->PointSuperContents = NULL;
2172 for (i = 0;i < 3;i++)
2174 loadmodel->normalmins[i] = pheader->mins[i];
2175 loadmodel->normalmaxs[i] = pheader->maxs[i];
2176 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2177 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2178 loadmodel->rotatedmins[i] = -pheader->allradius;
2179 loadmodel->rotatedmaxs[i] = pheader->allradius;
2181 loadmodel->radius = pheader->allradius;
2182 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2184 // load external .skin files if present
2185 skinfiles = Mod_LoadSkinFiles();
2186 if (loadmodel->numskins < 1)
2187 loadmodel->numskins = 1;
2192 // gather combined statistics from the meshes
2193 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2194 for (i = 0;i < (int)pheader->num_meshs;i++)
2196 int numverts = BigLong(dpmmesh->num_verts);
2197 meshvertices += numverts;
2198 meshtriangles += BigLong(dpmmesh->num_tris);
2202 loadmodel->numframes = pheader->num_frames;
2203 loadmodel->num_bones = pheader->num_bones;
2204 loadmodel->num_poses = loadmodel->numframes;
2205 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2206 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2207 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2208 // do most allocations as one merged chunk
2209 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));
2210 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2211 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2212 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2213 loadmodel->surfmesh.num_vertices = meshvertices;
2214 loadmodel->surfmesh.num_triangles = meshtriangles;
2215 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2216 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2217 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2218 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2219 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2220 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2221 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2222 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2223 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2224 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2225 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2226 loadmodel->surfmesh.num_blends = 0;
2227 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2228 if (meshvertices <= 65536)
2229 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2230 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2231 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
2233 for (i = 0;i < loadmodel->numskins;i++)
2235 loadmodel->skinscenes[i].firstframe = i;
2236 loadmodel->skinscenes[i].framecount = 1;
2237 loadmodel->skinscenes[i].loop = true;
2238 loadmodel->skinscenes[i].framerate = 10;
2241 // load the bone info
2242 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2243 for (i = 0;i < loadmodel->num_bones;i++)
2245 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2246 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2247 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2248 if (loadmodel->data_bones[i].parent >= i)
2249 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2253 frames = (dpmframe_t *) (pbase + pheader->ofs_frames);
2254 // figure out scale of model from root bone, for compatibility with old dpmodel versions
2255 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2256 tempvec[0] = BigFloat(poses[0]);
2257 tempvec[1] = BigFloat(poses[1]);
2258 tempvec[2] = BigFloat(poses[2]);
2259 modelscale = VectorLength(tempvec);
2261 for (i = 0;i < loadmodel->numframes;i++)
2263 memcpy(loadmodel->animscenes[i].name, frames[i].name, sizeof(frames[i].name));
2264 loadmodel->animscenes[i].firstframe = i;
2265 loadmodel->animscenes[i].framecount = 1;
2266 loadmodel->animscenes[i].loop = true;
2267 loadmodel->animscenes[i].framerate = 10;
2268 // load the bone poses for this frame
2269 poses = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2270 for (j = 0;j < loadmodel->num_bones*12;j++)
2272 f = fabs(BigFloat(poses[j]));
2273 biggestorigin = max(biggestorigin, f);
2275 // stuff not processed here: mins, maxs, yawradius, allradius
2277 loadmodel->num_posescale = biggestorigin / 32767.0f;
2278 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2279 for (i = 0;i < loadmodel->numframes;i++)
2281 const float *frameposes = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2282 for (j = 0;j < loadmodel->num_bones;j++)
2285 matrix4x4_t posematrix;
2286 for (k = 0;k < 12;k++)
2287 pose[k] = BigFloat(frameposes[j*12+k]);
2288 // scale child bones to match the root scale
2289 if (loadmodel->data_bones[j].parent >= 0)
2291 pose[3] *= modelscale;
2292 pose[7] *= modelscale;
2293 pose[11] *= modelscale;
2295 // normalize rotation matrix
2296 VectorNormalize(pose + 0);
2297 VectorNormalize(pose + 4);
2298 VectorNormalize(pose + 8);
2299 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2300 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
2304 // load the meshes now
2305 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2308 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2309 // (converting from weight-blending skeletal animation to
2310 // deformation-based skeletal animation)
2311 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2312 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2313 for (i = 0;i < loadmodel->num_bones;i++)
2316 for (k = 0;k < 12;k++)
2317 m[k] = BigFloat(poses[i*12+k]);
2318 if (loadmodel->data_bones[i].parent >= 0)
2319 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2321 for (k = 0;k < 12;k++)
2322 bonepose[12*i+k] = m[k];
2324 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2326 const int *inelements;
2328 const float *intexcoord;
2329 msurface_t *surface;
2331 loadmodel->sortedmodelsurfaces[i] = i;
2332 surface = loadmodel->data_surfaces + i;
2333 surface->texture = loadmodel->data_textures + i;
2334 surface->num_firsttriangle = meshtriangles;
2335 surface->num_triangles = BigLong(dpmmesh->num_tris);
2336 surface->num_firstvertex = meshvertices;
2337 surface->num_vertices = BigLong(dpmmesh->num_verts);
2338 meshvertices += surface->num_vertices;
2339 meshtriangles += surface->num_triangles;
2341 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2342 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2343 for (j = 0;j < surface->num_triangles;j++)
2345 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2346 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2347 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2348 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2353 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2354 for (j = 0;j < surface->num_vertices*2;j++)
2355 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2357 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2358 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2360 int weightindex[4] = { 0, 0, 0, 0 };
2361 float weightinfluence[4] = { 0, 0, 0, 0 };
2363 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2364 data += sizeof(dpmvertex_t);
2365 for (k = 0;k < numweights;k++)
2367 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2368 int boneindex = BigLong(vert->bonenum);
2369 const float *m = bonepose + 12 * boneindex;
2370 float influence = BigFloat(vert->influence);
2371 float relativeorigin[3], relativenormal[3];
2372 relativeorigin[0] = BigFloat(vert->origin[0]);
2373 relativeorigin[1] = BigFloat(vert->origin[1]);
2374 relativeorigin[2] = BigFloat(vert->origin[2]);
2375 relativenormal[0] = BigFloat(vert->normal[0]);
2376 relativenormal[1] = BigFloat(vert->normal[1]);
2377 relativenormal[2] = BigFloat(vert->normal[2]);
2378 // blend the vertex bone weights into the base mesh
2379 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2380 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2381 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2382 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2383 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2384 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2387 // store the first (and often only) weight
2388 weightinfluence[0] = influence;
2389 weightindex[0] = boneindex;
2393 // sort the new weight into this vertex's weight table
2394 // (which only accepts up to 4 bones per vertex)
2395 for (l = 0;l < 4;l++)
2397 if (weightinfluence[l] < influence)
2399 // move weaker influence weights out of the way first
2401 for (l2 = 3;l2 > l;l2--)
2403 weightinfluence[l2] = weightinfluence[l2-1];
2404 weightindex[l2] = weightindex[l2-1];
2406 // store the new weight
2407 weightinfluence[l] = influence;
2408 weightindex[l] = boneindex;
2413 data += sizeof(dpmbonevert_t);
2415 loadmodel->surfmesh.blends[j] = Mod_Skeletal_AddBlend(loadmodel, weightindex, weightinfluence);
2418 // since dpm models do not have named sections, reuse their shader name as the section name
2419 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2421 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2423 if (loadmodel->surfmesh.num_blends < meshvertices)
2424 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2426 Mod_FreeSkinFiles(skinfiles);
2427 Mod_MakeSortedSurfaces(loadmodel);
2429 // compute all the mesh information that was not loaded from the file
2430 if (loadmodel->surfmesh.data_element3s)
2431 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2432 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2433 Mod_BuildBaseBonePoses();
2434 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);
2435 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2437 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2440 // no idea why PSK/PSA files contain weird quaternions but they do...
2441 #define PSKQUATNEGATIONS
2442 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2444 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2445 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2446 fs_offset_t filesize;
2451 pskboneinfo_t *bones;
2452 pskrawweights_t *rawweights;
2453 //pskboneinfo_t *animbones;
2454 pskaniminfo_t *anims;
2455 pskanimkeys_t *animkeys;
2456 void *animfilebuffer, *animbuffer, *animbufferend;
2457 unsigned char *data;
2459 skinfile_t *skinfiles;
2460 char animname[MAX_QPATH];
2462 float biggestorigin;
2464 pchunk = (pskchunk_t *)buffer;
2465 if (strcmp(pchunk->id, "ACTRHEAD"))
2466 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2468 loadmodel->modeldatatypestring = "PSK";
2470 loadmodel->type = mod_alias;
2471 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2472 loadmodel->DrawSky = NULL;
2473 loadmodel->DrawAddWaterPlanes = NULL;
2474 loadmodel->Draw = R_Q1BSP_Draw;
2475 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2476 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2477 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2478 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2479 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2480 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2481 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2482 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2483 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2484 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2485 loadmodel->PointSuperContents = NULL;
2486 loadmodel->synctype = ST_RAND;
2488 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2489 strlcat(animname, ".psa", sizeof(animname));
2490 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2491 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2492 if (animbuffer == NULL)
2493 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2512 while (buffer < bufferend)
2514 pchunk = (pskchunk_t *)buffer;
2515 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2516 version = LittleLong(pchunk->version);
2517 recordsize = LittleLong(pchunk->recordsize);
2518 numrecords = LittleLong(pchunk->numrecords);
2519 if (developer_extra.integer)
2520 Con_DPrintf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2521 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2522 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);
2523 if (!strcmp(pchunk->id, "ACTRHEAD"))
2527 else if (!strcmp(pchunk->id, "PNTS0000"))
2530 if (recordsize != sizeof(*p))
2531 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2532 // byteswap in place and keep the pointer
2533 numpnts = numrecords;
2534 pnts = (pskpnts_t *)buffer;
2535 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2537 p->origin[0] = LittleFloat(p->origin[0]);
2538 p->origin[1] = LittleFloat(p->origin[1]);
2539 p->origin[2] = LittleFloat(p->origin[2]);
2543 else if (!strcmp(pchunk->id, "VTXW0000"))
2546 if (recordsize != sizeof(*p))
2547 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2548 // byteswap in place and keep the pointer
2549 numvtxw = numrecords;
2550 vtxw = (pskvtxw_t *)buffer;
2551 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2553 p->pntsindex = LittleShort(p->pntsindex);
2554 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2555 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2556 if (p->pntsindex >= numpnts)
2558 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2564 else if (!strcmp(pchunk->id, "FACE0000"))
2567 if (recordsize != sizeof(*p))
2568 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2569 // byteswap in place and keep the pointer
2570 numfaces = numrecords;
2571 faces = (pskface_t *)buffer;
2572 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2574 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2575 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2576 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2577 p->group = LittleLong(p->group);
2578 if (p->vtxwindex[0] >= numvtxw)
2580 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2581 p->vtxwindex[0] = 0;
2583 if (p->vtxwindex[1] >= numvtxw)
2585 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2586 p->vtxwindex[1] = 0;
2588 if (p->vtxwindex[2] >= numvtxw)
2590 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2591 p->vtxwindex[2] = 0;
2596 else if (!strcmp(pchunk->id, "MATT0000"))
2599 if (recordsize != sizeof(*p))
2600 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2601 // byteswap in place and keep the pointer
2602 nummatts = numrecords;
2603 matts = (pskmatt_t *)buffer;
2604 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2610 else if (!strcmp(pchunk->id, "REFSKELT"))
2613 if (recordsize != sizeof(*p))
2614 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2615 // byteswap in place and keep the pointer
2616 numbones = numrecords;
2617 bones = (pskboneinfo_t *)buffer;
2618 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2620 p->numchildren = LittleLong(p->numchildren);
2621 p->parent = LittleLong(p->parent);
2622 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2623 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2624 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2625 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2626 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2627 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2628 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2629 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2630 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2631 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2632 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2633 #ifdef PSKQUATNEGATIONS
2636 p->basepose.quat[0] *= -1;
2637 p->basepose.quat[1] *= -1;
2638 p->basepose.quat[2] *= -1;
2642 p->basepose.quat[0] *= 1;
2643 p->basepose.quat[1] *= -1;
2644 p->basepose.quat[2] *= 1;
2647 if (p->parent < 0 || p->parent >= numbones)
2649 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2655 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2658 if (recordsize != sizeof(*p))
2659 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2660 // byteswap in place and keep the pointer
2661 numrawweights = numrecords;
2662 rawweights = (pskrawweights_t *)buffer;
2663 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2665 p->weight = LittleFloat(p->weight);
2666 p->pntsindex = LittleLong(p->pntsindex);
2667 p->boneindex = LittleLong(p->boneindex);
2668 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2670 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2673 if (p->boneindex < 0 || p->boneindex >= numbones)
2675 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2683 while (animbuffer < animbufferend)
2685 pchunk = (pskchunk_t *)animbuffer;
2686 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2687 version = LittleLong(pchunk->version);
2688 recordsize = LittleLong(pchunk->recordsize);
2689 numrecords = LittleLong(pchunk->numrecords);
2690 if (developer_extra.integer)
2691 Con_DPrintf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2692 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2693 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);
2694 if (!strcmp(pchunk->id, "ANIMHEAD"))
2698 else if (!strcmp(pchunk->id, "BONENAMES"))
2701 if (recordsize != sizeof(*p))
2702 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2703 // byteswap in place and keep the pointer
2704 numanimbones = numrecords;
2705 //animbones = (pskboneinfo_t *)animbuffer;
2706 // NOTE: supposedly psa does not need to match the psk model, the
2707 // bones missing from the psa would simply use their base
2708 // positions from the psk, but this is hard for me to implement
2709 // and people can easily make animations that match.
2710 if (numanimbones != numbones)
2711 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2712 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2714 p->numchildren = LittleLong(p->numchildren);
2715 p->parent = LittleLong(p->parent);
2716 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2717 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2718 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2719 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2720 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2721 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2722 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2723 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2724 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2725 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2726 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2727 #ifdef PSKQUATNEGATIONS
2730 p->basepose.quat[0] *= -1;
2731 p->basepose.quat[1] *= -1;
2732 p->basepose.quat[2] *= -1;
2736 p->basepose.quat[0] *= 1;
2737 p->basepose.quat[1] *= -1;
2738 p->basepose.quat[2] *= 1;
2741 if (p->parent < 0 || p->parent >= numanimbones)
2743 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2746 // check that bones are the same as in the base
2747 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2748 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2752 else if (!strcmp(pchunk->id, "ANIMINFO"))
2755 if (recordsize != sizeof(*p))
2756 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2757 // byteswap in place and keep the pointer
2758 numanims = numrecords;
2759 anims = (pskaniminfo_t *)animbuffer;
2760 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2762 p->numbones = LittleLong(p->numbones);
2763 p->playtime = LittleFloat(p->playtime);
2764 p->fps = LittleFloat(p->fps);
2765 p->firstframe = LittleLong(p->firstframe);
2766 p->numframes = LittleLong(p->numframes);
2767 if (p->numbones != numbones)
2768 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2772 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2775 if (recordsize != sizeof(*p))
2776 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2777 numanimkeys = numrecords;
2778 animkeys = (pskanimkeys_t *)animbuffer;
2779 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2781 p->origin[0] = LittleFloat(p->origin[0]);
2782 p->origin[1] = LittleFloat(p->origin[1]);
2783 p->origin[2] = LittleFloat(p->origin[2]);
2784 p->quat[0] = LittleFloat(p->quat[0]);
2785 p->quat[1] = LittleFloat(p->quat[1]);
2786 p->quat[2] = LittleFloat(p->quat[2]);
2787 p->quat[3] = LittleFloat(p->quat[3]);
2788 p->frametime = LittleFloat(p->frametime);
2789 #ifdef PSKQUATNEGATIONS
2790 if (index % numbones)
2805 // TODO: allocate bonepose stuff
2808 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2811 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2812 Host_Error("%s: missing required chunks", loadmodel->name);
2814 loadmodel->numframes = 0;
2815 for (index = 0;index < numanims;index++)
2816 loadmodel->numframes += anims[index].numframes;
2818 if (numanimkeys != numbones * loadmodel->numframes)
2819 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2821 meshvertices = numvtxw;
2822 meshtriangles = numfaces;
2824 // load external .skin files if present
2825 skinfiles = Mod_LoadSkinFiles();
2826 if (loadmodel->numskins < 1)
2827 loadmodel->numskins = 1;
2828 loadmodel->num_bones = numbones;
2829 loadmodel->num_poses = loadmodel->numframes;
2830 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2831 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2832 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2833 loadmodel->surfmesh.num_vertices = meshvertices;
2834 loadmodel->surfmesh.num_triangles = meshtriangles;
2835 // do most allocations as one merged chunk
2836 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);
2837 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2838 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2839 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2840 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2841 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2842 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2843 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2844 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2845 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2846 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2847 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2848 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2849 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2850 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2851 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2852 loadmodel->surfmesh.num_blends = 0;
2853 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2854 if (loadmodel->surfmesh.num_vertices <= 65536)
2855 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2856 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2857 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(blendweights_t));
2859 for (i = 0;i < loadmodel->numskins;i++)
2861 loadmodel->skinscenes[i].firstframe = i;
2862 loadmodel->skinscenes[i].framecount = 1;
2863 loadmodel->skinscenes[i].loop = true;
2864 loadmodel->skinscenes[i].framerate = 10;
2868 for (index = 0, i = 0;index < nummatts;index++)
2870 // since psk models do not have named sections, reuse their shader name as the section name
2871 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2872 loadmodel->sortedmodelsurfaces[index] = index;
2873 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2874 loadmodel->data_surfaces[index].num_firstvertex = 0;
2875 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2878 // copy over the vertex locations and texcoords
2879 for (index = 0;index < numvtxw;index++)
2881 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2882 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2883 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2884 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2885 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2888 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2889 for (index = 0;index < numfaces;index++)
2890 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2891 for (index = 0, i = 0;index < nummatts;index++)
2893 loadmodel->data_surfaces[index].num_firsttriangle = i;
2894 i += loadmodel->data_surfaces[index].num_triangles;
2895 loadmodel->data_surfaces[index].num_triangles = 0;
2897 for (index = 0;index < numfaces;index++)
2899 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2900 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2901 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2902 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2905 // copy over the bones
2906 for (index = 0;index < numbones;index++)
2908 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2909 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2910 if (loadmodel->data_bones[index].parent >= index)
2911 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2914 // sort the psk point weights into the vertex weight tables
2915 // (which only accept up to 4 bones per vertex)
2916 for (index = 0;index < numvtxw;index++)
2918 int weightindex[4] = { 0, 0, 0, 0 };
2919 float weightinfluence[4] = { 0, 0, 0, 0 };
2921 for (j = 0;j < numrawweights;j++)
2923 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2925 int boneindex = rawweights[j].boneindex;
2926 float influence = rawweights[j].weight;
2927 for (l = 0;l < 4;l++)
2929 if (weightinfluence[l] < influence)
2931 // move lower influence weights out of the way first
2933 for (l2 = 3;l2 > l;l2--)
2935 weightinfluence[l2] = weightinfluence[l2-1];
2936 weightindex[l2] = weightindex[l2-1];
2938 // store the new weight
2939 weightinfluence[l] = influence;
2940 weightindex[l] = boneindex;
2946 loadmodel->surfmesh.blends[index] = Mod_Skeletal_AddBlend(loadmodel, weightindex, weightinfluence);
2948 if (loadmodel->surfmesh.num_blends < loadmodel->surfmesh.num_vertices)
2949 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2951 // set up the animscenes based on the anims
2952 for (index = 0, i = 0;index < numanims;index++)
2954 for (j = 0;j < anims[index].numframes;j++, i++)
2956 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2957 loadmodel->animscenes[i].firstframe = i;
2958 loadmodel->animscenes[i].framecount = 1;
2959 loadmodel->animscenes[i].loop = true;
2960 loadmodel->animscenes[i].framerate = 10;
2964 // calculate the scaling value for bone origins so they can be compressed to short
2966 for (index = 0;index < numanimkeys;index++)
2968 pskanimkeys_t *k = animkeys + index;
2969 biggestorigin = max(biggestorigin, fabs(k->origin[0]));
2970 biggestorigin = max(biggestorigin, fabs(k->origin[1]));
2971 biggestorigin = max(biggestorigin, fabs(k->origin[2]));
2973 loadmodel->num_posescale = biggestorigin / 32767.0f;
2974 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2976 // load the poses from the animkeys
2977 for (index = 0;index < numanimkeys;index++)
2979 pskanimkeys_t *k = animkeys + index;
2981 Vector4Copy(k->quat, quat);
2983 Vector4Negate(quat, quat);
2984 Vector4Normalize2(quat, quat);
2985 // compress poses to the short[6] format for longterm storage
2986 loadmodel->data_poses6s[index*6+0] = k->origin[0] * loadmodel->num_poseinvscale;
2987 loadmodel->data_poses6s[index*6+1] = k->origin[1] * loadmodel->num_poseinvscale;
2988 loadmodel->data_poses6s[index*6+2] = k->origin[2] * loadmodel->num_poseinvscale;
2989 loadmodel->data_poses6s[index*6+3] = quat[0] * 32767.0f;
2990 loadmodel->data_poses6s[index*6+4] = quat[1] * 32767.0f;
2991 loadmodel->data_poses6s[index*6+5] = quat[2] * 32767.0f;
2993 Mod_FreeSkinFiles(skinfiles);
2994 Mem_Free(animfilebuffer);
2995 Mod_MakeSortedSurfaces(loadmodel);
2997 // compute all the mesh information that was not loaded from the file
2998 // TODO: honor smoothing groups somehow?
2999 if (loadmodel->surfmesh.data_element3s)
3000 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3001 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3002 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
3003 Mod_BuildBaseBonePoses();
3004 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
3005 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);
3006 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3007 Mod_Alias_CalculateBoundingBox();
3009 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;