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_TraceBox(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask)
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(boxmins, boxmaxs))
744 VectorAdd(start, boxmins, shiftstart);
745 VectorAdd(end, boxmins, shiftend);
746 Mod_MDLMD2MD3_TraceLine(model, frameblend, skeleton, trace, shiftstart, shiftend, hitsupercontentsmask);
747 VectorSubtract(trace->endpos, boxmins, 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 segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
764 segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
765 segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
766 segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
767 segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
768 segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
769 VectorAdd(start, boxmins, boxstartmins);
770 VectorAdd(start, boxmaxs, boxstartmaxs);
771 VectorAdd(end, boxmins, boxendmins);
772 VectorAdd(end, boxmaxs, boxendmaxs);
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_MDLMD2MD3_TraceBox;
977 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
978 loadmodel->PointSuperContents = NULL;
980 loadmodel->num_surfaces = 1;
981 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
982 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
983 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
984 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
985 loadmodel->sortedmodelsurfaces[0] = 0;
987 loadmodel->numskins = LittleLong(pinmodel->numskins);
988 BOUNDI(loadmodel->numskins,0,65536);
989 skinwidth = LittleLong (pinmodel->skinwidth);
990 BOUNDI(skinwidth,0,65536);
991 skinheight = LittleLong (pinmodel->skinheight);
992 BOUNDI(skinheight,0,65536);
993 numverts = LittleLong(pinmodel->numverts);
994 BOUNDI(numverts,0,65536);
995 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
996 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
997 loadmodel->numframes = LittleLong(pinmodel->numframes);
998 BOUNDI(loadmodel->numframes,0,65536);
999 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
1000 BOUNDI((int)loadmodel->synctype,0,2);
1001 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1002 i = LittleLong (pinmodel->flags);
1003 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1005 for (i = 0;i < 3;i++)
1007 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
1008 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
1011 startskins = datapointer;
1013 for (i = 0;i < loadmodel->numskins;i++)
1015 pinskintype = (daliasskintype_t *)datapointer;
1016 datapointer += sizeof(daliasskintype_t);
1017 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
1021 pinskingroup = (daliasskingroup_t *)datapointer;
1022 datapointer += sizeof(daliasskingroup_t);
1023 groupskins = LittleLong(pinskingroup->numskins);
1024 datapointer += sizeof(daliasskininterval_t) * groupskins;
1027 for (j = 0;j < groupskins;j++)
1029 datapointer += skinwidth * skinheight;
1034 pinstverts = (stvert_t *)datapointer;
1035 datapointer += sizeof(stvert_t) * numverts;
1037 pintriangles = (dtriangle_t *)datapointer;
1038 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
1040 startframes = datapointer;
1041 loadmodel->surfmesh.num_morphframes = 0;
1042 for (i = 0;i < loadmodel->numframes;i++)
1044 pinframetype = (daliasframetype_t *)datapointer;
1045 datapointer += sizeof(daliasframetype_t);
1046 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
1050 pinframegroup = (daliasgroup_t *)datapointer;
1051 datapointer += sizeof(daliasgroup_t);
1052 groupframes = LittleLong(pinframegroup->numframes);
1053 datapointer += sizeof(daliasinterval_t) * groupframes;
1056 for (j = 0;j < groupframes;j++)
1058 datapointer += sizeof(daliasframe_t);
1059 datapointer += sizeof(trivertx_t) * numverts;
1060 loadmodel->surfmesh.num_morphframes++;
1063 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1065 // store texture coordinates into temporary array, they will be stored
1066 // after usage is determined (triangle data)
1067 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
1068 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
1069 vertonseam = vertremap + numverts * 2;
1071 scales = 1.0 / skinwidth;
1072 scalet = 1.0 / skinheight;
1073 for (i = 0;i < numverts;i++)
1075 vertonseam[i] = LittleLong(pinstverts[i].onseam);
1076 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
1077 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
1078 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
1079 vertst[(i+numverts)*2+1] = vertst[i*2+1];
1082 // load triangle data
1083 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1085 // read the triangle elements
1086 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1087 for (j = 0;j < 3;j++)
1088 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1089 // validate (note numverts is used because this is the original data)
1090 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1091 // now butcher the elements according to vertonseam and tri->facesfront
1092 // and then compact the vertex set to remove duplicates
1093 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1094 if (!LittleLong(pintriangles[i].facesfront)) // backface
1095 for (j = 0;j < 3;j++)
1096 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1097 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1099 // (this uses vertremap to count usage to save some memory)
1100 for (i = 0;i < numverts*2;i++)
1102 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1103 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1104 // build remapping table and compact array
1105 loadmodel->surfmesh.num_vertices = 0;
1106 for (i = 0;i < numverts*2;i++)
1110 vertremap[i] = loadmodel->surfmesh.num_vertices;
1111 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1112 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1113 loadmodel->surfmesh.num_vertices++;
1116 vertremap[i] = -1; // not used at all
1118 // remap the elements to the new vertex set
1119 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1120 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1121 // store the texture coordinates
1122 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1123 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1125 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1126 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1129 // generate ushort elements array if possible
1130 if (loadmodel->surfmesh.num_vertices <= 65536)
1131 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1132 if (loadmodel->surfmesh.data_element3s)
1133 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1134 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1137 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1138 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1139 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1140 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1141 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1142 Mod_Alias_CalculateBoundingBox();
1143 Mod_Alias_MorphMesh_CompileFrames();
1146 Mem_Free(vertremap);
1149 skinfiles = Mod_LoadSkinFiles();
1152 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1153 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1154 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1155 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1156 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1157 Mod_FreeSkinFiles(skinfiles);
1158 for (i = 0;i < loadmodel->numskins;i++)
1160 loadmodel->skinscenes[i].firstframe = i;
1161 loadmodel->skinscenes[i].framecount = 1;
1162 loadmodel->skinscenes[i].loop = true;
1163 loadmodel->skinscenes[i].framerate = 10;
1168 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1169 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1170 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1171 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1173 datapointer = startskins;
1174 for (i = 0;i < loadmodel->numskins;i++)
1176 pinskintype = (daliasskintype_t *)datapointer;
1177 datapointer += sizeof(daliasskintype_t);
1179 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1186 pinskingroup = (daliasskingroup_t *)datapointer;
1187 datapointer += sizeof(daliasskingroup_t);
1189 groupskins = LittleLong (pinskingroup->numskins);
1191 pinskinintervals = (daliasskininterval_t *)datapointer;
1192 datapointer += sizeof(daliasskininterval_t) * groupskins;
1194 interval = LittleFloat(pinskinintervals[0].interval);
1195 if (interval < 0.01f)
1197 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1202 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1203 loadmodel->skinscenes[i].firstframe = totalskins;
1204 loadmodel->skinscenes[i].framecount = groupskins;
1205 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1206 loadmodel->skinscenes[i].loop = true;
1208 for (j = 0;j < groupskins;j++)
1211 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1213 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1214 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))
1215 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));
1216 datapointer += skinwidth * skinheight;
1220 // check for skins that don't exist in the model, but do exist as external images
1221 // (this was added because yummyluv kept pestering me about support for it)
1222 // TODO: support shaders here?
1223 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)))
1225 // expand the arrays to make room
1226 tempskinscenes = loadmodel->skinscenes;
1227 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1228 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1229 Mem_Free(tempskinscenes);
1231 tempaliasskins = loadmodel->data_textures;
1232 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1233 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1234 Mem_Free(tempaliasskins);
1236 // store the info about the new skin
1237 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1238 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1239 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1240 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1241 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1242 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1244 //increase skin counts
1245 loadmodel->numskins++;
1248 // fix up the pointers since they are pointing at the old textures array
1249 // FIXME: this is a hack!
1250 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1251 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1255 surface = loadmodel->data_surfaces;
1256 surface->texture = loadmodel->data_textures;
1257 surface->num_firsttriangle = 0;
1258 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1259 surface->num_firstvertex = 0;
1260 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1262 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1265 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1267 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1268 float iskinwidth, iskinheight;
1269 unsigned char *data;
1270 msurface_t *surface;
1272 unsigned char *base, *datapointer;
1273 md2frame_t *pinframe;
1275 md2triangle_t *intri;
1276 unsigned short *inst;
1277 struct md2verthash_s
1279 struct md2verthash_s *next;
1283 *hash, **md2verthash, *md2verthashdata;
1284 skinfile_t *skinfiles;
1286 pinmodel = (md2_t *)buffer;
1287 base = (unsigned char *)buffer;
1289 version = LittleLong (pinmodel->version);
1290 if (version != MD2ALIAS_VERSION)
1291 Host_Error ("%s has wrong version number (%i should be %i)",
1292 loadmodel->name, version, MD2ALIAS_VERSION);
1294 loadmodel->modeldatatypestring = "MD2";
1296 loadmodel->type = mod_alias;
1297 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1298 loadmodel->DrawSky = NULL;
1299 loadmodel->DrawAddWaterPlanes = NULL;
1300 loadmodel->Draw = R_Q1BSP_Draw;
1301 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1302 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1303 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1304 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1305 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1306 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1307 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1308 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1309 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1310 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1311 loadmodel->PointSuperContents = NULL;
1313 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1314 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1315 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1316 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1317 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1318 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1319 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1320 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1322 end = LittleLong(pinmodel->ofs_end);
1323 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1324 Host_Error ("%s is not a valid model", loadmodel->name);
1325 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1326 Host_Error ("%s is not a valid model", loadmodel->name);
1327 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1328 Host_Error ("%s is not a valid model", loadmodel->name);
1329 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1330 Host_Error ("%s is not a valid model", loadmodel->name);
1331 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1332 Host_Error ("%s is not a valid model", loadmodel->name);
1334 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1335 numxyz = LittleLong(pinmodel->num_xyz);
1336 numst = LittleLong(pinmodel->num_st);
1337 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1338 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1339 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1340 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1341 skinwidth = LittleLong(pinmodel->skinwidth);
1342 skinheight = LittleLong(pinmodel->skinheight);
1343 iskinwidth = 1.0f / skinwidth;
1344 iskinheight = 1.0f / skinheight;
1346 loadmodel->num_surfaces = 1;
1347 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1348 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]));
1349 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1350 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1351 loadmodel->sortedmodelsurfaces[0] = 0;
1352 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1353 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1354 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1355 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1357 loadmodel->synctype = ST_RAND;
1360 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1361 skinfiles = Mod_LoadSkinFiles();
1364 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1365 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1366 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1367 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1368 Mod_FreeSkinFiles(skinfiles);
1370 else if (loadmodel->numskins)
1372 // skins found (most likely not a player model)
1373 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1374 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1375 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1376 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1377 Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
1381 // no skins (most likely a player model)
1382 loadmodel->numskins = 1;
1383 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1384 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1385 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1386 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1389 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1390 for (i = 0;i < loadmodel->numskins;i++)
1392 loadmodel->skinscenes[i].firstframe = i;
1393 loadmodel->skinscenes[i].framecount = 1;
1394 loadmodel->skinscenes[i].loop = true;
1395 loadmodel->skinscenes[i].framerate = 10;
1398 // load the triangles and stvert data
1399 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1400 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1401 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1402 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1403 // swap the triangle list
1404 loadmodel->surfmesh.num_vertices = 0;
1405 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1407 for (j = 0;j < 3;j++)
1409 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1410 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1413 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1418 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1421 hashindex = (xyz * 256 + st) & 65535;
1422 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1423 if (hash->xyz == xyz && hash->st == st)
1427 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1430 hash->next = md2verthash[hashindex];
1431 md2verthash[hashindex] = hash;
1433 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1437 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1438 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));
1439 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1440 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1441 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1444 hash = md2verthashdata + i;
1445 vertremap[i] = hash->xyz;
1446 sts = LittleShort(inst[hash->st*2+0]);
1447 stt = LittleShort(inst[hash->st*2+1]);
1448 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1450 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1454 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1455 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1458 Mem_Free(md2verthash);
1459 Mem_Free(md2verthashdata);
1461 // generate ushort elements array if possible
1462 if (loadmodel->surfmesh.num_vertices <= 65536)
1463 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1464 if (loadmodel->surfmesh.data_element3s)
1465 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1466 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1469 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1470 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1475 pinframe = (md2frame_t *)datapointer;
1476 datapointer += sizeof(md2frame_t);
1477 // store the frame scale/translate into the appropriate array
1478 for (j = 0;j < 3;j++)
1480 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1481 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1483 // convert the vertices
1484 v = (trivertx_t *)datapointer;
1485 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1486 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1487 out[k] = v[vertremap[k]];
1488 datapointer += numxyz * sizeof(trivertx_t);
1490 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1491 loadmodel->animscenes[i].firstframe = i;
1492 loadmodel->animscenes[i].framecount = 1;
1493 loadmodel->animscenes[i].framerate = 10;
1494 loadmodel->animscenes[i].loop = true;
1497 Mem_Free(vertremap);
1499 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1500 Mod_Alias_CalculateBoundingBox();
1501 Mod_Alias_MorphMesh_CompileFrames();
1503 surface = loadmodel->data_surfaces;
1504 surface->texture = loadmodel->data_textures;
1505 surface->num_firsttriangle = 0;
1506 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1507 surface->num_firstvertex = 0;
1508 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1510 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1513 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1515 int i, j, k, version, meshvertices, meshtriangles;
1516 unsigned char *data;
1517 msurface_t *surface;
1518 md3modelheader_t *pinmodel;
1519 md3frameinfo_t *pinframe;
1522 skinfile_t *skinfiles;
1524 pinmodel = (md3modelheader_t *)buffer;
1526 if (memcmp(pinmodel->identifier, "IDP3", 4))
1527 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1528 version = LittleLong (pinmodel->version);
1529 if (version != MD3VERSION)
1530 Host_Error ("%s has wrong version number (%i should be %i)",
1531 loadmodel->name, version, MD3VERSION);
1533 skinfiles = Mod_LoadSkinFiles();
1534 if (loadmodel->numskins < 1)
1535 loadmodel->numskins = 1;
1537 loadmodel->modeldatatypestring = "MD3";
1539 loadmodel->type = mod_alias;
1540 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1541 loadmodel->DrawSky = NULL;
1542 loadmodel->DrawAddWaterPlanes = NULL;
1543 loadmodel->Draw = R_Q1BSP_Draw;
1544 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1545 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1546 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1547 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1548 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1549 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1550 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1551 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1552 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1553 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1554 loadmodel->PointSuperContents = NULL;
1555 loadmodel->synctype = ST_RAND;
1556 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1557 i = LittleLong (pinmodel->flags);
1558 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1560 // set up some global info about the model
1561 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1562 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1564 // make skinscenes for the skins (no groups)
1565 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1566 for (i = 0;i < loadmodel->numskins;i++)
1568 loadmodel->skinscenes[i].firstframe = i;
1569 loadmodel->skinscenes[i].framecount = 1;
1570 loadmodel->skinscenes[i].loop = true;
1571 loadmodel->skinscenes[i].framerate = 10;
1575 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1576 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1578 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1579 loadmodel->animscenes[i].firstframe = i;
1580 loadmodel->animscenes[i].framecount = 1;
1581 loadmodel->animscenes[i].framerate = 10;
1582 loadmodel->animscenes[i].loop = true;
1586 loadmodel->num_tagframes = loadmodel->numframes;
1587 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1588 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1589 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1591 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1592 for (j = 0;j < 9;j++)
1593 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1594 for (j = 0;j < 3;j++)
1595 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1596 //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);
1602 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)))
1604 if (memcmp(pinmesh->identifier, "IDP3", 4))
1605 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1606 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1607 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1608 meshvertices += LittleLong(pinmesh->num_vertices);
1609 meshtriangles += LittleLong(pinmesh->num_triangles);
1612 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1613 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1614 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1615 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));
1616 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1617 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1618 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1619 loadmodel->surfmesh.num_vertices = meshvertices;
1620 loadmodel->surfmesh.num_triangles = meshtriangles;
1621 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1622 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1623 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1624 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1625 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1626 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1627 if (meshvertices <= 65536)
1628 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1632 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)))
1634 if (memcmp(pinmesh->identifier, "IDP3", 4))
1635 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1636 loadmodel->sortedmodelsurfaces[i] = i;
1637 surface = loadmodel->data_surfaces + i;
1638 surface->texture = loadmodel->data_textures + i;
1639 surface->num_firsttriangle = meshtriangles;
1640 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1641 surface->num_firstvertex = meshvertices;
1642 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1643 meshvertices += surface->num_vertices;
1644 meshtriangles += surface->num_triangles;
1646 for (j = 0;j < surface->num_triangles * 3;j++)
1647 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1648 for (j = 0;j < surface->num_vertices;j++)
1650 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1651 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1653 for (j = 0;j < loadmodel->numframes;j++)
1655 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1656 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1657 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1659 out->origin[0] = LittleShort(in->origin[0]);
1660 out->origin[1] = LittleShort(in->origin[1]);
1661 out->origin[2] = LittleShort(in->origin[2]);
1662 out->pitch = in->pitch;
1667 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1669 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1671 if (loadmodel->surfmesh.data_element3s)
1672 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1673 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1674 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1675 Mod_Alias_MorphMesh_CompileFrames();
1676 Mod_Alias_CalculateBoundingBox();
1677 Mod_FreeSkinFiles(skinfiles);
1678 Mod_MakeSortedSurfaces(loadmodel);
1680 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1681 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1684 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1686 zymtype1header_t *pinmodel, *pheader;
1687 unsigned char *pbase;
1688 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1689 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose, f, biggestorigin, tempvec[3], modelscale;
1690 zymvertex_t *verts, *vertdata;
1694 skinfile_t *skinfiles;
1695 unsigned char *data;
1696 msurface_t *surface;
1698 pinmodel = (zymtype1header_t *)buffer;
1699 pbase = (unsigned char *)buffer;
1700 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1701 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1702 if (BigLong(pinmodel->type) != 1)
1703 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1705 loadmodel->modeldatatypestring = "ZYM";
1707 loadmodel->type = mod_alias;
1708 loadmodel->synctype = ST_RAND;
1712 pheader->type = BigLong(pinmodel->type);
1713 pheader->filesize = BigLong(pinmodel->filesize);
1714 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1715 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1716 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1717 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1718 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1719 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1720 pheader->radius = BigFloat(pinmodel->radius);
1721 pheader->numverts = BigLong(pinmodel->numverts);
1722 pheader->numtris = BigLong(pinmodel->numtris);
1723 pheader->numshaders = BigLong(pinmodel->numshaders);
1724 pheader->numbones = BigLong(pinmodel->numbones);
1725 pheader->numscenes = BigLong(pinmodel->numscenes);
1726 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1727 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1728 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1729 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1730 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1731 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1732 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1733 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1734 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1735 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1736 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1737 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1738 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1739 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1740 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1741 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1742 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1743 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1745 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1747 Con_Printf("%s has no geometry\n", loadmodel->name);
1750 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1752 Con_Printf("%s has no animations\n", loadmodel->name);
1756 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1757 loadmodel->DrawSky = NULL;
1758 loadmodel->DrawAddWaterPlanes = NULL;
1759 loadmodel->Draw = R_Q1BSP_Draw;
1760 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1761 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1762 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1763 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1764 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1765 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1766 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1767 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1768 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1769 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1770 loadmodel->PointSuperContents = NULL;
1772 loadmodel->numframes = pheader->numscenes;
1773 loadmodel->num_surfaces = pheader->numshaders;
1775 skinfiles = Mod_LoadSkinFiles();
1776 if (loadmodel->numskins < 1)
1777 loadmodel->numskins = 1;
1779 // make skinscenes for the skins (no groups)
1780 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1781 for (i = 0;i < loadmodel->numskins;i++)
1783 loadmodel->skinscenes[i].firstframe = i;
1784 loadmodel->skinscenes[i].framecount = 1;
1785 loadmodel->skinscenes[i].loop = true;
1786 loadmodel->skinscenes[i].framerate = 10;
1790 modelradius = pheader->radius;
1791 for (i = 0;i < 3;i++)
1793 loadmodel->normalmins[i] = pheader->mins[i];
1794 loadmodel->normalmaxs[i] = pheader->maxs[i];
1795 loadmodel->rotatedmins[i] = -modelradius;
1796 loadmodel->rotatedmaxs[i] = modelradius;
1798 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1799 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1800 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1801 if (loadmodel->yawmaxs[0] > modelradius)
1802 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1803 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1804 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1805 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1806 loadmodel->radius = modelradius;
1807 loadmodel->radius2 = modelradius * modelradius;
1809 // go through the lumps, swapping things
1811 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1812 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1813 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1814 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1815 for (i = 0;i < pheader->numscenes;i++)
1817 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1818 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1819 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1820 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1821 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1822 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1823 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1824 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1825 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1826 if (loadmodel->animscenes[i].framerate < 0)
1827 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1831 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1832 loadmodel->num_bones = pheader->numbones;
1833 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1834 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1835 for (i = 0;i < pheader->numbones;i++)
1837 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1838 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1839 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1840 if (loadmodel->data_bones[i].parent >= i)
1841 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1844 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1845 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1846 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1847 for (i = 0;i < pheader->numverts;i++)
1849 vertbonecounts[i] = BigLong(bonecount[i]);
1850 if (vertbonecounts[i] != 1)
1851 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1854 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1856 meshvertices = pheader->numverts;
1857 meshtriangles = pheader->numtris;
1859 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1860 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1861 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1862 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]));
1863 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1864 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1865 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1866 loadmodel->surfmesh.num_vertices = meshvertices;
1867 loadmodel->surfmesh.num_triangles = meshtriangles;
1868 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1869 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1870 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1871 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1872 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1873 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1874 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1875 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1876 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1877 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1878 if (loadmodel->surfmesh.num_vertices <= 65536)
1879 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1880 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
1882 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1883 poses = (float *) (pheader->lump_poses.start + pbase);
1884 // figure out scale of model from root bone, for compatibility with old zmodel versions
1885 tempvec[0] = BigFloat(poses[0]);
1886 tempvec[1] = BigFloat(poses[1]);
1887 tempvec[2] = BigFloat(poses[2]);
1888 modelscale = VectorLength(tempvec);
1890 for (i = 0;i < loadmodel->num_bones * numposes * 12;i++)
1892 f = fabs(BigFloat(poses[i]));
1893 biggestorigin = max(biggestorigin, f);
1895 loadmodel->num_posescale = biggestorigin / 32767.0f;
1896 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
1897 for (i = 0;i < numposes;i++)
1899 const float *frameposes = (float *) (pheader->lump_poses.start + pbase) + 12*i*loadmodel->num_bones;
1900 for (j = 0;j < loadmodel->num_bones;j++)
1903 matrix4x4_t posematrix;
1904 for (k = 0;k < 12;k++)
1905 pose[k] = BigFloat(frameposes[j*12+k]);
1906 //if (j < loadmodel->num_bones)
1907 // 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));
1908 // scale child bones to match the root scale
1909 if (loadmodel->data_bones[j].parent >= 0)
1911 pose[3] *= modelscale;
1912 pose[7] *= modelscale;
1913 pose[11] *= modelscale;
1915 // normalize rotation matrix
1916 VectorNormalize(pose + 0);
1917 VectorNormalize(pose + 4);
1918 VectorNormalize(pose + 8);
1919 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
1920 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
1924 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1925 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1926 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1927 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1928 // (converting from weight-blending skeletal animation to
1929 // deformation-based skeletal animation)
1930 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1931 for (i = 0;i < loadmodel->num_bones;i++)
1934 for (k = 0;k < 12;k++)
1935 m[k] = BigFloat(poses[i*12+k]);
1936 if (loadmodel->data_bones[i].parent >= 0)
1937 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1939 for (k = 0;k < 12;k++)
1940 bonepose[12*i+k] = m[k];
1942 for (j = 0;j < pheader->numverts;j++)
1944 // this format really should have had a per vertexweight weight value...
1945 // but since it does not, the weighting is completely ignored and
1946 // only one weight is allowed per vertex
1947 int boneindex = BigLong(vertdata[j].bonenum);
1948 const float *m = bonepose + 12 * boneindex;
1949 float relativeorigin[3];
1950 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1951 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1952 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1953 // transform the vertex bone weight into the base mesh
1954 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1955 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1956 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1957 // store the weight as the primary weight on this vertex
1958 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
1959 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = 1;
1962 // normals and tangents are calculated after elements are loaded
1964 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1965 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1966 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1967 for (i = 0;i < pheader->numverts;i++)
1969 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1970 // flip T coordinate for OpenGL
1971 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1974 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1975 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1976 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1978 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1979 //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)
1980 // byteswap, validate, and swap winding order of tris
1981 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1982 if (pheader->lump_render.length != count)
1983 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1984 renderlist = (int *) (pheader->lump_render.start + pbase);
1985 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1987 for (i = 0;i < loadmodel->num_surfaces;i++)
1989 int firstvertex, lastvertex;
1990 if (renderlist >= renderlistend)
1991 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1992 count = BigLong(*renderlist);renderlist++;
1993 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1994 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1996 loadmodel->sortedmodelsurfaces[i] = i;
1997 surface = loadmodel->data_surfaces + i;
1998 surface->texture = loadmodel->data_textures + i;
1999 surface->num_firsttriangle = meshtriangles;
2000 surface->num_triangles = count;
2001 meshtriangles += surface->num_triangles;
2003 // load the elements
2004 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2005 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
2007 outelements[j*3+2] = BigLong(renderlist[0]);
2008 outelements[j*3+1] = BigLong(renderlist[1]);
2009 outelements[j*3+0] = BigLong(renderlist[2]);
2011 // validate the elements and find the used vertex range
2012 firstvertex = meshvertices;
2014 for (j = 0;j < surface->num_triangles * 3;j++)
2016 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
2017 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
2018 firstvertex = min(firstvertex, outelements[j]);
2019 lastvertex = max(lastvertex, outelements[j]);
2021 surface->num_firstvertex = firstvertex;
2022 surface->num_vertices = lastvertex + 1 - firstvertex;
2024 // since zym models do not have named sections, reuse their shader
2025 // name as the section name
2026 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
2027 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
2029 Mod_FreeSkinFiles(skinfiles);
2030 Mem_Free(vertbonecounts);
2032 Mod_MakeSortedSurfaces(loadmodel);
2034 // compute all the mesh information that was not loaded from the file
2035 if (loadmodel->surfmesh.data_element3s)
2036 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2037 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2038 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2039 Mod_BuildBaseBonePoses();
2040 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2041 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);
2042 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2044 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2047 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2049 dpmheader_t *pheader;
2053 unsigned char *pbase;
2054 int i, j, k, meshvertices, meshtriangles;
2055 skinfile_t *skinfiles;
2056 unsigned char *data;
2058 float biggestorigin, tempvec[3], modelscale;
2062 pheader = (dpmheader_t *)buffer;
2063 pbase = (unsigned char *)buffer;
2064 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2065 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2066 if (BigLong(pheader->type) != 2)
2067 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2069 loadmodel->modeldatatypestring = "DPM";
2071 loadmodel->type = mod_alias;
2072 loadmodel->synctype = ST_RAND;
2075 pheader->type = BigLong(pheader->type);
2076 pheader->filesize = BigLong(pheader->filesize);
2077 pheader->mins[0] = BigFloat(pheader->mins[0]);
2078 pheader->mins[1] = BigFloat(pheader->mins[1]);
2079 pheader->mins[2] = BigFloat(pheader->mins[2]);
2080 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2081 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2082 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2083 pheader->yawradius = BigFloat(pheader->yawradius);
2084 pheader->allradius = BigFloat(pheader->allradius);
2085 pheader->num_bones = BigLong(pheader->num_bones);
2086 pheader->num_meshs = BigLong(pheader->num_meshs);
2087 pheader->num_frames = BigLong(pheader->num_frames);
2088 pheader->ofs_bones = BigLong(pheader->ofs_bones);
2089 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2090 pheader->ofs_frames = BigLong(pheader->ofs_frames);
2092 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2094 Con_Printf("%s has no geometry\n", loadmodel->name);
2097 if (pheader->num_frames < 1)
2099 Con_Printf("%s has no frames\n", loadmodel->name);
2103 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2104 loadmodel->DrawSky = NULL;
2105 loadmodel->DrawAddWaterPlanes = NULL;
2106 loadmodel->Draw = R_Q1BSP_Draw;
2107 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2108 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2109 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2110 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2111 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2112 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2113 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2114 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2115 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2116 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2117 loadmodel->PointSuperContents = NULL;
2120 for (i = 0;i < 3;i++)
2122 loadmodel->normalmins[i] = pheader->mins[i];
2123 loadmodel->normalmaxs[i] = pheader->maxs[i];
2124 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2125 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2126 loadmodel->rotatedmins[i] = -pheader->allradius;
2127 loadmodel->rotatedmaxs[i] = pheader->allradius;
2129 loadmodel->radius = pheader->allradius;
2130 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2132 // load external .skin files if present
2133 skinfiles = Mod_LoadSkinFiles();
2134 if (loadmodel->numskins < 1)
2135 loadmodel->numskins = 1;
2140 // gather combined statistics from the meshes
2141 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2142 for (i = 0;i < (int)pheader->num_meshs;i++)
2144 int numverts = BigLong(dpmmesh->num_verts);
2145 meshvertices += numverts;
2146 meshtriangles += BigLong(dpmmesh->num_tris);
2150 loadmodel->numframes = pheader->num_frames;
2151 loadmodel->num_bones = pheader->num_bones;
2152 loadmodel->num_poses = loadmodel->numframes;
2153 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2154 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2155 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2156 // do most allocations as one merged chunk
2157 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));
2158 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2159 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2160 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2161 loadmodel->surfmesh.num_vertices = meshvertices;
2162 loadmodel->surfmesh.num_triangles = meshtriangles;
2163 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2164 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2165 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2166 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2167 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2168 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2169 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2170 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
2171 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
2172 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2173 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2174 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2175 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2176 if (meshvertices <= 65536)
2177 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2178 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2180 for (i = 0;i < loadmodel->numskins;i++)
2182 loadmodel->skinscenes[i].firstframe = i;
2183 loadmodel->skinscenes[i].framecount = 1;
2184 loadmodel->skinscenes[i].loop = true;
2185 loadmodel->skinscenes[i].framerate = 10;
2188 // load the bone info
2189 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2190 for (i = 0;i < loadmodel->num_bones;i++)
2192 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2193 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2194 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2195 if (loadmodel->data_bones[i].parent >= i)
2196 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2200 frames = (dpmframe_t *) (pbase + pheader->ofs_frames);
2201 // figure out scale of model from root bone, for compatibility with old dpmodel versions
2202 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2203 tempvec[0] = BigFloat(poses[0]);
2204 tempvec[1] = BigFloat(poses[1]);
2205 tempvec[2] = BigFloat(poses[2]);
2206 modelscale = VectorLength(tempvec);
2208 for (i = 0;i < loadmodel->numframes;i++)
2210 memcpy(loadmodel->animscenes[i].name, frames[i].name, sizeof(frames[i].name));
2211 loadmodel->animscenes[i].firstframe = i;
2212 loadmodel->animscenes[i].framecount = 1;
2213 loadmodel->animscenes[i].loop = true;
2214 loadmodel->animscenes[i].framerate = 10;
2215 // load the bone poses for this frame
2216 poses = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2217 for (j = 0;j < loadmodel->num_bones*12;j++)
2219 f = fabs(BigFloat(poses[j]));
2220 biggestorigin = max(biggestorigin, f);
2222 // stuff not processed here: mins, maxs, yawradius, allradius
2224 loadmodel->num_posescale = biggestorigin / 32767.0f;
2225 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2226 for (i = 0;i < loadmodel->numframes;i++)
2228 const float *frameposes = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2229 for (j = 0;j < loadmodel->num_bones;j++)
2232 matrix4x4_t posematrix;
2233 for (k = 0;k < 12;k++)
2234 pose[k] = BigFloat(frameposes[j*12+k]);
2235 // scale child bones to match the root scale
2236 if (loadmodel->data_bones[j].parent >= 0)
2238 pose[3] *= modelscale;
2239 pose[7] *= modelscale;
2240 pose[11] *= modelscale;
2242 // normalize rotation matrix
2243 VectorNormalize(pose + 0);
2244 VectorNormalize(pose + 4);
2245 VectorNormalize(pose + 8);
2246 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2247 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
2251 // load the meshes now
2252 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2255 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2256 // (converting from weight-blending skeletal animation to
2257 // deformation-based skeletal animation)
2258 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2259 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2260 for (i = 0;i < loadmodel->num_bones;i++)
2263 for (k = 0;k < 12;k++)
2264 m[k] = BigFloat(poses[i*12+k]);
2265 if (loadmodel->data_bones[i].parent >= 0)
2266 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2268 for (k = 0;k < 12;k++)
2269 bonepose[12*i+k] = m[k];
2271 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2273 const int *inelements;
2275 const float *intexcoord;
2276 msurface_t *surface;
2278 loadmodel->sortedmodelsurfaces[i] = i;
2279 surface = loadmodel->data_surfaces + i;
2280 surface->texture = loadmodel->data_textures + i;
2281 surface->num_firsttriangle = meshtriangles;
2282 surface->num_triangles = BigLong(dpmmesh->num_tris);
2283 surface->num_firstvertex = meshvertices;
2284 surface->num_vertices = BigLong(dpmmesh->num_verts);
2285 meshvertices += surface->num_vertices;
2286 meshtriangles += surface->num_triangles;
2288 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2289 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2290 for (j = 0;j < surface->num_triangles;j++)
2292 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2293 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2294 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2295 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2300 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2301 for (j = 0;j < surface->num_vertices*2;j++)
2302 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2304 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2305 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2309 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2310 data += sizeof(dpmvertex_t);
2311 for (k = 0;k < numweights;k++)
2313 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2314 int boneindex = BigLong(vert->bonenum);
2315 const float *m = bonepose + 12 * boneindex;
2316 float influence = BigFloat(vert->influence);
2317 float relativeorigin[3], relativenormal[3];
2318 relativeorigin[0] = BigFloat(vert->origin[0]);
2319 relativeorigin[1] = BigFloat(vert->origin[1]);
2320 relativeorigin[2] = BigFloat(vert->origin[2]);
2321 relativenormal[0] = BigFloat(vert->normal[0]);
2322 relativenormal[1] = BigFloat(vert->normal[1]);
2323 relativenormal[2] = BigFloat(vert->normal[2]);
2324 // blend the vertex bone weights into the base mesh
2325 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2326 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2327 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2328 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2329 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2330 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2333 // store the first (and often only) weight
2334 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = influence;
2335 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
2339 // sort the new weight into this vertex's weight table
2340 // (which only accepts up to 4 bones per vertex)
2341 for (l = 0;l < 4;l++)
2343 if (loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] < influence)
2345 // move weaker influence weights out of the way first
2347 for (l2 = 3;l2 > l;l2--)
2349 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2-1];
2350 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2-1];
2352 // store the new weight
2353 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] = influence;
2354 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l] = boneindex;
2359 data += sizeof(dpmbonevert_t);
2362 for (l = 0;l < 4;l++)
2363 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l];
2364 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2366 float f = 1.0f / sum;
2367 for (l = 0;l < 4;l++)
2368 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] *= f;
2372 // since dpm models do not have named sections, reuse their shader name as the section name
2373 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2375 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2378 Mod_FreeSkinFiles(skinfiles);
2379 Mod_MakeSortedSurfaces(loadmodel);
2381 // compute all the mesh information that was not loaded from the file
2382 if (loadmodel->surfmesh.data_element3s)
2383 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2384 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2385 Mod_BuildBaseBonePoses();
2386 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);
2387 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2389 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2392 // no idea why PSK/PSA files contain weird quaternions but they do...
2393 #define PSKQUATNEGATIONS
2394 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2396 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2397 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2398 fs_offset_t filesize;
2403 pskboneinfo_t *bones;
2404 pskrawweights_t *rawweights;
2405 //pskboneinfo_t *animbones;
2406 pskaniminfo_t *anims;
2407 pskanimkeys_t *animkeys;
2408 void *animfilebuffer, *animbuffer, *animbufferend;
2409 unsigned char *data;
2411 skinfile_t *skinfiles;
2412 char animname[MAX_QPATH];
2414 float biggestorigin;
2416 pchunk = (pskchunk_t *)buffer;
2417 if (strcmp(pchunk->id, "ACTRHEAD"))
2418 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2420 loadmodel->modeldatatypestring = "PSK";
2422 loadmodel->type = mod_alias;
2423 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2424 loadmodel->DrawSky = NULL;
2425 loadmodel->DrawAddWaterPlanes = NULL;
2426 loadmodel->Draw = R_Q1BSP_Draw;
2427 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2428 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2429 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2430 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2431 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2432 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2433 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2434 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2435 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2436 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2437 loadmodel->PointSuperContents = NULL;
2438 loadmodel->synctype = ST_RAND;
2440 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2441 strlcat(animname, ".psa", sizeof(animname));
2442 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2443 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2444 if (animbuffer == NULL)
2445 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2464 while (buffer < bufferend)
2466 pchunk = (pskchunk_t *)buffer;
2467 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2468 version = LittleLong(pchunk->version);
2469 recordsize = LittleLong(pchunk->recordsize);
2470 numrecords = LittleLong(pchunk->numrecords);
2471 if (developer_extra.integer)
2472 Con_DPrintf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2473 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2474 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);
2475 if (!strcmp(pchunk->id, "ACTRHEAD"))
2479 else if (!strcmp(pchunk->id, "PNTS0000"))
2482 if (recordsize != sizeof(*p))
2483 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2484 // byteswap in place and keep the pointer
2485 numpnts = numrecords;
2486 pnts = (pskpnts_t *)buffer;
2487 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2489 p->origin[0] = LittleFloat(p->origin[0]);
2490 p->origin[1] = LittleFloat(p->origin[1]);
2491 p->origin[2] = LittleFloat(p->origin[2]);
2495 else if (!strcmp(pchunk->id, "VTXW0000"))
2498 if (recordsize != sizeof(*p))
2499 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2500 // byteswap in place and keep the pointer
2501 numvtxw = numrecords;
2502 vtxw = (pskvtxw_t *)buffer;
2503 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2505 p->pntsindex = LittleShort(p->pntsindex);
2506 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2507 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2508 if (p->pntsindex >= numpnts)
2510 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2516 else if (!strcmp(pchunk->id, "FACE0000"))
2519 if (recordsize != sizeof(*p))
2520 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2521 // byteswap in place and keep the pointer
2522 numfaces = numrecords;
2523 faces = (pskface_t *)buffer;
2524 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2526 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2527 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2528 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2529 p->group = LittleLong(p->group);
2530 if (p->vtxwindex[0] >= numvtxw)
2532 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2533 p->vtxwindex[0] = 0;
2535 if (p->vtxwindex[1] >= numvtxw)
2537 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2538 p->vtxwindex[1] = 0;
2540 if (p->vtxwindex[2] >= numvtxw)
2542 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2543 p->vtxwindex[2] = 0;
2548 else if (!strcmp(pchunk->id, "MATT0000"))
2551 if (recordsize != sizeof(*p))
2552 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2553 // byteswap in place and keep the pointer
2554 nummatts = numrecords;
2555 matts = (pskmatt_t *)buffer;
2556 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2562 else if (!strcmp(pchunk->id, "REFSKELT"))
2565 if (recordsize != sizeof(*p))
2566 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2567 // byteswap in place and keep the pointer
2568 numbones = numrecords;
2569 bones = (pskboneinfo_t *)buffer;
2570 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2572 p->numchildren = LittleLong(p->numchildren);
2573 p->parent = LittleLong(p->parent);
2574 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2575 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2576 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2577 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2578 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2579 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2580 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2581 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2582 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2583 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2584 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2585 #ifdef PSKQUATNEGATIONS
2588 p->basepose.quat[0] *= -1;
2589 p->basepose.quat[1] *= -1;
2590 p->basepose.quat[2] *= -1;
2594 p->basepose.quat[0] *= 1;
2595 p->basepose.quat[1] *= -1;
2596 p->basepose.quat[2] *= 1;
2599 if (p->parent < 0 || p->parent >= numbones)
2601 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2607 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2610 if (recordsize != sizeof(*p))
2611 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2612 // byteswap in place and keep the pointer
2613 numrawweights = numrecords;
2614 rawweights = (pskrawweights_t *)buffer;
2615 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2617 p->weight = LittleFloat(p->weight);
2618 p->pntsindex = LittleLong(p->pntsindex);
2619 p->boneindex = LittleLong(p->boneindex);
2620 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2622 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2625 if (p->boneindex < 0 || p->boneindex >= numbones)
2627 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2635 while (animbuffer < animbufferend)
2637 pchunk = (pskchunk_t *)animbuffer;
2638 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2639 version = LittleLong(pchunk->version);
2640 recordsize = LittleLong(pchunk->recordsize);
2641 numrecords = LittleLong(pchunk->numrecords);
2642 if (developer_extra.integer)
2643 Con_DPrintf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2644 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2645 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);
2646 if (!strcmp(pchunk->id, "ANIMHEAD"))
2650 else if (!strcmp(pchunk->id, "BONENAMES"))
2653 if (recordsize != sizeof(*p))
2654 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2655 // byteswap in place and keep the pointer
2656 numanimbones = numrecords;
2657 //animbones = (pskboneinfo_t *)animbuffer;
2658 // NOTE: supposedly psa does not need to match the psk model, the
2659 // bones missing from the psa would simply use their base
2660 // positions from the psk, but this is hard for me to implement
2661 // and people can easily make animations that match.
2662 if (numanimbones != numbones)
2663 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2664 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2666 p->numchildren = LittleLong(p->numchildren);
2667 p->parent = LittleLong(p->parent);
2668 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2669 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2670 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2671 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2672 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2673 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2674 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2675 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2676 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2677 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2678 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2679 #ifdef PSKQUATNEGATIONS
2682 p->basepose.quat[0] *= -1;
2683 p->basepose.quat[1] *= -1;
2684 p->basepose.quat[2] *= -1;
2688 p->basepose.quat[0] *= 1;
2689 p->basepose.quat[1] *= -1;
2690 p->basepose.quat[2] *= 1;
2693 if (p->parent < 0 || p->parent >= numanimbones)
2695 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2698 // check that bones are the same as in the base
2699 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2700 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2704 else if (!strcmp(pchunk->id, "ANIMINFO"))
2707 if (recordsize != sizeof(*p))
2708 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2709 // byteswap in place and keep the pointer
2710 numanims = numrecords;
2711 anims = (pskaniminfo_t *)animbuffer;
2712 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2714 p->numbones = LittleLong(p->numbones);
2715 p->playtime = LittleFloat(p->playtime);
2716 p->fps = LittleFloat(p->fps);
2717 p->firstframe = LittleLong(p->firstframe);
2718 p->numframes = LittleLong(p->numframes);
2719 if (p->numbones != numbones)
2720 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2724 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2727 if (recordsize != sizeof(*p))
2728 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2729 numanimkeys = numrecords;
2730 animkeys = (pskanimkeys_t *)animbuffer;
2731 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2733 p->origin[0] = LittleFloat(p->origin[0]);
2734 p->origin[1] = LittleFloat(p->origin[1]);
2735 p->origin[2] = LittleFloat(p->origin[2]);
2736 p->quat[0] = LittleFloat(p->quat[0]);
2737 p->quat[1] = LittleFloat(p->quat[1]);
2738 p->quat[2] = LittleFloat(p->quat[2]);
2739 p->quat[3] = LittleFloat(p->quat[3]);
2740 p->frametime = LittleFloat(p->frametime);
2741 #ifdef PSKQUATNEGATIONS
2742 if (index % numbones)
2757 // TODO: allocate bonepose stuff
2760 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2763 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2764 Host_Error("%s: missing required chunks", loadmodel->name);
2766 loadmodel->numframes = 0;
2767 for (index = 0;index < numanims;index++)
2768 loadmodel->numframes += anims[index].numframes;
2770 if (numanimkeys != numbones * loadmodel->numframes)
2771 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2773 meshvertices = numvtxw;
2774 meshtriangles = numfaces;
2776 // load external .skin files if present
2777 skinfiles = Mod_LoadSkinFiles();
2778 if (loadmodel->numskins < 1)
2779 loadmodel->numskins = 1;
2780 loadmodel->num_bones = numbones;
2781 loadmodel->num_poses = loadmodel->numframes;
2782 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2783 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2784 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2785 loadmodel->surfmesh.num_vertices = meshvertices;
2786 loadmodel->surfmesh.num_triangles = meshtriangles;
2787 // do most allocations as one merged chunk
2788 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);
2789 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2790 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2791 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2792 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2793 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2794 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2795 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2796 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2797 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2798 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2799 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2800 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += loadmodel->surfmesh.num_vertices * sizeof(int[4]);
2801 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[4]);
2802 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2803 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2804 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2805 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2806 if (loadmodel->surfmesh.num_vertices <= 65536)
2807 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2808 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2810 for (i = 0;i < loadmodel->numskins;i++)
2812 loadmodel->skinscenes[i].firstframe = i;
2813 loadmodel->skinscenes[i].framecount = 1;
2814 loadmodel->skinscenes[i].loop = true;
2815 loadmodel->skinscenes[i].framerate = 10;
2819 for (index = 0, i = 0;index < nummatts;index++)
2821 // since psk models do not have named sections, reuse their shader name as the section name
2822 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2823 loadmodel->sortedmodelsurfaces[index] = index;
2824 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2825 loadmodel->data_surfaces[index].num_firstvertex = 0;
2826 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2829 // copy over the vertex locations and texcoords
2830 for (index = 0;index < numvtxw;index++)
2832 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2833 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2834 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2835 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2836 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2839 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2840 for (index = 0;index < numfaces;index++)
2841 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2842 for (index = 0, i = 0;index < nummatts;index++)
2844 loadmodel->data_surfaces[index].num_firsttriangle = i;
2845 i += loadmodel->data_surfaces[index].num_triangles;
2846 loadmodel->data_surfaces[index].num_triangles = 0;
2848 for (index = 0;index < numfaces;index++)
2850 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2851 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2852 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2853 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2856 // copy over the bones
2857 for (index = 0;index < numbones;index++)
2859 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2860 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2861 if (loadmodel->data_bones[index].parent >= index)
2862 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2865 // sort the psk point weights into the vertex weight tables
2866 // (which only accept up to 4 bones per vertex)
2867 for (index = 0;index < numvtxw;index++)
2871 for (j = 0;j < numrawweights;j++)
2873 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2875 int boneindex = rawweights[j].boneindex;
2876 float influence = rawweights[j].weight;
2877 for (l = 0;l < 4;l++)
2879 if (loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] < influence)
2881 // move lower influence weights out of the way first
2883 for (l2 = 3;l2 > l;l2--)
2885 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2-1];
2886 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2-1];
2888 // store the new weight
2889 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] = influence;
2890 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l] = boneindex;
2897 for (l = 0;l < 4;l++)
2898 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l];
2899 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2901 float f = 1.0f / sum;
2902 for (l = 0;l < 4;l++)
2903 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] *= f;
2907 // set up the animscenes based on the anims
2908 for (index = 0, i = 0;index < numanims;index++)
2910 for (j = 0;j < anims[index].numframes;j++, i++)
2912 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2913 loadmodel->animscenes[i].firstframe = i;
2914 loadmodel->animscenes[i].framecount = 1;
2915 loadmodel->animscenes[i].loop = true;
2916 loadmodel->animscenes[i].framerate = 10;
2920 // calculate the scaling value for bone origins so they can be compressed to short
2922 for (index = 0;index < numanimkeys;index++)
2924 pskanimkeys_t *k = animkeys + index;
2925 biggestorigin = max(biggestorigin, fabs(k->origin[0]));
2926 biggestorigin = max(biggestorigin, fabs(k->origin[1]));
2927 biggestorigin = max(biggestorigin, fabs(k->origin[2]));
2929 loadmodel->num_posescale = biggestorigin / 32767.0f;
2930 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2932 // load the poses from the animkeys
2933 for (index = 0;index < numanimkeys;index++)
2935 pskanimkeys_t *k = animkeys + index;
2937 Vector4Copy(k->quat, quat);
2939 Vector4Negate(quat, quat);
2940 Vector4Normalize2(quat, quat);
2941 // compress poses to the short[6] format for longterm storage
2942 loadmodel->data_poses6s[index*6+0] = k->origin[0] * loadmodel->num_poseinvscale;
2943 loadmodel->data_poses6s[index*6+1] = k->origin[1] * loadmodel->num_poseinvscale;
2944 loadmodel->data_poses6s[index*6+2] = k->origin[2] * loadmodel->num_poseinvscale;
2945 loadmodel->data_poses6s[index*6+3] = quat[0] * 32767.0f;
2946 loadmodel->data_poses6s[index*6+4] = quat[1] * 32767.0f;
2947 loadmodel->data_poses6s[index*6+5] = quat[2] * 32767.0f;
2949 Mod_FreeSkinFiles(skinfiles);
2950 Mem_Free(animfilebuffer);
2951 Mod_MakeSortedSurfaces(loadmodel);
2953 // compute all the mesh information that was not loaded from the file
2954 // TODO: honor smoothing groups somehow?
2955 if (loadmodel->surfmesh.data_element3s)
2956 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2957 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2958 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2959 Mod_BuildBaseBonePoses();
2960 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2961 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);
2962 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2963 Mod_Alias_CalculateBoundingBox();
2965 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;