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->hasalpha)
901 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
902 texture->currentmaterialflags = texture->basematerialflags;
903 texture->specularscalemod = 1;
904 texture->specularpowermod = 1;
907 static void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
910 skinfileitem_t *skinfileitem;
913 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
914 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
916 memset(skin, 0, sizeof(*skin));
918 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
920 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
921 if (!strcmp(skinfileitem->name, meshname))
923 Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
929 // don't render unmentioned meshes
930 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
931 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
936 Mod_LoadTextureFromQ3Shader(skin, shadername, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
939 #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);
940 #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);
941 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
943 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
944 float scales, scalet, interval;
948 stvert_t *pinstverts;
949 dtriangle_t *pintriangles;
950 daliasskintype_t *pinskintype;
951 daliasskingroup_t *pinskingroup;
952 daliasskininterval_t *pinskinintervals;
953 daliasframetype_t *pinframetype;
954 daliasgroup_t *pinframegroup;
955 unsigned char *datapointer, *startframes, *startskins;
956 char name[MAX_QPATH];
957 skinframe_t *tempskinframe;
958 animscene_t *tempskinscenes;
959 texture_t *tempaliasskins;
961 int *vertonseam, *vertremap;
962 skinfile_t *skinfiles;
964 datapointer = (unsigned char *)buffer;
965 pinmodel = (mdl_t *)datapointer;
966 datapointer += sizeof(mdl_t);
968 version = LittleLong (pinmodel->version);
969 if (version != ALIAS_VERSION)
970 Host_Error ("%s has wrong version number (%i should be %i)",
971 loadmodel->name, version, ALIAS_VERSION);
973 loadmodel->modeldatatypestring = "MDL";
975 loadmodel->type = mod_alias;
976 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
977 loadmodel->DrawSky = NULL;
978 loadmodel->DrawAddWaterPlanes = NULL;
979 loadmodel->Draw = R_Q1BSP_Draw;
980 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
981 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
982 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
983 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
984 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
985 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
986 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
987 loadmodel->DrawLight = R_Q1BSP_DrawLight;
988 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
989 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
990 loadmodel->PointSuperContents = NULL;
992 loadmodel->num_surfaces = 1;
993 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
994 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
995 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
996 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
997 loadmodel->sortedmodelsurfaces[0] = 0;
999 loadmodel->numskins = LittleLong(pinmodel->numskins);
1000 BOUNDI(loadmodel->numskins,0,65536);
1001 skinwidth = LittleLong (pinmodel->skinwidth);
1002 BOUNDI(skinwidth,0,65536);
1003 skinheight = LittleLong (pinmodel->skinheight);
1004 BOUNDI(skinheight,0,65536);
1005 numverts = LittleLong(pinmodel->numverts);
1006 BOUNDI(numverts,0,65536);
1007 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
1008 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
1009 loadmodel->numframes = LittleLong(pinmodel->numframes);
1010 BOUNDI(loadmodel->numframes,0,65536);
1011 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
1012 BOUNDI(loadmodel->synctype,0,2);
1013 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1014 i = LittleLong (pinmodel->flags);
1015 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1017 for (i = 0;i < 3;i++)
1019 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
1020 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
1023 startskins = datapointer;
1025 for (i = 0;i < loadmodel->numskins;i++)
1027 pinskintype = (daliasskintype_t *)datapointer;
1028 datapointer += sizeof(daliasskintype_t);
1029 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
1033 pinskingroup = (daliasskingroup_t *)datapointer;
1034 datapointer += sizeof(daliasskingroup_t);
1035 groupskins = LittleLong(pinskingroup->numskins);
1036 datapointer += sizeof(daliasskininterval_t) * groupskins;
1039 for (j = 0;j < groupskins;j++)
1041 datapointer += skinwidth * skinheight;
1046 pinstverts = (stvert_t *)datapointer;
1047 datapointer += sizeof(stvert_t) * numverts;
1049 pintriangles = (dtriangle_t *)datapointer;
1050 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
1052 startframes = datapointer;
1053 loadmodel->surfmesh.num_morphframes = 0;
1054 for (i = 0;i < loadmodel->numframes;i++)
1056 pinframetype = (daliasframetype_t *)datapointer;
1057 datapointer += sizeof(daliasframetype_t);
1058 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
1062 pinframegroup = (daliasgroup_t *)datapointer;
1063 datapointer += sizeof(daliasgroup_t);
1064 groupframes = LittleLong(pinframegroup->numframes);
1065 datapointer += sizeof(daliasinterval_t) * groupframes;
1068 for (j = 0;j < groupframes;j++)
1070 datapointer += sizeof(daliasframe_t);
1071 datapointer += sizeof(trivertx_t) * numverts;
1072 loadmodel->surfmesh.num_morphframes++;
1075 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1077 // store texture coordinates into temporary array, they will be stored
1078 // after usage is determined (triangle data)
1079 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
1080 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
1081 vertonseam = vertremap + numverts * 2;
1083 scales = 1.0 / skinwidth;
1084 scalet = 1.0 / skinheight;
1085 for (i = 0;i < numverts;i++)
1087 vertonseam[i] = LittleLong(pinstverts[i].onseam);
1088 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
1089 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
1090 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
1091 vertst[(i+numverts)*2+1] = vertst[i*2+1];
1094 // load triangle data
1095 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1097 // read the triangle elements
1098 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1099 for (j = 0;j < 3;j++)
1100 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1101 // validate (note numverts is used because this is the original data)
1102 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1103 // now butcher the elements according to vertonseam and tri->facesfront
1104 // and then compact the vertex set to remove duplicates
1105 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1106 if (!LittleLong(pintriangles[i].facesfront)) // backface
1107 for (j = 0;j < 3;j++)
1108 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1109 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1111 // (this uses vertremap to count usage to save some memory)
1112 for (i = 0;i < numverts*2;i++)
1114 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1115 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1116 // build remapping table and compact array
1117 loadmodel->surfmesh.num_vertices = 0;
1118 for (i = 0;i < numverts*2;i++)
1122 vertremap[i] = loadmodel->surfmesh.num_vertices;
1123 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1124 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1125 loadmodel->surfmesh.num_vertices++;
1128 vertremap[i] = -1; // not used at all
1130 // remap the elements to the new vertex set
1131 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1132 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1133 // store the texture coordinates
1134 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1135 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1137 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1138 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1141 // generate ushort elements array if possible
1142 if (loadmodel->surfmesh.num_vertices <= 65536)
1143 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1144 if (loadmodel->surfmesh.data_element3s)
1145 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1146 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1149 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1150 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1151 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1152 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1153 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1154 Mod_Alias_CalculateBoundingBox();
1155 Mod_Alias_MorphMesh_CompileFrames();
1158 Mem_Free(vertremap);
1161 skinfiles = Mod_LoadSkinFiles();
1164 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1165 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1166 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1167 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1168 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1169 Mod_FreeSkinFiles(skinfiles);
1170 for (i = 0;i < loadmodel->numskins;i++)
1172 loadmodel->skinscenes[i].firstframe = i;
1173 loadmodel->skinscenes[i].framecount = 1;
1174 loadmodel->skinscenes[i].loop = true;
1175 loadmodel->skinscenes[i].framerate = 10;
1180 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1181 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1182 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1183 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1185 datapointer = startskins;
1186 for (i = 0;i < loadmodel->numskins;i++)
1188 pinskintype = (daliasskintype_t *)datapointer;
1189 datapointer += sizeof(daliasskintype_t);
1191 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1198 pinskingroup = (daliasskingroup_t *)datapointer;
1199 datapointer += sizeof(daliasskingroup_t);
1201 groupskins = LittleLong (pinskingroup->numskins);
1203 pinskinintervals = (daliasskininterval_t *)datapointer;
1204 datapointer += sizeof(daliasskininterval_t) * groupskins;
1206 interval = LittleFloat(pinskinintervals[0].interval);
1207 if (interval < 0.01f)
1209 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1214 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1215 loadmodel->skinscenes[i].firstframe = totalskins;
1216 loadmodel->skinscenes[i].framecount = groupskins;
1217 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1218 loadmodel->skinscenes[i].loop = true;
1220 for (j = 0;j < groupskins;j++)
1223 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1225 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1226 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))
1227 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));
1228 datapointer += skinwidth * skinheight;
1232 // check for skins that don't exist in the model, but do exist as external images
1233 // (this was added because yummyluv kept pestering me about support for it)
1234 // TODO: support shaders here?
1235 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)))
1237 // expand the arrays to make room
1238 tempskinscenes = loadmodel->skinscenes;
1239 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1240 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1241 Mem_Free(tempskinscenes);
1243 tempaliasskins = loadmodel->data_textures;
1244 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1245 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1246 Mem_Free(tempaliasskins);
1248 // store the info about the new skin
1249 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1250 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1251 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1252 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1253 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1254 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1256 //increase skin counts
1257 loadmodel->numskins++;
1260 // fix up the pointers since they are pointing at the old textures array
1261 // FIXME: this is a hack!
1262 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1263 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1267 surface = loadmodel->data_surfaces;
1268 surface->texture = loadmodel->data_textures;
1269 surface->num_firsttriangle = 0;
1270 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1271 surface->num_firstvertex = 0;
1272 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1274 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1277 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1279 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1280 float iskinwidth, iskinheight;
1281 unsigned char *data;
1282 msurface_t *surface;
1284 unsigned char *base, *datapointer;
1285 md2frame_t *pinframe;
1287 md2triangle_t *intri;
1288 unsigned short *inst;
1289 struct md2verthash_s
1291 struct md2verthash_s *next;
1295 *hash, **md2verthash, *md2verthashdata;
1296 skinfile_t *skinfiles;
1298 pinmodel = (md2_t *)buffer;
1299 base = (unsigned char *)buffer;
1301 version = LittleLong (pinmodel->version);
1302 if (version != MD2ALIAS_VERSION)
1303 Host_Error ("%s has wrong version number (%i should be %i)",
1304 loadmodel->name, version, MD2ALIAS_VERSION);
1306 loadmodel->modeldatatypestring = "MD2";
1308 loadmodel->type = mod_alias;
1309 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1310 loadmodel->DrawSky = NULL;
1311 loadmodel->DrawAddWaterPlanes = NULL;
1312 loadmodel->Draw = R_Q1BSP_Draw;
1313 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1314 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1315 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1316 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1317 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1318 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1319 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1320 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1321 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1322 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1323 loadmodel->PointSuperContents = NULL;
1325 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1326 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1327 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1328 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1329 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1330 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1331 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1332 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1334 end = LittleLong(pinmodel->ofs_end);
1335 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1336 Host_Error ("%s is not a valid model", loadmodel->name);
1337 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1338 Host_Error ("%s is not a valid model", loadmodel->name);
1339 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1340 Host_Error ("%s is not a valid model", loadmodel->name);
1341 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1342 Host_Error ("%s is not a valid model", loadmodel->name);
1343 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1344 Host_Error ("%s is not a valid model", loadmodel->name);
1346 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1347 numxyz = LittleLong(pinmodel->num_xyz);
1348 numst = LittleLong(pinmodel->num_st);
1349 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1350 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1351 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1352 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1353 skinwidth = LittleLong(pinmodel->skinwidth);
1354 skinheight = LittleLong(pinmodel->skinheight);
1355 iskinwidth = 1.0f / skinwidth;
1356 iskinheight = 1.0f / skinheight;
1358 loadmodel->num_surfaces = 1;
1359 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1360 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]));
1361 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1362 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1363 loadmodel->sortedmodelsurfaces[0] = 0;
1364 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1365 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1366 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1367 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1369 loadmodel->synctype = ST_RAND;
1372 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1373 skinfiles = Mod_LoadSkinFiles();
1376 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1377 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1378 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1379 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1380 Mod_FreeSkinFiles(skinfiles);
1382 else if (loadmodel->numskins)
1384 // skins found (most likely not a player model)
1385 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1386 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1387 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1388 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1389 Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
1393 // no skins (most likely a player model)
1394 loadmodel->numskins = 1;
1395 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1396 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1397 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1398 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1401 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1402 for (i = 0;i < loadmodel->numskins;i++)
1404 loadmodel->skinscenes[i].firstframe = i;
1405 loadmodel->skinscenes[i].framecount = 1;
1406 loadmodel->skinscenes[i].loop = true;
1407 loadmodel->skinscenes[i].framerate = 10;
1410 // load the triangles and stvert data
1411 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1412 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1413 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1414 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1415 // swap the triangle list
1416 loadmodel->surfmesh.num_vertices = 0;
1417 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1419 for (j = 0;j < 3;j++)
1421 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1422 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1425 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1430 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1433 hashindex = (xyz * 256 + st) & 65535;
1434 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1435 if (hash->xyz == xyz && hash->st == st)
1439 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1442 hash->next = md2verthash[hashindex];
1443 md2verthash[hashindex] = hash;
1445 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1449 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1450 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));
1451 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1452 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1453 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1456 hash = md2verthashdata + i;
1457 vertremap[i] = hash->xyz;
1458 sts = LittleShort(inst[hash->st*2+0]);
1459 stt = LittleShort(inst[hash->st*2+1]);
1460 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1462 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1466 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1467 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1470 Mem_Free(md2verthash);
1471 Mem_Free(md2verthashdata);
1473 // generate ushort elements array if possible
1474 if (loadmodel->surfmesh.num_vertices <= 65536)
1475 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1476 if (loadmodel->surfmesh.data_element3s)
1477 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1478 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1481 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1482 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1487 pinframe = (md2frame_t *)datapointer;
1488 datapointer += sizeof(md2frame_t);
1489 // store the frame scale/translate into the appropriate array
1490 for (j = 0;j < 3;j++)
1492 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1493 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1495 // convert the vertices
1496 v = (trivertx_t *)datapointer;
1497 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1498 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1499 out[k] = v[vertremap[k]];
1500 datapointer += numxyz * sizeof(trivertx_t);
1502 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1503 loadmodel->animscenes[i].firstframe = i;
1504 loadmodel->animscenes[i].framecount = 1;
1505 loadmodel->animscenes[i].framerate = 10;
1506 loadmodel->animscenes[i].loop = true;
1509 Mem_Free(vertremap);
1511 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1512 Mod_Alias_CalculateBoundingBox();
1513 Mod_Alias_MorphMesh_CompileFrames();
1515 surface = loadmodel->data_surfaces;
1516 surface->texture = loadmodel->data_textures;
1517 surface->num_firsttriangle = 0;
1518 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1519 surface->num_firstvertex = 0;
1520 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1522 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1525 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1527 int i, j, k, version, meshvertices, meshtriangles;
1528 unsigned char *data;
1529 msurface_t *surface;
1530 md3modelheader_t *pinmodel;
1531 md3frameinfo_t *pinframe;
1534 skinfile_t *skinfiles;
1536 pinmodel = (md3modelheader_t *)buffer;
1538 if (memcmp(pinmodel->identifier, "IDP3", 4))
1539 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1540 version = LittleLong (pinmodel->version);
1541 if (version != MD3VERSION)
1542 Host_Error ("%s has wrong version number (%i should be %i)",
1543 loadmodel->name, version, MD3VERSION);
1545 skinfiles = Mod_LoadSkinFiles();
1546 if (loadmodel->numskins < 1)
1547 loadmodel->numskins = 1;
1549 loadmodel->modeldatatypestring = "MD3";
1551 loadmodel->type = mod_alias;
1552 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1553 loadmodel->DrawSky = NULL;
1554 loadmodel->DrawAddWaterPlanes = NULL;
1555 loadmodel->Draw = R_Q1BSP_Draw;
1556 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1557 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1558 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1559 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1560 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1561 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1562 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1563 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1564 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1565 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1566 loadmodel->PointSuperContents = NULL;
1567 loadmodel->synctype = ST_RAND;
1568 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1569 i = LittleLong (pinmodel->flags);
1570 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1572 // set up some global info about the model
1573 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1574 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1576 // make skinscenes for the skins (no groups)
1577 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1578 for (i = 0;i < loadmodel->numskins;i++)
1580 loadmodel->skinscenes[i].firstframe = i;
1581 loadmodel->skinscenes[i].framecount = 1;
1582 loadmodel->skinscenes[i].loop = true;
1583 loadmodel->skinscenes[i].framerate = 10;
1587 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1588 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1590 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1591 loadmodel->animscenes[i].firstframe = i;
1592 loadmodel->animscenes[i].framecount = 1;
1593 loadmodel->animscenes[i].framerate = 10;
1594 loadmodel->animscenes[i].loop = true;
1598 loadmodel->num_tagframes = loadmodel->numframes;
1599 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1600 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1601 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1603 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1604 for (j = 0;j < 9;j++)
1605 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1606 for (j = 0;j < 3;j++)
1607 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1608 //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);
1614 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)))
1616 if (memcmp(pinmesh->identifier, "IDP3", 4))
1617 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1618 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1619 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1620 meshvertices += LittleLong(pinmesh->num_vertices);
1621 meshtriangles += LittleLong(pinmesh->num_triangles);
1624 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1625 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1626 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1627 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));
1628 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1629 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1630 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1631 loadmodel->surfmesh.num_vertices = meshvertices;
1632 loadmodel->surfmesh.num_triangles = meshtriangles;
1633 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1634 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1635 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1636 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1637 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1638 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1639 if (meshvertices <= 65536)
1640 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1644 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)))
1646 if (memcmp(pinmesh->identifier, "IDP3", 4))
1647 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1648 loadmodel->sortedmodelsurfaces[i] = i;
1649 surface = loadmodel->data_surfaces + i;
1650 surface->texture = loadmodel->data_textures + i;
1651 surface->num_firsttriangle = meshtriangles;
1652 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1653 surface->num_firstvertex = meshvertices;
1654 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1655 meshvertices += surface->num_vertices;
1656 meshtriangles += surface->num_triangles;
1658 for (j = 0;j < surface->num_triangles * 3;j++)
1659 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1660 for (j = 0;j < surface->num_vertices;j++)
1662 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1663 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1665 for (j = 0;j < loadmodel->numframes;j++)
1667 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1668 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1669 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1671 out->origin[0] = LittleShort(in->origin[0]);
1672 out->origin[1] = LittleShort(in->origin[1]);
1673 out->origin[2] = LittleShort(in->origin[2]);
1674 out->pitch = in->pitch;
1679 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1681 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1683 if (loadmodel->surfmesh.data_element3s)
1684 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1685 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1686 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1687 Mod_Alias_MorphMesh_CompileFrames();
1688 Mod_Alias_CalculateBoundingBox();
1689 Mod_FreeSkinFiles(skinfiles);
1690 Mod_MakeSortedSurfaces(loadmodel);
1692 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1693 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1696 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1698 zymtype1header_t *pinmodel, *pheader;
1699 unsigned char *pbase;
1700 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1701 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose;
1702 zymvertex_t *verts, *vertdata;
1706 skinfile_t *skinfiles;
1707 unsigned char *data;
1708 msurface_t *surface;
1710 pinmodel = (zymtype1header_t *)buffer;
1711 pbase = (unsigned char *)buffer;
1712 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1713 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1714 if (BigLong(pinmodel->type) != 1)
1715 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1717 loadmodel->modeldatatypestring = "ZYM";
1719 loadmodel->type = mod_alias;
1720 loadmodel->synctype = ST_RAND;
1724 pheader->type = BigLong(pinmodel->type);
1725 pheader->filesize = BigLong(pinmodel->filesize);
1726 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1727 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1728 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1729 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1730 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1731 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1732 pheader->radius = BigFloat(pinmodel->radius);
1733 pheader->numverts = BigLong(pinmodel->numverts);
1734 pheader->numtris = BigLong(pinmodel->numtris);
1735 pheader->numshaders = BigLong(pinmodel->numshaders);
1736 pheader->numbones = BigLong(pinmodel->numbones);
1737 pheader->numscenes = BigLong(pinmodel->numscenes);
1738 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1739 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1740 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1741 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1742 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1743 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1744 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1745 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1746 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1747 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1748 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1749 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1750 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1751 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1752 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1753 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1754 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1755 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1757 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1759 Con_Printf("%s has no geometry\n", loadmodel->name);
1762 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1764 Con_Printf("%s has no animations\n", loadmodel->name);
1768 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1769 loadmodel->DrawSky = NULL;
1770 loadmodel->DrawAddWaterPlanes = NULL;
1771 loadmodel->Draw = R_Q1BSP_Draw;
1772 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1773 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1774 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1775 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1776 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1777 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1778 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1779 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1780 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1781 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1782 loadmodel->PointSuperContents = NULL;
1784 loadmodel->numframes = pheader->numscenes;
1785 loadmodel->num_surfaces = pheader->numshaders;
1787 skinfiles = Mod_LoadSkinFiles();
1788 if (loadmodel->numskins < 1)
1789 loadmodel->numskins = 1;
1791 // make skinscenes for the skins (no groups)
1792 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1793 for (i = 0;i < loadmodel->numskins;i++)
1795 loadmodel->skinscenes[i].firstframe = i;
1796 loadmodel->skinscenes[i].framecount = 1;
1797 loadmodel->skinscenes[i].loop = true;
1798 loadmodel->skinscenes[i].framerate = 10;
1802 modelradius = pheader->radius;
1803 for (i = 0;i < 3;i++)
1805 loadmodel->normalmins[i] = pheader->mins[i];
1806 loadmodel->normalmaxs[i] = pheader->maxs[i];
1807 loadmodel->rotatedmins[i] = -modelradius;
1808 loadmodel->rotatedmaxs[i] = modelradius;
1810 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1811 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1812 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1813 if (loadmodel->yawmaxs[0] > modelradius)
1814 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1815 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1816 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1817 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1818 loadmodel->radius = modelradius;
1819 loadmodel->radius2 = modelradius * modelradius;
1821 // go through the lumps, swapping things
1823 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1824 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1825 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1826 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1827 for (i = 0;i < pheader->numscenes;i++)
1829 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1830 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1831 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1832 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1833 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1834 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1835 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1836 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1837 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1838 if (loadmodel->animscenes[i].framerate < 0)
1839 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1843 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1844 loadmodel->num_bones = pheader->numbones;
1845 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1846 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1847 for (i = 0;i < pheader->numbones;i++)
1849 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1850 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1851 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1852 if (loadmodel->data_bones[i].parent >= i)
1853 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1856 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1857 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1858 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1859 for (i = 0;i < pheader->numverts;i++)
1861 vertbonecounts[i] = BigLong(bonecount[i]);
1862 if (vertbonecounts[i] != 1)
1863 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1866 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1868 meshvertices = pheader->numverts;
1869 meshtriangles = pheader->numtris;
1871 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1872 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1873 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1874 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]));
1875 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1876 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1877 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1878 loadmodel->surfmesh.num_vertices = meshvertices;
1879 loadmodel->surfmesh.num_triangles = meshtriangles;
1880 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1881 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1882 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1883 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1884 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1885 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1886 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1887 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1888 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1889 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
1890 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1891 if (loadmodel->surfmesh.num_vertices <= 65536)
1892 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1894 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1895 poses = (float *) (pheader->lump_poses.start + pbase);
1896 for (i = 0;i < pheader->lump_poses.length / 4;i++)
1897 loadmodel->data_poses[i] = BigFloat(poses[i]);
1899 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1900 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1901 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1902 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1903 // (converting from weight-blending skeletal animation to
1904 // deformation-based skeletal animation)
1905 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1906 for (i = 0;i < loadmodel->num_bones;i++)
1908 const float *m = loadmodel->data_poses + i * 12;
1909 if (loadmodel->data_bones[i].parent >= 0)
1910 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1912 for (k = 0;k < 12;k++)
1913 bonepose[12*i+k] = m[k];
1915 for (j = 0;j < pheader->numverts;j++)
1917 // this format really should have had a per vertexweight weight value...
1918 // but since it does not, the weighting is completely ignored and
1919 // only one weight is allowed per vertex
1920 int boneindex = BigLong(vertdata[j].bonenum);
1921 const float *m = bonepose + 12 * boneindex;
1922 float relativeorigin[3];
1923 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1924 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1925 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1926 // transform the vertex bone weight into the base mesh
1927 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1928 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1929 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1930 // store the weight as the primary weight on this vertex
1931 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
1932 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = 1;
1935 // normals and tangents are calculated after elements are loaded
1937 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1938 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1939 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1940 for (i = 0;i < pheader->numverts;i++)
1942 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1943 // flip T coordinate for OpenGL
1944 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1947 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1948 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1949 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1951 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1952 //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)
1953 // byteswap, validate, and swap winding order of tris
1954 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1955 if (pheader->lump_render.length != count)
1956 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1957 renderlist = (int *) (pheader->lump_render.start + pbase);
1958 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1960 for (i = 0;i < loadmodel->num_surfaces;i++)
1962 int firstvertex, lastvertex;
1963 if (renderlist >= renderlistend)
1964 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1965 count = BigLong(*renderlist);renderlist++;
1966 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1967 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1969 loadmodel->sortedmodelsurfaces[i] = i;
1970 surface = loadmodel->data_surfaces + i;
1971 surface->texture = loadmodel->data_textures + i;
1972 surface->num_firsttriangle = meshtriangles;
1973 surface->num_triangles = count;
1974 meshtriangles += surface->num_triangles;
1976 // load the elements
1977 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
1978 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
1980 outelements[j*3+2] = BigLong(renderlist[0]);
1981 outelements[j*3+1] = BigLong(renderlist[1]);
1982 outelements[j*3+0] = BigLong(renderlist[2]);
1984 // validate the elements and find the used vertex range
1985 firstvertex = meshvertices;
1987 for (j = 0;j < surface->num_triangles * 3;j++)
1989 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
1990 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
1991 firstvertex = min(firstvertex, outelements[j]);
1992 lastvertex = max(lastvertex, outelements[j]);
1994 surface->num_firstvertex = firstvertex;
1995 surface->num_vertices = lastvertex + 1 - firstvertex;
1997 // since zym models do not have named sections, reuse their shader
1998 // name as the section name
1999 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
2000 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
2002 Mod_FreeSkinFiles(skinfiles);
2003 Mem_Free(vertbonecounts);
2005 Mod_MakeSortedSurfaces(loadmodel);
2007 // compute all the mesh information that was not loaded from the file
2008 if (loadmodel->surfmesh.data_element3s)
2009 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2010 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2011 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2012 Mod_BuildBaseBonePoses();
2013 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2014 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);
2015 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2017 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2020 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2022 dpmheader_t *pheader;
2026 unsigned char *pbase;
2027 int i, j, k, meshvertices, meshtriangles;
2028 skinfile_t *skinfiles;
2029 unsigned char *data;
2032 pheader = (dpmheader_t *)buffer;
2033 pbase = (unsigned char *)buffer;
2034 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2035 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2036 if (BigLong(pheader->type) != 2)
2037 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2039 loadmodel->modeldatatypestring = "DPM";
2041 loadmodel->type = mod_alias;
2042 loadmodel->synctype = ST_RAND;
2045 pheader->type = BigLong(pheader->type);
2046 pheader->filesize = BigLong(pheader->filesize);
2047 pheader->mins[0] = BigFloat(pheader->mins[0]);
2048 pheader->mins[1] = BigFloat(pheader->mins[1]);
2049 pheader->mins[2] = BigFloat(pheader->mins[2]);
2050 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2051 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2052 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2053 pheader->yawradius = BigFloat(pheader->yawradius);
2054 pheader->allradius = BigFloat(pheader->allradius);
2055 pheader->num_bones = BigLong(pheader->num_bones);
2056 pheader->num_meshs = BigLong(pheader->num_meshs);
2057 pheader->num_frames = BigLong(pheader->num_frames);
2058 pheader->ofs_bones = BigLong(pheader->ofs_bones);
2059 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2060 pheader->ofs_frames = BigLong(pheader->ofs_frames);
2062 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2064 Con_Printf("%s has no geometry\n", loadmodel->name);
2067 if (pheader->num_frames < 1)
2069 Con_Printf("%s has no frames\n", loadmodel->name);
2073 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2074 loadmodel->DrawSky = NULL;
2075 loadmodel->DrawAddWaterPlanes = NULL;
2076 loadmodel->Draw = R_Q1BSP_Draw;
2077 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2078 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2079 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2080 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2081 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2082 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2083 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2084 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2085 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2086 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2087 loadmodel->PointSuperContents = NULL;
2090 for (i = 0;i < 3;i++)
2092 loadmodel->normalmins[i] = pheader->mins[i];
2093 loadmodel->normalmaxs[i] = pheader->maxs[i];
2094 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2095 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2096 loadmodel->rotatedmins[i] = -pheader->allradius;
2097 loadmodel->rotatedmaxs[i] = pheader->allradius;
2099 loadmodel->radius = pheader->allradius;
2100 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2102 // load external .skin files if present
2103 skinfiles = Mod_LoadSkinFiles();
2104 if (loadmodel->numskins < 1)
2105 loadmodel->numskins = 1;
2110 // gather combined statistics from the meshes
2111 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2112 for (i = 0;i < (int)pheader->num_meshs;i++)
2114 int numverts = BigLong(dpmmesh->num_verts);
2115 meshvertices += numverts;
2116 meshtriangles += BigLong(dpmmesh->num_tris);
2120 loadmodel->numframes = pheader->num_frames;
2121 loadmodel->num_bones = pheader->num_bones;
2122 loadmodel->num_poses = loadmodel->numframes;
2123 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2124 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2125 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2126 // do most allocations as one merged chunk
2127 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));
2128 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2129 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2130 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2131 loadmodel->surfmesh.num_vertices = meshvertices;
2132 loadmodel->surfmesh.num_triangles = meshtriangles;
2133 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2134 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2135 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2136 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2137 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2138 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2139 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2140 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
2141 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
2142 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
2143 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2144 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2145 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2146 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2147 if (meshvertices <= 65536)
2148 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2150 for (i = 0;i < loadmodel->numskins;i++)
2152 loadmodel->skinscenes[i].firstframe = i;
2153 loadmodel->skinscenes[i].framecount = 1;
2154 loadmodel->skinscenes[i].loop = true;
2155 loadmodel->skinscenes[i].framerate = 10;
2158 // load the bone info
2159 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2160 for (i = 0;i < loadmodel->num_bones;i++)
2162 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2163 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2164 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2165 if (loadmodel->data_bones[i].parent >= i)
2166 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2170 frame = (dpmframe_t *) (pbase + pheader->ofs_frames);
2171 for (i = 0;i < loadmodel->numframes;i++)
2174 memcpy(loadmodel->animscenes[i].name, frame->name, sizeof(frame->name));
2175 loadmodel->animscenes[i].firstframe = i;
2176 loadmodel->animscenes[i].framecount = 1;
2177 loadmodel->animscenes[i].loop = true;
2178 loadmodel->animscenes[i].framerate = 10;
2179 // load the bone poses for this frame
2180 poses = (float *) (pbase + BigLong(frame->ofs_bonepositions));
2181 for (j = 0;j < loadmodel->num_bones*12;j++)
2182 loadmodel->data_poses[i * loadmodel->num_bones*12 + j] = BigFloat(poses[j]);
2183 // stuff not processed here: mins, maxs, yawradius, allradius
2187 // load the meshes now
2188 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2191 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2192 // (converting from weight-blending skeletal animation to
2193 // deformation-based skeletal animation)
2194 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2195 for (i = 0;i < loadmodel->num_bones;i++)
2197 const float *m = loadmodel->data_poses + i * 12;
2198 if (loadmodel->data_bones[i].parent >= 0)
2199 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2201 for (k = 0;k < 12;k++)
2202 bonepose[12*i+k] = m[k];
2204 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2206 const int *inelements;
2208 const float *intexcoord;
2209 msurface_t *surface;
2211 loadmodel->sortedmodelsurfaces[i] = i;
2212 surface = loadmodel->data_surfaces + i;
2213 surface->texture = loadmodel->data_textures + i;
2214 surface->num_firsttriangle = meshtriangles;
2215 surface->num_triangles = BigLong(dpmmesh->num_tris);
2216 surface->num_firstvertex = meshvertices;
2217 surface->num_vertices = BigLong(dpmmesh->num_verts);
2218 meshvertices += surface->num_vertices;
2219 meshtriangles += surface->num_triangles;
2221 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2222 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2223 for (j = 0;j < surface->num_triangles;j++)
2225 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2226 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2227 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2228 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2233 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2234 for (j = 0;j < surface->num_vertices*2;j++)
2235 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2237 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2238 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2242 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2243 data += sizeof(dpmvertex_t);
2244 for (k = 0;k < numweights;k++)
2246 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2247 int boneindex = BigLong(vert->bonenum);
2248 const float *m = bonepose + 12 * boneindex;
2249 float influence = BigFloat(vert->influence);
2250 float relativeorigin[3], relativenormal[3];
2251 relativeorigin[0] = BigFloat(vert->origin[0]);
2252 relativeorigin[1] = BigFloat(vert->origin[1]);
2253 relativeorigin[2] = BigFloat(vert->origin[2]);
2254 relativenormal[0] = BigFloat(vert->normal[0]);
2255 relativenormal[1] = BigFloat(vert->normal[1]);
2256 relativenormal[2] = BigFloat(vert->normal[2]);
2257 // blend the vertex bone weights into the base mesh
2258 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2259 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2260 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2261 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2262 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2263 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2266 // store the first (and often only) weight
2267 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = influence;
2268 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
2272 // sort the new weight into this vertex's weight table
2273 // (which only accepts up to 4 bones per vertex)
2274 for (l = 0;l < 4;l++)
2276 if (loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] < influence)
2278 // move weaker influence weights out of the way first
2280 for (l2 = 3;l2 > l;l2--)
2282 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2-1];
2283 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2-1];
2285 // store the new weight
2286 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] = influence;
2287 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l] = boneindex;
2292 data += sizeof(dpmbonevert_t);
2295 for (l = 0;l < 4;l++)
2296 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l];
2297 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2299 float f = 1.0f / sum;
2300 for (l = 0;l < 4;l++)
2301 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] *= f;
2305 // since dpm models do not have named sections, reuse their shader name as the section name
2306 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2308 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2311 Mod_FreeSkinFiles(skinfiles);
2312 Mod_MakeSortedSurfaces(loadmodel);
2314 // compute all the mesh information that was not loaded from the file
2315 if (loadmodel->surfmesh.data_element3s)
2316 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2317 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2318 Mod_BuildBaseBonePoses();
2319 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);
2320 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2322 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2325 // no idea why PSK/PSA files contain weird quaternions but they do...
2326 #define PSKQUATNEGATIONS
2327 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2329 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2330 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2331 fs_offset_t filesize;
2336 pskboneinfo_t *bones;
2337 pskrawweights_t *rawweights;
2338 pskboneinfo_t *animbones;
2339 pskaniminfo_t *anims;
2340 pskanimkeys_t *animkeys;
2341 void *animfilebuffer, *animbuffer, *animbufferend;
2342 unsigned char *data;
2344 skinfile_t *skinfiles;
2345 char animname[MAX_QPATH];
2348 pchunk = (pskchunk_t *)buffer;
2349 if (strcmp(pchunk->id, "ACTRHEAD"))
2350 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2352 loadmodel->modeldatatypestring = "PSK";
2354 loadmodel->type = mod_alias;
2355 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2356 loadmodel->DrawSky = NULL;
2357 loadmodel->DrawAddWaterPlanes = NULL;
2358 loadmodel->Draw = R_Q1BSP_Draw;
2359 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2360 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2361 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2362 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2363 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2364 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2365 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2366 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2367 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2368 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2369 loadmodel->PointSuperContents = NULL;
2370 loadmodel->synctype = ST_RAND;
2372 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2373 strlcat(animname, ".psa", sizeof(animname));
2374 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2375 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2376 if (animbuffer == NULL)
2377 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2396 while (buffer < bufferend)
2398 pchunk = (pskchunk_t *)buffer;
2399 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2400 version = LittleLong(pchunk->version);
2401 recordsize = LittleLong(pchunk->recordsize);
2402 numrecords = LittleLong(pchunk->numrecords);
2403 if (developer.integer >= 100)
2404 Con_Printf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2405 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2406 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);
2407 if (!strcmp(pchunk->id, "ACTRHEAD"))
2411 else if (!strcmp(pchunk->id, "PNTS0000"))
2414 if (recordsize != sizeof(*p))
2415 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2416 // byteswap in place and keep the pointer
2417 numpnts = numrecords;
2418 pnts = (pskpnts_t *)buffer;
2419 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2421 p->origin[0] = LittleFloat(p->origin[0]);
2422 p->origin[1] = LittleFloat(p->origin[1]);
2423 p->origin[2] = LittleFloat(p->origin[2]);
2427 else if (!strcmp(pchunk->id, "VTXW0000"))
2430 if (recordsize != sizeof(*p))
2431 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2432 // byteswap in place and keep the pointer
2433 numvtxw = numrecords;
2434 vtxw = (pskvtxw_t *)buffer;
2435 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2437 p->pntsindex = LittleShort(p->pntsindex);
2438 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2439 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2440 if (p->pntsindex >= numpnts)
2442 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2448 else if (!strcmp(pchunk->id, "FACE0000"))
2451 if (recordsize != sizeof(*p))
2452 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2453 // byteswap in place and keep the pointer
2454 numfaces = numrecords;
2455 faces = (pskface_t *)buffer;
2456 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2458 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2459 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2460 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2461 p->group = LittleLong(p->group);
2462 if (p->vtxwindex[0] >= numvtxw)
2464 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2465 p->vtxwindex[0] = 0;
2467 if (p->vtxwindex[1] >= numvtxw)
2469 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2470 p->vtxwindex[1] = 0;
2472 if (p->vtxwindex[2] >= numvtxw)
2474 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2475 p->vtxwindex[2] = 0;
2480 else if (!strcmp(pchunk->id, "MATT0000"))
2483 if (recordsize != sizeof(*p))
2484 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2485 // byteswap in place and keep the pointer
2486 nummatts = numrecords;
2487 matts = (pskmatt_t *)buffer;
2488 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2494 else if (!strcmp(pchunk->id, "REFSKELT"))
2497 if (recordsize != sizeof(*p))
2498 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2499 // byteswap in place and keep the pointer
2500 numbones = numrecords;
2501 bones = (pskboneinfo_t *)buffer;
2502 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2504 p->numchildren = LittleLong(p->numchildren);
2505 p->parent = LittleLong(p->parent);
2506 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2507 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2508 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2509 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2510 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2511 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2512 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2513 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2514 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2515 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2516 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2517 #ifdef PSKQUATNEGATIONS
2520 p->basepose.quat[0] *= -1;
2521 p->basepose.quat[1] *= -1;
2522 p->basepose.quat[2] *= -1;
2526 p->basepose.quat[0] *= 1;
2527 p->basepose.quat[1] *= -1;
2528 p->basepose.quat[2] *= 1;
2531 if (p->parent < 0 || p->parent >= numbones)
2533 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2539 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2542 if (recordsize != sizeof(*p))
2543 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2544 // byteswap in place and keep the pointer
2545 numrawweights = numrecords;
2546 rawweights = (pskrawweights_t *)buffer;
2547 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2549 p->weight = LittleFloat(p->weight);
2550 p->pntsindex = LittleLong(p->pntsindex);
2551 p->boneindex = LittleLong(p->boneindex);
2552 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2554 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2557 if (p->boneindex < 0 || p->boneindex >= numbones)
2559 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2567 while (animbuffer < animbufferend)
2569 pchunk = (pskchunk_t *)animbuffer;
2570 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2571 version = LittleLong(pchunk->version);
2572 recordsize = LittleLong(pchunk->recordsize);
2573 numrecords = LittleLong(pchunk->numrecords);
2574 if (developer.integer >= 100)
2575 Con_Printf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2576 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2577 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);
2578 if (!strcmp(pchunk->id, "ANIMHEAD"))
2582 else if (!strcmp(pchunk->id, "BONENAMES"))
2585 if (recordsize != sizeof(*p))
2586 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2587 // byteswap in place and keep the pointer
2588 numanimbones = numrecords;
2589 animbones = (pskboneinfo_t *)animbuffer;
2590 // NOTE: supposedly psa does not need to match the psk model, the
2591 // bones missing from the psa would simply use their base
2592 // positions from the psk, but this is hard for me to implement
2593 // and people can easily make animations that match.
2594 if (numanimbones != numbones)
2595 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2596 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2598 p->numchildren = LittleLong(p->numchildren);
2599 p->parent = LittleLong(p->parent);
2600 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2601 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2602 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2603 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2604 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2605 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2606 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2607 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2608 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2609 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2610 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2611 #ifdef PSKQUATNEGATIONS
2614 p->basepose.quat[0] *= -1;
2615 p->basepose.quat[1] *= -1;
2616 p->basepose.quat[2] *= -1;
2620 p->basepose.quat[0] *= 1;
2621 p->basepose.quat[1] *= -1;
2622 p->basepose.quat[2] *= 1;
2625 if (p->parent < 0 || p->parent >= numanimbones)
2627 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2630 // check that bones are the same as in the base
2631 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2632 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2636 else if (!strcmp(pchunk->id, "ANIMINFO"))
2639 if (recordsize != sizeof(*p))
2640 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2641 // byteswap in place and keep the pointer
2642 numanims = numrecords;
2643 anims = (pskaniminfo_t *)animbuffer;
2644 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2646 p->numbones = LittleLong(p->numbones);
2647 p->playtime = LittleFloat(p->playtime);
2648 p->fps = LittleFloat(p->fps);
2649 p->firstframe = LittleLong(p->firstframe);
2650 p->numframes = LittleLong(p->numframes);
2651 if (p->numbones != numbones)
2652 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2656 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2659 if (recordsize != sizeof(*p))
2660 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2661 numanimkeys = numrecords;
2662 animkeys = (pskanimkeys_t *)animbuffer;
2663 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2665 p->origin[0] = LittleFloat(p->origin[0]);
2666 p->origin[1] = LittleFloat(p->origin[1]);
2667 p->origin[2] = LittleFloat(p->origin[2]);
2668 p->quat[0] = LittleFloat(p->quat[0]);
2669 p->quat[1] = LittleFloat(p->quat[1]);
2670 p->quat[2] = LittleFloat(p->quat[2]);
2671 p->quat[3] = LittleFloat(p->quat[3]);
2672 p->frametime = LittleFloat(p->frametime);
2673 #ifdef PSKQUATNEGATIONS
2674 if (index % numbones)
2689 // TODO: allocate bonepose stuff
2692 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2695 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2696 Host_Error("%s: missing required chunks", loadmodel->name);
2698 loadmodel->numframes = 0;
2699 for (index = 0;index < numanims;index++)
2700 loadmodel->numframes += anims[index].numframes;
2702 if (numanimkeys != numbones * loadmodel->numframes)
2703 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2705 meshvertices = numvtxw;
2706 meshtriangles = numfaces;
2708 // load external .skin files if present
2709 skinfiles = Mod_LoadSkinFiles();
2710 if (loadmodel->numskins < 1)
2711 loadmodel->numskins = 1;
2712 loadmodel->num_bones = numbones;
2713 loadmodel->num_poses = loadmodel->numframes;
2714 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2715 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2716 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2717 loadmodel->surfmesh.num_vertices = meshvertices;
2718 loadmodel->surfmesh.num_triangles = meshtriangles;
2719 // do most allocations as one merged chunk
2720 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);
2721 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2722 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2723 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2724 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2725 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2726 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2727 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2728 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2729 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2730 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2731 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2732 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += loadmodel->surfmesh.num_vertices * sizeof(int[4]);
2733 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[4]);
2734 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
2735 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2736 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2737 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2738 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2739 if (loadmodel->surfmesh.num_vertices <= 65536)
2740 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2742 for (i = 0;i < loadmodel->numskins;i++)
2744 loadmodel->skinscenes[i].firstframe = i;
2745 loadmodel->skinscenes[i].framecount = 1;
2746 loadmodel->skinscenes[i].loop = true;
2747 loadmodel->skinscenes[i].framerate = 10;
2751 for (index = 0, i = 0;index < nummatts;index++)
2753 // since psk models do not have named sections, reuse their shader name as the section name
2754 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2755 loadmodel->sortedmodelsurfaces[index] = index;
2756 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2757 loadmodel->data_surfaces[index].num_firstvertex = 0;
2758 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2761 // copy over the vertex locations and texcoords
2762 for (index = 0;index < numvtxw;index++)
2764 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2765 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2766 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2767 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2768 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2771 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2772 for (index = 0;index < numfaces;index++)
2773 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2774 for (index = 0, i = 0;index < nummatts;index++)
2776 loadmodel->data_surfaces[index].num_firsttriangle = i;
2777 i += loadmodel->data_surfaces[index].num_triangles;
2778 loadmodel->data_surfaces[index].num_triangles = 0;
2780 for (index = 0;index < numfaces;index++)
2782 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2783 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2784 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2785 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2788 // copy over the bones
2789 for (index = 0;index < numbones;index++)
2791 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2792 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2793 if (loadmodel->data_bones[index].parent >= index)
2794 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2797 // sort the psk point weights into the vertex weight tables
2798 // (which only accept up to 4 bones per vertex)
2799 for (index = 0;index < numvtxw;index++)
2803 for (j = 0;j < numrawweights;j++)
2805 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2807 int boneindex = rawweights[j].boneindex;
2808 float influence = rawweights[j].weight;
2809 for (l = 0;l < 4;l++)
2811 if (loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] < influence)
2813 // move lower influence weights out of the way first
2815 for (l2 = 3;l2 > l;l2--)
2817 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2-1];
2818 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2-1];
2820 // store the new weight
2821 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] = influence;
2822 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l] = boneindex;
2829 for (l = 0;l < 4;l++)
2830 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l];
2831 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2833 float f = 1.0f / sum;
2834 for (l = 0;l < 4;l++)
2835 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] *= f;
2839 // set up the animscenes based on the anims
2840 for (index = 0, i = 0;index < numanims;index++)
2842 for (j = 0;j < anims[index].numframes;j++, i++)
2844 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2845 loadmodel->animscenes[i].firstframe = i;
2846 loadmodel->animscenes[i].framecount = 1;
2847 loadmodel->animscenes[i].loop = true;
2848 loadmodel->animscenes[i].framerate = 10;
2852 // load the poses from the animkeys
2853 for (index = 0;index < numanimkeys;index++)
2855 pskanimkeys_t *k = animkeys + index;
2857 Matrix4x4_FromOriginQuat(&matrix, k->origin[0], k->origin[1], k->origin[2], k->quat[0], k->quat[1], k->quat[2], k->quat[3]);
2858 Matrix4x4_ToArray12FloatD3D(&matrix, loadmodel->data_poses + index*12);
2860 Mod_FreeSkinFiles(skinfiles);
2861 Mem_Free(animfilebuffer);
2862 Mod_MakeSortedSurfaces(loadmodel);
2864 // compute all the mesh information that was not loaded from the file
2865 // TODO: honor smoothing groups somehow?
2866 if (loadmodel->surfmesh.data_element3s)
2867 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2868 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2869 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2870 Mod_BuildBaseBonePoses();
2871 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2872 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);
2873 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2874 Mod_Alias_CalculateBoundingBox();
2876 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;