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 void Mod_Skeletal_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
52 // vertex weighted skeletal
55 float boneposerelative[MAX_BONES][12];
56 float m[12], bonepose[MAX_BONES][12];
58 if (skeleton && !skeleton->relativetransforms)
61 // interpolate matrices
64 for (i = 0;i < model->num_bones;i++)
66 Matrix4x4_ToArray12FloatD3D(&skeleton->relativetransforms[i], m);
67 if (model->data_bones[i].parent >= 0)
68 R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
70 for (k = 0;k < 12;k++)
71 bonepose[i][k] = m[k];
73 // create a relative deformation matrix to describe displacement
74 // from the base mesh, which is used by the actual weighting
75 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]);
80 float originscale = model->num_posescale;
83 for (i = 0;i < model->num_bones;i++)
85 for (k = 0;k < 12;k++)
87 for (blends = 0;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++)
89 pose6s = model->data_poses6s + 6 * (frameblend[blends].subframe * model->num_bones + i);
90 lerp = frameblend[blends].lerp;
91 x = pose6s[3] * (1.0f / 32767.0f);
92 y = pose6s[4] * (1.0f / 32767.0f);
93 z = pose6s[5] * (1.0f / 32767.0f);
94 w = 1.0f - (x*x+y*y+z*z);
95 w = w > 0.0f ? -sqrt(w) : 0.0f;
96 m[ 0] += (1-2*(y*y+z*z)) * lerp;
97 m[ 1] += ( 2*(x*y-z*w)) * lerp;
98 m[ 2] += ( 2*(x*z+y*w)) * lerp;
99 m[ 3] += (pose6s[0] * originscale) * lerp;
100 m[ 4] += ( 2*(x*y+z*w)) * lerp;
101 m[ 5] += (1-2*(x*x+z*z)) * lerp;
102 m[ 6] += ( 2*(y*z-x*w)) * lerp;
103 m[ 7] += (pose6s[1] * originscale) * lerp;
104 m[ 8] += ( 2*(x*z-y*w)) * lerp;
105 m[ 9] += ( 2*(y*z+x*w)) * lerp;
106 m[10] += (1-2*(x*x+y*y)) * lerp;
107 m[11] += (pose6s[2] * originscale) * lerp;
110 VectorNormalize(m + 4);
111 VectorNormalize(m + 8);
112 if (i == r_skeletal_debugbone.integer)
113 m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
114 m[3] *= r_skeletal_debugtranslatex.value;
115 m[7] *= r_skeletal_debugtranslatey.value;
116 m[11] *= r_skeletal_debugtranslatez.value;
117 if (model->data_bones[i].parent >= 0)
118 R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
120 for (k = 0;k < 12;k++)
121 bonepose[i][k] = m[k];
122 // create a relative deformation matrix to describe displacement
123 // from the base mesh, which is used by the actual weighting
124 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]);
128 // blend the vertex bone weights
129 // special case for the extremely common wf[0] == 1 because it saves 3 multiplies per array when compared to the other case (w[0] is always 1 if only one bone controls this vertex, artists only use multiple bones for certain special cases)
130 // special case for the first bone because it avoids the need to memset the arrays before filling
133 const float *v = model->surfmesh.data_vertex3f;
134 const int *wi = model->surfmesh.data_vertexweightindex4i;
135 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
136 memset(vertex3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
137 for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, wi += 4, wf += 4, vertex3f += 3)
141 const float *m = boneposerelative[wi[0]];
142 vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
143 vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
144 vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
148 const float *m = boneposerelative[wi[0]];
150 vertex3f[0] = f * (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
151 vertex3f[1] = f * (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
152 vertex3f[2] = f * (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
153 for (k = 1;k < 4 && wf[k];k++)
155 const float *m = boneposerelative[wi[k]];
157 vertex3f[0] += f * (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
158 vertex3f[1] += f * (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
159 vertex3f[2] += f * (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
166 const float *n = model->surfmesh.data_normal3f;
167 const int *wi = model->surfmesh.data_vertexweightindex4i;
168 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
169 memset(normal3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
170 for (i = 0;i < model->surfmesh.num_vertices;i++, n += 3, wi += 4, wf += 4, normal3f += 3)
174 const float *m = boneposerelative[wi[0]];
175 normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
176 normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
177 normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
181 const float *m = boneposerelative[wi[0]];
183 normal3f[0] = f * (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
184 normal3f[1] = f * (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
185 normal3f[2] = f * (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
186 for (k = 1;k < 4 && wf[k];k++)
188 const float *m = boneposerelative[wi[k]];
190 normal3f[0] += f * (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
191 normal3f[1] += f * (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
192 normal3f[2] += f * (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
199 const float *sv = model->surfmesh.data_svector3f;
200 const int *wi = model->surfmesh.data_vertexweightindex4i;
201 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
202 memset(svector3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
203 for (i = 0;i < model->surfmesh.num_vertices;i++, sv += 3, wi += 4, wf += 4, svector3f += 3)
207 const float *m = boneposerelative[wi[0]];
208 svector3f[0] = (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
209 svector3f[1] = (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
210 svector3f[2] = (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
214 const float *m = boneposerelative[wi[0]];
216 svector3f[0] = f * (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
217 svector3f[1] = f * (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
218 svector3f[2] = f * (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
219 for (k = 1;k < 4 && wf[k];k++)
221 const float *m = boneposerelative[wi[k]];
223 svector3f[0] += f * (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
224 svector3f[1] += f * (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
225 svector3f[2] += f * (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
232 const float *tv = model->surfmesh.data_tvector3f;
233 const int *wi = model->surfmesh.data_vertexweightindex4i;
234 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
235 memset(tvector3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
236 for (i = 0;i < model->surfmesh.num_vertices;i++, tv += 3, wi += 4, wf += 4, tvector3f += 3)
240 const float *m = boneposerelative[wi[0]];
241 tvector3f[0] = (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
242 tvector3f[1] = (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
243 tvector3f[2] = (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
247 const float *m = boneposerelative[wi[0]];
249 tvector3f[0] = f * (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
250 tvector3f[1] = f * (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
251 tvector3f[2] = f * (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
252 for (k = 1;k < 4 && wf[k];k++)
254 const float *m = boneposerelative[wi[k]];
256 tvector3f[0] += f * (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
257 tvector3f[1] += f * (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
258 tvector3f[2] += f * (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
265 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)
268 int i, numblends, blendnum;
269 int numverts = model->surfmesh.num_vertices;
271 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
273 //VectorMA(translate, model->surfmesh.num_morphmdlframetranslate, frameblend[blendnum].lerp, translate);
274 if (frameblend[blendnum].lerp > 0)
275 numblends = blendnum + 1;
277 // special case for the first blend because it avoids some adds and the need to memset the arrays first
278 for (blendnum = 0;blendnum < numblends;blendnum++)
280 const md3vertex_t *verts = model->surfmesh.data_morphmd3vertex + numverts * frameblend[blendnum].subframe;
283 float scale = frameblend[blendnum].lerp * (1.0f / 64.0f);
286 for (i = 0;i < numverts;i++)
288 vertex3f[i * 3 + 0] = verts[i].origin[0] * scale;
289 vertex3f[i * 3 + 1] = verts[i].origin[1] * scale;
290 vertex3f[i * 3 + 2] = verts[i].origin[2] * scale;
295 for (i = 0;i < numverts;i++)
297 vertex3f[i * 3 + 0] += verts[i].origin[0] * scale;
298 vertex3f[i * 3 + 1] += verts[i].origin[1] * scale;
299 vertex3f[i * 3 + 2] += verts[i].origin[2] * scale;
303 // the yaw and pitch stored in md3 models are 8bit quantized angles
304 // (0-255), and as such a lookup table is very well suited to
305 // decoding them, and since cosine is equivilant to sine with an
306 // extra 45 degree rotation, this uses one lookup table for both
307 // sine and cosine with a +64 bias to get cosine.
310 float lerp = frameblend[blendnum].lerp;
313 for (i = 0;i < numverts;i++)
315 normal3f[i * 3 + 0] = mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
316 normal3f[i * 3 + 1] = mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
317 normal3f[i * 3 + 2] = mod_md3_sin[verts[i].pitch + 64] * lerp;
322 for (i = 0;i < numverts;i++)
324 normal3f[i * 3 + 0] += mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
325 normal3f[i * 3 + 1] += mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
326 normal3f[i * 3 + 2] += mod_md3_sin[verts[i].pitch + 64] * lerp;
332 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
333 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
336 for (i = 0;i < numverts;i++, texvecvert++)
338 VectorScale(texvecvert->svec, f, svector3f + i*3);
339 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
344 for (i = 0;i < numverts;i++, texvecvert++)
346 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
347 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
354 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)
357 int i, numblends, blendnum;
358 int numverts = model->surfmesh.num_vertices;
360 VectorClear(translate);
362 // blend the frame translates to avoid redundantly doing so on each vertex
363 // (a bit of a brain twister but it works)
364 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
366 if (model->surfmesh.data_morphmd2framesize6f)
367 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6 + 3, translate);
369 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.num_morphmdlframetranslate, translate);
370 if (frameblend[blendnum].lerp > 0)
371 numblends = blendnum + 1;
373 // special case for the first blend because it avoids some adds and the need to memset the arrays first
374 for (blendnum = 0;blendnum < numblends;blendnum++)
376 const trivertx_t *verts = model->surfmesh.data_morphmdlvertex + numverts * frameblend[blendnum].subframe;
380 if (model->surfmesh.data_morphmd2framesize6f)
381 VectorScale(model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6, frameblend[blendnum].lerp, scale);
383 VectorScale(model->surfmesh.num_morphmdlframescale, frameblend[blendnum].lerp, scale);
386 for (i = 0;i < numverts;i++)
388 vertex3f[i * 3 + 0] = translate[0] + verts[i].v[0] * scale[0];
389 vertex3f[i * 3 + 1] = translate[1] + verts[i].v[1] * scale[1];
390 vertex3f[i * 3 + 2] = translate[2] + verts[i].v[2] * scale[2];
395 for (i = 0;i < numverts;i++)
397 vertex3f[i * 3 + 0] += verts[i].v[0] * scale[0];
398 vertex3f[i * 3 + 1] += verts[i].v[1] * scale[1];
399 vertex3f[i * 3 + 2] += verts[i].v[2] * scale[2];
403 // the vertex normals in mdl models are an index into a table of
404 // 162 unique values, this very crude quantization reduces the
405 // vertex normal to only one byte, which saves a lot of space but
406 // also makes lighting pretty coarse
409 float lerp = frameblend[blendnum].lerp;
412 for (i = 0;i < numverts;i++)
414 const float *vn = m_bytenormals[verts[i].lightnormalindex];
415 VectorScale(vn, lerp, normal3f + i*3);
420 for (i = 0;i < numverts;i++)
422 const float *vn = m_bytenormals[verts[i].lightnormalindex];
423 VectorMA(normal3f + i*3, lerp, vn, normal3f + i*3);
429 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
430 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
433 for (i = 0;i < numverts;i++, texvecvert++)
435 VectorScale(texvecvert->svec, f, svector3f + i*3);
436 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
441 for (i = 0;i < numverts;i++, texvecvert++)
443 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
444 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
451 int Mod_Alias_GetTagMatrix(const dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, int tagindex, matrix4x4_t *outmatrix)
454 matrix4x4_t parentbonematrix;
455 matrix4x4_t tempbonematrix;
456 matrix4x4_t bonematrix;
457 matrix4x4_t blendmatrix;
464 *outmatrix = identitymatrix;
465 if (skeleton && skeleton->relativetransforms)
467 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
469 *outmatrix = skeleton->relativetransforms[tagindex];
470 while ((tagindex = model->data_bones[tagindex].parent) >= 0)
473 Matrix4x4_Concat(outmatrix, &skeleton->relativetransforms[tagindex], &temp);
476 else if (model->num_bones)
478 if (tagindex < 0 || tagindex >= model->num_bones)
480 Matrix4x4_Clear(&blendmatrix);
481 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
483 lerp = frameblend[blendindex].lerp;
484 Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
485 parenttagindex = tagindex;
486 while ((parenttagindex = model->data_bones[parenttagindex].parent) >= 0)
488 Matrix4x4_FromBonePose6s(&parentbonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + parenttagindex));
489 tempbonematrix = bonematrix;
490 Matrix4x4_Concat(&bonematrix, &parentbonematrix, &tempbonematrix);
492 Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
494 *outmatrix = blendmatrix;
496 else if (model->num_tags)
498 if (tagindex < 0 || tagindex >= model->num_tags)
500 for (k = 0;k < 12;k++)
502 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
504 lerp = frameblend[blendindex].lerp;
505 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
506 for (k = 0;k < 12;k++)
507 blendtag[k] += input[k] * lerp;
509 Matrix4x4_FromArray12FloatGL(outmatrix, blendtag);
512 if(!mod_alias_supporttagscale.integer)
513 Matrix4x4_Normalize3(outmatrix, outmatrix);
518 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)
523 matrix4x4_t bonematrix;
524 matrix4x4_t blendmatrix;
528 if (skeleton && skeleton->relativetransforms)
530 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
532 *parentindex = skeleton->model->data_bones[tagindex].parent;
533 *tagname = skeleton->model->data_bones[tagindex].name;
534 *tag_localmatrix = skeleton->relativetransforms[tagindex];
537 else if (model->num_bones)
539 if (tagindex < 0 || tagindex >= model->num_bones)
541 *parentindex = model->data_bones[tagindex].parent;
542 *tagname = model->data_bones[tagindex].name;
543 Matrix4x4_Clear(&blendmatrix);
544 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
546 lerp = frameblend[blendindex].lerp;
547 Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
548 Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
550 *tag_localmatrix = blendmatrix;
553 else if (model->num_tags)
555 if (tagindex < 0 || tagindex >= model->num_tags)
558 *tagname = model->data_tags[tagindex].name;
559 for (k = 0;k < 12;k++)
561 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
563 lerp = frameblend[blendindex].lerp;
564 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
565 for (k = 0;k < 12;k++)
566 blendtag[k] += input[k] * lerp;
568 Matrix4x4_FromArray12FloatGL(tag_localmatrix, blendtag);
575 int Mod_Alias_GetTagIndexForName(const dp_model_t *model, unsigned int skin, const char *tagname)
578 if(skin >= (unsigned int)model->numskins)
580 if (model->num_bones)
581 for (i = 0;i < model->num_bones;i++)
582 if (!strcasecmp(tagname, model->data_bones[i].name))
585 for (i = 0;i < model->num_tags;i++)
586 if (!strcasecmp(tagname, model->data_tags[i].name))
591 static void Mod_BuildBaseBonePoses(void)
594 matrix4x4_t *basebonepose;
595 float *outinvmatrix = loadmodel->data_baseboneposeinverse;
596 matrix4x4_t bonematrix;
597 matrix4x4_t tempbonematrix;
598 if (!loadmodel->num_bones)
600 basebonepose = (matrix4x4_t *)Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(matrix4x4_t));
601 for (boneindex = 0;boneindex < loadmodel->num_bones;boneindex++)
603 Matrix4x4_FromBonePose6s(&bonematrix, loadmodel->num_posescale, loadmodel->data_poses6s + 6 * boneindex);
604 if (loadmodel->data_bones[boneindex].parent >= 0)
606 tempbonematrix = bonematrix;
607 Matrix4x4_Concat(&bonematrix, basebonepose + loadmodel->data_bones[boneindex].parent, &tempbonematrix);
609 basebonepose[boneindex] = bonematrix;
610 Matrix4x4_Invert_Simple(&tempbonematrix, basebonepose + boneindex);
611 Matrix4x4_ToArray12FloatD3D(&tempbonematrix, outinvmatrix + 12*boneindex);
613 Mem_Free(basebonepose);
616 static void Mod_Alias_CalculateBoundingBox(void)
619 qboolean firstvertex = true;
620 float dist, yawradius, radius;
623 frameblend_t frameblend[MAX_FRAMEBLENDS];
624 memset(frameblend, 0, sizeof(frameblend));
625 frameblend[0].lerp = 1;
626 vertex3f = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
627 VectorClear(loadmodel->normalmins);
628 VectorClear(loadmodel->normalmaxs);
631 for (frameblend[0].subframe = 0;frameblend[0].subframe < loadmodel->num_poses;frameblend[0].subframe++)
633 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, vertex3f, NULL, NULL, NULL);
634 for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
639 VectorCopy(v, loadmodel->normalmins);
640 VectorCopy(v, loadmodel->normalmaxs);
644 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
645 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
646 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
647 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
648 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
649 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
651 dist = v[0] * v[0] + v[1] * v[1];
652 if (yawradius < dist)
661 radius = sqrt(radius);
662 yawradius = sqrt(yawradius);
663 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
664 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
665 loadmodel->yawmins[2] = loadmodel->normalmins[2];
666 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
667 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
668 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
669 loadmodel->radius = radius;
670 loadmodel->radius2 = radius * radius;
673 static void Mod_Alias_MorphMesh_CompileFrames(void)
676 frameblend_t frameblend[MAX_FRAMEBLENDS];
677 unsigned char *datapointer;
678 memset(frameblend, 0, sizeof(frameblend));
679 frameblend[0].lerp = 1;
680 datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
681 loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
682 loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
683 loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
684 loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
685 loadmodel->surfmesh.data_morphtexvecvertex = (texvecvertex_t *)datapointer;datapointer += loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices * sizeof(texvecvertex_t);
686 // 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)
687 for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
689 frameblend[0].subframe = i;
690 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
691 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);
692 // encode the svector and tvector in 3 byte format for permanent storage
693 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
695 VectorScaleCast(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
696 VectorScaleCast(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
701 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)
704 float segmentmins[3], segmentmaxs[3];
706 static int maxvertices = 0;
707 static float *vertex3f = NULL;
708 memset(trace, 0, sizeof(*trace));
710 trace->realfraction = 1;
711 trace->hitsupercontentsmask = hitsupercontentsmask;
712 if (maxvertices < model->surfmesh.num_vertices)
716 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
717 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
719 segmentmins[0] = min(start[0], end[0]) - 1;
720 segmentmins[1] = min(start[1], end[1]) - 1;
721 segmentmins[2] = min(start[2], end[2]) - 1;
722 segmentmaxs[0] = max(start[0], end[0]) + 1;
723 segmentmaxs[1] = max(start[1], end[1]) + 1;
724 segmentmaxs[2] = max(start[2], end[2]) + 1;
725 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
726 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
727 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);
730 static int maxvertices = 0;
731 static float *vertex3f = NULL;
733 static void Mod_MDLMD2MD3_TraceBoxBox(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t startboxmins, const vec3_t startboxmaxs, const vec3_t end, const vec3_t endboxmins, const vec3_t endboxmaxs, int hitsupercontentsmask)
736 vec3_t shiftstart, shiftend;
737 float segmentmins[3], segmentmaxs[3];
739 colboxbrushf_t thisbrush_start, thisbrush_end;
740 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
742 if (VectorCompare(startboxmins, startboxmaxs) && VectorCompare(startboxmins, endboxmins) && VectorCompare(startboxmaxs, endboxmaxs))
744 VectorAdd(start, startboxmins, shiftstart);
745 VectorAdd(end, startboxmins, shiftend);
746 Mod_MDLMD2MD3_TraceLine(model, frameblend, skeleton, trace, start, end, hitsupercontentsmask);
747 VectorSubtract(trace->endpos, startboxmins, trace->endpos);
751 // box trace, performed as brush trace
752 memset(trace, 0, sizeof(*trace));
754 trace->realfraction = 1;
755 trace->hitsupercontentsmask = hitsupercontentsmask;
756 if (maxvertices < model->surfmesh.num_vertices)
760 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
761 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
763 VectorAdd(start, startboxmins, boxstartmins);
764 VectorAdd(start, startboxmaxs, boxstartmaxs);
765 VectorAdd(end, endboxmins, boxendmins);
766 VectorAdd(end, endboxmaxs, boxendmaxs);
767 segmentmins[0] = min(startboxmins[0], endboxmins[0]) - 1;
768 segmentmins[1] = min(startboxmins[1], endboxmins[1]) - 1;
769 segmentmins[2] = min(startboxmins[2], endboxmins[2]) - 1;
770 segmentmaxs[0] = max(startboxmaxs[0], endboxmaxs[0]) + 1;
771 segmentmaxs[1] = max(startboxmaxs[1], endboxmaxs[1]) + 1;
772 segmentmaxs[2] = max(startboxmaxs[2], endboxmaxs[2]) + 1;
773 Collision_BrushForBox(&thisbrush_start, boxstartmins, boxstartmaxs, 0, 0, NULL);
774 Collision_BrushForBox(&thisbrush_end, boxendmins, boxendmaxs, 0, 0, NULL);
775 if (maxvertices < model->surfmesh.num_vertices)
779 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
780 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
782 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
783 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
784 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);
787 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
790 for (i = 0;i < inverts;i++)
792 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
794 j = vertremap[i]; // not onseam
797 j = vertremap[i+inverts]; // onseam
803 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
805 int i, f, pose, groupframes;
807 daliasframetype_t *pframetype;
808 daliasframe_t *pinframe;
809 daliasgroup_t *group;
810 daliasinterval_t *intervals;
813 scene = loadmodel->animscenes;
814 for (f = 0;f < loadmodel->numframes;f++)
816 pframetype = (daliasframetype_t *)datapointer;
817 datapointer += sizeof(daliasframetype_t);
818 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
820 // a single frame is still treated as a group
827 group = (daliasgroup_t *)datapointer;
828 datapointer += sizeof(daliasgroup_t);
829 groupframes = LittleLong (group->numframes);
831 // intervals (time per frame)
832 intervals = (daliasinterval_t *)datapointer;
833 datapointer += sizeof(daliasinterval_t) * groupframes;
835 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
836 if (interval < 0.01f)
838 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
843 // get scene name from first frame
844 pinframe = (daliasframe_t *)datapointer;
846 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
847 scene->firstframe = pose;
848 scene->framecount = groupframes;
849 scene->framerate = 1.0f / interval;
854 for (i = 0;i < groupframes;i++)
856 pinframe = (daliasframe_t *)datapointer;
857 datapointer += sizeof(daliasframe_t);
858 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
859 datapointer += sizeof(trivertx_t) * inverts;
865 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
867 if (cls.state == ca_dedicated)
871 skinframe = R_SkinFrame_LoadMissing();
872 memset(texture, 0, sizeof(*texture));
873 texture->currentframe = texture;
874 //texture->animated = false;
875 texture->numskinframes = 1;
876 texture->skinframerate = 1;
877 texture->skinframes[0] = skinframe;
878 texture->currentskinframe = skinframe;
879 //texture->backgroundnumskinframes = 0;
880 //texture->customblendfunc[0] = 0;
881 //texture->customblendfunc[1] = 0;
882 //texture->surfaceflags = 0;
883 //texture->supercontents = 0;
884 //texture->surfaceparms = 0;
885 //texture->textureflags = 0;
887 texture->basematerialflags = MATERIALFLAG_WALL;
888 if (texture->currentskinframe->hasalpha)
889 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
890 texture->currentmaterialflags = texture->basematerialflags;
891 texture->specularscalemod = 1;
892 texture->specularpowermod = 1;
895 void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
898 skinfileitem_t *skinfileitem;
901 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
902 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
904 memset(skin, 0, sizeof(*skin));
906 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
908 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
909 if (!strcmp(skinfileitem->name, meshname))
911 Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
917 // don't render unmentioned meshes
918 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
919 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
924 Mod_LoadTextureFromQ3Shader(skin, shadername, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
927 #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);
928 #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);
929 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
931 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
932 float scales, scalet, interval;
936 stvert_t *pinstverts;
937 dtriangle_t *pintriangles;
938 daliasskintype_t *pinskintype;
939 daliasskingroup_t *pinskingroup;
940 daliasskininterval_t *pinskinintervals;
941 daliasframetype_t *pinframetype;
942 daliasgroup_t *pinframegroup;
943 unsigned char *datapointer, *startframes, *startskins;
944 char name[MAX_QPATH];
945 skinframe_t *tempskinframe;
946 animscene_t *tempskinscenes;
947 texture_t *tempaliasskins;
949 int *vertonseam, *vertremap;
950 skinfile_t *skinfiles;
952 datapointer = (unsigned char *)buffer;
953 pinmodel = (mdl_t *)datapointer;
954 datapointer += sizeof(mdl_t);
956 version = LittleLong (pinmodel->version);
957 if (version != ALIAS_VERSION)
958 Host_Error ("%s has wrong version number (%i should be %i)",
959 loadmodel->name, version, ALIAS_VERSION);
961 loadmodel->modeldatatypestring = "MDL";
963 loadmodel->type = mod_alias;
964 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
965 loadmodel->DrawSky = NULL;
966 loadmodel->DrawAddWaterPlanes = NULL;
967 loadmodel->Draw = R_Q1BSP_Draw;
968 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
969 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
970 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
971 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
972 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
973 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
974 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
975 loadmodel->DrawLight = R_Q1BSP_DrawLight;
976 loadmodel->TraceBox = Mod_TraceBox_using_TraceBoxBox;
977 loadmodel->TraceBoxBox = Mod_MDLMD2MD3_TraceBoxBox;
978 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
979 loadmodel->PointSuperContents = NULL;
981 loadmodel->num_surfaces = 1;
982 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
983 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
984 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
985 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
986 loadmodel->sortedmodelsurfaces[0] = 0;
988 loadmodel->numskins = LittleLong(pinmodel->numskins);
989 BOUNDI(loadmodel->numskins,0,65536);
990 skinwidth = LittleLong (pinmodel->skinwidth);
991 BOUNDI(skinwidth,0,65536);
992 skinheight = LittleLong (pinmodel->skinheight);
993 BOUNDI(skinheight,0,65536);
994 numverts = LittleLong(pinmodel->numverts);
995 BOUNDI(numverts,0,65536);
996 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
997 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
998 loadmodel->numframes = LittleLong(pinmodel->numframes);
999 BOUNDI(loadmodel->numframes,0,65536);
1000 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
1001 BOUNDI(loadmodel->synctype,0,2);
1002 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1003 i = LittleLong (pinmodel->flags);
1004 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1006 for (i = 0;i < 3;i++)
1008 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
1009 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
1012 startskins = datapointer;
1014 for (i = 0;i < loadmodel->numskins;i++)
1016 pinskintype = (daliasskintype_t *)datapointer;
1017 datapointer += sizeof(daliasskintype_t);
1018 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
1022 pinskingroup = (daliasskingroup_t *)datapointer;
1023 datapointer += sizeof(daliasskingroup_t);
1024 groupskins = LittleLong(pinskingroup->numskins);
1025 datapointer += sizeof(daliasskininterval_t) * groupskins;
1028 for (j = 0;j < groupskins;j++)
1030 datapointer += skinwidth * skinheight;
1035 pinstverts = (stvert_t *)datapointer;
1036 datapointer += sizeof(stvert_t) * numverts;
1038 pintriangles = (dtriangle_t *)datapointer;
1039 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
1041 startframes = datapointer;
1042 loadmodel->surfmesh.num_morphframes = 0;
1043 for (i = 0;i < loadmodel->numframes;i++)
1045 pinframetype = (daliasframetype_t *)datapointer;
1046 datapointer += sizeof(daliasframetype_t);
1047 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
1051 pinframegroup = (daliasgroup_t *)datapointer;
1052 datapointer += sizeof(daliasgroup_t);
1053 groupframes = LittleLong(pinframegroup->numframes);
1054 datapointer += sizeof(daliasinterval_t) * groupframes;
1057 for (j = 0;j < groupframes;j++)
1059 datapointer += sizeof(daliasframe_t);
1060 datapointer += sizeof(trivertx_t) * numverts;
1061 loadmodel->surfmesh.num_morphframes++;
1064 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1066 // store texture coordinates into temporary array, they will be stored
1067 // after usage is determined (triangle data)
1068 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
1069 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
1070 vertonseam = vertremap + numverts * 2;
1072 scales = 1.0 / skinwidth;
1073 scalet = 1.0 / skinheight;
1074 for (i = 0;i < numverts;i++)
1076 vertonseam[i] = LittleLong(pinstverts[i].onseam);
1077 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
1078 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
1079 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
1080 vertst[(i+numverts)*2+1] = vertst[i*2+1];
1083 // load triangle data
1084 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1086 // read the triangle elements
1087 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1088 for (j = 0;j < 3;j++)
1089 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1090 // validate (note numverts is used because this is the original data)
1091 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1092 // now butcher the elements according to vertonseam and tri->facesfront
1093 // and then compact the vertex set to remove duplicates
1094 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1095 if (!LittleLong(pintriangles[i].facesfront)) // backface
1096 for (j = 0;j < 3;j++)
1097 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1098 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1100 // (this uses vertremap to count usage to save some memory)
1101 for (i = 0;i < numverts*2;i++)
1103 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1104 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1105 // build remapping table and compact array
1106 loadmodel->surfmesh.num_vertices = 0;
1107 for (i = 0;i < numverts*2;i++)
1111 vertremap[i] = loadmodel->surfmesh.num_vertices;
1112 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1113 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1114 loadmodel->surfmesh.num_vertices++;
1117 vertremap[i] = -1; // not used at all
1119 // remap the elements to the new vertex set
1120 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1121 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1122 // store the texture coordinates
1123 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1124 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1126 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1127 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1130 // generate ushort elements array if possible
1131 if (loadmodel->surfmesh.num_vertices <= 65536)
1132 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1133 if (loadmodel->surfmesh.data_element3s)
1134 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1135 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1138 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1139 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1140 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1141 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1142 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1143 Mod_Alias_CalculateBoundingBox();
1144 Mod_Alias_MorphMesh_CompileFrames();
1147 Mem_Free(vertremap);
1150 skinfiles = Mod_LoadSkinFiles();
1153 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1154 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1155 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1156 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1157 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1158 Mod_FreeSkinFiles(skinfiles);
1159 for (i = 0;i < loadmodel->numskins;i++)
1161 loadmodel->skinscenes[i].firstframe = i;
1162 loadmodel->skinscenes[i].framecount = 1;
1163 loadmodel->skinscenes[i].loop = true;
1164 loadmodel->skinscenes[i].framerate = 10;
1169 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1170 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1171 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1172 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1174 datapointer = startskins;
1175 for (i = 0;i < loadmodel->numskins;i++)
1177 pinskintype = (daliasskintype_t *)datapointer;
1178 datapointer += sizeof(daliasskintype_t);
1180 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1187 pinskingroup = (daliasskingroup_t *)datapointer;
1188 datapointer += sizeof(daliasskingroup_t);
1190 groupskins = LittleLong (pinskingroup->numskins);
1192 pinskinintervals = (daliasskininterval_t *)datapointer;
1193 datapointer += sizeof(daliasskininterval_t) * groupskins;
1195 interval = LittleFloat(pinskinintervals[0].interval);
1196 if (interval < 0.01f)
1198 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1203 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1204 loadmodel->skinscenes[i].firstframe = totalskins;
1205 loadmodel->skinscenes[i].framecount = groupskins;
1206 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1207 loadmodel->skinscenes[i].loop = true;
1209 for (j = 0;j < groupskins;j++)
1212 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1214 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1215 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))
1216 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));
1217 datapointer += skinwidth * skinheight;
1221 // check for skins that don't exist in the model, but do exist as external images
1222 // (this was added because yummyluv kept pestering me about support for it)
1223 // TODO: support shaders here?
1224 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)))
1226 // expand the arrays to make room
1227 tempskinscenes = loadmodel->skinscenes;
1228 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1229 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1230 Mem_Free(tempskinscenes);
1232 tempaliasskins = loadmodel->data_textures;
1233 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1234 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1235 Mem_Free(tempaliasskins);
1237 // store the info about the new skin
1238 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1239 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1240 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1241 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1242 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1243 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1245 //increase skin counts
1246 loadmodel->numskins++;
1249 // fix up the pointers since they are pointing at the old textures array
1250 // FIXME: this is a hack!
1251 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1252 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1256 surface = loadmodel->data_surfaces;
1257 surface->texture = loadmodel->data_textures;
1258 surface->num_firsttriangle = 0;
1259 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1260 surface->num_firstvertex = 0;
1261 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1263 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1266 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1268 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1269 float iskinwidth, iskinheight;
1270 unsigned char *data;
1271 msurface_t *surface;
1273 unsigned char *base, *datapointer;
1274 md2frame_t *pinframe;
1276 md2triangle_t *intri;
1277 unsigned short *inst;
1278 struct md2verthash_s
1280 struct md2verthash_s *next;
1284 *hash, **md2verthash, *md2verthashdata;
1285 skinfile_t *skinfiles;
1287 pinmodel = (md2_t *)buffer;
1288 base = (unsigned char *)buffer;
1290 version = LittleLong (pinmodel->version);
1291 if (version != MD2ALIAS_VERSION)
1292 Host_Error ("%s has wrong version number (%i should be %i)",
1293 loadmodel->name, version, MD2ALIAS_VERSION);
1295 loadmodel->modeldatatypestring = "MD2";
1297 loadmodel->type = mod_alias;
1298 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1299 loadmodel->DrawSky = NULL;
1300 loadmodel->DrawAddWaterPlanes = NULL;
1301 loadmodel->Draw = R_Q1BSP_Draw;
1302 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1303 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1304 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1305 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1306 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1307 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1308 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1309 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1310 loadmodel->TraceBox = Mod_TraceBox_using_TraceBoxBox;
1311 loadmodel->TraceBoxBox = Mod_MDLMD2MD3_TraceBoxBox;
1312 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1313 loadmodel->PointSuperContents = NULL;
1315 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1316 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1317 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1318 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1319 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1320 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1321 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1322 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1324 end = LittleLong(pinmodel->ofs_end);
1325 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1326 Host_Error ("%s is not a valid model", loadmodel->name);
1327 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1328 Host_Error ("%s is not a valid model", loadmodel->name);
1329 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1330 Host_Error ("%s is not a valid model", loadmodel->name);
1331 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1332 Host_Error ("%s is not a valid model", loadmodel->name);
1333 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1334 Host_Error ("%s is not a valid model", loadmodel->name);
1336 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1337 numxyz = LittleLong(pinmodel->num_xyz);
1338 numst = LittleLong(pinmodel->num_st);
1339 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1340 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1341 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1342 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1343 skinwidth = LittleLong(pinmodel->skinwidth);
1344 skinheight = LittleLong(pinmodel->skinheight);
1345 iskinwidth = 1.0f / skinwidth;
1346 iskinheight = 1.0f / skinheight;
1348 loadmodel->num_surfaces = 1;
1349 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1350 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]));
1351 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1352 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1353 loadmodel->sortedmodelsurfaces[0] = 0;
1354 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1355 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1356 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1357 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1359 loadmodel->synctype = ST_RAND;
1362 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1363 skinfiles = Mod_LoadSkinFiles();
1366 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1367 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1368 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1369 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1370 Mod_FreeSkinFiles(skinfiles);
1372 else if (loadmodel->numskins)
1374 // skins found (most likely not a player model)
1375 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1376 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1377 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1378 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1379 Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
1383 // no skins (most likely a player model)
1384 loadmodel->numskins = 1;
1385 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1386 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1387 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1388 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1391 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1392 for (i = 0;i < loadmodel->numskins;i++)
1394 loadmodel->skinscenes[i].firstframe = i;
1395 loadmodel->skinscenes[i].framecount = 1;
1396 loadmodel->skinscenes[i].loop = true;
1397 loadmodel->skinscenes[i].framerate = 10;
1400 // load the triangles and stvert data
1401 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1402 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1403 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1404 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1405 // swap the triangle list
1406 loadmodel->surfmesh.num_vertices = 0;
1407 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1409 for (j = 0;j < 3;j++)
1411 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1412 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1415 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1420 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1423 hashindex = (xyz * 256 + st) & 65535;
1424 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1425 if (hash->xyz == xyz && hash->st == st)
1429 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1432 hash->next = md2verthash[hashindex];
1433 md2verthash[hashindex] = hash;
1435 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1439 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1440 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));
1441 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1442 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1443 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1446 hash = md2verthashdata + i;
1447 vertremap[i] = hash->xyz;
1448 sts = LittleShort(inst[hash->st*2+0]);
1449 stt = LittleShort(inst[hash->st*2+1]);
1450 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1452 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1456 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1457 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1460 Mem_Free(md2verthash);
1461 Mem_Free(md2verthashdata);
1463 // generate ushort elements array if possible
1464 if (loadmodel->surfmesh.num_vertices <= 65536)
1465 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1466 if (loadmodel->surfmesh.data_element3s)
1467 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1468 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1471 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1472 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1477 pinframe = (md2frame_t *)datapointer;
1478 datapointer += sizeof(md2frame_t);
1479 // store the frame scale/translate into the appropriate array
1480 for (j = 0;j < 3;j++)
1482 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1483 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1485 // convert the vertices
1486 v = (trivertx_t *)datapointer;
1487 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1488 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1489 out[k] = v[vertremap[k]];
1490 datapointer += numxyz * sizeof(trivertx_t);
1492 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1493 loadmodel->animscenes[i].firstframe = i;
1494 loadmodel->animscenes[i].framecount = 1;
1495 loadmodel->animscenes[i].framerate = 10;
1496 loadmodel->animscenes[i].loop = true;
1499 Mem_Free(vertremap);
1501 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1502 Mod_Alias_CalculateBoundingBox();
1503 Mod_Alias_MorphMesh_CompileFrames();
1505 surface = loadmodel->data_surfaces;
1506 surface->texture = loadmodel->data_textures;
1507 surface->num_firsttriangle = 0;
1508 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1509 surface->num_firstvertex = 0;
1510 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1512 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1515 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1517 int i, j, k, version, meshvertices, meshtriangles;
1518 unsigned char *data;
1519 msurface_t *surface;
1520 md3modelheader_t *pinmodel;
1521 md3frameinfo_t *pinframe;
1524 skinfile_t *skinfiles;
1526 pinmodel = (md3modelheader_t *)buffer;
1528 if (memcmp(pinmodel->identifier, "IDP3", 4))
1529 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1530 version = LittleLong (pinmodel->version);
1531 if (version != MD3VERSION)
1532 Host_Error ("%s has wrong version number (%i should be %i)",
1533 loadmodel->name, version, MD3VERSION);
1535 skinfiles = Mod_LoadSkinFiles();
1536 if (loadmodel->numskins < 1)
1537 loadmodel->numskins = 1;
1539 loadmodel->modeldatatypestring = "MD3";
1541 loadmodel->type = mod_alias;
1542 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1543 loadmodel->DrawSky = NULL;
1544 loadmodel->DrawAddWaterPlanes = NULL;
1545 loadmodel->Draw = R_Q1BSP_Draw;
1546 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1547 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1548 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1549 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1550 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1551 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1552 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1553 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1554 loadmodel->TraceBox = Mod_TraceBox_using_TraceBoxBox;
1555 loadmodel->TraceBoxBox = Mod_MDLMD2MD3_TraceBoxBox;
1556 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1557 loadmodel->PointSuperContents = NULL;
1558 loadmodel->synctype = ST_RAND;
1559 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1560 i = LittleLong (pinmodel->flags);
1561 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1563 // set up some global info about the model
1564 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1565 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1567 // make skinscenes for the skins (no groups)
1568 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1569 for (i = 0;i < loadmodel->numskins;i++)
1571 loadmodel->skinscenes[i].firstframe = i;
1572 loadmodel->skinscenes[i].framecount = 1;
1573 loadmodel->skinscenes[i].loop = true;
1574 loadmodel->skinscenes[i].framerate = 10;
1578 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1579 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1581 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1582 loadmodel->animscenes[i].firstframe = i;
1583 loadmodel->animscenes[i].framecount = 1;
1584 loadmodel->animscenes[i].framerate = 10;
1585 loadmodel->animscenes[i].loop = true;
1589 loadmodel->num_tagframes = loadmodel->numframes;
1590 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1591 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1592 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1594 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1595 for (j = 0;j < 9;j++)
1596 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1597 for (j = 0;j < 3;j++)
1598 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1599 //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);
1605 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)))
1607 if (memcmp(pinmesh->identifier, "IDP3", 4))
1608 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1609 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1610 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1611 meshvertices += LittleLong(pinmesh->num_vertices);
1612 meshtriangles += LittleLong(pinmesh->num_triangles);
1615 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1616 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1617 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1618 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));
1619 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1620 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1621 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1622 loadmodel->surfmesh.num_vertices = meshvertices;
1623 loadmodel->surfmesh.num_triangles = meshtriangles;
1624 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1625 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1626 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1627 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1628 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1629 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1630 if (meshvertices <= 65536)
1631 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1635 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)))
1637 if (memcmp(pinmesh->identifier, "IDP3", 4))
1638 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1639 loadmodel->sortedmodelsurfaces[i] = i;
1640 surface = loadmodel->data_surfaces + i;
1641 surface->texture = loadmodel->data_textures + i;
1642 surface->num_firsttriangle = meshtriangles;
1643 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1644 surface->num_firstvertex = meshvertices;
1645 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1646 meshvertices += surface->num_vertices;
1647 meshtriangles += surface->num_triangles;
1649 for (j = 0;j < surface->num_triangles * 3;j++)
1650 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1651 for (j = 0;j < surface->num_vertices;j++)
1653 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1654 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1656 for (j = 0;j < loadmodel->numframes;j++)
1658 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1659 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1660 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1662 out->origin[0] = LittleShort(in->origin[0]);
1663 out->origin[1] = LittleShort(in->origin[1]);
1664 out->origin[2] = LittleShort(in->origin[2]);
1665 out->pitch = in->pitch;
1670 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1672 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1674 if (loadmodel->surfmesh.data_element3s)
1675 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1676 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1677 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1678 Mod_Alias_MorphMesh_CompileFrames();
1679 Mod_Alias_CalculateBoundingBox();
1680 Mod_FreeSkinFiles(skinfiles);
1681 Mod_MakeSortedSurfaces(loadmodel);
1683 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1684 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1687 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1689 zymtype1header_t *pinmodel, *pheader;
1690 unsigned char *pbase;
1691 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1692 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose, f, biggestorigin, tempvec[3], modelscale;
1693 zymvertex_t *verts, *vertdata;
1697 skinfile_t *skinfiles;
1698 unsigned char *data;
1699 msurface_t *surface;
1701 pinmodel = (zymtype1header_t *)buffer;
1702 pbase = (unsigned char *)buffer;
1703 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1704 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1705 if (BigLong(pinmodel->type) != 1)
1706 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1708 loadmodel->modeldatatypestring = "ZYM";
1710 loadmodel->type = mod_alias;
1711 loadmodel->synctype = ST_RAND;
1715 pheader->type = BigLong(pinmodel->type);
1716 pheader->filesize = BigLong(pinmodel->filesize);
1717 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1718 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1719 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1720 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1721 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1722 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1723 pheader->radius = BigFloat(pinmodel->radius);
1724 pheader->numverts = BigLong(pinmodel->numverts);
1725 pheader->numtris = BigLong(pinmodel->numtris);
1726 pheader->numshaders = BigLong(pinmodel->numshaders);
1727 pheader->numbones = BigLong(pinmodel->numbones);
1728 pheader->numscenes = BigLong(pinmodel->numscenes);
1729 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1730 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1731 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1732 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1733 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1734 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1735 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1736 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1737 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1738 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1739 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1740 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1741 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1742 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1743 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1744 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1745 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1746 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1748 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1750 Con_Printf("%s has no geometry\n", loadmodel->name);
1753 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1755 Con_Printf("%s has no animations\n", loadmodel->name);
1759 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1760 loadmodel->DrawSky = NULL;
1761 loadmodel->DrawAddWaterPlanes = NULL;
1762 loadmodel->Draw = R_Q1BSP_Draw;
1763 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1764 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1765 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1766 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1767 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1768 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1769 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1770 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1771 loadmodel->TraceBox = Mod_TraceBox_using_TraceBoxBox;
1772 loadmodel->TraceBoxBox = Mod_MDLMD2MD3_TraceBoxBox;
1773 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1774 loadmodel->PointSuperContents = NULL;
1776 loadmodel->numframes = pheader->numscenes;
1777 loadmodel->num_surfaces = pheader->numshaders;
1779 skinfiles = Mod_LoadSkinFiles();
1780 if (loadmodel->numskins < 1)
1781 loadmodel->numskins = 1;
1783 // make skinscenes for the skins (no groups)
1784 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1785 for (i = 0;i < loadmodel->numskins;i++)
1787 loadmodel->skinscenes[i].firstframe = i;
1788 loadmodel->skinscenes[i].framecount = 1;
1789 loadmodel->skinscenes[i].loop = true;
1790 loadmodel->skinscenes[i].framerate = 10;
1794 modelradius = pheader->radius;
1795 for (i = 0;i < 3;i++)
1797 loadmodel->normalmins[i] = pheader->mins[i];
1798 loadmodel->normalmaxs[i] = pheader->maxs[i];
1799 loadmodel->rotatedmins[i] = -modelradius;
1800 loadmodel->rotatedmaxs[i] = modelradius;
1802 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1803 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1804 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1805 if (loadmodel->yawmaxs[0] > modelradius)
1806 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1807 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1808 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1809 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1810 loadmodel->radius = modelradius;
1811 loadmodel->radius2 = modelradius * modelradius;
1813 // go through the lumps, swapping things
1815 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1816 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1817 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1818 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1819 for (i = 0;i < pheader->numscenes;i++)
1821 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1822 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1823 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1824 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1825 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1826 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1827 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1828 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1829 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1830 if (loadmodel->animscenes[i].framerate < 0)
1831 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1835 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1836 loadmodel->num_bones = pheader->numbones;
1837 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1838 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1839 for (i = 0;i < pheader->numbones;i++)
1841 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1842 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1843 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1844 if (loadmodel->data_bones[i].parent >= i)
1845 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1848 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1849 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1850 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1851 for (i = 0;i < pheader->numverts;i++)
1853 vertbonecounts[i] = BigLong(bonecount[i]);
1854 if (vertbonecounts[i] != 1)
1855 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1858 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1860 meshvertices = pheader->numverts;
1861 meshtriangles = pheader->numtris;
1863 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1864 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1865 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1866 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(int[4]) + meshvertices * sizeof(float[4]) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]) + loadmodel->num_bones * sizeof(float[12]));
1867 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1868 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1869 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1870 loadmodel->surfmesh.num_vertices = meshvertices;
1871 loadmodel->surfmesh.num_triangles = meshtriangles;
1872 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1873 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1874 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1875 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1876 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1877 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1878 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1879 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1880 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1881 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1882 if (loadmodel->surfmesh.num_vertices <= 65536)
1883 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1884 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
1886 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1887 poses = (float *) (pheader->lump_poses.start + pbase);
1888 // figure out scale of model from root bone, for compatibility with old zmodel versions
1889 tempvec[0] = BigFloat(poses[0]);
1890 tempvec[1] = BigFloat(poses[1]);
1891 tempvec[2] = BigFloat(poses[2]);
1892 modelscale = VectorLength(tempvec);
1894 for (i = 0;i < loadmodel->num_bones * numposes * 12;i++)
1896 f = fabs(BigFloat(poses[i]));
1897 biggestorigin = max(biggestorigin, f);
1899 loadmodel->num_posescale = biggestorigin / 32767.0f;
1900 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
1901 for (i = 0;i < numposes;i++)
1903 const float *frameposes = (float *) (pheader->lump_poses.start + pbase) + 12*i*loadmodel->num_bones;
1904 for (j = 0;j < loadmodel->num_bones;j++)
1907 matrix4x4_t posematrix;
1908 for (k = 0;k < 12;k++)
1909 pose[k] = BigFloat(frameposes[j*12+k]);
1910 //if (j < loadmodel->num_bones)
1911 // 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));
1912 // scale child bones to match the root scale
1913 if (loadmodel->data_bones[j].parent >= 0)
1915 pose[3] *= modelscale;
1916 pose[7] *= modelscale;
1917 pose[11] *= modelscale;
1919 // normalize rotation matrix
1920 VectorNormalize(pose + 0);
1921 VectorNormalize(pose + 4);
1922 VectorNormalize(pose + 8);
1923 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
1924 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
1928 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1929 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1930 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1931 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1932 // (converting from weight-blending skeletal animation to
1933 // deformation-based skeletal animation)
1934 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1935 for (i = 0;i < loadmodel->num_bones;i++)
1938 for (k = 0;k < 12;k++)
1939 m[k] = BigFloat(poses[i*12+k]);
1940 if (loadmodel->data_bones[i].parent >= 0)
1941 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1943 for (k = 0;k < 12;k++)
1944 bonepose[12*i+k] = m[k];
1946 for (j = 0;j < pheader->numverts;j++)
1948 // this format really should have had a per vertexweight weight value...
1949 // but since it does not, the weighting is completely ignored and
1950 // only one weight is allowed per vertex
1951 int boneindex = BigLong(vertdata[j].bonenum);
1952 const float *m = bonepose + 12 * boneindex;
1953 float relativeorigin[3];
1954 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1955 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1956 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1957 // transform the vertex bone weight into the base mesh
1958 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1959 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1960 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1961 // store the weight as the primary weight on this vertex
1962 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
1963 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = 1;
1966 // normals and tangents are calculated after elements are loaded
1968 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1969 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1970 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1971 for (i = 0;i < pheader->numverts;i++)
1973 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1974 // flip T coordinate for OpenGL
1975 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1978 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1979 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1980 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1982 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1983 //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)
1984 // byteswap, validate, and swap winding order of tris
1985 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1986 if (pheader->lump_render.length != count)
1987 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1988 renderlist = (int *) (pheader->lump_render.start + pbase);
1989 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1991 for (i = 0;i < loadmodel->num_surfaces;i++)
1993 int firstvertex, lastvertex;
1994 if (renderlist >= renderlistend)
1995 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1996 count = BigLong(*renderlist);renderlist++;
1997 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1998 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2000 loadmodel->sortedmodelsurfaces[i] = i;
2001 surface = loadmodel->data_surfaces + i;
2002 surface->texture = loadmodel->data_textures + i;
2003 surface->num_firsttriangle = meshtriangles;
2004 surface->num_triangles = count;
2005 meshtriangles += surface->num_triangles;
2007 // load the elements
2008 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2009 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
2011 outelements[j*3+2] = BigLong(renderlist[0]);
2012 outelements[j*3+1] = BigLong(renderlist[1]);
2013 outelements[j*3+0] = BigLong(renderlist[2]);
2015 // validate the elements and find the used vertex range
2016 firstvertex = meshvertices;
2018 for (j = 0;j < surface->num_triangles * 3;j++)
2020 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
2021 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
2022 firstvertex = min(firstvertex, outelements[j]);
2023 lastvertex = max(lastvertex, outelements[j]);
2025 surface->num_firstvertex = firstvertex;
2026 surface->num_vertices = lastvertex + 1 - firstvertex;
2028 // since zym models do not have named sections, reuse their shader
2029 // name as the section name
2030 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
2031 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
2033 Mod_FreeSkinFiles(skinfiles);
2034 Mem_Free(vertbonecounts);
2036 Mod_MakeSortedSurfaces(loadmodel);
2038 // compute all the mesh information that was not loaded from the file
2039 if (loadmodel->surfmesh.data_element3s)
2040 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2041 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2042 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2043 Mod_BuildBaseBonePoses();
2044 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2045 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);
2046 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2048 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2051 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2053 dpmheader_t *pheader;
2057 unsigned char *pbase;
2058 int i, j, k, meshvertices, meshtriangles;
2059 skinfile_t *skinfiles;
2060 unsigned char *data;
2062 float biggestorigin, tempvec[3], modelscale;
2066 pheader = (dpmheader_t *)buffer;
2067 pbase = (unsigned char *)buffer;
2068 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2069 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2070 if (BigLong(pheader->type) != 2)
2071 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2073 loadmodel->modeldatatypestring = "DPM";
2075 loadmodel->type = mod_alias;
2076 loadmodel->synctype = ST_RAND;
2079 pheader->type = BigLong(pheader->type);
2080 pheader->filesize = BigLong(pheader->filesize);
2081 pheader->mins[0] = BigFloat(pheader->mins[0]);
2082 pheader->mins[1] = BigFloat(pheader->mins[1]);
2083 pheader->mins[2] = BigFloat(pheader->mins[2]);
2084 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2085 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2086 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2087 pheader->yawradius = BigFloat(pheader->yawradius);
2088 pheader->allradius = BigFloat(pheader->allradius);
2089 pheader->num_bones = BigLong(pheader->num_bones);
2090 pheader->num_meshs = BigLong(pheader->num_meshs);
2091 pheader->num_frames = BigLong(pheader->num_frames);
2092 pheader->ofs_bones = BigLong(pheader->ofs_bones);
2093 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2094 pheader->ofs_frames = BigLong(pheader->ofs_frames);
2096 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2098 Con_Printf("%s has no geometry\n", loadmodel->name);
2101 if (pheader->num_frames < 1)
2103 Con_Printf("%s has no frames\n", loadmodel->name);
2107 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2108 loadmodel->DrawSky = NULL;
2109 loadmodel->DrawAddWaterPlanes = NULL;
2110 loadmodel->Draw = R_Q1BSP_Draw;
2111 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2112 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2113 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2114 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2115 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2116 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2117 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2118 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2119 loadmodel->TraceBox = Mod_TraceBox_using_TraceBoxBox;
2120 loadmodel->TraceBoxBox = Mod_MDLMD2MD3_TraceBoxBox;
2121 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2122 loadmodel->PointSuperContents = NULL;
2125 for (i = 0;i < 3;i++)
2127 loadmodel->normalmins[i] = pheader->mins[i];
2128 loadmodel->normalmaxs[i] = pheader->maxs[i];
2129 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2130 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2131 loadmodel->rotatedmins[i] = -pheader->allradius;
2132 loadmodel->rotatedmaxs[i] = pheader->allradius;
2134 loadmodel->radius = pheader->allradius;
2135 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2137 // load external .skin files if present
2138 skinfiles = Mod_LoadSkinFiles();
2139 if (loadmodel->numskins < 1)
2140 loadmodel->numskins = 1;
2145 // gather combined statistics from the meshes
2146 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2147 for (i = 0;i < (int)pheader->num_meshs;i++)
2149 int numverts = BigLong(dpmmesh->num_verts);
2150 meshvertices += numverts;
2151 meshtriangles += BigLong(dpmmesh->num_tris);
2155 loadmodel->numframes = pheader->num_frames;
2156 loadmodel->num_bones = pheader->num_bones;
2157 loadmodel->num_poses = loadmodel->numframes;
2158 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2159 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2160 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2161 // do most allocations as one merged chunk
2162 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(int[4]) + sizeof(float[4])) + 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));
2163 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2164 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2165 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2166 loadmodel->surfmesh.num_vertices = meshvertices;
2167 loadmodel->surfmesh.num_triangles = meshtriangles;
2168 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2169 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2170 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2171 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2172 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2173 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2174 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2175 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
2176 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
2177 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2178 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2179 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2180 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2181 if (meshvertices <= 65536)
2182 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2183 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2185 for (i = 0;i < loadmodel->numskins;i++)
2187 loadmodel->skinscenes[i].firstframe = i;
2188 loadmodel->skinscenes[i].framecount = 1;
2189 loadmodel->skinscenes[i].loop = true;
2190 loadmodel->skinscenes[i].framerate = 10;
2193 // load the bone info
2194 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2195 for (i = 0;i < loadmodel->num_bones;i++)
2197 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2198 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2199 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2200 if (loadmodel->data_bones[i].parent >= i)
2201 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2205 frames = (dpmframe_t *) (pbase + pheader->ofs_frames);
2206 // figure out scale of model from root bone, for compatibility with old dpmodel versions
2207 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2208 tempvec[0] = BigFloat(poses[0]);
2209 tempvec[1] = BigFloat(poses[1]);
2210 tempvec[2] = BigFloat(poses[2]);
2211 modelscale = VectorLength(tempvec);
2213 for (i = 0;i < loadmodel->numframes;i++)
2215 memcpy(loadmodel->animscenes[i].name, frames[i].name, sizeof(frames[i].name));
2216 loadmodel->animscenes[i].firstframe = i;
2217 loadmodel->animscenes[i].framecount = 1;
2218 loadmodel->animscenes[i].loop = true;
2219 loadmodel->animscenes[i].framerate = 10;
2220 // load the bone poses for this frame
2221 poses = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2222 for (j = 0;j < loadmodel->num_bones*12;j++)
2224 f = fabs(BigFloat(poses[j]));
2225 biggestorigin = max(biggestorigin, f);
2227 // stuff not processed here: mins, maxs, yawradius, allradius
2229 loadmodel->num_posescale = biggestorigin / 32767.0f;
2230 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2231 for (i = 0;i < loadmodel->numframes;i++)
2233 const float *frameposes = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2234 for (j = 0;j < loadmodel->num_bones;j++)
2237 matrix4x4_t posematrix;
2238 for (k = 0;k < 12;k++)
2239 pose[k] = BigFloat(frameposes[j*12+k]);
2240 // scale child bones to match the root scale
2241 if (loadmodel->data_bones[j].parent >= 0)
2243 pose[3] *= modelscale;
2244 pose[7] *= modelscale;
2245 pose[11] *= modelscale;
2247 // normalize rotation matrix
2248 VectorNormalize(pose + 0);
2249 VectorNormalize(pose + 4);
2250 VectorNormalize(pose + 8);
2251 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2252 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
2256 // load the meshes now
2257 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2260 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2261 // (converting from weight-blending skeletal animation to
2262 // deformation-based skeletal animation)
2263 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2264 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2265 for (i = 0;i < loadmodel->num_bones;i++)
2268 for (k = 0;k < 12;k++)
2269 m[k] = BigFloat(poses[i*12+k]);
2270 if (loadmodel->data_bones[i].parent >= 0)
2271 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2273 for (k = 0;k < 12;k++)
2274 bonepose[12*i+k] = m[k];
2276 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2278 const int *inelements;
2280 const float *intexcoord;
2281 msurface_t *surface;
2283 loadmodel->sortedmodelsurfaces[i] = i;
2284 surface = loadmodel->data_surfaces + i;
2285 surface->texture = loadmodel->data_textures + i;
2286 surface->num_firsttriangle = meshtriangles;
2287 surface->num_triangles = BigLong(dpmmesh->num_tris);
2288 surface->num_firstvertex = meshvertices;
2289 surface->num_vertices = BigLong(dpmmesh->num_verts);
2290 meshvertices += surface->num_vertices;
2291 meshtriangles += surface->num_triangles;
2293 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2294 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2295 for (j = 0;j < surface->num_triangles;j++)
2297 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2298 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2299 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2300 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2305 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2306 for (j = 0;j < surface->num_vertices*2;j++)
2307 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2309 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2310 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2314 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2315 data += sizeof(dpmvertex_t);
2316 for (k = 0;k < numweights;k++)
2318 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2319 int boneindex = BigLong(vert->bonenum);
2320 const float *m = bonepose + 12 * boneindex;
2321 float influence = BigFloat(vert->influence);
2322 float relativeorigin[3], relativenormal[3];
2323 relativeorigin[0] = BigFloat(vert->origin[0]);
2324 relativeorigin[1] = BigFloat(vert->origin[1]);
2325 relativeorigin[2] = BigFloat(vert->origin[2]);
2326 relativenormal[0] = BigFloat(vert->normal[0]);
2327 relativenormal[1] = BigFloat(vert->normal[1]);
2328 relativenormal[2] = BigFloat(vert->normal[2]);
2329 // blend the vertex bone weights into the base mesh
2330 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2331 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2332 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2333 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2334 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2335 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2338 // store the first (and often only) weight
2339 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = influence;
2340 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
2344 // sort the new weight into this vertex's weight table
2345 // (which only accepts up to 4 bones per vertex)
2346 for (l = 0;l < 4;l++)
2348 if (loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] < influence)
2350 // move weaker influence weights out of the way first
2352 for (l2 = 3;l2 > l;l2--)
2354 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2-1];
2355 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2-1];
2357 // store the new weight
2358 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] = influence;
2359 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l] = boneindex;
2364 data += sizeof(dpmbonevert_t);
2367 for (l = 0;l < 4;l++)
2368 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l];
2369 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2371 float f = 1.0f / sum;
2372 for (l = 0;l < 4;l++)
2373 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] *= f;
2377 // since dpm models do not have named sections, reuse their shader name as the section name
2378 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2380 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2383 Mod_FreeSkinFiles(skinfiles);
2384 Mod_MakeSortedSurfaces(loadmodel);
2386 // compute all the mesh information that was not loaded from the file
2387 if (loadmodel->surfmesh.data_element3s)
2388 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2389 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2390 Mod_BuildBaseBonePoses();
2391 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);
2392 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2394 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2397 // no idea why PSK/PSA files contain weird quaternions but they do...
2398 #define PSKQUATNEGATIONS
2399 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2401 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2402 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2403 fs_offset_t filesize;
2408 pskboneinfo_t *bones;
2409 pskrawweights_t *rawweights;
2410 pskboneinfo_t *animbones;
2411 pskaniminfo_t *anims;
2412 pskanimkeys_t *animkeys;
2413 void *animfilebuffer, *animbuffer, *animbufferend;
2414 unsigned char *data;
2416 skinfile_t *skinfiles;
2417 char animname[MAX_QPATH];
2419 float biggestorigin;
2421 pchunk = (pskchunk_t *)buffer;
2422 if (strcmp(pchunk->id, "ACTRHEAD"))
2423 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2425 loadmodel->modeldatatypestring = "PSK";
2427 loadmodel->type = mod_alias;
2428 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2429 loadmodel->DrawSky = NULL;
2430 loadmodel->DrawAddWaterPlanes = NULL;
2431 loadmodel->Draw = R_Q1BSP_Draw;
2432 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2433 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2434 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2435 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2436 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2437 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2438 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2439 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2440 loadmodel->TraceBox = Mod_TraceBox_using_TraceBoxBox;
2441 loadmodel->TraceBoxBox = Mod_MDLMD2MD3_TraceBoxBox;
2442 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2443 loadmodel->PointSuperContents = NULL;
2444 loadmodel->synctype = ST_RAND;
2446 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2447 strlcat(animname, ".psa", sizeof(animname));
2448 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2449 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2450 if (animbuffer == NULL)
2451 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2470 while (buffer < bufferend)
2472 pchunk = (pskchunk_t *)buffer;
2473 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2474 version = LittleLong(pchunk->version);
2475 recordsize = LittleLong(pchunk->recordsize);
2476 numrecords = LittleLong(pchunk->numrecords);
2477 if (developer_extra.integer)
2478 Con_DPrintf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2479 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2480 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);
2481 if (!strcmp(pchunk->id, "ACTRHEAD"))
2485 else if (!strcmp(pchunk->id, "PNTS0000"))
2488 if (recordsize != sizeof(*p))
2489 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2490 // byteswap in place and keep the pointer
2491 numpnts = numrecords;
2492 pnts = (pskpnts_t *)buffer;
2493 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2495 p->origin[0] = LittleFloat(p->origin[0]);
2496 p->origin[1] = LittleFloat(p->origin[1]);
2497 p->origin[2] = LittleFloat(p->origin[2]);
2501 else if (!strcmp(pchunk->id, "VTXW0000"))
2504 if (recordsize != sizeof(*p))
2505 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2506 // byteswap in place and keep the pointer
2507 numvtxw = numrecords;
2508 vtxw = (pskvtxw_t *)buffer;
2509 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2511 p->pntsindex = LittleShort(p->pntsindex);
2512 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2513 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2514 if (p->pntsindex >= numpnts)
2516 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2522 else if (!strcmp(pchunk->id, "FACE0000"))
2525 if (recordsize != sizeof(*p))
2526 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2527 // byteswap in place and keep the pointer
2528 numfaces = numrecords;
2529 faces = (pskface_t *)buffer;
2530 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2532 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2533 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2534 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2535 p->group = LittleLong(p->group);
2536 if (p->vtxwindex[0] >= numvtxw)
2538 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2539 p->vtxwindex[0] = 0;
2541 if (p->vtxwindex[1] >= numvtxw)
2543 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2544 p->vtxwindex[1] = 0;
2546 if (p->vtxwindex[2] >= numvtxw)
2548 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2549 p->vtxwindex[2] = 0;
2554 else if (!strcmp(pchunk->id, "MATT0000"))
2557 if (recordsize != sizeof(*p))
2558 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2559 // byteswap in place and keep the pointer
2560 nummatts = numrecords;
2561 matts = (pskmatt_t *)buffer;
2562 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2568 else if (!strcmp(pchunk->id, "REFSKELT"))
2571 if (recordsize != sizeof(*p))
2572 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2573 // byteswap in place and keep the pointer
2574 numbones = numrecords;
2575 bones = (pskboneinfo_t *)buffer;
2576 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2578 p->numchildren = LittleLong(p->numchildren);
2579 p->parent = LittleLong(p->parent);
2580 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2581 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2582 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2583 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2584 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2585 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2586 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2587 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2588 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2589 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2590 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2591 #ifdef PSKQUATNEGATIONS
2594 p->basepose.quat[0] *= -1;
2595 p->basepose.quat[1] *= -1;
2596 p->basepose.quat[2] *= -1;
2600 p->basepose.quat[0] *= 1;
2601 p->basepose.quat[1] *= -1;
2602 p->basepose.quat[2] *= 1;
2605 if (p->parent < 0 || p->parent >= numbones)
2607 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2613 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2616 if (recordsize != sizeof(*p))
2617 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2618 // byteswap in place and keep the pointer
2619 numrawweights = numrecords;
2620 rawweights = (pskrawweights_t *)buffer;
2621 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2623 p->weight = LittleFloat(p->weight);
2624 p->pntsindex = LittleLong(p->pntsindex);
2625 p->boneindex = LittleLong(p->boneindex);
2626 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2628 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2631 if (p->boneindex < 0 || p->boneindex >= numbones)
2633 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2641 while (animbuffer < animbufferend)
2643 pchunk = (pskchunk_t *)animbuffer;
2644 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2645 version = LittleLong(pchunk->version);
2646 recordsize = LittleLong(pchunk->recordsize);
2647 numrecords = LittleLong(pchunk->numrecords);
2648 if (developer_extra.integer)
2649 Con_DPrintf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2650 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2651 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);
2652 if (!strcmp(pchunk->id, "ANIMHEAD"))
2656 else if (!strcmp(pchunk->id, "BONENAMES"))
2659 if (recordsize != sizeof(*p))
2660 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2661 // byteswap in place and keep the pointer
2662 numanimbones = numrecords;
2663 animbones = (pskboneinfo_t *)animbuffer;
2664 // NOTE: supposedly psa does not need to match the psk model, the
2665 // bones missing from the psa would simply use their base
2666 // positions from the psk, but this is hard for me to implement
2667 // and people can easily make animations that match.
2668 if (numanimbones != numbones)
2669 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2670 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2672 p->numchildren = LittleLong(p->numchildren);
2673 p->parent = LittleLong(p->parent);
2674 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2675 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2676 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2677 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2678 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2679 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2680 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2681 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2682 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2683 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2684 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2685 #ifdef PSKQUATNEGATIONS
2688 p->basepose.quat[0] *= -1;
2689 p->basepose.quat[1] *= -1;
2690 p->basepose.quat[2] *= -1;
2694 p->basepose.quat[0] *= 1;
2695 p->basepose.quat[1] *= -1;
2696 p->basepose.quat[2] *= 1;
2699 if (p->parent < 0 || p->parent >= numanimbones)
2701 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2704 // check that bones are the same as in the base
2705 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2706 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2710 else if (!strcmp(pchunk->id, "ANIMINFO"))
2713 if (recordsize != sizeof(*p))
2714 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2715 // byteswap in place and keep the pointer
2716 numanims = numrecords;
2717 anims = (pskaniminfo_t *)animbuffer;
2718 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2720 p->numbones = LittleLong(p->numbones);
2721 p->playtime = LittleFloat(p->playtime);
2722 p->fps = LittleFloat(p->fps);
2723 p->firstframe = LittleLong(p->firstframe);
2724 p->numframes = LittleLong(p->numframes);
2725 if (p->numbones != numbones)
2726 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2730 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2733 if (recordsize != sizeof(*p))
2734 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2735 numanimkeys = numrecords;
2736 animkeys = (pskanimkeys_t *)animbuffer;
2737 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2739 p->origin[0] = LittleFloat(p->origin[0]);
2740 p->origin[1] = LittleFloat(p->origin[1]);
2741 p->origin[2] = LittleFloat(p->origin[2]);
2742 p->quat[0] = LittleFloat(p->quat[0]);
2743 p->quat[1] = LittleFloat(p->quat[1]);
2744 p->quat[2] = LittleFloat(p->quat[2]);
2745 p->quat[3] = LittleFloat(p->quat[3]);
2746 p->frametime = LittleFloat(p->frametime);
2747 #ifdef PSKQUATNEGATIONS
2748 if (index % numbones)
2763 // TODO: allocate bonepose stuff
2766 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2769 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2770 Host_Error("%s: missing required chunks", loadmodel->name);
2772 loadmodel->numframes = 0;
2773 for (index = 0;index < numanims;index++)
2774 loadmodel->numframes += anims[index].numframes;
2776 if (numanimkeys != numbones * loadmodel->numframes)
2777 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2779 meshvertices = numvtxw;
2780 meshtriangles = numfaces;
2782 // load external .skin files if present
2783 skinfiles = Mod_LoadSkinFiles();
2784 if (loadmodel->numskins < 1)
2785 loadmodel->numskins = 1;
2786 loadmodel->num_bones = numbones;
2787 loadmodel->num_poses = loadmodel->numframes;
2788 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2789 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2790 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2791 loadmodel->surfmesh.num_vertices = meshvertices;
2792 loadmodel->surfmesh.num_triangles = meshtriangles;
2793 // do most allocations as one merged chunk
2794 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(int[4]) + loadmodel->surfmesh.num_vertices * sizeof(float[4]) + 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);
2795 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2796 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2797 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2798 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2799 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2800 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2801 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2802 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2803 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2804 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2805 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2806 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += loadmodel->surfmesh.num_vertices * sizeof(int[4]);
2807 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[4]);
2808 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2809 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2810 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2811 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2812 if (loadmodel->surfmesh.num_vertices <= 65536)
2813 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2814 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2816 for (i = 0;i < loadmodel->numskins;i++)
2818 loadmodel->skinscenes[i].firstframe = i;
2819 loadmodel->skinscenes[i].framecount = 1;
2820 loadmodel->skinscenes[i].loop = true;
2821 loadmodel->skinscenes[i].framerate = 10;
2825 for (index = 0, i = 0;index < nummatts;index++)
2827 // since psk models do not have named sections, reuse their shader name as the section name
2828 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2829 loadmodel->sortedmodelsurfaces[index] = index;
2830 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2831 loadmodel->data_surfaces[index].num_firstvertex = 0;
2832 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2835 // copy over the vertex locations and texcoords
2836 for (index = 0;index < numvtxw;index++)
2838 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2839 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2840 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2841 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2842 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2845 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2846 for (index = 0;index < numfaces;index++)
2847 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2848 for (index = 0, i = 0;index < nummatts;index++)
2850 loadmodel->data_surfaces[index].num_firsttriangle = i;
2851 i += loadmodel->data_surfaces[index].num_triangles;
2852 loadmodel->data_surfaces[index].num_triangles = 0;
2854 for (index = 0;index < numfaces;index++)
2856 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2857 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2858 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2859 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2862 // copy over the bones
2863 for (index = 0;index < numbones;index++)
2865 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2866 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2867 if (loadmodel->data_bones[index].parent >= index)
2868 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2871 // sort the psk point weights into the vertex weight tables
2872 // (which only accept up to 4 bones per vertex)
2873 for (index = 0;index < numvtxw;index++)
2877 for (j = 0;j < numrawweights;j++)
2879 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2881 int boneindex = rawweights[j].boneindex;
2882 float influence = rawweights[j].weight;
2883 for (l = 0;l < 4;l++)
2885 if (loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] < influence)
2887 // move lower influence weights out of the way first
2889 for (l2 = 3;l2 > l;l2--)
2891 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2-1];
2892 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2-1];
2894 // store the new weight
2895 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] = influence;
2896 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l] = boneindex;
2903 for (l = 0;l < 4;l++)
2904 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l];
2905 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2907 float f = 1.0f / sum;
2908 for (l = 0;l < 4;l++)
2909 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] *= f;
2913 // set up the animscenes based on the anims
2914 for (index = 0, i = 0;index < numanims;index++)
2916 for (j = 0;j < anims[index].numframes;j++, i++)
2918 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2919 loadmodel->animscenes[i].firstframe = i;
2920 loadmodel->animscenes[i].framecount = 1;
2921 loadmodel->animscenes[i].loop = true;
2922 loadmodel->animscenes[i].framerate = 10;
2926 // calculate the scaling value for bone origins so they can be compressed to short
2928 for (index = 0;index < numanimkeys;index++)
2930 pskanimkeys_t *k = animkeys + index;
2931 biggestorigin = max(biggestorigin, fabs(k->origin[0]));
2932 biggestorigin = max(biggestorigin, fabs(k->origin[1]));
2933 biggestorigin = max(biggestorigin, fabs(k->origin[2]));
2935 loadmodel->num_posescale = biggestorigin / 32767.0f;
2936 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2938 // load the poses from the animkeys
2939 for (index = 0;index < numanimkeys;index++)
2941 pskanimkeys_t *k = animkeys + index;
2943 Vector4Copy(k->quat, quat);
2945 Vector4Negate(quat, quat);
2946 Vector4Normalize2(quat, quat);
2947 // compress poses to the short[6] format for longterm storage
2948 loadmodel->data_poses6s[index*6+0] = k->origin[0] * loadmodel->num_poseinvscale;
2949 loadmodel->data_poses6s[index*6+1] = k->origin[1] * loadmodel->num_poseinvscale;
2950 loadmodel->data_poses6s[index*6+2] = k->origin[2] * loadmodel->num_poseinvscale;
2951 loadmodel->data_poses6s[index*6+3] = quat[0] * 32767.0f;
2952 loadmodel->data_poses6s[index*6+4] = quat[1] * 32767.0f;
2953 loadmodel->data_poses6s[index*6+5] = quat[2] * 32767.0f;
2955 Mod_FreeSkinFiles(skinfiles);
2956 Mem_Free(animfilebuffer);
2957 Mod_MakeSortedSurfaces(loadmodel);
2959 // compute all the mesh information that was not loaded from the file
2960 // TODO: honor smoothing groups somehow?
2961 if (loadmodel->surfmesh.data_element3s)
2962 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2963 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2964 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2965 Mod_BuildBaseBonePoses();
2966 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2967 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);
2968 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2969 Mod_Alias_CalculateBoundingBox();
2971 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;