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;
905 static void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
908 skinfileitem_t *skinfileitem;
911 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
912 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
914 memset(skin, 0, sizeof(*skin));
916 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
918 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
919 if (!strcmp(skinfileitem->name, meshname))
921 Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
927 // don't render unmentioned meshes
928 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
929 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
934 Mod_LoadTextureFromQ3Shader(skin, shadername, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
937 #define BOUNDI(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid ##VALUE (%d exceeds %d - %d)", loadmodel->name, VALUE, MIN, MAX);
938 #define BOUNDF(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid ##VALUE (%f exceeds %f - %f)", loadmodel->name, VALUE, MIN, MAX);
939 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
941 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
942 float scales, scalet, interval;
946 stvert_t *pinstverts;
947 dtriangle_t *pintriangles;
948 daliasskintype_t *pinskintype;
949 daliasskingroup_t *pinskingroup;
950 daliasskininterval_t *pinskinintervals;
951 daliasframetype_t *pinframetype;
952 daliasgroup_t *pinframegroup;
953 unsigned char *datapointer, *startframes, *startskins;
954 char name[MAX_QPATH];
955 skinframe_t *tempskinframe;
956 animscene_t *tempskinscenes;
957 texture_t *tempaliasskins;
959 int *vertonseam, *vertremap;
960 skinfile_t *skinfiles;
962 datapointer = (unsigned char *)buffer;
963 pinmodel = (mdl_t *)datapointer;
964 datapointer += sizeof(mdl_t);
966 version = LittleLong (pinmodel->version);
967 if (version != ALIAS_VERSION)
968 Host_Error ("%s has wrong version number (%i should be %i)",
969 loadmodel->name, version, ALIAS_VERSION);
971 loadmodel->modeldatatypestring = "MDL";
973 loadmodel->type = mod_alias;
974 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
975 loadmodel->DrawSky = NULL;
976 loadmodel->DrawAddWaterPlanes = NULL;
977 loadmodel->Draw = R_Q1BSP_Draw;
978 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
979 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
980 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
981 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
982 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
983 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
984 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
985 loadmodel->DrawLight = R_Q1BSP_DrawLight;
986 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
987 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
988 loadmodel->PointSuperContents = NULL;
990 loadmodel->num_surfaces = 1;
991 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
992 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
993 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
994 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
995 loadmodel->sortedmodelsurfaces[0] = 0;
997 loadmodel->numskins = LittleLong(pinmodel->numskins);
998 BOUNDI(loadmodel->numskins,0,65536);
999 skinwidth = LittleLong (pinmodel->skinwidth);
1000 BOUNDI(skinwidth,0,65536);
1001 skinheight = LittleLong (pinmodel->skinheight);
1002 BOUNDI(skinheight,0,65536);
1003 numverts = LittleLong(pinmodel->numverts);
1004 BOUNDI(numverts,0,65536);
1005 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
1006 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
1007 loadmodel->numframes = LittleLong(pinmodel->numframes);
1008 BOUNDI(loadmodel->numframes,0,65536);
1009 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
1010 BOUNDI(loadmodel->synctype,0,2);
1011 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1012 i = LittleLong (pinmodel->flags);
1013 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1015 for (i = 0;i < 3;i++)
1017 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
1018 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
1021 startskins = datapointer;
1023 for (i = 0;i < loadmodel->numskins;i++)
1025 pinskintype = (daliasskintype_t *)datapointer;
1026 datapointer += sizeof(daliasskintype_t);
1027 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
1031 pinskingroup = (daliasskingroup_t *)datapointer;
1032 datapointer += sizeof(daliasskingroup_t);
1033 groupskins = LittleLong(pinskingroup->numskins);
1034 datapointer += sizeof(daliasskininterval_t) * groupskins;
1037 for (j = 0;j < groupskins;j++)
1039 datapointer += skinwidth * skinheight;
1044 pinstverts = (stvert_t *)datapointer;
1045 datapointer += sizeof(stvert_t) * numverts;
1047 pintriangles = (dtriangle_t *)datapointer;
1048 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
1050 startframes = datapointer;
1051 loadmodel->surfmesh.num_morphframes = 0;
1052 for (i = 0;i < loadmodel->numframes;i++)
1054 pinframetype = (daliasframetype_t *)datapointer;
1055 datapointer += sizeof(daliasframetype_t);
1056 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
1060 pinframegroup = (daliasgroup_t *)datapointer;
1061 datapointer += sizeof(daliasgroup_t);
1062 groupframes = LittleLong(pinframegroup->numframes);
1063 datapointer += sizeof(daliasinterval_t) * groupframes;
1066 for (j = 0;j < groupframes;j++)
1068 datapointer += sizeof(daliasframe_t);
1069 datapointer += sizeof(trivertx_t) * numverts;
1070 loadmodel->surfmesh.num_morphframes++;
1073 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1075 // store texture coordinates into temporary array, they will be stored
1076 // after usage is determined (triangle data)
1077 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
1078 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
1079 vertonseam = vertremap + numverts * 2;
1081 scales = 1.0 / skinwidth;
1082 scalet = 1.0 / skinheight;
1083 for (i = 0;i < numverts;i++)
1085 vertonseam[i] = LittleLong(pinstverts[i].onseam);
1086 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
1087 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
1088 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
1089 vertst[(i+numverts)*2+1] = vertst[i*2+1];
1092 // load triangle data
1093 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1095 // read the triangle elements
1096 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1097 for (j = 0;j < 3;j++)
1098 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1099 // validate (note numverts is used because this is the original data)
1100 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1101 // now butcher the elements according to vertonseam and tri->facesfront
1102 // and then compact the vertex set to remove duplicates
1103 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1104 if (!LittleLong(pintriangles[i].facesfront)) // backface
1105 for (j = 0;j < 3;j++)
1106 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1107 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1109 // (this uses vertremap to count usage to save some memory)
1110 for (i = 0;i < numverts*2;i++)
1112 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1113 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1114 // build remapping table and compact array
1115 loadmodel->surfmesh.num_vertices = 0;
1116 for (i = 0;i < numverts*2;i++)
1120 vertremap[i] = loadmodel->surfmesh.num_vertices;
1121 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1122 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1123 loadmodel->surfmesh.num_vertices++;
1126 vertremap[i] = -1; // not used at all
1128 // remap the elements to the new vertex set
1129 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1130 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1131 // store the texture coordinates
1132 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1133 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1135 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1136 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1139 // generate ushort elements array if possible
1140 if (loadmodel->surfmesh.num_vertices <= 65536)
1141 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1142 if (loadmodel->surfmesh.data_element3s)
1143 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1144 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1147 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1148 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1149 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1150 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1151 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1152 Mod_Alias_CalculateBoundingBox();
1153 Mod_Alias_MorphMesh_CompileFrames();
1156 Mem_Free(vertremap);
1159 skinfiles = Mod_LoadSkinFiles();
1162 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1163 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1164 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1165 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1166 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1167 Mod_FreeSkinFiles(skinfiles);
1168 for (i = 0;i < loadmodel->numskins;i++)
1170 loadmodel->skinscenes[i].firstframe = i;
1171 loadmodel->skinscenes[i].framecount = 1;
1172 loadmodel->skinscenes[i].loop = true;
1173 loadmodel->skinscenes[i].framerate = 10;
1178 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1179 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1180 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1181 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1183 datapointer = startskins;
1184 for (i = 0;i < loadmodel->numskins;i++)
1186 pinskintype = (daliasskintype_t *)datapointer;
1187 datapointer += sizeof(daliasskintype_t);
1189 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1196 pinskingroup = (daliasskingroup_t *)datapointer;
1197 datapointer += sizeof(daliasskingroup_t);
1199 groupskins = LittleLong (pinskingroup->numskins);
1201 pinskinintervals = (daliasskininterval_t *)datapointer;
1202 datapointer += sizeof(daliasskininterval_t) * groupskins;
1204 interval = LittleFloat(pinskinintervals[0].interval);
1205 if (interval < 0.01f)
1207 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1212 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1213 loadmodel->skinscenes[i].firstframe = totalskins;
1214 loadmodel->skinscenes[i].framecount = groupskins;
1215 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1216 loadmodel->skinscenes[i].loop = true;
1218 for (j = 0;j < groupskins;j++)
1221 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1223 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1224 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 | TEXF_PRECACHE))
1225 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, R_SkinFrame_LoadInternalQuake(name, TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP, true, r_fullbrights.integer, (unsigned char *)datapointer, skinwidth, skinheight));
1226 datapointer += skinwidth * skinheight;
1230 // check for skins that don't exist in the model, but do exist as external images
1231 // (this was added because yummyluv kept pestering me about support for it)
1232 // TODO: support shaders here?
1233 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)))
1235 // expand the arrays to make room
1236 tempskinscenes = loadmodel->skinscenes;
1237 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1238 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1239 Mem_Free(tempskinscenes);
1241 tempaliasskins = loadmodel->data_textures;
1242 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1243 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1244 Mem_Free(tempaliasskins);
1246 // store the info about the new skin
1247 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1248 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1249 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1250 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1251 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1252 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1254 //increase skin counts
1255 loadmodel->numskins++;
1258 // fix up the pointers since they are pointing at the old textures array
1259 // FIXME: this is a hack!
1260 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1261 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1265 surface = loadmodel->data_surfaces;
1266 surface->texture = loadmodel->data_textures;
1267 surface->num_firsttriangle = 0;
1268 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1269 surface->num_firstvertex = 0;
1270 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1272 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1275 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1277 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1278 float iskinwidth, iskinheight;
1279 unsigned char *data;
1280 msurface_t *surface;
1282 unsigned char *base, *datapointer;
1283 md2frame_t *pinframe;
1285 md2triangle_t *intri;
1286 unsigned short *inst;
1287 struct md2verthash_s
1289 struct md2verthash_s *next;
1293 *hash, **md2verthash, *md2verthashdata;
1294 skinfile_t *skinfiles;
1296 pinmodel = (md2_t *)buffer;
1297 base = (unsigned char *)buffer;
1299 version = LittleLong (pinmodel->version);
1300 if (version != MD2ALIAS_VERSION)
1301 Host_Error ("%s has wrong version number (%i should be %i)",
1302 loadmodel->name, version, MD2ALIAS_VERSION);
1304 loadmodel->modeldatatypestring = "MD2";
1306 loadmodel->type = mod_alias;
1307 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1308 loadmodel->DrawSky = NULL;
1309 loadmodel->DrawAddWaterPlanes = NULL;
1310 loadmodel->Draw = R_Q1BSP_Draw;
1311 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1312 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1313 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1314 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1315 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1316 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1317 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1318 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1319 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1320 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1321 loadmodel->PointSuperContents = NULL;
1323 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1324 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1325 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1326 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1327 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1328 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1329 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1330 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1332 end = LittleLong(pinmodel->ofs_end);
1333 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1334 Host_Error ("%s is not a valid model", loadmodel->name);
1335 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1336 Host_Error ("%s is not a valid model", loadmodel->name);
1337 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1338 Host_Error ("%s is not a valid model", loadmodel->name);
1339 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1340 Host_Error ("%s is not a valid model", loadmodel->name);
1341 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1342 Host_Error ("%s is not a valid model", loadmodel->name);
1344 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1345 numxyz = LittleLong(pinmodel->num_xyz);
1346 numst = LittleLong(pinmodel->num_st);
1347 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1348 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1349 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1350 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1351 skinwidth = LittleLong(pinmodel->skinwidth);
1352 skinheight = LittleLong(pinmodel->skinheight);
1353 iskinwidth = 1.0f / skinwidth;
1354 iskinheight = 1.0f / skinheight;
1356 loadmodel->num_surfaces = 1;
1357 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1358 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]));
1359 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1360 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1361 loadmodel->sortedmodelsurfaces[0] = 0;
1362 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1363 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1364 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1365 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1367 loadmodel->synctype = ST_RAND;
1370 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1371 skinfiles = Mod_LoadSkinFiles();
1374 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1375 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1376 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1377 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1378 Mod_FreeSkinFiles(skinfiles);
1380 else if (loadmodel->numskins)
1382 // skins found (most likely not a player model)
1383 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1384 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1385 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1386 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1387 Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
1391 // no skins (most likely a player model)
1392 loadmodel->numskins = 1;
1393 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1394 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1395 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1396 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1399 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1400 for (i = 0;i < loadmodel->numskins;i++)
1402 loadmodel->skinscenes[i].firstframe = i;
1403 loadmodel->skinscenes[i].framecount = 1;
1404 loadmodel->skinscenes[i].loop = true;
1405 loadmodel->skinscenes[i].framerate = 10;
1408 // load the triangles and stvert data
1409 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1410 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1411 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1412 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1413 // swap the triangle list
1414 loadmodel->surfmesh.num_vertices = 0;
1415 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1417 for (j = 0;j < 3;j++)
1419 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1420 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1423 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1428 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1431 hashindex = (xyz * 256 + st) & 65535;
1432 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1433 if (hash->xyz == xyz && hash->st == st)
1437 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1440 hash->next = md2verthash[hashindex];
1441 md2verthash[hashindex] = hash;
1443 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1447 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1448 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));
1449 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1450 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1451 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1454 hash = md2verthashdata + i;
1455 vertremap[i] = hash->xyz;
1456 sts = LittleShort(inst[hash->st*2+0]);
1457 stt = LittleShort(inst[hash->st*2+1]);
1458 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1460 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1464 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1465 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1468 Mem_Free(md2verthash);
1469 Mem_Free(md2verthashdata);
1471 // generate ushort elements array if possible
1472 if (loadmodel->surfmesh.num_vertices <= 65536)
1473 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1474 if (loadmodel->surfmesh.data_element3s)
1475 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1476 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1479 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1480 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1485 pinframe = (md2frame_t *)datapointer;
1486 datapointer += sizeof(md2frame_t);
1487 // store the frame scale/translate into the appropriate array
1488 for (j = 0;j < 3;j++)
1490 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1491 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1493 // convert the vertices
1494 v = (trivertx_t *)datapointer;
1495 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1496 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1497 out[k] = v[vertremap[k]];
1498 datapointer += numxyz * sizeof(trivertx_t);
1500 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1501 loadmodel->animscenes[i].firstframe = i;
1502 loadmodel->animscenes[i].framecount = 1;
1503 loadmodel->animscenes[i].framerate = 10;
1504 loadmodel->animscenes[i].loop = true;
1507 Mem_Free(vertremap);
1509 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1510 Mod_Alias_CalculateBoundingBox();
1511 Mod_Alias_MorphMesh_CompileFrames();
1513 surface = loadmodel->data_surfaces;
1514 surface->texture = loadmodel->data_textures;
1515 surface->num_firsttriangle = 0;
1516 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1517 surface->num_firstvertex = 0;
1518 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1520 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1523 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1525 int i, j, k, version, meshvertices, meshtriangles;
1526 unsigned char *data;
1527 msurface_t *surface;
1528 md3modelheader_t *pinmodel;
1529 md3frameinfo_t *pinframe;
1532 skinfile_t *skinfiles;
1534 pinmodel = (md3modelheader_t *)buffer;
1536 if (memcmp(pinmodel->identifier, "IDP3", 4))
1537 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1538 version = LittleLong (pinmodel->version);
1539 if (version != MD3VERSION)
1540 Host_Error ("%s has wrong version number (%i should be %i)",
1541 loadmodel->name, version, MD3VERSION);
1543 skinfiles = Mod_LoadSkinFiles();
1544 if (loadmodel->numskins < 1)
1545 loadmodel->numskins = 1;
1547 loadmodel->modeldatatypestring = "MD3";
1549 loadmodel->type = mod_alias;
1550 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1551 loadmodel->DrawSky = NULL;
1552 loadmodel->DrawAddWaterPlanes = NULL;
1553 loadmodel->Draw = R_Q1BSP_Draw;
1554 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1555 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1556 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1557 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1558 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1559 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1560 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1561 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1562 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1563 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1564 loadmodel->PointSuperContents = NULL;
1565 loadmodel->synctype = ST_RAND;
1566 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1567 i = LittleLong (pinmodel->flags);
1568 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1570 // set up some global info about the model
1571 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1572 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1574 // make skinscenes for the skins (no groups)
1575 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1576 for (i = 0;i < loadmodel->numskins;i++)
1578 loadmodel->skinscenes[i].firstframe = i;
1579 loadmodel->skinscenes[i].framecount = 1;
1580 loadmodel->skinscenes[i].loop = true;
1581 loadmodel->skinscenes[i].framerate = 10;
1585 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1586 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1588 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1589 loadmodel->animscenes[i].firstframe = i;
1590 loadmodel->animscenes[i].framecount = 1;
1591 loadmodel->animscenes[i].framerate = 10;
1592 loadmodel->animscenes[i].loop = true;
1596 loadmodel->num_tagframes = loadmodel->numframes;
1597 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1598 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1599 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1601 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1602 for (j = 0;j < 9;j++)
1603 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1604 for (j = 0;j < 3;j++)
1605 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1606 //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);
1612 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)))
1614 if (memcmp(pinmesh->identifier, "IDP3", 4))
1615 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1616 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1617 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1618 meshvertices += LittleLong(pinmesh->num_vertices);
1619 meshtriangles += LittleLong(pinmesh->num_triangles);
1622 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1623 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1624 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1625 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));
1626 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1627 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1628 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1629 loadmodel->surfmesh.num_vertices = meshvertices;
1630 loadmodel->surfmesh.num_triangles = meshtriangles;
1631 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1632 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1633 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1634 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1635 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1636 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1637 if (meshvertices <= 65536)
1638 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1642 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)))
1644 if (memcmp(pinmesh->identifier, "IDP3", 4))
1645 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1646 loadmodel->sortedmodelsurfaces[i] = i;
1647 surface = loadmodel->data_surfaces + i;
1648 surface->texture = loadmodel->data_textures + i;
1649 surface->num_firsttriangle = meshtriangles;
1650 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1651 surface->num_firstvertex = meshvertices;
1652 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1653 meshvertices += surface->num_vertices;
1654 meshtriangles += surface->num_triangles;
1656 for (j = 0;j < surface->num_triangles * 3;j++)
1657 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1658 for (j = 0;j < surface->num_vertices;j++)
1660 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1661 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1663 for (j = 0;j < loadmodel->numframes;j++)
1665 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1666 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1667 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1669 out->origin[0] = LittleShort(in->origin[0]);
1670 out->origin[1] = LittleShort(in->origin[1]);
1671 out->origin[2] = LittleShort(in->origin[2]);
1672 out->pitch = in->pitch;
1677 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1679 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1681 if (loadmodel->surfmesh.data_element3s)
1682 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1683 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1684 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1685 Mod_Alias_MorphMesh_CompileFrames();
1686 Mod_Alias_CalculateBoundingBox();
1687 Mod_FreeSkinFiles(skinfiles);
1688 Mod_MakeSortedSurfaces(loadmodel);
1690 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1691 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1694 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1696 zymtype1header_t *pinmodel, *pheader;
1697 unsigned char *pbase;
1698 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1699 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose;
1700 zymvertex_t *verts, *vertdata;
1704 skinfile_t *skinfiles;
1705 unsigned char *data;
1706 msurface_t *surface;
1708 pinmodel = (zymtype1header_t *)buffer;
1709 pbase = (unsigned char *)buffer;
1710 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1711 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1712 if (BigLong(pinmodel->type) != 1)
1713 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1715 loadmodel->modeldatatypestring = "ZYM";
1717 loadmodel->type = mod_alias;
1718 loadmodel->synctype = ST_RAND;
1722 pheader->type = BigLong(pinmodel->type);
1723 pheader->filesize = BigLong(pinmodel->filesize);
1724 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1725 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1726 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1727 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1728 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1729 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1730 pheader->radius = BigFloat(pinmodel->radius);
1731 pheader->numverts = BigLong(pinmodel->numverts);
1732 pheader->numtris = BigLong(pinmodel->numtris);
1733 pheader->numshaders = BigLong(pinmodel->numshaders);
1734 pheader->numbones = BigLong(pinmodel->numbones);
1735 pheader->numscenes = BigLong(pinmodel->numscenes);
1736 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1737 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1738 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1739 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1740 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1741 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1742 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1743 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1744 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1745 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1746 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1747 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1748 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1749 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1750 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1751 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1752 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1753 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1755 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1757 Con_Printf("%s has no geometry\n", loadmodel->name);
1760 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1762 Con_Printf("%s has no animations\n", loadmodel->name);
1766 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1767 loadmodel->DrawSky = NULL;
1768 loadmodel->DrawAddWaterPlanes = NULL;
1769 loadmodel->Draw = R_Q1BSP_Draw;
1770 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1771 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1772 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1773 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1774 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1775 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1776 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1777 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1778 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1779 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1780 loadmodel->PointSuperContents = NULL;
1782 loadmodel->numframes = pheader->numscenes;
1783 loadmodel->num_surfaces = pheader->numshaders;
1785 skinfiles = Mod_LoadSkinFiles();
1786 if (loadmodel->numskins < 1)
1787 loadmodel->numskins = 1;
1789 // make skinscenes for the skins (no groups)
1790 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1791 for (i = 0;i < loadmodel->numskins;i++)
1793 loadmodel->skinscenes[i].firstframe = i;
1794 loadmodel->skinscenes[i].framecount = 1;
1795 loadmodel->skinscenes[i].loop = true;
1796 loadmodel->skinscenes[i].framerate = 10;
1800 modelradius = pheader->radius;
1801 for (i = 0;i < 3;i++)
1803 loadmodel->normalmins[i] = pheader->mins[i];
1804 loadmodel->normalmaxs[i] = pheader->maxs[i];
1805 loadmodel->rotatedmins[i] = -modelradius;
1806 loadmodel->rotatedmaxs[i] = modelradius;
1808 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1809 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1810 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1811 if (loadmodel->yawmaxs[0] > modelradius)
1812 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1813 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1814 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1815 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1816 loadmodel->radius = modelradius;
1817 loadmodel->radius2 = modelradius * modelradius;
1819 // go through the lumps, swapping things
1821 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1822 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1823 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1824 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1825 for (i = 0;i < pheader->numscenes;i++)
1827 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1828 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1829 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1830 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1831 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1832 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1833 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1834 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1835 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1836 if (loadmodel->animscenes[i].framerate < 0)
1837 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1841 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1842 loadmodel->num_bones = pheader->numbones;
1843 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1844 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1845 for (i = 0;i < pheader->numbones;i++)
1847 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1848 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1849 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1850 if (loadmodel->data_bones[i].parent >= i)
1851 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1854 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1855 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1856 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1857 for (i = 0;i < pheader->numverts;i++)
1859 vertbonecounts[i] = BigLong(bonecount[i]);
1860 if (vertbonecounts[i] != 1)
1861 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1864 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1866 meshvertices = pheader->numverts;
1867 meshtriangles = pheader->numtris;
1869 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1870 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1871 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1872 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]));
1873 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1874 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1875 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1876 loadmodel->surfmesh.num_vertices = meshvertices;
1877 loadmodel->surfmesh.num_triangles = meshtriangles;
1878 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1879 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1880 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1881 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1882 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1883 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1884 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1885 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1886 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1887 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
1888 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1889 if (loadmodel->surfmesh.num_vertices <= 65536)
1890 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1892 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1893 poses = (float *) (pheader->lump_poses.start + pbase);
1894 for (i = 0;i < pheader->lump_poses.length / 4;i++)
1895 loadmodel->data_poses[i] = BigFloat(poses[i]);
1897 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1898 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1899 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1900 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1901 // (converting from weight-blending skeletal animation to
1902 // deformation-based skeletal animation)
1903 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1904 for (i = 0;i < loadmodel->num_bones;i++)
1906 const float *m = loadmodel->data_poses + i * 12;
1907 if (loadmodel->data_bones[i].parent >= 0)
1908 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1910 for (k = 0;k < 12;k++)
1911 bonepose[12*i+k] = m[k];
1913 for (j = 0;j < pheader->numverts;j++)
1915 // this format really should have had a per vertexweight weight value...
1916 // but since it does not, the weighting is completely ignored and
1917 // only one weight is allowed per vertex
1918 int boneindex = BigLong(vertdata[j].bonenum);
1919 const float *m = bonepose + 12 * boneindex;
1920 float relativeorigin[3];
1921 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1922 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1923 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1924 // transform the vertex bone weight into the base mesh
1925 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1926 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1927 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1928 // store the weight as the primary weight on this vertex
1929 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
1930 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = 1;
1933 // normals and tangents are calculated after elements are loaded
1935 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1936 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1937 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1938 for (i = 0;i < pheader->numverts;i++)
1940 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1941 // flip T coordinate for OpenGL
1942 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1945 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1946 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1947 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1949 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1950 //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)
1951 // byteswap, validate, and swap winding order of tris
1952 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1953 if (pheader->lump_render.length != count)
1954 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1955 renderlist = (int *) (pheader->lump_render.start + pbase);
1956 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1958 for (i = 0;i < loadmodel->num_surfaces;i++)
1960 int firstvertex, lastvertex;
1961 if (renderlist >= renderlistend)
1962 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1963 count = BigLong(*renderlist);renderlist++;
1964 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1965 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1967 loadmodel->sortedmodelsurfaces[i] = i;
1968 surface = loadmodel->data_surfaces + i;
1969 surface->texture = loadmodel->data_textures + i;
1970 surface->num_firsttriangle = meshtriangles;
1971 surface->num_triangles = count;
1972 meshtriangles += surface->num_triangles;
1974 // load the elements
1975 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
1976 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
1978 outelements[j*3+2] = BigLong(renderlist[0]);
1979 outelements[j*3+1] = BigLong(renderlist[1]);
1980 outelements[j*3+0] = BigLong(renderlist[2]);
1982 // validate the elements and find the used vertex range
1983 firstvertex = meshvertices;
1985 for (j = 0;j < surface->num_triangles * 3;j++)
1987 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
1988 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
1989 firstvertex = min(firstvertex, outelements[j]);
1990 lastvertex = max(lastvertex, outelements[j]);
1992 surface->num_firstvertex = firstvertex;
1993 surface->num_vertices = lastvertex + 1 - firstvertex;
1995 // since zym models do not have named sections, reuse their shader
1996 // name as the section name
1997 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
1998 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
2000 Mod_FreeSkinFiles(skinfiles);
2001 Mem_Free(vertbonecounts);
2003 Mod_MakeSortedSurfaces(loadmodel);
2005 // compute all the mesh information that was not loaded from the file
2006 if (loadmodel->surfmesh.data_element3s)
2007 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2008 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2009 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2010 Mod_BuildBaseBonePoses();
2011 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2012 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);
2013 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2015 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2018 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2020 dpmheader_t *pheader;
2024 unsigned char *pbase;
2025 int i, j, k, meshvertices, meshtriangles;
2026 skinfile_t *skinfiles;
2027 unsigned char *data;
2030 pheader = (dpmheader_t *)buffer;
2031 pbase = (unsigned char *)buffer;
2032 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2033 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2034 if (BigLong(pheader->type) != 2)
2035 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2037 loadmodel->modeldatatypestring = "DPM";
2039 loadmodel->type = mod_alias;
2040 loadmodel->synctype = ST_RAND;
2043 pheader->type = BigLong(pheader->type);
2044 pheader->filesize = BigLong(pheader->filesize);
2045 pheader->mins[0] = BigFloat(pheader->mins[0]);
2046 pheader->mins[1] = BigFloat(pheader->mins[1]);
2047 pheader->mins[2] = BigFloat(pheader->mins[2]);
2048 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2049 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2050 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2051 pheader->yawradius = BigFloat(pheader->yawradius);
2052 pheader->allradius = BigFloat(pheader->allradius);
2053 pheader->num_bones = BigLong(pheader->num_bones);
2054 pheader->num_meshs = BigLong(pheader->num_meshs);
2055 pheader->num_frames = BigLong(pheader->num_frames);
2056 pheader->ofs_bones = BigLong(pheader->ofs_bones);
2057 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2058 pheader->ofs_frames = BigLong(pheader->ofs_frames);
2060 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2062 Con_Printf("%s has no geometry\n", loadmodel->name);
2065 if (pheader->num_frames < 1)
2067 Con_Printf("%s has no frames\n", loadmodel->name);
2071 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2072 loadmodel->DrawSky = NULL;
2073 loadmodel->DrawAddWaterPlanes = NULL;
2074 loadmodel->Draw = R_Q1BSP_Draw;
2075 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2076 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2077 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2078 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2079 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2080 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2081 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2082 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2083 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2084 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2085 loadmodel->PointSuperContents = NULL;
2088 for (i = 0;i < 3;i++)
2090 loadmodel->normalmins[i] = pheader->mins[i];
2091 loadmodel->normalmaxs[i] = pheader->maxs[i];
2092 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2093 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2094 loadmodel->rotatedmins[i] = -pheader->allradius;
2095 loadmodel->rotatedmaxs[i] = pheader->allradius;
2097 loadmodel->radius = pheader->allradius;
2098 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2100 // load external .skin files if present
2101 skinfiles = Mod_LoadSkinFiles();
2102 if (loadmodel->numskins < 1)
2103 loadmodel->numskins = 1;
2108 // gather combined statistics from the meshes
2109 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2110 for (i = 0;i < (int)pheader->num_meshs;i++)
2112 int numverts = BigLong(dpmmesh->num_verts);
2113 meshvertices += numverts;
2114 meshtriangles += BigLong(dpmmesh->num_tris);
2118 loadmodel->numframes = pheader->num_frames;
2119 loadmodel->num_bones = pheader->num_bones;
2120 loadmodel->num_poses = loadmodel->numframes;
2121 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2122 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2123 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2124 // do most allocations as one merged chunk
2125 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));
2126 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2127 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2128 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2129 loadmodel->surfmesh.num_vertices = meshvertices;
2130 loadmodel->surfmesh.num_triangles = meshtriangles;
2131 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2132 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2133 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2134 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2135 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2136 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2137 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2138 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
2139 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
2140 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
2141 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2142 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2143 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2144 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2145 if (meshvertices <= 65536)
2146 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2148 for (i = 0;i < loadmodel->numskins;i++)
2150 loadmodel->skinscenes[i].firstframe = i;
2151 loadmodel->skinscenes[i].framecount = 1;
2152 loadmodel->skinscenes[i].loop = true;
2153 loadmodel->skinscenes[i].framerate = 10;
2156 // load the bone info
2157 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2158 for (i = 0;i < loadmodel->num_bones;i++)
2160 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2161 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2162 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2163 if (loadmodel->data_bones[i].parent >= i)
2164 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2168 frame = (dpmframe_t *) (pbase + pheader->ofs_frames);
2169 for (i = 0;i < loadmodel->numframes;i++)
2172 memcpy(loadmodel->animscenes[i].name, frame->name, sizeof(frame->name));
2173 loadmodel->animscenes[i].firstframe = i;
2174 loadmodel->animscenes[i].framecount = 1;
2175 loadmodel->animscenes[i].loop = true;
2176 loadmodel->animscenes[i].framerate = 10;
2177 // load the bone poses for this frame
2178 poses = (float *) (pbase + BigLong(frame->ofs_bonepositions));
2179 for (j = 0;j < loadmodel->num_bones*12;j++)
2180 loadmodel->data_poses[i * loadmodel->num_bones*12 + j] = BigFloat(poses[j]);
2181 // stuff not processed here: mins, maxs, yawradius, allradius
2185 // load the meshes now
2186 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2189 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2190 // (converting from weight-blending skeletal animation to
2191 // deformation-based skeletal animation)
2192 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2193 for (i = 0;i < loadmodel->num_bones;i++)
2195 const float *m = loadmodel->data_poses + i * 12;
2196 if (loadmodel->data_bones[i].parent >= 0)
2197 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2199 for (k = 0;k < 12;k++)
2200 bonepose[12*i+k] = m[k];
2202 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2204 const int *inelements;
2206 const float *intexcoord;
2207 msurface_t *surface;
2209 loadmodel->sortedmodelsurfaces[i] = i;
2210 surface = loadmodel->data_surfaces + i;
2211 surface->texture = loadmodel->data_textures + i;
2212 surface->num_firsttriangle = meshtriangles;
2213 surface->num_triangles = BigLong(dpmmesh->num_tris);
2214 surface->num_firstvertex = meshvertices;
2215 surface->num_vertices = BigLong(dpmmesh->num_verts);
2216 meshvertices += surface->num_vertices;
2217 meshtriangles += surface->num_triangles;
2219 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2220 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2221 for (j = 0;j < surface->num_triangles;j++)
2223 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2224 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2225 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2226 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2231 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2232 for (j = 0;j < surface->num_vertices*2;j++)
2233 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2235 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2236 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2240 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2241 data += sizeof(dpmvertex_t);
2242 for (k = 0;k < numweights;k++)
2244 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2245 int boneindex = BigLong(vert->bonenum);
2246 const float *m = bonepose + 12 * boneindex;
2247 float influence = BigFloat(vert->influence);
2248 float relativeorigin[3], relativenormal[3];
2249 relativeorigin[0] = BigFloat(vert->origin[0]);
2250 relativeorigin[1] = BigFloat(vert->origin[1]);
2251 relativeorigin[2] = BigFloat(vert->origin[2]);
2252 relativenormal[0] = BigFloat(vert->normal[0]);
2253 relativenormal[1] = BigFloat(vert->normal[1]);
2254 relativenormal[2] = BigFloat(vert->normal[2]);
2255 // blend the vertex bone weights into the base mesh
2256 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2257 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2258 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2259 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2260 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2261 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2264 // store the first (and often only) weight
2265 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = influence;
2266 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
2270 // sort the new weight into this vertex's weight table
2271 // (which only accepts up to 4 bones per vertex)
2272 for (l = 0;l < 4;l++)
2274 if (loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] < influence)
2276 // move weaker influence weights out of the way first
2278 for (l2 = 3;l2 > l;l2--)
2280 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2-1];
2281 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2-1];
2283 // store the new weight
2284 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] = influence;
2285 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l] = boneindex;
2290 data += sizeof(dpmbonevert_t);
2293 for (l = 0;l < 4;l++)
2294 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l];
2295 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2297 float f = 1.0f / sum;
2298 for (l = 0;l < 4;l++)
2299 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] *= f;
2303 // since dpm models do not have named sections, reuse their shader name as the section name
2304 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2306 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2309 Mod_FreeSkinFiles(skinfiles);
2310 Mod_MakeSortedSurfaces(loadmodel);
2312 // compute all the mesh information that was not loaded from the file
2313 if (loadmodel->surfmesh.data_element3s)
2314 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2315 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2316 Mod_BuildBaseBonePoses();
2317 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);
2318 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2320 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2323 // no idea why PSK/PSA files contain weird quaternions but they do...
2324 #define PSKQUATNEGATIONS
2325 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2327 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2328 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2329 fs_offset_t filesize;
2334 pskboneinfo_t *bones;
2335 pskrawweights_t *rawweights;
2336 pskboneinfo_t *animbones;
2337 pskaniminfo_t *anims;
2338 pskanimkeys_t *animkeys;
2339 void *animfilebuffer, *animbuffer, *animbufferend;
2340 unsigned char *data;
2342 skinfile_t *skinfiles;
2343 char animname[MAX_QPATH];
2346 pchunk = (pskchunk_t *)buffer;
2347 if (strcmp(pchunk->id, "ACTRHEAD"))
2348 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2350 loadmodel->modeldatatypestring = "PSK";
2352 loadmodel->type = mod_alias;
2353 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2354 loadmodel->DrawSky = NULL;
2355 loadmodel->DrawAddWaterPlanes = NULL;
2356 loadmodel->Draw = R_Q1BSP_Draw;
2357 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2358 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2359 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2360 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2361 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2362 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2363 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2364 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2365 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2366 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2367 loadmodel->PointSuperContents = NULL;
2368 loadmodel->synctype = ST_RAND;
2370 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2371 strlcat(animname, ".psa", sizeof(animname));
2372 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2373 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2374 if (animbuffer == NULL)
2375 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2394 while (buffer < bufferend)
2396 pchunk = (pskchunk_t *)buffer;
2397 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2398 version = LittleLong(pchunk->version);
2399 recordsize = LittleLong(pchunk->recordsize);
2400 numrecords = LittleLong(pchunk->numrecords);
2401 if (developer.integer >= 100)
2402 Con_Printf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2403 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2404 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);
2405 if (!strcmp(pchunk->id, "ACTRHEAD"))
2409 else if (!strcmp(pchunk->id, "PNTS0000"))
2412 if (recordsize != sizeof(*p))
2413 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2414 // byteswap in place and keep the pointer
2415 numpnts = numrecords;
2416 pnts = (pskpnts_t *)buffer;
2417 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2419 p->origin[0] = LittleFloat(p->origin[0]);
2420 p->origin[1] = LittleFloat(p->origin[1]);
2421 p->origin[2] = LittleFloat(p->origin[2]);
2425 else if (!strcmp(pchunk->id, "VTXW0000"))
2428 if (recordsize != sizeof(*p))
2429 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2430 // byteswap in place and keep the pointer
2431 numvtxw = numrecords;
2432 vtxw = (pskvtxw_t *)buffer;
2433 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2435 p->pntsindex = LittleShort(p->pntsindex);
2436 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2437 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2438 if (p->pntsindex >= numpnts)
2440 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2446 else if (!strcmp(pchunk->id, "FACE0000"))
2449 if (recordsize != sizeof(*p))
2450 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2451 // byteswap in place and keep the pointer
2452 numfaces = numrecords;
2453 faces = (pskface_t *)buffer;
2454 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2456 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2457 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2458 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2459 p->group = LittleLong(p->group);
2460 if (p->vtxwindex[0] >= numvtxw)
2462 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2463 p->vtxwindex[0] = 0;
2465 if (p->vtxwindex[1] >= numvtxw)
2467 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2468 p->vtxwindex[1] = 0;
2470 if (p->vtxwindex[2] >= numvtxw)
2472 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2473 p->vtxwindex[2] = 0;
2478 else if (!strcmp(pchunk->id, "MATT0000"))
2481 if (recordsize != sizeof(*p))
2482 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2483 // byteswap in place and keep the pointer
2484 nummatts = numrecords;
2485 matts = (pskmatt_t *)buffer;
2486 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2492 else if (!strcmp(pchunk->id, "REFSKELT"))
2495 if (recordsize != sizeof(*p))
2496 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2497 // byteswap in place and keep the pointer
2498 numbones = numrecords;
2499 bones = (pskboneinfo_t *)buffer;
2500 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2502 p->numchildren = LittleLong(p->numchildren);
2503 p->parent = LittleLong(p->parent);
2504 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2505 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2506 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2507 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2508 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2509 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2510 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2511 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2512 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2513 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2514 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2515 #ifdef PSKQUATNEGATIONS
2518 p->basepose.quat[0] *= -1;
2519 p->basepose.quat[1] *= -1;
2520 p->basepose.quat[2] *= -1;
2524 p->basepose.quat[0] *= 1;
2525 p->basepose.quat[1] *= -1;
2526 p->basepose.quat[2] *= 1;
2529 if (p->parent < 0 || p->parent >= numbones)
2531 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2537 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2540 if (recordsize != sizeof(*p))
2541 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2542 // byteswap in place and keep the pointer
2543 numrawweights = numrecords;
2544 rawweights = (pskrawweights_t *)buffer;
2545 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2547 p->weight = LittleFloat(p->weight);
2548 p->pntsindex = LittleLong(p->pntsindex);
2549 p->boneindex = LittleLong(p->boneindex);
2550 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2552 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2555 if (p->boneindex < 0 || p->boneindex >= numbones)
2557 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2565 while (animbuffer < animbufferend)
2567 pchunk = (pskchunk_t *)animbuffer;
2568 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2569 version = LittleLong(pchunk->version);
2570 recordsize = LittleLong(pchunk->recordsize);
2571 numrecords = LittleLong(pchunk->numrecords);
2572 if (developer.integer >= 100)
2573 Con_Printf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2574 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2575 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);
2576 if (!strcmp(pchunk->id, "ANIMHEAD"))
2580 else if (!strcmp(pchunk->id, "BONENAMES"))
2583 if (recordsize != sizeof(*p))
2584 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2585 // byteswap in place and keep the pointer
2586 numanimbones = numrecords;
2587 animbones = (pskboneinfo_t *)animbuffer;
2588 // NOTE: supposedly psa does not need to match the psk model, the
2589 // bones missing from the psa would simply use their base
2590 // positions from the psk, but this is hard for me to implement
2591 // and people can easily make animations that match.
2592 if (numanimbones != numbones)
2593 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2594 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2596 p->numchildren = LittleLong(p->numchildren);
2597 p->parent = LittleLong(p->parent);
2598 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2599 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2600 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2601 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2602 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2603 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2604 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2605 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2606 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2607 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2608 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2609 #ifdef PSKQUATNEGATIONS
2612 p->basepose.quat[0] *= -1;
2613 p->basepose.quat[1] *= -1;
2614 p->basepose.quat[2] *= -1;
2618 p->basepose.quat[0] *= 1;
2619 p->basepose.quat[1] *= -1;
2620 p->basepose.quat[2] *= 1;
2623 if (p->parent < 0 || p->parent >= numanimbones)
2625 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2628 // check that bones are the same as in the base
2629 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2630 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2634 else if (!strcmp(pchunk->id, "ANIMINFO"))
2637 if (recordsize != sizeof(*p))
2638 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2639 // byteswap in place and keep the pointer
2640 numanims = numrecords;
2641 anims = (pskaniminfo_t *)animbuffer;
2642 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2644 p->numbones = LittleLong(p->numbones);
2645 p->playtime = LittleFloat(p->playtime);
2646 p->fps = LittleFloat(p->fps);
2647 p->firstframe = LittleLong(p->firstframe);
2648 p->numframes = LittleLong(p->numframes);
2649 if (p->numbones != numbones)
2650 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2654 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2657 if (recordsize != sizeof(*p))
2658 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2659 numanimkeys = numrecords;
2660 animkeys = (pskanimkeys_t *)animbuffer;
2661 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2663 p->origin[0] = LittleFloat(p->origin[0]);
2664 p->origin[1] = LittleFloat(p->origin[1]);
2665 p->origin[2] = LittleFloat(p->origin[2]);
2666 p->quat[0] = LittleFloat(p->quat[0]);
2667 p->quat[1] = LittleFloat(p->quat[1]);
2668 p->quat[2] = LittleFloat(p->quat[2]);
2669 p->quat[3] = LittleFloat(p->quat[3]);
2670 p->frametime = LittleFloat(p->frametime);
2671 #ifdef PSKQUATNEGATIONS
2672 if (index % numbones)
2687 // TODO: allocate bonepose stuff
2690 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2693 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2694 Host_Error("%s: missing required chunks", loadmodel->name);
2696 loadmodel->numframes = 0;
2697 for (index = 0;index < numanims;index++)
2698 loadmodel->numframes += anims[index].numframes;
2700 if (numanimkeys != numbones * loadmodel->numframes)
2701 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2703 meshvertices = numvtxw;
2704 meshtriangles = numfaces;
2706 // load external .skin files if present
2707 skinfiles = Mod_LoadSkinFiles();
2708 if (loadmodel->numskins < 1)
2709 loadmodel->numskins = 1;
2710 loadmodel->num_bones = numbones;
2711 loadmodel->num_poses = loadmodel->numframes;
2712 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2713 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2714 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2715 loadmodel->surfmesh.num_vertices = meshvertices;
2716 loadmodel->surfmesh.num_triangles = meshtriangles;
2717 // do most allocations as one merged chunk
2718 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);
2719 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2720 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2721 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2722 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2723 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2724 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2725 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2726 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2727 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2728 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2729 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2730 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += loadmodel->surfmesh.num_vertices * sizeof(int[4]);
2731 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[4]);
2732 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
2733 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2734 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2735 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2736 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2737 if (loadmodel->surfmesh.num_vertices <= 65536)
2738 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2740 for (i = 0;i < loadmodel->numskins;i++)
2742 loadmodel->skinscenes[i].firstframe = i;
2743 loadmodel->skinscenes[i].framecount = 1;
2744 loadmodel->skinscenes[i].loop = true;
2745 loadmodel->skinscenes[i].framerate = 10;
2749 for (index = 0, i = 0;index < nummatts;index++)
2751 // since psk models do not have named sections, reuse their shader name as the section name
2752 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2753 loadmodel->sortedmodelsurfaces[index] = index;
2754 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2755 loadmodel->data_surfaces[index].num_firstvertex = 0;
2756 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2759 // copy over the vertex locations and texcoords
2760 for (index = 0;index < numvtxw;index++)
2762 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2763 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2764 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2765 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2766 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2769 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2770 for (index = 0;index < numfaces;index++)
2771 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2772 for (index = 0, i = 0;index < nummatts;index++)
2774 loadmodel->data_surfaces[index].num_firsttriangle = i;
2775 i += loadmodel->data_surfaces[index].num_triangles;
2776 loadmodel->data_surfaces[index].num_triangles = 0;
2778 for (index = 0;index < numfaces;index++)
2780 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2781 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2782 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2783 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2786 // copy over the bones
2787 for (index = 0;index < numbones;index++)
2789 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2790 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2791 if (loadmodel->data_bones[index].parent >= index)
2792 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2795 // sort the psk point weights into the vertex weight tables
2796 // (which only accept up to 4 bones per vertex)
2797 for (index = 0;index < numvtxw;index++)
2801 for (j = 0;j < numrawweights;j++)
2803 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2805 int boneindex = rawweights[j].boneindex;
2806 float influence = rawweights[j].weight;
2807 for (l = 0;l < 4;l++)
2809 if (loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] < influence)
2811 // move lower influence weights out of the way first
2813 for (l2 = 3;l2 > l;l2--)
2815 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2-1];
2816 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2-1];
2818 // store the new weight
2819 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] = influence;
2820 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l] = boneindex;
2827 for (l = 0;l < 4;l++)
2828 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l];
2829 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2831 float f = 1.0f / sum;
2832 for (l = 0;l < 4;l++)
2833 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] *= f;
2837 // set up the animscenes based on the anims
2838 for (index = 0, i = 0;index < numanims;index++)
2840 for (j = 0;j < anims[index].numframes;j++, i++)
2842 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2843 loadmodel->animscenes[i].firstframe = i;
2844 loadmodel->animscenes[i].framecount = 1;
2845 loadmodel->animscenes[i].loop = true;
2846 loadmodel->animscenes[i].framerate = 10;
2850 // load the poses from the animkeys
2851 for (index = 0;index < numanimkeys;index++)
2853 pskanimkeys_t *k = animkeys + index;
2855 Matrix4x4_FromOriginQuat(&matrix, k->origin[0], k->origin[1], k->origin[2], k->quat[0], k->quat[1], k->quat[2], k->quat[3]);
2856 Matrix4x4_ToArray12FloatD3D(&matrix, loadmodel->data_poses + index*12);
2858 Mod_FreeSkinFiles(skinfiles);
2859 Mem_Free(animfilebuffer);
2860 Mod_MakeSortedSurfaces(loadmodel);
2862 // compute all the mesh information that was not loaded from the file
2863 // TODO: honor smoothing groups somehow?
2864 if (loadmodel->surfmesh.data_element3s)
2865 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2866 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2867 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2868 Mod_BuildBaseBonePoses();
2869 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2870 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);
2871 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2872 Mod_Alias_CalculateBoundingBox();
2874 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;