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 desiredscale[3];
56 float boneposerelative[MAX_BONES][12];
57 float *matrix, m[12], bonepose[MAX_BONES][12];
59 if (skeleton && !skeleton->relativetransforms)
62 // interpolate matrices
65 for (i = 0;i < model->num_bones;i++)
67 Matrix4x4_ToArray12FloatD3D(&skeleton->relativetransforms[i], m);
68 if (model->data_bones[i].parent >= 0)
69 R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
71 for (k = 0;k < 12;k++)
72 bonepose[i][k] = m[k];
74 // create a relative deformation matrix to describe displacement
75 // from the base mesh, which is used by the actual weighting
76 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]);
81 for (i = 0;i < model->num_bones;i++)
83 for (k = 0;k < 12;k++)
85 VectorClear(desiredscale);
86 for (blends = 0;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++)
88 matrix = model->data_poses + (frameblend[blends].subframe * model->num_bones + i) * 12;
89 for (k = 0;k < 12;k++)
90 m[k] += matrix[k] * frameblend[blends].lerp;
91 desiredscale[0] += frameblend[blends].lerp * VectorLength(matrix );
92 desiredscale[1] += frameblend[blends].lerp * VectorLength(matrix + 4);
93 desiredscale[2] += frameblend[blends].lerp * VectorLength(matrix + 8);
96 VectorNormalize(m + 4);
97 VectorNormalize(m + 8);
98 VectorScale(m , desiredscale[0], m );
99 VectorScale(m + 4, desiredscale[1], m + 4);
100 VectorScale(m + 8, desiredscale[2], m + 8);
101 if (i == r_skeletal_debugbone.integer)
102 m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
103 m[3] *= r_skeletal_debugtranslatex.value;
104 m[7] *= r_skeletal_debugtranslatey.value;
105 m[11] *= r_skeletal_debugtranslatez.value;
106 if (model->data_bones[i].parent >= 0)
107 R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
109 for (k = 0;k < 12;k++)
110 bonepose[i][k] = m[k];
111 // create a relative deformation matrix to describe displacement
112 // from the base mesh, which is used by the actual weighting
113 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]);
117 // blend the vertex bone weights
118 // 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)
119 // special case for the first bone because it avoids the need to memset the arrays before filling
122 const float *v = model->surfmesh.data_vertex3f;
123 const int *wi = model->surfmesh.data_vertexweightindex4i;
124 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
125 memset(vertex3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
126 for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, wi += 4, wf += 4, vertex3f += 3)
130 const float *m = boneposerelative[wi[0]];
131 vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
132 vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
133 vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
137 const float *m = boneposerelative[wi[0]];
139 vertex3f[0] = f * (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
140 vertex3f[1] = f * (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
141 vertex3f[2] = f * (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
142 for (k = 1;k < 4 && wf[k];k++)
144 const float *m = boneposerelative[wi[k]];
146 vertex3f[0] += f * (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
147 vertex3f[1] += f * (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
148 vertex3f[2] += f * (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
155 const float *n = model->surfmesh.data_normal3f;
156 const int *wi = model->surfmesh.data_vertexweightindex4i;
157 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
158 memset(normal3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
159 for (i = 0;i < model->surfmesh.num_vertices;i++, n += 3, wi += 4, wf += 4, normal3f += 3)
163 const float *m = boneposerelative[wi[0]];
164 normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
165 normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
166 normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
170 const float *m = boneposerelative[wi[0]];
172 normal3f[0] = f * (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
173 normal3f[1] = f * (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
174 normal3f[2] = f * (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
175 for (k = 1;k < 4 && wf[k];k++)
177 const float *m = boneposerelative[wi[k]];
179 normal3f[0] += f * (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
180 normal3f[1] += f * (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
181 normal3f[2] += f * (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
188 const float *sv = model->surfmesh.data_svector3f;
189 const int *wi = model->surfmesh.data_vertexweightindex4i;
190 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
191 memset(svector3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
192 for (i = 0;i < model->surfmesh.num_vertices;i++, sv += 3, wi += 4, wf += 4, svector3f += 3)
196 const float *m = boneposerelative[wi[0]];
197 svector3f[0] = (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
198 svector3f[1] = (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
199 svector3f[2] = (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
203 const float *m = boneposerelative[wi[0]];
205 svector3f[0] = f * (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
206 svector3f[1] = f * (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
207 svector3f[2] = f * (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
208 for (k = 1;k < 4 && wf[k];k++)
210 const float *m = boneposerelative[wi[k]];
212 svector3f[0] += f * (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
213 svector3f[1] += f * (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
214 svector3f[2] += f * (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
221 const float *tv = model->surfmesh.data_tvector3f;
222 const int *wi = model->surfmesh.data_vertexweightindex4i;
223 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
224 memset(tvector3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
225 for (i = 0;i < model->surfmesh.num_vertices;i++, tv += 3, wi += 4, wf += 4, tvector3f += 3)
229 const float *m = boneposerelative[wi[0]];
230 tvector3f[0] = (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
231 tvector3f[1] = (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
232 tvector3f[2] = (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
236 const float *m = boneposerelative[wi[0]];
238 tvector3f[0] = f * (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
239 tvector3f[1] = f * (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
240 tvector3f[2] = f * (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
241 for (k = 1;k < 4 && wf[k];k++)
243 const float *m = boneposerelative[wi[k]];
245 tvector3f[0] += f * (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
246 tvector3f[1] += f * (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
247 tvector3f[2] += f * (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
254 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)
257 int i, numblends, blendnum;
258 int numverts = model->surfmesh.num_vertices;
260 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
262 //VectorMA(translate, model->surfmesh.num_morphmdlframetranslate, frameblend[blendnum].lerp, translate);
263 if (frameblend[blendnum].lerp > 0)
264 numblends = blendnum + 1;
266 // special case for the first blend because it avoids some adds and the need to memset the arrays first
267 for (blendnum = 0;blendnum < numblends;blendnum++)
269 const md3vertex_t *verts = model->surfmesh.data_morphmd3vertex + numverts * frameblend[blendnum].subframe;
272 float scale = frameblend[blendnum].lerp * (1.0f / 64.0f);
275 for (i = 0;i < numverts;i++)
277 vertex3f[i * 3 + 0] = verts[i].origin[0] * scale;
278 vertex3f[i * 3 + 1] = verts[i].origin[1] * scale;
279 vertex3f[i * 3 + 2] = verts[i].origin[2] * scale;
284 for (i = 0;i < numverts;i++)
286 vertex3f[i * 3 + 0] += verts[i].origin[0] * scale;
287 vertex3f[i * 3 + 1] += verts[i].origin[1] * scale;
288 vertex3f[i * 3 + 2] += verts[i].origin[2] * scale;
292 // the yaw and pitch stored in md3 models are 8bit quantized angles
293 // (0-255), and as such a lookup table is very well suited to
294 // decoding them, and since cosine is equivilant to sine with an
295 // extra 45 degree rotation, this uses one lookup table for both
296 // sine and cosine with a +64 bias to get cosine.
299 float lerp = frameblend[blendnum].lerp;
302 for (i = 0;i < numverts;i++)
304 normal3f[i * 3 + 0] = mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
305 normal3f[i * 3 + 1] = mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
306 normal3f[i * 3 + 2] = mod_md3_sin[verts[i].pitch + 64] * lerp;
311 for (i = 0;i < numverts;i++)
313 normal3f[i * 3 + 0] += mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
314 normal3f[i * 3 + 1] += mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
315 normal3f[i * 3 + 2] += mod_md3_sin[verts[i].pitch + 64] * lerp;
321 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
322 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
325 for (i = 0;i < numverts;i++, texvecvert++)
327 VectorScale(texvecvert->svec, f, svector3f + i*3);
328 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
333 for (i = 0;i < numverts;i++, texvecvert++)
335 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
336 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
343 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)
346 int i, numblends, blendnum;
347 int numverts = model->surfmesh.num_vertices;
349 VectorClear(translate);
351 // blend the frame translates to avoid redundantly doing so on each vertex
352 // (a bit of a brain twister but it works)
353 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
355 if (model->surfmesh.data_morphmd2framesize6f)
356 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6 + 3, translate);
358 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.num_morphmdlframetranslate, translate);
359 if (frameblend[blendnum].lerp > 0)
360 numblends = blendnum + 1;
362 // special case for the first blend because it avoids some adds and the need to memset the arrays first
363 for (blendnum = 0;blendnum < numblends;blendnum++)
365 const trivertx_t *verts = model->surfmesh.data_morphmdlvertex + numverts * frameblend[blendnum].subframe;
369 if (model->surfmesh.data_morphmd2framesize6f)
370 VectorScale(model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6, frameblend[blendnum].lerp, scale);
372 VectorScale(model->surfmesh.num_morphmdlframescale, frameblend[blendnum].lerp, scale);
375 for (i = 0;i < numverts;i++)
377 vertex3f[i * 3 + 0] = translate[0] + verts[i].v[0] * scale[0];
378 vertex3f[i * 3 + 1] = translate[1] + verts[i].v[1] * scale[1];
379 vertex3f[i * 3 + 2] = translate[2] + verts[i].v[2] * scale[2];
384 for (i = 0;i < numverts;i++)
386 vertex3f[i * 3 + 0] += verts[i].v[0] * scale[0];
387 vertex3f[i * 3 + 1] += verts[i].v[1] * scale[1];
388 vertex3f[i * 3 + 2] += verts[i].v[2] * scale[2];
392 // the vertex normals in mdl models are an index into a table of
393 // 162 unique values, this very crude quantization reduces the
394 // vertex normal to only one byte, which saves a lot of space but
395 // also makes lighting pretty coarse
398 float lerp = frameblend[blendnum].lerp;
401 for (i = 0;i < numverts;i++)
403 const float *vn = m_bytenormals[verts[i].lightnormalindex];
404 VectorScale(vn, lerp, normal3f + i*3);
409 for (i = 0;i < numverts;i++)
411 const float *vn = m_bytenormals[verts[i].lightnormalindex];
412 VectorMA(normal3f + i*3, lerp, vn, normal3f + i*3);
418 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
419 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
422 for (i = 0;i < numverts;i++, texvecvert++)
424 VectorScale(texvecvert->svec, f, svector3f + i*3);
425 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
430 for (i = 0;i < numverts;i++, texvecvert++)
432 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
433 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
440 int Mod_Alias_GetTagMatrix(const dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, int tagindex, matrix4x4_t *outmatrix)
443 const float *boneframe;
449 float tempbonematrix[12], bonematrix[12], blendmatrix[12];
450 *outmatrix = identitymatrix;
451 if (skeleton && skeleton->relativetransforms)
453 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
455 *outmatrix = skeleton->relativetransforms[tagindex];
456 while ((tagindex = model->data_bones[tagindex].parent) >= 0)
459 Matrix4x4_Concat(outmatrix, &skeleton->relativetransforms[tagindex], &temp);
462 else if (model->num_bones)
464 if (tagindex < 0 || tagindex >= model->num_bones)
466 for (k = 0;k < 12;k++)
468 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
470 lerp = frameblend[blendindex].lerp;
471 boneframe = model->data_poses + frameblend[blendindex].subframe * model->num_bones * 12;
472 input = boneframe + tagindex * 12;
473 for (k = 0;k < 12;k++)
474 bonematrix[k] = input[k];
475 parenttagindex = tagindex;
476 while ((parenttagindex = model->data_bones[parenttagindex].parent) >= 0)
478 for (k = 0;k < 12;k++)
479 tempbonematrix[k] = bonematrix[k];
480 input = boneframe + parenttagindex * 12;
481 R_ConcatTransforms(input, tempbonematrix, bonematrix);
483 for (k = 0;k < 12;k++)
484 blendmatrix[k] += bonematrix[k] * lerp;
486 Matrix4x4_FromArray12FloatD3D(outmatrix, blendmatrix);
488 else if (model->num_tags)
490 if (tagindex < 0 || tagindex >= model->num_tags)
492 for (k = 0;k < 12;k++)
494 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
496 lerp = frameblend[blendindex].lerp;
497 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
498 for (k = 0;k < 12;k++)
499 blendmatrix[k] += input[k] * lerp;
501 Matrix4x4_FromArray12FloatGL(outmatrix, blendmatrix);
504 if(!mod_alias_supporttagscale.integer)
505 Matrix4x4_Normalize3(outmatrix, outmatrix);
510 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)
512 const float *boneframe;
517 float blendmatrix[12];
519 if (skeleton && skeleton->relativetransforms)
521 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
523 *parentindex = skeleton->model->data_bones[tagindex].parent;
524 *tagname = skeleton->model->data_bones[tagindex].name;
525 *tag_localmatrix = skeleton->relativetransforms[tagindex];
528 else if (model->num_bones)
530 if(tagindex >= model->num_bones || tagindex < 0)
532 *parentindex = model->data_bones[tagindex].parent;
533 *tagname = model->data_bones[tagindex].name;
534 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
536 lerp = frameblend[blendindex].lerp;
537 boneframe = model->data_poses + frameblend[blendindex].subframe * model->num_bones * 12;
538 input = boneframe + tagindex * 12;
539 for (k = 0;k < 12;k++)
540 blendmatrix[k] += input[k] * lerp;
542 Matrix4x4_FromArray12FloatD3D(tag_localmatrix, blendmatrix);
545 else if (model->num_tags)
547 if(tagindex >= model->num_tags || tagindex < 0)
550 *tagname = model->data_tags[tagindex].name;
551 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
553 lerp = frameblend[blendindex].lerp;
554 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
555 for (k = 0;k < 12;k++)
556 blendmatrix[k] += input[k] * lerp;
558 Matrix4x4_FromArray12FloatGL(tag_localmatrix, blendmatrix);
565 int Mod_Alias_GetTagIndexForName(const dp_model_t *model, unsigned int skin, const char *tagname)
568 if(skin >= (unsigned int)model->numskins)
570 if (model->num_bones)
571 for (i = 0;i < model->num_bones;i++)
572 if (!strcasecmp(tagname, model->data_bones[i].name))
575 for (i = 0;i < model->num_tags;i++)
576 if (!strcasecmp(tagname, model->data_tags[i].name))
581 static void Mod_BuildBaseBonePoses(void)
586 float *in12f = loadmodel->data_poses;
588 float *outinv12f = loadmodel->data_baseboneposeinverse;
589 if (!loadmodel->num_bones)
591 out12f = basebonepose = (float *) Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(float[12]));
592 for (i = 0;i < loadmodel->num_bones;i++, in12f += 12, out12f += 12, outinv12f += 12)
594 if (loadmodel->data_bones[i].parent >= 0)
595 R_ConcatTransforms(basebonepose + 12 * loadmodel->data_bones[i].parent, in12f, out12f);
597 for (k = 0;k < 12;k++)
598 out12f[k] = in12f[k];
602 // we only support uniform scaling, so assume the first row is enough
603 // (note the lack of sqrt here, because we're trying to undo the scaling,
604 // this means multiplying by the inverse scale twice - squaring it, which
605 // makes the sqrt a waste of time)
606 scale = 1.0 / (out12f[ 0] * out12f[ 0] + out12f[ 1] * out12f[ 1] + out12f[ 2] * out12f[ 2]);
608 // invert the rotation by transposing and multiplying by the squared
609 // recipricol of the input matrix scale as described above
610 outinv12f[ 0] = (float)(out12f[ 0] * scale);
611 outinv12f[ 1] = (float)(out12f[ 4] * scale);
612 outinv12f[ 2] = (float)(out12f[ 8] * scale);
613 outinv12f[ 4] = (float)(out12f[ 1] * scale);
614 outinv12f[ 5] = (float)(out12f[ 5] * scale);
615 outinv12f[ 6] = (float)(out12f[ 9] * scale);
616 outinv12f[ 8] = (float)(out12f[ 2] * scale);
617 outinv12f[ 9] = (float)(out12f[ 6] * scale);
618 outinv12f[10] = (float)(out12f[10] * scale);
620 // invert the translate
621 outinv12f[ 3] = -(out12f[ 3] * outinv12f[ 0] + out12f[ 7] * outinv12f[ 1] + out12f[11] * outinv12f[ 2]);
622 outinv12f[ 7] = -(out12f[ 3] * outinv12f[ 4] + out12f[ 7] * outinv12f[ 5] + out12f[11] * outinv12f[ 6]);
623 outinv12f[11] = -(out12f[ 3] * outinv12f[ 8] + out12f[ 7] * outinv12f[ 9] + out12f[11] * outinv12f[10]);
625 Mem_Free(basebonepose);
628 static void Mod_Alias_CalculateBoundingBox(void)
631 qboolean firstvertex = true;
632 float dist, yawradius, radius;
635 frameblend_t frameblend[MAX_FRAMEBLENDS];
636 memset(frameblend, 0, sizeof(frameblend));
637 frameblend[0].lerp = 1;
638 vertex3f = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
639 VectorClear(loadmodel->normalmins);
640 VectorClear(loadmodel->normalmaxs);
643 for (frameblend[0].subframe = 0;frameblend[0].subframe < loadmodel->num_poses;frameblend[0].subframe++)
645 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, vertex3f, NULL, NULL, NULL);
646 for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
651 VectorCopy(v, loadmodel->normalmins);
652 VectorCopy(v, loadmodel->normalmaxs);
656 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
657 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
658 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
659 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
660 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
661 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
663 dist = v[0] * v[0] + v[1] * v[1];
664 if (yawradius < dist)
673 radius = sqrt(radius);
674 yawradius = sqrt(yawradius);
675 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
676 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
677 loadmodel->yawmins[2] = loadmodel->normalmins[2];
678 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
679 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
680 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
681 loadmodel->radius = radius;
682 loadmodel->radius2 = radius * radius;
685 static void Mod_Alias_MorphMesh_CompileFrames(void)
688 frameblend_t frameblend[MAX_FRAMEBLENDS];
689 unsigned char *datapointer;
690 memset(frameblend, 0, sizeof(frameblend));
691 frameblend[0].lerp = 1;
692 datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
693 loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
694 loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
695 loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
696 loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
697 loadmodel->surfmesh.data_morphtexvecvertex = (texvecvertex_t *)datapointer;datapointer += loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices * sizeof(texvecvertex_t);
698 // 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)
699 for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
701 frameblend[0].subframe = i;
702 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
703 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);
704 // encode the svector and tvector in 3 byte format for permanent storage
705 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
707 VectorScaleCast(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
708 VectorScaleCast(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
713 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)
716 float segmentmins[3], segmentmaxs[3];
718 static int maxvertices = 0;
719 static float *vertex3f = NULL;
720 memset(trace, 0, sizeof(*trace));
722 trace->realfraction = 1;
723 trace->hitsupercontentsmask = hitsupercontentsmask;
724 if (maxvertices < model->surfmesh.num_vertices)
728 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
729 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
731 segmentmins[0] = min(start[0], end[0]) - 1;
732 segmentmins[1] = min(start[1], end[1]) - 1;
733 segmentmins[2] = min(start[2], end[2]) - 1;
734 segmentmaxs[0] = max(start[0], end[0]) + 1;
735 segmentmaxs[1] = max(start[1], end[1]) + 1;
736 segmentmaxs[2] = max(start[2], end[2]) + 1;
737 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
738 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
739 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);
742 static int maxvertices = 0;
743 static float *vertex3f = NULL;
745 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)
748 vec3_t shiftstart, shiftend;
749 float segmentmins[3], segmentmaxs[3];
751 colboxbrushf_t thisbrush_start, thisbrush_end;
752 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
754 if (VectorCompare(boxmins, boxmaxs))
756 VectorAdd(start, boxmins, shiftstart);
757 VectorAdd(end, boxmins, shiftend);
758 Mod_MDLMD2MD3_TraceLine(model, frameblend, skeleton, trace, start, end, hitsupercontentsmask);
759 VectorSubtract(trace->endpos, boxmins, trace->endpos);
763 // box trace, performed as brush trace
764 memset(trace, 0, sizeof(*trace));
766 trace->realfraction = 1;
767 trace->hitsupercontentsmask = hitsupercontentsmask;
768 if (maxvertices < model->surfmesh.num_vertices)
772 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
773 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
775 segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
776 segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
777 segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
778 segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
779 segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
780 segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
781 VectorAdd(start, boxmins, boxstartmins);
782 VectorAdd(start, boxmaxs, boxstartmaxs);
783 VectorAdd(end, boxmins, boxendmins);
784 VectorAdd(end, boxmaxs, boxendmaxs);
785 Collision_BrushForBox(&thisbrush_start, boxstartmins, boxstartmaxs, 0, 0, NULL);
786 Collision_BrushForBox(&thisbrush_end, boxendmins, boxendmaxs, 0, 0, NULL);
787 if (maxvertices < model->surfmesh.num_vertices)
791 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
792 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
794 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
795 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
796 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);
799 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
802 for (i = 0;i < inverts;i++)
804 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
806 j = vertremap[i]; // not onseam
809 j = vertremap[i+inverts]; // onseam
815 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
817 int i, f, pose, groupframes;
819 daliasframetype_t *pframetype;
820 daliasframe_t *pinframe;
821 daliasgroup_t *group;
822 daliasinterval_t *intervals;
825 scene = loadmodel->animscenes;
826 for (f = 0;f < loadmodel->numframes;f++)
828 pframetype = (daliasframetype_t *)datapointer;
829 datapointer += sizeof(daliasframetype_t);
830 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
832 // a single frame is still treated as a group
839 group = (daliasgroup_t *)datapointer;
840 datapointer += sizeof(daliasgroup_t);
841 groupframes = LittleLong (group->numframes);
843 // intervals (time per frame)
844 intervals = (daliasinterval_t *)datapointer;
845 datapointer += sizeof(daliasinterval_t) * groupframes;
847 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
848 if (interval < 0.01f)
850 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
855 // get scene name from first frame
856 pinframe = (daliasframe_t *)datapointer;
858 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
859 scene->firstframe = pose;
860 scene->framecount = groupframes;
861 scene->framerate = 1.0f / interval;
866 for (i = 0;i < groupframes;i++)
868 pinframe = (daliasframe_t *)datapointer;
869 datapointer += sizeof(daliasframe_t);
870 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
871 datapointer += sizeof(trivertx_t) * inverts;
877 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
879 if (cls.state == ca_dedicated)
883 skinframe = R_SkinFrame_LoadMissing();
884 memset(texture, 0, sizeof(*texture));
885 texture->currentframe = texture;
886 //texture->animated = false;
887 texture->numskinframes = 1;
888 texture->skinframerate = 1;
889 texture->skinframes[0] = skinframe;
890 texture->currentskinframe = skinframe;
891 //texture->backgroundnumskinframes = 0;
892 //texture->customblendfunc[0] = 0;
893 //texture->customblendfunc[1] = 0;
894 //texture->surfaceflags = 0;
895 //texture->supercontents = 0;
896 //texture->surfaceparms = 0;
897 //texture->textureflags = 0;
899 texture->basematerialflags = MATERIALFLAG_WALL;
900 if (texture->currentskinframe->fog)
901 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
902 texture->currentmaterialflags = texture->basematerialflags;
905 static void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
908 skinfileitem_t *skinfileitem;
911 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
912 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
914 memset(skin, 0, sizeof(*skin));
916 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
918 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
919 if (!strcmp(skinfileitem->name, meshname))
921 Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
927 // don't render unmentioned meshes
928 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
929 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
934 Mod_LoadTextureFromQ3Shader(skin, shadername, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
937 #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);
938 #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);
939 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
941 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
942 float scales, scalet, interval;
946 stvert_t *pinstverts;
947 dtriangle_t *pintriangles;
948 daliasskintype_t *pinskintype;
949 daliasskingroup_t *pinskingroup;
950 daliasskininterval_t *pinskinintervals;
951 daliasframetype_t *pinframetype;
952 daliasgroup_t *pinframegroup;
953 unsigned char *datapointer, *startframes, *startskins;
954 char name[MAX_QPATH];
955 skinframe_t *tempskinframe;
956 animscene_t *tempskinscenes;
957 texture_t *tempaliasskins;
959 int *vertonseam, *vertremap;
960 skinfile_t *skinfiles;
962 datapointer = (unsigned char *)buffer;
963 pinmodel = (mdl_t *)datapointer;
964 datapointer += sizeof(mdl_t);
966 version = LittleLong (pinmodel->version);
967 if (version != ALIAS_VERSION)
968 Host_Error ("%s has wrong version number (%i should be %i)",
969 loadmodel->name, version, ALIAS_VERSION);
971 loadmodel->modeldatatypestring = "MDL";
973 loadmodel->type = mod_alias;
974 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
975 loadmodel->DrawSky = NULL;
976 loadmodel->DrawAddWaterPlanes = NULL;
977 loadmodel->Draw = R_Q1BSP_Draw;
978 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
979 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
980 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
981 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
982 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
983 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
984 loadmodel->DrawLight = R_Q1BSP_DrawLight;
985 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
986 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
987 loadmodel->PointSuperContents = NULL;
989 loadmodel->num_surfaces = 1;
990 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
991 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
992 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
993 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
994 loadmodel->sortedmodelsurfaces[0] = 0;
996 loadmodel->numskins = LittleLong(pinmodel->numskins);
997 BOUNDI(loadmodel->numskins,0,65536);
998 skinwidth = LittleLong (pinmodel->skinwidth);
999 BOUNDI(skinwidth,0,65536);
1000 skinheight = LittleLong (pinmodel->skinheight);
1001 BOUNDI(skinheight,0,65536);
1002 numverts = LittleLong(pinmodel->numverts);
1003 BOUNDI(numverts,0,65536);
1004 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
1005 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
1006 loadmodel->numframes = LittleLong(pinmodel->numframes);
1007 BOUNDI(loadmodel->numframes,0,65536);
1008 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
1009 BOUNDI(loadmodel->synctype,0,2);
1010 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1011 i = LittleLong (pinmodel->flags);
1012 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1014 for (i = 0;i < 3;i++)
1016 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
1017 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
1020 startskins = datapointer;
1022 for (i = 0;i < loadmodel->numskins;i++)
1024 pinskintype = (daliasskintype_t *)datapointer;
1025 datapointer += sizeof(daliasskintype_t);
1026 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
1030 pinskingroup = (daliasskingroup_t *)datapointer;
1031 datapointer += sizeof(daliasskingroup_t);
1032 groupskins = LittleLong(pinskingroup->numskins);
1033 datapointer += sizeof(daliasskininterval_t) * groupskins;
1036 for (j = 0;j < groupskins;j++)
1038 datapointer += skinwidth * skinheight;
1043 pinstverts = (stvert_t *)datapointer;
1044 datapointer += sizeof(stvert_t) * numverts;
1046 pintriangles = (dtriangle_t *)datapointer;
1047 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
1049 startframes = datapointer;
1050 loadmodel->surfmesh.num_morphframes = 0;
1051 for (i = 0;i < loadmodel->numframes;i++)
1053 pinframetype = (daliasframetype_t *)datapointer;
1054 datapointer += sizeof(daliasframetype_t);
1055 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
1059 pinframegroup = (daliasgroup_t *)datapointer;
1060 datapointer += sizeof(daliasgroup_t);
1061 groupframes = LittleLong(pinframegroup->numframes);
1062 datapointer += sizeof(daliasinterval_t) * groupframes;
1065 for (j = 0;j < groupframes;j++)
1067 datapointer += sizeof(daliasframe_t);
1068 datapointer += sizeof(trivertx_t) * numverts;
1069 loadmodel->surfmesh.num_morphframes++;
1072 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1074 // store texture coordinates into temporary array, they will be stored
1075 // after usage is determined (triangle data)
1076 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
1077 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
1078 vertonseam = vertremap + numverts * 2;
1080 scales = 1.0 / skinwidth;
1081 scalet = 1.0 / skinheight;
1082 for (i = 0;i < numverts;i++)
1084 vertonseam[i] = LittleLong(pinstverts[i].onseam);
1085 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
1086 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
1087 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
1088 vertst[(i+numverts)*2+1] = vertst[i*2+1];
1091 // load triangle data
1092 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1094 // read the triangle elements
1095 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1096 for (j = 0;j < 3;j++)
1097 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1098 // validate (note numverts is used because this is the original data)
1099 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1100 // now butcher the elements according to vertonseam and tri->facesfront
1101 // and then compact the vertex set to remove duplicates
1102 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1103 if (!LittleLong(pintriangles[i].facesfront)) // backface
1104 for (j = 0;j < 3;j++)
1105 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1106 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1108 // (this uses vertremap to count usage to save some memory)
1109 for (i = 0;i < numverts*2;i++)
1111 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1112 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1113 // build remapping table and compact array
1114 loadmodel->surfmesh.num_vertices = 0;
1115 for (i = 0;i < numverts*2;i++)
1119 vertremap[i] = loadmodel->surfmesh.num_vertices;
1120 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1121 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1122 loadmodel->surfmesh.num_vertices++;
1125 vertremap[i] = -1; // not used at all
1127 // remap the elements to the new vertex set
1128 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1129 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1130 // store the texture coordinates
1131 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1132 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1134 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1135 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1138 // generate ushort elements array if possible
1139 if (loadmodel->surfmesh.num_vertices <= 65536)
1140 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1141 if (loadmodel->surfmesh.data_element3s)
1142 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1143 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1146 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1147 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1148 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1149 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1150 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1151 Mod_Alias_CalculateBoundingBox();
1152 Mod_Alias_MorphMesh_CompileFrames();
1155 Mem_Free(vertremap);
1158 skinfiles = Mod_LoadSkinFiles();
1161 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1162 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1163 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1164 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1165 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1166 Mod_FreeSkinFiles(skinfiles);
1167 for (i = 0;i < loadmodel->numskins;i++)
1169 loadmodel->skinscenes[i].firstframe = i;
1170 loadmodel->skinscenes[i].framecount = 1;
1171 loadmodel->skinscenes[i].loop = true;
1172 loadmodel->skinscenes[i].framerate = 10;
1177 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1178 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1179 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1180 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1182 datapointer = startskins;
1183 for (i = 0;i < loadmodel->numskins;i++)
1185 pinskintype = (daliasskintype_t *)datapointer;
1186 datapointer += sizeof(daliasskintype_t);
1188 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1195 pinskingroup = (daliasskingroup_t *)datapointer;
1196 datapointer += sizeof(daliasskingroup_t);
1198 groupskins = LittleLong (pinskingroup->numskins);
1200 pinskinintervals = (daliasskininterval_t *)datapointer;
1201 datapointer += sizeof(daliasskininterval_t) * groupskins;
1203 interval = LittleFloat(pinskinintervals[0].interval);
1204 if (interval < 0.01f)
1206 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1211 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1212 loadmodel->skinscenes[i].firstframe = totalskins;
1213 loadmodel->skinscenes[i].framecount = groupskins;
1214 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1215 loadmodel->skinscenes[i].loop = true;
1217 for (j = 0;j < groupskins;j++)
1220 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1222 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1223 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))
1224 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));
1225 datapointer += skinwidth * skinheight;
1229 // check for skins that don't exist in the model, but do exist as external images
1230 // (this was added because yummyluv kept pestering me about support for it)
1231 // TODO: support shaders here?
1232 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)))
1234 // expand the arrays to make room
1235 tempskinscenes = loadmodel->skinscenes;
1236 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1237 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1238 Mem_Free(tempskinscenes);
1240 tempaliasskins = loadmodel->data_textures;
1241 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1242 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1243 Mem_Free(tempaliasskins);
1245 // store the info about the new skin
1246 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1247 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1248 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1249 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1250 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1251 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1253 //increase skin counts
1254 loadmodel->numskins++;
1257 // fix up the pointers since they are pointing at the old textures array
1258 // FIXME: this is a hack!
1259 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1260 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1264 surface = loadmodel->data_surfaces;
1265 surface->texture = loadmodel->data_textures;
1266 surface->num_firsttriangle = 0;
1267 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1268 surface->num_firstvertex = 0;
1269 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1271 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1274 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1276 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1277 float iskinwidth, iskinheight;
1278 unsigned char *data;
1279 msurface_t *surface;
1281 unsigned char *base, *datapointer;
1282 md2frame_t *pinframe;
1284 md2triangle_t *intri;
1285 unsigned short *inst;
1286 struct md2verthash_s
1288 struct md2verthash_s *next;
1292 *hash, **md2verthash, *md2verthashdata;
1293 skinfile_t *skinfiles;
1295 pinmodel = (md2_t *)buffer;
1296 base = (unsigned char *)buffer;
1298 version = LittleLong (pinmodel->version);
1299 if (version != MD2ALIAS_VERSION)
1300 Host_Error ("%s has wrong version number (%i should be %i)",
1301 loadmodel->name, version, MD2ALIAS_VERSION);
1303 loadmodel->modeldatatypestring = "MD2";
1305 loadmodel->type = mod_alias;
1306 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1307 loadmodel->DrawSky = NULL;
1308 loadmodel->DrawAddWaterPlanes = NULL;
1309 loadmodel->Draw = R_Q1BSP_Draw;
1310 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1311 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1312 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1313 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1314 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1315 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1316 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1317 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1318 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1319 loadmodel->PointSuperContents = NULL;
1321 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1322 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1323 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1324 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1325 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1326 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1327 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1328 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1330 end = LittleLong(pinmodel->ofs_end);
1331 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1332 Host_Error ("%s is not a valid model", loadmodel->name);
1333 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1334 Host_Error ("%s is not a valid model", loadmodel->name);
1335 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1336 Host_Error ("%s is not a valid model", loadmodel->name);
1337 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1338 Host_Error ("%s is not a valid model", loadmodel->name);
1339 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1340 Host_Error ("%s is not a valid model", loadmodel->name);
1342 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1343 numxyz = LittleLong(pinmodel->num_xyz);
1344 numst = LittleLong(pinmodel->num_st);
1345 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1346 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1347 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1348 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1349 skinwidth = LittleLong(pinmodel->skinwidth);
1350 skinheight = LittleLong(pinmodel->skinheight);
1351 iskinwidth = 1.0f / skinwidth;
1352 iskinheight = 1.0f / skinheight;
1354 loadmodel->num_surfaces = 1;
1355 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1356 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]));
1357 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1358 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1359 loadmodel->sortedmodelsurfaces[0] = 0;
1360 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1361 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1362 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1363 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1365 loadmodel->synctype = ST_RAND;
1368 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1369 skinfiles = Mod_LoadSkinFiles();
1372 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1373 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1374 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1375 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1376 Mod_FreeSkinFiles(skinfiles);
1378 else if (loadmodel->numskins)
1380 // skins found (most likely not a player model)
1381 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1382 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1383 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1384 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1385 Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
1389 // no skins (most likely a player model)
1390 loadmodel->numskins = 1;
1391 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1392 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1393 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1394 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1397 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1398 for (i = 0;i < loadmodel->numskins;i++)
1400 loadmodel->skinscenes[i].firstframe = i;
1401 loadmodel->skinscenes[i].framecount = 1;
1402 loadmodel->skinscenes[i].loop = true;
1403 loadmodel->skinscenes[i].framerate = 10;
1406 // load the triangles and stvert data
1407 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1408 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1409 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1410 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1411 // swap the triangle list
1412 loadmodel->surfmesh.num_vertices = 0;
1413 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1415 for (j = 0;j < 3;j++)
1417 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1418 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1421 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1426 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1429 hashindex = (xyz * 256 + st) & 65535;
1430 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1431 if (hash->xyz == xyz && hash->st == st)
1435 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1438 hash->next = md2verthash[hashindex];
1439 md2verthash[hashindex] = hash;
1441 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1445 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1446 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));
1447 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1448 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1449 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1452 hash = md2verthashdata + i;
1453 vertremap[i] = hash->xyz;
1454 sts = LittleShort(inst[hash->st*2+0]);
1455 stt = LittleShort(inst[hash->st*2+1]);
1456 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1458 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1462 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1463 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1466 Mem_Free(md2verthash);
1467 Mem_Free(md2verthashdata);
1469 // generate ushort elements array if possible
1470 if (loadmodel->surfmesh.num_vertices <= 65536)
1471 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1472 if (loadmodel->surfmesh.data_element3s)
1473 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1474 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1477 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1478 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1483 pinframe = (md2frame_t *)datapointer;
1484 datapointer += sizeof(md2frame_t);
1485 // store the frame scale/translate into the appropriate array
1486 for (j = 0;j < 3;j++)
1488 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1489 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1491 // convert the vertices
1492 v = (trivertx_t *)datapointer;
1493 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1494 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1495 out[k] = v[vertremap[k]];
1496 datapointer += numxyz * sizeof(trivertx_t);
1498 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1499 loadmodel->animscenes[i].firstframe = i;
1500 loadmodel->animscenes[i].framecount = 1;
1501 loadmodel->animscenes[i].framerate = 10;
1502 loadmodel->animscenes[i].loop = true;
1505 Mem_Free(vertremap);
1507 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1508 Mod_Alias_CalculateBoundingBox();
1509 Mod_Alias_MorphMesh_CompileFrames();
1511 surface = loadmodel->data_surfaces;
1512 surface->texture = loadmodel->data_textures;
1513 surface->num_firsttriangle = 0;
1514 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1515 surface->num_firstvertex = 0;
1516 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1518 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1521 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1523 int i, j, k, version, meshvertices, meshtriangles;
1524 unsigned char *data;
1525 msurface_t *surface;
1526 md3modelheader_t *pinmodel;
1527 md3frameinfo_t *pinframe;
1530 skinfile_t *skinfiles;
1532 pinmodel = (md3modelheader_t *)buffer;
1534 if (memcmp(pinmodel->identifier, "IDP3", 4))
1535 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1536 version = LittleLong (pinmodel->version);
1537 if (version != MD3VERSION)
1538 Host_Error ("%s has wrong version number (%i should be %i)",
1539 loadmodel->name, version, MD3VERSION);
1541 skinfiles = Mod_LoadSkinFiles();
1542 if (loadmodel->numskins < 1)
1543 loadmodel->numskins = 1;
1545 loadmodel->modeldatatypestring = "MD3";
1547 loadmodel->type = mod_alias;
1548 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1549 loadmodel->DrawSky = NULL;
1550 loadmodel->DrawAddWaterPlanes = NULL;
1551 loadmodel->Draw = R_Q1BSP_Draw;
1552 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1553 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1554 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1555 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1556 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1557 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1558 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1559 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1560 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1561 loadmodel->PointSuperContents = NULL;
1562 loadmodel->synctype = ST_RAND;
1563 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1564 i = LittleLong (pinmodel->flags);
1565 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1567 // set up some global info about the model
1568 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1569 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1571 // make skinscenes for the skins (no groups)
1572 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1573 for (i = 0;i < loadmodel->numskins;i++)
1575 loadmodel->skinscenes[i].firstframe = i;
1576 loadmodel->skinscenes[i].framecount = 1;
1577 loadmodel->skinscenes[i].loop = true;
1578 loadmodel->skinscenes[i].framerate = 10;
1582 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1583 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1585 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1586 loadmodel->animscenes[i].firstframe = i;
1587 loadmodel->animscenes[i].framecount = 1;
1588 loadmodel->animscenes[i].framerate = 10;
1589 loadmodel->animscenes[i].loop = true;
1593 loadmodel->num_tagframes = loadmodel->numframes;
1594 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1595 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1596 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1598 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1599 for (j = 0;j < 9;j++)
1600 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1601 for (j = 0;j < 3;j++)
1602 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1603 //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);
1609 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)))
1611 if (memcmp(pinmesh->identifier, "IDP3", 4))
1612 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1613 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1614 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1615 meshvertices += LittleLong(pinmesh->num_vertices);
1616 meshtriangles += LittleLong(pinmesh->num_triangles);
1619 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1620 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1621 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1622 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));
1623 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1624 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1625 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1626 loadmodel->surfmesh.num_vertices = meshvertices;
1627 loadmodel->surfmesh.num_triangles = meshtriangles;
1628 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1629 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1630 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1631 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1632 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1633 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1634 if (meshvertices <= 65536)
1635 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1639 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)))
1641 if (memcmp(pinmesh->identifier, "IDP3", 4))
1642 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1643 loadmodel->sortedmodelsurfaces[i] = i;
1644 surface = loadmodel->data_surfaces + i;
1645 surface->texture = loadmodel->data_textures + i;
1646 surface->num_firsttriangle = meshtriangles;
1647 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1648 surface->num_firstvertex = meshvertices;
1649 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1650 meshvertices += surface->num_vertices;
1651 meshtriangles += surface->num_triangles;
1653 for (j = 0;j < surface->num_triangles * 3;j++)
1654 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1655 for (j = 0;j < surface->num_vertices;j++)
1657 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1658 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1660 for (j = 0;j < loadmodel->numframes;j++)
1662 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1663 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1664 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1666 out->origin[0] = LittleShort(in->origin[0]);
1667 out->origin[1] = LittleShort(in->origin[1]);
1668 out->origin[2] = LittleShort(in->origin[2]);
1669 out->pitch = in->pitch;
1674 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1676 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1678 if (loadmodel->surfmesh.data_element3s)
1679 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1680 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1681 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1682 Mod_Alias_MorphMesh_CompileFrames();
1683 Mod_Alias_CalculateBoundingBox();
1684 Mod_FreeSkinFiles(skinfiles);
1685 Mod_MakeSortedSurfaces(loadmodel);
1687 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1688 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1691 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1693 zymtype1header_t *pinmodel, *pheader;
1694 unsigned char *pbase;
1695 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1696 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose;
1697 zymvertex_t *verts, *vertdata;
1701 skinfile_t *skinfiles;
1702 unsigned char *data;
1703 msurface_t *surface;
1705 pinmodel = (zymtype1header_t *)buffer;
1706 pbase = (unsigned char *)buffer;
1707 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1708 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1709 if (BigLong(pinmodel->type) != 1)
1710 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1712 loadmodel->modeldatatypestring = "ZYM";
1714 loadmodel->type = mod_alias;
1715 loadmodel->synctype = ST_RAND;
1719 pheader->type = BigLong(pinmodel->type);
1720 pheader->filesize = BigLong(pinmodel->filesize);
1721 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1722 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1723 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1724 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1725 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1726 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1727 pheader->radius = BigFloat(pinmodel->radius);
1728 pheader->numverts = BigLong(pinmodel->numverts);
1729 pheader->numtris = BigLong(pinmodel->numtris);
1730 pheader->numshaders = BigLong(pinmodel->numshaders);
1731 pheader->numbones = BigLong(pinmodel->numbones);
1732 pheader->numscenes = BigLong(pinmodel->numscenes);
1733 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1734 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1735 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1736 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1737 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1738 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1739 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1740 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1741 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1742 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1743 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1744 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1745 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1746 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1747 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1748 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1749 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1750 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1752 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1754 Con_Printf("%s has no geometry\n", loadmodel->name);
1757 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1759 Con_Printf("%s has no animations\n", loadmodel->name);
1763 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1764 loadmodel->DrawSky = NULL;
1765 loadmodel->DrawAddWaterPlanes = NULL;
1766 loadmodel->Draw = R_Q1BSP_Draw;
1767 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1768 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1769 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1770 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1771 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1772 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1773 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1774 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1775 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1776 loadmodel->PointSuperContents = NULL;
1778 loadmodel->numframes = pheader->numscenes;
1779 loadmodel->num_surfaces = pheader->numshaders;
1781 skinfiles = Mod_LoadSkinFiles();
1782 if (loadmodel->numskins < 1)
1783 loadmodel->numskins = 1;
1785 // make skinscenes for the skins (no groups)
1786 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1787 for (i = 0;i < loadmodel->numskins;i++)
1789 loadmodel->skinscenes[i].firstframe = i;
1790 loadmodel->skinscenes[i].framecount = 1;
1791 loadmodel->skinscenes[i].loop = true;
1792 loadmodel->skinscenes[i].framerate = 10;
1796 modelradius = pheader->radius;
1797 for (i = 0;i < 3;i++)
1799 loadmodel->normalmins[i] = pheader->mins[i];
1800 loadmodel->normalmaxs[i] = pheader->maxs[i];
1801 loadmodel->rotatedmins[i] = -modelradius;
1802 loadmodel->rotatedmaxs[i] = modelradius;
1804 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1805 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1806 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1807 if (loadmodel->yawmaxs[0] > modelradius)
1808 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1809 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1810 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1811 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1812 loadmodel->radius = modelradius;
1813 loadmodel->radius2 = modelradius * modelradius;
1815 // go through the lumps, swapping things
1817 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1818 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1819 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1820 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1821 for (i = 0;i < pheader->numscenes;i++)
1823 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1824 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1825 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1826 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1827 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1828 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1829 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1830 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1831 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1832 if (loadmodel->animscenes[i].framerate < 0)
1833 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1837 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1838 loadmodel->num_bones = pheader->numbones;
1839 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1840 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1841 for (i = 0;i < pheader->numbones;i++)
1843 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1844 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1845 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1846 if (loadmodel->data_bones[i].parent >= i)
1847 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1850 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1851 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1852 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1853 for (i = 0;i < pheader->numverts;i++)
1855 vertbonecounts[i] = BigLong(bonecount[i]);
1856 if (vertbonecounts[i] != 1)
1857 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1860 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1862 meshvertices = pheader->numverts;
1863 meshtriangles = pheader->numtris;
1865 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1866 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1867 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1868 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(float[12]) + loadmodel->num_bones * sizeof(float[12]));
1869 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1870 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1871 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1872 loadmodel->surfmesh.num_vertices = meshvertices;
1873 loadmodel->surfmesh.num_triangles = meshtriangles;
1874 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1875 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1876 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1877 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1878 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1879 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1880 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1881 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1882 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1883 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
1884 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1885 if (loadmodel->surfmesh.num_vertices <= 65536)
1886 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1888 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1889 poses = (float *) (pheader->lump_poses.start + pbase);
1890 for (i = 0;i < pheader->lump_poses.length / 4;i++)
1891 loadmodel->data_poses[i] = BigFloat(poses[i]);
1893 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1894 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1895 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1896 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1897 // (converting from weight-blending skeletal animation to
1898 // deformation-based skeletal animation)
1899 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1900 for (i = 0;i < loadmodel->num_bones;i++)
1902 const float *m = loadmodel->data_poses + i * 12;
1903 if (loadmodel->data_bones[i].parent >= 0)
1904 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1906 for (k = 0;k < 12;k++)
1907 bonepose[12*i+k] = m[k];
1909 for (j = 0;j < pheader->numverts;j++)
1911 // this format really should have had a per vertexweight weight value...
1912 // but since it does not, the weighting is completely ignored and
1913 // only one weight is allowed per vertex
1914 int boneindex = BigLong(vertdata[j].bonenum);
1915 const float *m = bonepose + 12 * boneindex;
1916 float relativeorigin[3];
1917 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1918 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1919 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1920 // transform the vertex bone weight into the base mesh
1921 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1922 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1923 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1924 // store the weight as the primary weight on this vertex
1925 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
1926 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = 1;
1929 // normals and tangents are calculated after elements are loaded
1931 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1932 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1933 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1934 for (i = 0;i < pheader->numverts;i++)
1936 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1937 // flip T coordinate for OpenGL
1938 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1941 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1942 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1943 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1945 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1946 //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)
1947 // byteswap, validate, and swap winding order of tris
1948 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1949 if (pheader->lump_render.length != count)
1950 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1951 renderlist = (int *) (pheader->lump_render.start + pbase);
1952 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1954 for (i = 0;i < loadmodel->num_surfaces;i++)
1956 int firstvertex, lastvertex;
1957 if (renderlist >= renderlistend)
1958 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1959 count = BigLong(*renderlist);renderlist++;
1960 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1961 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1963 loadmodel->sortedmodelsurfaces[i] = i;
1964 surface = loadmodel->data_surfaces + i;
1965 surface->texture = loadmodel->data_textures + i;
1966 surface->num_firsttriangle = meshtriangles;
1967 surface->num_triangles = count;
1968 meshtriangles += surface->num_triangles;
1970 // load the elements
1971 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
1972 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
1974 outelements[j*3+2] = BigLong(renderlist[0]);
1975 outelements[j*3+1] = BigLong(renderlist[1]);
1976 outelements[j*3+0] = BigLong(renderlist[2]);
1978 // validate the elements and find the used vertex range
1979 firstvertex = meshvertices;
1981 for (j = 0;j < surface->num_triangles * 3;j++)
1983 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
1984 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
1985 firstvertex = min(firstvertex, outelements[j]);
1986 lastvertex = max(lastvertex, outelements[j]);
1988 surface->num_firstvertex = firstvertex;
1989 surface->num_vertices = lastvertex + 1 - firstvertex;
1991 // since zym models do not have named sections, reuse their shader
1992 // name as the section name
1993 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
1994 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
1996 Mod_FreeSkinFiles(skinfiles);
1997 Mem_Free(vertbonecounts);
1999 Mod_MakeSortedSurfaces(loadmodel);
2001 // compute all the mesh information that was not loaded from the file
2002 if (loadmodel->surfmesh.data_element3s)
2003 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2004 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2005 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2006 Mod_BuildBaseBonePoses();
2007 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2008 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);
2009 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2011 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2014 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2016 dpmheader_t *pheader;
2020 unsigned char *pbase;
2021 int i, j, k, meshvertices, meshtriangles;
2022 skinfile_t *skinfiles;
2023 unsigned char *data;
2026 pheader = (dpmheader_t *)buffer;
2027 pbase = (unsigned char *)buffer;
2028 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2029 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2030 if (BigLong(pheader->type) != 2)
2031 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2033 loadmodel->modeldatatypestring = "DPM";
2035 loadmodel->type = mod_alias;
2036 loadmodel->synctype = ST_RAND;
2039 pheader->type = BigLong(pheader->type);
2040 pheader->filesize = BigLong(pheader->filesize);
2041 pheader->mins[0] = BigFloat(pheader->mins[0]);
2042 pheader->mins[1] = BigFloat(pheader->mins[1]);
2043 pheader->mins[2] = BigFloat(pheader->mins[2]);
2044 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2045 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2046 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2047 pheader->yawradius = BigFloat(pheader->yawradius);
2048 pheader->allradius = BigFloat(pheader->allradius);
2049 pheader->num_bones = BigLong(pheader->num_bones);
2050 pheader->num_meshs = BigLong(pheader->num_meshs);
2051 pheader->num_frames = BigLong(pheader->num_frames);
2052 pheader->ofs_bones = BigLong(pheader->ofs_bones);
2053 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2054 pheader->ofs_frames = BigLong(pheader->ofs_frames);
2056 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2058 Con_Printf("%s has no geometry\n", loadmodel->name);
2061 if (pheader->num_frames < 1)
2063 Con_Printf("%s has no frames\n", loadmodel->name);
2067 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2068 loadmodel->DrawSky = NULL;
2069 loadmodel->DrawAddWaterPlanes = NULL;
2070 loadmodel->Draw = R_Q1BSP_Draw;
2071 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2072 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2073 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2074 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2075 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2076 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2077 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2078 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2079 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2080 loadmodel->PointSuperContents = NULL;
2083 for (i = 0;i < 3;i++)
2085 loadmodel->normalmins[i] = pheader->mins[i];
2086 loadmodel->normalmaxs[i] = pheader->maxs[i];
2087 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2088 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2089 loadmodel->rotatedmins[i] = -pheader->allradius;
2090 loadmodel->rotatedmaxs[i] = pheader->allradius;
2092 loadmodel->radius = pheader->allradius;
2093 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2095 // load external .skin files if present
2096 skinfiles = Mod_LoadSkinFiles();
2097 if (loadmodel->numskins < 1)
2098 loadmodel->numskins = 1;
2103 // gather combined statistics from the meshes
2104 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2105 for (i = 0;i < (int)pheader->num_meshs;i++)
2107 int numverts = BigLong(dpmmesh->num_verts);
2108 meshvertices += numverts;
2109 meshtriangles += BigLong(dpmmesh->num_tris);
2113 loadmodel->numframes = pheader->num_frames;
2114 loadmodel->num_bones = pheader->num_bones;
2115 loadmodel->num_poses = loadmodel->numframes;
2116 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2117 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2118 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2119 // do most allocations as one merged chunk
2120 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(float[12]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
2121 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2122 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2123 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2124 loadmodel->surfmesh.num_vertices = meshvertices;
2125 loadmodel->surfmesh.num_triangles = meshtriangles;
2126 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2127 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2128 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2129 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2130 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2131 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2132 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2133 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
2134 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
2135 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
2136 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2137 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2138 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2139 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2140 if (meshvertices <= 65536)
2141 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2143 for (i = 0;i < loadmodel->numskins;i++)
2145 loadmodel->skinscenes[i].firstframe = i;
2146 loadmodel->skinscenes[i].framecount = 1;
2147 loadmodel->skinscenes[i].loop = true;
2148 loadmodel->skinscenes[i].framerate = 10;
2151 // load the bone info
2152 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2153 for (i = 0;i < loadmodel->num_bones;i++)
2155 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2156 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2157 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2158 if (loadmodel->data_bones[i].parent >= i)
2159 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2163 frame = (dpmframe_t *) (pbase + pheader->ofs_frames);
2164 for (i = 0;i < loadmodel->numframes;i++)
2167 memcpy(loadmodel->animscenes[i].name, frame->name, sizeof(frame->name));
2168 loadmodel->animscenes[i].firstframe = i;
2169 loadmodel->animscenes[i].framecount = 1;
2170 loadmodel->animscenes[i].loop = true;
2171 loadmodel->animscenes[i].framerate = 10;
2172 // load the bone poses for this frame
2173 poses = (float *) (pbase + BigLong(frame->ofs_bonepositions));
2174 for (j = 0;j < loadmodel->num_bones*12;j++)
2175 loadmodel->data_poses[i * loadmodel->num_bones*12 + j] = BigFloat(poses[j]);
2176 // stuff not processed here: mins, maxs, yawradius, allradius
2180 // load the meshes now
2181 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2184 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2185 // (converting from weight-blending skeletal animation to
2186 // deformation-based skeletal animation)
2187 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2188 for (i = 0;i < loadmodel->num_bones;i++)
2190 const float *m = loadmodel->data_poses + i * 12;
2191 if (loadmodel->data_bones[i].parent >= 0)
2192 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2194 for (k = 0;k < 12;k++)
2195 bonepose[12*i+k] = m[k];
2197 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2199 const int *inelements;
2201 const float *intexcoord;
2202 msurface_t *surface;
2204 loadmodel->sortedmodelsurfaces[i] = i;
2205 surface = loadmodel->data_surfaces + i;
2206 surface->texture = loadmodel->data_textures + i;
2207 surface->num_firsttriangle = meshtriangles;
2208 surface->num_triangles = BigLong(dpmmesh->num_tris);
2209 surface->num_firstvertex = meshvertices;
2210 surface->num_vertices = BigLong(dpmmesh->num_verts);
2211 meshvertices += surface->num_vertices;
2212 meshtriangles += surface->num_triangles;
2214 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2215 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2216 for (j = 0;j < surface->num_triangles;j++)
2218 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2219 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2220 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2221 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2226 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2227 for (j = 0;j < surface->num_vertices*2;j++)
2228 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2230 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2231 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2235 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2236 data += sizeof(dpmvertex_t);
2237 for (k = 0;k < numweights;k++)
2239 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2240 int boneindex = BigLong(vert->bonenum);
2241 const float *m = bonepose + 12 * boneindex;
2242 float influence = BigFloat(vert->influence);
2243 float relativeorigin[3], relativenormal[3];
2244 relativeorigin[0] = BigFloat(vert->origin[0]);
2245 relativeorigin[1] = BigFloat(vert->origin[1]);
2246 relativeorigin[2] = BigFloat(vert->origin[2]);
2247 relativenormal[0] = BigFloat(vert->normal[0]);
2248 relativenormal[1] = BigFloat(vert->normal[1]);
2249 relativenormal[2] = BigFloat(vert->normal[2]);
2250 // blend the vertex bone weights into the base mesh
2251 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2252 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2253 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2254 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2255 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2256 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2259 // store the first (and often only) weight
2260 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = influence;
2261 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
2265 // sort the new weight into this vertex's weight table
2266 // (which only accepts up to 4 bones per vertex)
2267 for (l = 0;l < 4;l++)
2269 if (loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] < influence)
2271 // move weaker influence weights out of the way first
2273 for (l2 = 3;l2 > l;l2--)
2275 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2-1];
2276 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2-1];
2278 // store the new weight
2279 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] = influence;
2280 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l] = boneindex;
2285 data += sizeof(dpmbonevert_t);
2288 for (l = 0;l < 4;l++)
2289 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l];
2290 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2292 float f = 1.0f / sum;
2293 for (l = 0;l < 4;l++)
2294 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] *= f;
2298 // since dpm models do not have named sections, reuse their shader name as the section name
2299 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2301 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2304 Mod_FreeSkinFiles(skinfiles);
2305 Mod_MakeSortedSurfaces(loadmodel);
2307 // compute all the mesh information that was not loaded from the file
2308 if (loadmodel->surfmesh.data_element3s)
2309 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2310 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2311 Mod_BuildBaseBonePoses();
2312 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);
2313 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2315 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2318 // no idea why PSK/PSA files contain weird quaternions but they do...
2319 #define PSKQUATNEGATIONS
2320 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2322 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2323 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2324 fs_offset_t filesize;
2329 pskboneinfo_t *bones;
2330 pskrawweights_t *rawweights;
2331 pskboneinfo_t *animbones;
2332 pskaniminfo_t *anims;
2333 pskanimkeys_t *animkeys;
2334 void *animfilebuffer, *animbuffer, *animbufferend;
2335 unsigned char *data;
2337 skinfile_t *skinfiles;
2338 char animname[MAX_QPATH];
2341 pchunk = (pskchunk_t *)buffer;
2342 if (strcmp(pchunk->id, "ACTRHEAD"))
2343 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2345 loadmodel->modeldatatypestring = "PSK";
2347 loadmodel->type = mod_alias;
2348 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2349 loadmodel->DrawSky = NULL;
2350 loadmodel->DrawAddWaterPlanes = NULL;
2351 loadmodel->Draw = R_Q1BSP_Draw;
2352 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2353 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2354 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2355 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2356 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2357 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2358 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2359 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2360 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2361 loadmodel->PointSuperContents = NULL;
2362 loadmodel->synctype = ST_RAND;
2364 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2365 strlcat(animname, ".psa", sizeof(animname));
2366 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2367 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2368 if (animbuffer == NULL)
2369 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2388 while (buffer < bufferend)
2390 pchunk = (pskchunk_t *)buffer;
2391 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2392 version = LittleLong(pchunk->version);
2393 recordsize = LittleLong(pchunk->recordsize);
2394 numrecords = LittleLong(pchunk->numrecords);
2395 if (developer.integer >= 100)
2396 Con_Printf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2397 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2398 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);
2399 if (!strcmp(pchunk->id, "ACTRHEAD"))
2403 else if (!strcmp(pchunk->id, "PNTS0000"))
2406 if (recordsize != sizeof(*p))
2407 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2408 // byteswap in place and keep the pointer
2409 numpnts = numrecords;
2410 pnts = (pskpnts_t *)buffer;
2411 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2413 p->origin[0] = LittleFloat(p->origin[0]);
2414 p->origin[1] = LittleFloat(p->origin[1]);
2415 p->origin[2] = LittleFloat(p->origin[2]);
2419 else if (!strcmp(pchunk->id, "VTXW0000"))
2422 if (recordsize != sizeof(*p))
2423 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2424 // byteswap in place and keep the pointer
2425 numvtxw = numrecords;
2426 vtxw = (pskvtxw_t *)buffer;
2427 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2429 p->pntsindex = LittleShort(p->pntsindex);
2430 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2431 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2432 if (p->pntsindex >= numpnts)
2434 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2440 else if (!strcmp(pchunk->id, "FACE0000"))
2443 if (recordsize != sizeof(*p))
2444 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2445 // byteswap in place and keep the pointer
2446 numfaces = numrecords;
2447 faces = (pskface_t *)buffer;
2448 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2450 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2451 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2452 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2453 p->group = LittleLong(p->group);
2454 if (p->vtxwindex[0] >= numvtxw)
2456 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2457 p->vtxwindex[0] = 0;
2459 if (p->vtxwindex[1] >= numvtxw)
2461 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2462 p->vtxwindex[1] = 0;
2464 if (p->vtxwindex[2] >= numvtxw)
2466 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2467 p->vtxwindex[2] = 0;
2472 else if (!strcmp(pchunk->id, "MATT0000"))
2475 if (recordsize != sizeof(*p))
2476 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2477 // byteswap in place and keep the pointer
2478 nummatts = numrecords;
2479 matts = (pskmatt_t *)buffer;
2480 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2486 else if (!strcmp(pchunk->id, "REFSKELT"))
2489 if (recordsize != sizeof(*p))
2490 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2491 // byteswap in place and keep the pointer
2492 numbones = numrecords;
2493 bones = (pskboneinfo_t *)buffer;
2494 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2496 p->numchildren = LittleLong(p->numchildren);
2497 p->parent = LittleLong(p->parent);
2498 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2499 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2500 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2501 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2502 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2503 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2504 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2505 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2506 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2507 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2508 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2509 #ifdef PSKQUATNEGATIONS
2512 p->basepose.quat[0] *= -1;
2513 p->basepose.quat[1] *= -1;
2514 p->basepose.quat[2] *= -1;
2518 p->basepose.quat[0] *= 1;
2519 p->basepose.quat[1] *= -1;
2520 p->basepose.quat[2] *= 1;
2523 if (p->parent < 0 || p->parent >= numbones)
2525 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2531 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2534 if (recordsize != sizeof(*p))
2535 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2536 // byteswap in place and keep the pointer
2537 numrawweights = numrecords;
2538 rawweights = (pskrawweights_t *)buffer;
2539 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2541 p->weight = LittleFloat(p->weight);
2542 p->pntsindex = LittleLong(p->pntsindex);
2543 p->boneindex = LittleLong(p->boneindex);
2544 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2546 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2549 if (p->boneindex < 0 || p->boneindex >= numbones)
2551 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2559 while (animbuffer < animbufferend)
2561 pchunk = (pskchunk_t *)animbuffer;
2562 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2563 version = LittleLong(pchunk->version);
2564 recordsize = LittleLong(pchunk->recordsize);
2565 numrecords = LittleLong(pchunk->numrecords);
2566 if (developer.integer >= 100)
2567 Con_Printf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2568 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2569 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);
2570 if (!strcmp(pchunk->id, "ANIMHEAD"))
2574 else if (!strcmp(pchunk->id, "BONENAMES"))
2577 if (recordsize != sizeof(*p))
2578 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2579 // byteswap in place and keep the pointer
2580 numanimbones = numrecords;
2581 animbones = (pskboneinfo_t *)animbuffer;
2582 // NOTE: supposedly psa does not need to match the psk model, the
2583 // bones missing from the psa would simply use their base
2584 // positions from the psk, but this is hard for me to implement
2585 // and people can easily make animations that match.
2586 if (numanimbones != numbones)
2587 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2588 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2590 p->numchildren = LittleLong(p->numchildren);
2591 p->parent = LittleLong(p->parent);
2592 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2593 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2594 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2595 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2596 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2597 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2598 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2599 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2600 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2601 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2602 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2603 #ifdef PSKQUATNEGATIONS
2606 p->basepose.quat[0] *= -1;
2607 p->basepose.quat[1] *= -1;
2608 p->basepose.quat[2] *= -1;
2612 p->basepose.quat[0] *= 1;
2613 p->basepose.quat[1] *= -1;
2614 p->basepose.quat[2] *= 1;
2617 if (p->parent < 0 || p->parent >= numanimbones)
2619 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2622 // check that bones are the same as in the base
2623 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2624 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2628 else if (!strcmp(pchunk->id, "ANIMINFO"))
2631 if (recordsize != sizeof(*p))
2632 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2633 // byteswap in place and keep the pointer
2634 numanims = numrecords;
2635 anims = (pskaniminfo_t *)animbuffer;
2636 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2638 p->numbones = LittleLong(p->numbones);
2639 p->playtime = LittleFloat(p->playtime);
2640 p->fps = LittleFloat(p->fps);
2641 p->firstframe = LittleLong(p->firstframe);
2642 p->numframes = LittleLong(p->numframes);
2643 if (p->numbones != numbones)
2644 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2648 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2651 if (recordsize != sizeof(*p))
2652 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2653 numanimkeys = numrecords;
2654 animkeys = (pskanimkeys_t *)animbuffer;
2655 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2657 p->origin[0] = LittleFloat(p->origin[0]);
2658 p->origin[1] = LittleFloat(p->origin[1]);
2659 p->origin[2] = LittleFloat(p->origin[2]);
2660 p->quat[0] = LittleFloat(p->quat[0]);
2661 p->quat[1] = LittleFloat(p->quat[1]);
2662 p->quat[2] = LittleFloat(p->quat[2]);
2663 p->quat[3] = LittleFloat(p->quat[3]);
2664 p->frametime = LittleFloat(p->frametime);
2665 #ifdef PSKQUATNEGATIONS
2666 if (index % numbones)
2681 // TODO: allocate bonepose stuff
2684 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2687 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2688 Host_Error("%s: missing required chunks", loadmodel->name);
2690 loadmodel->numframes = 0;
2691 for (index = 0;index < numanims;index++)
2692 loadmodel->numframes += anims[index].numframes;
2694 if (numanimkeys != numbones * loadmodel->numframes)
2695 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2697 meshvertices = numvtxw;
2698 meshtriangles = numfaces;
2700 // load external .skin files if present
2701 skinfiles = Mod_LoadSkinFiles();
2702 if (loadmodel->numskins < 1)
2703 loadmodel->numskins = 1;
2704 loadmodel->num_bones = numbones;
2705 loadmodel->num_poses = loadmodel->numframes;
2706 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2707 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2708 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2709 loadmodel->surfmesh.num_vertices = meshvertices;
2710 loadmodel->surfmesh.num_triangles = meshtriangles;
2711 // do most allocations as one merged chunk
2712 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(float[12]) + 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);
2713 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2714 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2715 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2716 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2717 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2718 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2719 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2720 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2721 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2722 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2723 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2724 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += loadmodel->surfmesh.num_vertices * sizeof(int[4]);
2725 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[4]);
2726 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
2727 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2728 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2729 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2730 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2731 if (loadmodel->surfmesh.num_vertices <= 65536)
2732 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2734 for (i = 0;i < loadmodel->numskins;i++)
2736 loadmodel->skinscenes[i].firstframe = i;
2737 loadmodel->skinscenes[i].framecount = 1;
2738 loadmodel->skinscenes[i].loop = true;
2739 loadmodel->skinscenes[i].framerate = 10;
2743 for (index = 0, i = 0;index < nummatts;index++)
2745 // since psk models do not have named sections, reuse their shader name as the section name
2746 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2747 loadmodel->sortedmodelsurfaces[index] = index;
2748 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2749 loadmodel->data_surfaces[index].num_firstvertex = 0;
2750 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2753 // copy over the vertex locations and texcoords
2754 for (index = 0;index < numvtxw;index++)
2756 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2757 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2758 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2759 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2760 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2763 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2764 for (index = 0;index < numfaces;index++)
2765 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2766 for (index = 0, i = 0;index < nummatts;index++)
2768 loadmodel->data_surfaces[index].num_firsttriangle = i;
2769 i += loadmodel->data_surfaces[index].num_triangles;
2770 loadmodel->data_surfaces[index].num_triangles = 0;
2772 for (index = 0;index < numfaces;index++)
2774 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2775 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2776 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2777 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2780 // copy over the bones
2781 for (index = 0;index < numbones;index++)
2783 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2784 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2785 if (loadmodel->data_bones[index].parent >= index)
2786 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2789 // sort the psk point weights into the vertex weight tables
2790 // (which only accept up to 4 bones per vertex)
2791 for (index = 0;index < numvtxw;index++)
2795 for (j = 0;j < numrawweights;j++)
2797 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2799 int boneindex = rawweights[j].boneindex;
2800 float influence = rawweights[j].weight;
2801 for (l = 0;l < 4;l++)
2803 if (loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] < influence)
2805 // move lower influence weights out of the way first
2807 for (l2 = 3;l2 > l;l2--)
2809 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2-1];
2810 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2-1];
2812 // store the new weight
2813 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] = influence;
2814 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l] = boneindex;
2821 for (l = 0;l < 4;l++)
2822 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l];
2823 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2825 float f = 1.0f / sum;
2826 for (l = 0;l < 4;l++)
2827 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] *= f;
2831 // set up the animscenes based on the anims
2832 for (index = 0, i = 0;index < numanims;index++)
2834 for (j = 0;j < anims[index].numframes;j++, i++)
2836 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2837 loadmodel->animscenes[i].firstframe = i;
2838 loadmodel->animscenes[i].framecount = 1;
2839 loadmodel->animscenes[i].loop = true;
2840 loadmodel->animscenes[i].framerate = 10;
2844 // load the poses from the animkeys
2845 for (index = 0;index < numanimkeys;index++)
2847 pskanimkeys_t *k = animkeys + index;
2849 Matrix4x4_FromOriginQuat(&matrix, k->origin[0], k->origin[1], k->origin[2], k->quat[0], k->quat[1], k->quat[2], k->quat[3]);
2850 Matrix4x4_ToArray12FloatD3D(&matrix, loadmodel->data_poses + index*12);
2852 Mod_FreeSkinFiles(skinfiles);
2853 Mem_Free(animfilebuffer);
2854 Mod_MakeSortedSurfaces(loadmodel);
2856 // compute all the mesh information that was not loaded from the file
2857 // TODO: honor smoothing groups somehow?
2858 if (loadmodel->surfmesh.data_element3s)
2859 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2860 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2861 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2862 Mod_BuildBaseBonePoses();
2863 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2864 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);
2865 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2866 Mod_Alias_CalculateBoundingBox();
2868 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;