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 memset(blendmatrix, 0, sizeof(blendmatrix));
535 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
537 lerp = frameblend[blendindex].lerp;
538 boneframe = model->data_poses + frameblend[blendindex].subframe * model->num_bones * 12;
539 input = boneframe + tagindex * 12;
540 for (k = 0;k < 12;k++)
541 blendmatrix[k] += input[k] * lerp;
543 Matrix4x4_FromArray12FloatD3D(tag_localmatrix, blendmatrix);
546 else if (model->num_tags)
548 if(tagindex >= model->num_tags || tagindex < 0)
551 *tagname = model->data_tags[tagindex].name;
552 memset(blendmatrix, 0, sizeof(blendmatrix));
553 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
555 lerp = frameblend[blendindex].lerp;
556 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
557 for (k = 0;k < 12;k++)
558 blendmatrix[k] += input[k] * lerp;
560 Matrix4x4_FromArray12FloatGL(tag_localmatrix, blendmatrix);
567 int Mod_Alias_GetTagIndexForName(const dp_model_t *model, unsigned int skin, const char *tagname)
570 if(skin >= (unsigned int)model->numskins)
572 if (model->num_bones)
573 for (i = 0;i < model->num_bones;i++)
574 if (!strcasecmp(tagname, model->data_bones[i].name))
577 for (i = 0;i < model->num_tags;i++)
578 if (!strcasecmp(tagname, model->data_tags[i].name))
583 static void Mod_BuildBaseBonePoses(void)
588 float *in12f = loadmodel->data_poses;
590 float *outinv12f = loadmodel->data_baseboneposeinverse;
591 if (!loadmodel->num_bones)
593 out12f = basebonepose = (float *) Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(float[12]));
594 for (i = 0;i < loadmodel->num_bones;i++, in12f += 12, out12f += 12, outinv12f += 12)
596 if (loadmodel->data_bones[i].parent >= 0)
597 R_ConcatTransforms(basebonepose + 12 * loadmodel->data_bones[i].parent, in12f, out12f);
599 for (k = 0;k < 12;k++)
600 out12f[k] = in12f[k];
604 // we only support uniform scaling, so assume the first row is enough
605 // (note the lack of sqrt here, because we're trying to undo the scaling,
606 // this means multiplying by the inverse scale twice - squaring it, which
607 // makes the sqrt a waste of time)
608 scale = 1.0 / (out12f[ 0] * out12f[ 0] + out12f[ 1] * out12f[ 1] + out12f[ 2] * out12f[ 2]);
610 // invert the rotation by transposing and multiplying by the squared
611 // recipricol of the input matrix scale as described above
612 outinv12f[ 0] = (float)(out12f[ 0] * scale);
613 outinv12f[ 1] = (float)(out12f[ 4] * scale);
614 outinv12f[ 2] = (float)(out12f[ 8] * scale);
615 outinv12f[ 4] = (float)(out12f[ 1] * scale);
616 outinv12f[ 5] = (float)(out12f[ 5] * scale);
617 outinv12f[ 6] = (float)(out12f[ 9] * scale);
618 outinv12f[ 8] = (float)(out12f[ 2] * scale);
619 outinv12f[ 9] = (float)(out12f[ 6] * scale);
620 outinv12f[10] = (float)(out12f[10] * scale);
622 // invert the translate
623 outinv12f[ 3] = -(out12f[ 3] * outinv12f[ 0] + out12f[ 7] * outinv12f[ 1] + out12f[11] * outinv12f[ 2]);
624 outinv12f[ 7] = -(out12f[ 3] * outinv12f[ 4] + out12f[ 7] * outinv12f[ 5] + out12f[11] * outinv12f[ 6]);
625 outinv12f[11] = -(out12f[ 3] * outinv12f[ 8] + out12f[ 7] * outinv12f[ 9] + out12f[11] * outinv12f[10]);
627 Mem_Free(basebonepose);
630 static void Mod_Alias_CalculateBoundingBox(void)
633 qboolean firstvertex = true;
634 float dist, yawradius, radius;
637 frameblend_t frameblend[MAX_FRAMEBLENDS];
638 memset(frameblend, 0, sizeof(frameblend));
639 frameblend[0].lerp = 1;
640 vertex3f = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
641 VectorClear(loadmodel->normalmins);
642 VectorClear(loadmodel->normalmaxs);
645 for (frameblend[0].subframe = 0;frameblend[0].subframe < loadmodel->num_poses;frameblend[0].subframe++)
647 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, vertex3f, NULL, NULL, NULL);
648 for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
653 VectorCopy(v, loadmodel->normalmins);
654 VectorCopy(v, loadmodel->normalmaxs);
658 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
659 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
660 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
661 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
662 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
663 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
665 dist = v[0] * v[0] + v[1] * v[1];
666 if (yawradius < dist)
675 radius = sqrt(radius);
676 yawradius = sqrt(yawradius);
677 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
678 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
679 loadmodel->yawmins[2] = loadmodel->normalmins[2];
680 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
681 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
682 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
683 loadmodel->radius = radius;
684 loadmodel->radius2 = radius * radius;
687 static void Mod_Alias_MorphMesh_CompileFrames(void)
690 frameblend_t frameblend[MAX_FRAMEBLENDS];
691 unsigned char *datapointer;
692 memset(frameblend, 0, sizeof(frameblend));
693 frameblend[0].lerp = 1;
694 datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
695 loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
696 loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
697 loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
698 loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
699 loadmodel->surfmesh.data_morphtexvecvertex = (texvecvertex_t *)datapointer;datapointer += loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices * sizeof(texvecvertex_t);
700 // 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)
701 for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
703 frameblend[0].subframe = i;
704 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
705 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);
706 // encode the svector and tvector in 3 byte format for permanent storage
707 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
709 VectorScaleCast(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
710 VectorScaleCast(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
715 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)
718 float segmentmins[3], segmentmaxs[3];
720 static int maxvertices = 0;
721 static float *vertex3f = NULL;
722 memset(trace, 0, sizeof(*trace));
724 trace->realfraction = 1;
725 trace->hitsupercontentsmask = hitsupercontentsmask;
726 if (maxvertices < model->surfmesh.num_vertices)
730 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
731 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
733 segmentmins[0] = min(start[0], end[0]) - 1;
734 segmentmins[1] = min(start[1], end[1]) - 1;
735 segmentmins[2] = min(start[2], end[2]) - 1;
736 segmentmaxs[0] = max(start[0], end[0]) + 1;
737 segmentmaxs[1] = max(start[1], end[1]) + 1;
738 segmentmaxs[2] = max(start[2], end[2]) + 1;
739 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
740 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
741 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);
744 static int maxvertices = 0;
745 static float *vertex3f = NULL;
747 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)
750 vec3_t shiftstart, shiftend;
751 float segmentmins[3], segmentmaxs[3];
753 colboxbrushf_t thisbrush_start, thisbrush_end;
754 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
756 if (VectorCompare(boxmins, boxmaxs))
758 VectorAdd(start, boxmins, shiftstart);
759 VectorAdd(end, boxmins, shiftend);
760 Mod_MDLMD2MD3_TraceLine(model, frameblend, skeleton, trace, start, end, hitsupercontentsmask);
761 VectorSubtract(trace->endpos, boxmins, trace->endpos);
765 // box trace, performed as brush trace
766 memset(trace, 0, sizeof(*trace));
768 trace->realfraction = 1;
769 trace->hitsupercontentsmask = hitsupercontentsmask;
770 if (maxvertices < model->surfmesh.num_vertices)
774 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
775 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
777 segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
778 segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
779 segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
780 segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
781 segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
782 segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
783 VectorAdd(start, boxmins, boxstartmins);
784 VectorAdd(start, boxmaxs, boxstartmaxs);
785 VectorAdd(end, boxmins, boxendmins);
786 VectorAdd(end, boxmaxs, boxendmaxs);
787 Collision_BrushForBox(&thisbrush_start, boxstartmins, boxstartmaxs, 0, 0, NULL);
788 Collision_BrushForBox(&thisbrush_end, boxendmins, boxendmaxs, 0, 0, NULL);
789 if (maxvertices < model->surfmesh.num_vertices)
793 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
794 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
796 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
797 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
798 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);
801 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
804 for (i = 0;i < inverts;i++)
806 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
808 j = vertremap[i]; // not onseam
811 j = vertremap[i+inverts]; // onseam
817 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
819 int i, f, pose, groupframes;
821 daliasframetype_t *pframetype;
822 daliasframe_t *pinframe;
823 daliasgroup_t *group;
824 daliasinterval_t *intervals;
827 scene = loadmodel->animscenes;
828 for (f = 0;f < loadmodel->numframes;f++)
830 pframetype = (daliasframetype_t *)datapointer;
831 datapointer += sizeof(daliasframetype_t);
832 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
834 // a single frame is still treated as a group
841 group = (daliasgroup_t *)datapointer;
842 datapointer += sizeof(daliasgroup_t);
843 groupframes = LittleLong (group->numframes);
845 // intervals (time per frame)
846 intervals = (daliasinterval_t *)datapointer;
847 datapointer += sizeof(daliasinterval_t) * groupframes;
849 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
850 if (interval < 0.01f)
852 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
857 // get scene name from first frame
858 pinframe = (daliasframe_t *)datapointer;
860 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
861 scene->firstframe = pose;
862 scene->framecount = groupframes;
863 scene->framerate = 1.0f / interval;
868 for (i = 0;i < groupframes;i++)
870 pinframe = (daliasframe_t *)datapointer;
871 datapointer += sizeof(daliasframe_t);
872 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
873 datapointer += sizeof(trivertx_t) * inverts;
879 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
881 if (cls.state == ca_dedicated)
885 skinframe = R_SkinFrame_LoadMissing();
886 memset(texture, 0, sizeof(*texture));
887 texture->currentframe = texture;
888 //texture->animated = false;
889 texture->numskinframes = 1;
890 texture->skinframerate = 1;
891 texture->skinframes[0] = skinframe;
892 texture->currentskinframe = skinframe;
893 //texture->backgroundnumskinframes = 0;
894 //texture->customblendfunc[0] = 0;
895 //texture->customblendfunc[1] = 0;
896 //texture->surfaceflags = 0;
897 //texture->supercontents = 0;
898 //texture->surfaceparms = 0;
899 //texture->textureflags = 0;
901 texture->basematerialflags = MATERIALFLAG_WALL;
902 if (texture->currentskinframe->hasalpha)
903 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
904 texture->currentmaterialflags = texture->basematerialflags;
905 texture->specularscalemod = 1;
906 texture->specularpowermod = 1;
909 void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
912 skinfileitem_t *skinfileitem;
915 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
916 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
918 memset(skin, 0, sizeof(*skin));
920 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
922 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
923 if (!strcmp(skinfileitem->name, meshname))
925 Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
931 // don't render unmentioned meshes
932 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
933 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
938 Mod_LoadTextureFromQ3Shader(skin, shadername, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
941 #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);
942 #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);
943 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
945 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
946 float scales, scalet, interval;
950 stvert_t *pinstverts;
951 dtriangle_t *pintriangles;
952 daliasskintype_t *pinskintype;
953 daliasskingroup_t *pinskingroup;
954 daliasskininterval_t *pinskinintervals;
955 daliasframetype_t *pinframetype;
956 daliasgroup_t *pinframegroup;
957 unsigned char *datapointer, *startframes, *startskins;
958 char name[MAX_QPATH];
959 skinframe_t *tempskinframe;
960 animscene_t *tempskinscenes;
961 texture_t *tempaliasskins;
963 int *vertonseam, *vertremap;
964 skinfile_t *skinfiles;
966 datapointer = (unsigned char *)buffer;
967 pinmodel = (mdl_t *)datapointer;
968 datapointer += sizeof(mdl_t);
970 version = LittleLong (pinmodel->version);
971 if (version != ALIAS_VERSION)
972 Host_Error ("%s has wrong version number (%i should be %i)",
973 loadmodel->name, version, ALIAS_VERSION);
975 loadmodel->modeldatatypestring = "MDL";
977 loadmodel->type = mod_alias;
978 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
979 loadmodel->DrawSky = NULL;
980 loadmodel->DrawAddWaterPlanes = NULL;
981 loadmodel->Draw = R_Q1BSP_Draw;
982 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
983 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
984 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
985 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
986 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
987 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
988 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
989 loadmodel->DrawLight = R_Q1BSP_DrawLight;
990 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
991 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
992 loadmodel->PointSuperContents = NULL;
994 loadmodel->num_surfaces = 1;
995 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
996 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
997 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
998 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
999 loadmodel->sortedmodelsurfaces[0] = 0;
1001 loadmodel->numskins = LittleLong(pinmodel->numskins);
1002 BOUNDI(loadmodel->numskins,0,65536);
1003 skinwidth = LittleLong (pinmodel->skinwidth);
1004 BOUNDI(skinwidth,0,65536);
1005 skinheight = LittleLong (pinmodel->skinheight);
1006 BOUNDI(skinheight,0,65536);
1007 numverts = LittleLong(pinmodel->numverts);
1008 BOUNDI(numverts,0,65536);
1009 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
1010 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
1011 loadmodel->numframes = LittleLong(pinmodel->numframes);
1012 BOUNDI(loadmodel->numframes,0,65536);
1013 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
1014 BOUNDI(loadmodel->synctype,0,2);
1015 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1016 i = LittleLong (pinmodel->flags);
1017 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1019 for (i = 0;i < 3;i++)
1021 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
1022 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
1025 startskins = datapointer;
1027 for (i = 0;i < loadmodel->numskins;i++)
1029 pinskintype = (daliasskintype_t *)datapointer;
1030 datapointer += sizeof(daliasskintype_t);
1031 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
1035 pinskingroup = (daliasskingroup_t *)datapointer;
1036 datapointer += sizeof(daliasskingroup_t);
1037 groupskins = LittleLong(pinskingroup->numskins);
1038 datapointer += sizeof(daliasskininterval_t) * groupskins;
1041 for (j = 0;j < groupskins;j++)
1043 datapointer += skinwidth * skinheight;
1048 pinstverts = (stvert_t *)datapointer;
1049 datapointer += sizeof(stvert_t) * numverts;
1051 pintriangles = (dtriangle_t *)datapointer;
1052 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
1054 startframes = datapointer;
1055 loadmodel->surfmesh.num_morphframes = 0;
1056 for (i = 0;i < loadmodel->numframes;i++)
1058 pinframetype = (daliasframetype_t *)datapointer;
1059 datapointer += sizeof(daliasframetype_t);
1060 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
1064 pinframegroup = (daliasgroup_t *)datapointer;
1065 datapointer += sizeof(daliasgroup_t);
1066 groupframes = LittleLong(pinframegroup->numframes);
1067 datapointer += sizeof(daliasinterval_t) * groupframes;
1070 for (j = 0;j < groupframes;j++)
1072 datapointer += sizeof(daliasframe_t);
1073 datapointer += sizeof(trivertx_t) * numverts;
1074 loadmodel->surfmesh.num_morphframes++;
1077 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1079 // store texture coordinates into temporary array, they will be stored
1080 // after usage is determined (triangle data)
1081 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
1082 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
1083 vertonseam = vertremap + numverts * 2;
1085 scales = 1.0 / skinwidth;
1086 scalet = 1.0 / skinheight;
1087 for (i = 0;i < numverts;i++)
1089 vertonseam[i] = LittleLong(pinstverts[i].onseam);
1090 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
1091 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
1092 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
1093 vertst[(i+numverts)*2+1] = vertst[i*2+1];
1096 // load triangle data
1097 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1099 // read the triangle elements
1100 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1101 for (j = 0;j < 3;j++)
1102 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1103 // validate (note numverts is used because this is the original data)
1104 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1105 // now butcher the elements according to vertonseam and tri->facesfront
1106 // and then compact the vertex set to remove duplicates
1107 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1108 if (!LittleLong(pintriangles[i].facesfront)) // backface
1109 for (j = 0;j < 3;j++)
1110 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1111 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1113 // (this uses vertremap to count usage to save some memory)
1114 for (i = 0;i < numverts*2;i++)
1116 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1117 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1118 // build remapping table and compact array
1119 loadmodel->surfmesh.num_vertices = 0;
1120 for (i = 0;i < numverts*2;i++)
1124 vertremap[i] = loadmodel->surfmesh.num_vertices;
1125 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1126 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1127 loadmodel->surfmesh.num_vertices++;
1130 vertremap[i] = -1; // not used at all
1132 // remap the elements to the new vertex set
1133 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1134 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1135 // store the texture coordinates
1136 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1137 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1139 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1140 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1143 // generate ushort elements array if possible
1144 if (loadmodel->surfmesh.num_vertices <= 65536)
1145 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1146 if (loadmodel->surfmesh.data_element3s)
1147 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1148 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1151 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1152 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1153 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1154 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1155 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1156 Mod_Alias_CalculateBoundingBox();
1157 Mod_Alias_MorphMesh_CompileFrames();
1160 Mem_Free(vertremap);
1163 skinfiles = Mod_LoadSkinFiles();
1166 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1167 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1168 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1169 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1170 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1171 Mod_FreeSkinFiles(skinfiles);
1172 for (i = 0;i < loadmodel->numskins;i++)
1174 loadmodel->skinscenes[i].firstframe = i;
1175 loadmodel->skinscenes[i].framecount = 1;
1176 loadmodel->skinscenes[i].loop = true;
1177 loadmodel->skinscenes[i].framerate = 10;
1182 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1183 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1184 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1185 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1187 datapointer = startskins;
1188 for (i = 0;i < loadmodel->numskins;i++)
1190 pinskintype = (daliasskintype_t *)datapointer;
1191 datapointer += sizeof(daliasskintype_t);
1193 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1200 pinskingroup = (daliasskingroup_t *)datapointer;
1201 datapointer += sizeof(daliasskingroup_t);
1203 groupskins = LittleLong (pinskingroup->numskins);
1205 pinskinintervals = (daliasskininterval_t *)datapointer;
1206 datapointer += sizeof(daliasskininterval_t) * groupskins;
1208 interval = LittleFloat(pinskinintervals[0].interval);
1209 if (interval < 0.01f)
1211 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1216 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1217 loadmodel->skinscenes[i].firstframe = totalskins;
1218 loadmodel->skinscenes[i].framecount = groupskins;
1219 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1220 loadmodel->skinscenes[i].loop = true;
1222 for (j = 0;j < groupskins;j++)
1225 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1227 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1228 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))
1229 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, R_SkinFrame_LoadInternalQuake(name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP, true, r_fullbrights.integer, (unsigned char *)datapointer, skinwidth, skinheight));
1230 datapointer += skinwidth * skinheight;
1234 // check for skins that don't exist in the model, but do exist as external images
1235 // (this was added because yummyluv kept pestering me about support for it)
1236 // TODO: support shaders here?
1237 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)))
1239 // expand the arrays to make room
1240 tempskinscenes = loadmodel->skinscenes;
1241 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1242 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1243 Mem_Free(tempskinscenes);
1245 tempaliasskins = loadmodel->data_textures;
1246 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1247 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1248 Mem_Free(tempaliasskins);
1250 // store the info about the new skin
1251 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1252 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1253 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1254 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1255 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1256 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1258 //increase skin counts
1259 loadmodel->numskins++;
1262 // fix up the pointers since they are pointing at the old textures array
1263 // FIXME: this is a hack!
1264 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1265 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1269 surface = loadmodel->data_surfaces;
1270 surface->texture = loadmodel->data_textures;
1271 surface->num_firsttriangle = 0;
1272 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1273 surface->num_firstvertex = 0;
1274 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1276 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1279 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1281 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1282 float iskinwidth, iskinheight;
1283 unsigned char *data;
1284 msurface_t *surface;
1286 unsigned char *base, *datapointer;
1287 md2frame_t *pinframe;
1289 md2triangle_t *intri;
1290 unsigned short *inst;
1291 struct md2verthash_s
1293 struct md2verthash_s *next;
1297 *hash, **md2verthash, *md2verthashdata;
1298 skinfile_t *skinfiles;
1300 pinmodel = (md2_t *)buffer;
1301 base = (unsigned char *)buffer;
1303 version = LittleLong (pinmodel->version);
1304 if (version != MD2ALIAS_VERSION)
1305 Host_Error ("%s has wrong version number (%i should be %i)",
1306 loadmodel->name, version, MD2ALIAS_VERSION);
1308 loadmodel->modeldatatypestring = "MD2";
1310 loadmodel->type = mod_alias;
1311 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1312 loadmodel->DrawSky = NULL;
1313 loadmodel->DrawAddWaterPlanes = NULL;
1314 loadmodel->Draw = R_Q1BSP_Draw;
1315 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1316 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1317 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1318 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1319 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1320 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1321 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1322 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1323 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1324 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1325 loadmodel->PointSuperContents = NULL;
1327 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1328 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1329 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1330 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1331 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1332 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1333 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1334 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1336 end = LittleLong(pinmodel->ofs_end);
1337 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1338 Host_Error ("%s is not a valid model", loadmodel->name);
1339 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1340 Host_Error ("%s is not a valid model", loadmodel->name);
1341 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1342 Host_Error ("%s is not a valid model", loadmodel->name);
1343 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1344 Host_Error ("%s is not a valid model", loadmodel->name);
1345 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1346 Host_Error ("%s is not a valid model", loadmodel->name);
1348 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1349 numxyz = LittleLong(pinmodel->num_xyz);
1350 numst = LittleLong(pinmodel->num_st);
1351 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1352 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1353 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1354 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1355 skinwidth = LittleLong(pinmodel->skinwidth);
1356 skinheight = LittleLong(pinmodel->skinheight);
1357 iskinwidth = 1.0f / skinwidth;
1358 iskinheight = 1.0f / skinheight;
1360 loadmodel->num_surfaces = 1;
1361 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1362 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]));
1363 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1364 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1365 loadmodel->sortedmodelsurfaces[0] = 0;
1366 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1367 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1368 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1369 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1371 loadmodel->synctype = ST_RAND;
1374 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1375 skinfiles = Mod_LoadSkinFiles();
1378 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1379 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1380 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1381 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1382 Mod_FreeSkinFiles(skinfiles);
1384 else if (loadmodel->numskins)
1386 // skins found (most likely not a player model)
1387 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1388 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1389 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1390 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1391 Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
1395 // no skins (most likely a player model)
1396 loadmodel->numskins = 1;
1397 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1398 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1399 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1400 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1403 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1404 for (i = 0;i < loadmodel->numskins;i++)
1406 loadmodel->skinscenes[i].firstframe = i;
1407 loadmodel->skinscenes[i].framecount = 1;
1408 loadmodel->skinscenes[i].loop = true;
1409 loadmodel->skinscenes[i].framerate = 10;
1412 // load the triangles and stvert data
1413 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1414 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1415 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1416 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1417 // swap the triangle list
1418 loadmodel->surfmesh.num_vertices = 0;
1419 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1421 for (j = 0;j < 3;j++)
1423 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1424 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1427 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1432 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1435 hashindex = (xyz * 256 + st) & 65535;
1436 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1437 if (hash->xyz == xyz && hash->st == st)
1441 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1444 hash->next = md2verthash[hashindex];
1445 md2verthash[hashindex] = hash;
1447 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1451 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1452 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));
1453 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1454 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1455 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1458 hash = md2verthashdata + i;
1459 vertremap[i] = hash->xyz;
1460 sts = LittleShort(inst[hash->st*2+0]);
1461 stt = LittleShort(inst[hash->st*2+1]);
1462 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1464 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1468 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1469 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1472 Mem_Free(md2verthash);
1473 Mem_Free(md2verthashdata);
1475 // generate ushort elements array if possible
1476 if (loadmodel->surfmesh.num_vertices <= 65536)
1477 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1478 if (loadmodel->surfmesh.data_element3s)
1479 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1480 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1483 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1484 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1489 pinframe = (md2frame_t *)datapointer;
1490 datapointer += sizeof(md2frame_t);
1491 // store the frame scale/translate into the appropriate array
1492 for (j = 0;j < 3;j++)
1494 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1495 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1497 // convert the vertices
1498 v = (trivertx_t *)datapointer;
1499 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1500 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1501 out[k] = v[vertremap[k]];
1502 datapointer += numxyz * sizeof(trivertx_t);
1504 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1505 loadmodel->animscenes[i].firstframe = i;
1506 loadmodel->animscenes[i].framecount = 1;
1507 loadmodel->animscenes[i].framerate = 10;
1508 loadmodel->animscenes[i].loop = true;
1511 Mem_Free(vertremap);
1513 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1514 Mod_Alias_CalculateBoundingBox();
1515 Mod_Alias_MorphMesh_CompileFrames();
1517 surface = loadmodel->data_surfaces;
1518 surface->texture = loadmodel->data_textures;
1519 surface->num_firsttriangle = 0;
1520 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1521 surface->num_firstvertex = 0;
1522 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1524 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1527 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1529 int i, j, k, version, meshvertices, meshtriangles;
1530 unsigned char *data;
1531 msurface_t *surface;
1532 md3modelheader_t *pinmodel;
1533 md3frameinfo_t *pinframe;
1536 skinfile_t *skinfiles;
1538 pinmodel = (md3modelheader_t *)buffer;
1540 if (memcmp(pinmodel->identifier, "IDP3", 4))
1541 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1542 version = LittleLong (pinmodel->version);
1543 if (version != MD3VERSION)
1544 Host_Error ("%s has wrong version number (%i should be %i)",
1545 loadmodel->name, version, MD3VERSION);
1547 skinfiles = Mod_LoadSkinFiles();
1548 if (loadmodel->numskins < 1)
1549 loadmodel->numskins = 1;
1551 loadmodel->modeldatatypestring = "MD3";
1553 loadmodel->type = mod_alias;
1554 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1555 loadmodel->DrawSky = NULL;
1556 loadmodel->DrawAddWaterPlanes = NULL;
1557 loadmodel->Draw = R_Q1BSP_Draw;
1558 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1559 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1560 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1561 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1562 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1563 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1564 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1565 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1566 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1567 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1568 loadmodel->PointSuperContents = NULL;
1569 loadmodel->synctype = ST_RAND;
1570 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1571 i = LittleLong (pinmodel->flags);
1572 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1574 // set up some global info about the model
1575 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1576 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1578 // make skinscenes for the skins (no groups)
1579 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1580 for (i = 0;i < loadmodel->numskins;i++)
1582 loadmodel->skinscenes[i].firstframe = i;
1583 loadmodel->skinscenes[i].framecount = 1;
1584 loadmodel->skinscenes[i].loop = true;
1585 loadmodel->skinscenes[i].framerate = 10;
1589 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1590 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1592 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1593 loadmodel->animscenes[i].firstframe = i;
1594 loadmodel->animscenes[i].framecount = 1;
1595 loadmodel->animscenes[i].framerate = 10;
1596 loadmodel->animscenes[i].loop = true;
1600 loadmodel->num_tagframes = loadmodel->numframes;
1601 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1602 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1603 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1605 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1606 for (j = 0;j < 9;j++)
1607 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1608 for (j = 0;j < 3;j++)
1609 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1610 //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);
1616 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)))
1618 if (memcmp(pinmesh->identifier, "IDP3", 4))
1619 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1620 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1621 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1622 meshvertices += LittleLong(pinmesh->num_vertices);
1623 meshtriangles += LittleLong(pinmesh->num_triangles);
1626 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1627 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1628 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1629 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));
1630 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1631 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1632 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1633 loadmodel->surfmesh.num_vertices = meshvertices;
1634 loadmodel->surfmesh.num_triangles = meshtriangles;
1635 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1636 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1637 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1638 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1639 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1640 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1641 if (meshvertices <= 65536)
1642 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1646 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)))
1648 if (memcmp(pinmesh->identifier, "IDP3", 4))
1649 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1650 loadmodel->sortedmodelsurfaces[i] = i;
1651 surface = loadmodel->data_surfaces + i;
1652 surface->texture = loadmodel->data_textures + i;
1653 surface->num_firsttriangle = meshtriangles;
1654 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1655 surface->num_firstvertex = meshvertices;
1656 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1657 meshvertices += surface->num_vertices;
1658 meshtriangles += surface->num_triangles;
1660 for (j = 0;j < surface->num_triangles * 3;j++)
1661 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1662 for (j = 0;j < surface->num_vertices;j++)
1664 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1665 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1667 for (j = 0;j < loadmodel->numframes;j++)
1669 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1670 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1671 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1673 out->origin[0] = LittleShort(in->origin[0]);
1674 out->origin[1] = LittleShort(in->origin[1]);
1675 out->origin[2] = LittleShort(in->origin[2]);
1676 out->pitch = in->pitch;
1681 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1683 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1685 if (loadmodel->surfmesh.data_element3s)
1686 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1687 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1688 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1689 Mod_Alias_MorphMesh_CompileFrames();
1690 Mod_Alias_CalculateBoundingBox();
1691 Mod_FreeSkinFiles(skinfiles);
1692 Mod_MakeSortedSurfaces(loadmodel);
1694 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1695 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1698 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1700 zymtype1header_t *pinmodel, *pheader;
1701 unsigned char *pbase;
1702 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1703 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose;
1704 zymvertex_t *verts, *vertdata;
1708 skinfile_t *skinfiles;
1709 unsigned char *data;
1710 msurface_t *surface;
1712 pinmodel = (zymtype1header_t *)buffer;
1713 pbase = (unsigned char *)buffer;
1714 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1715 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1716 if (BigLong(pinmodel->type) != 1)
1717 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1719 loadmodel->modeldatatypestring = "ZYM";
1721 loadmodel->type = mod_alias;
1722 loadmodel->synctype = ST_RAND;
1726 pheader->type = BigLong(pinmodel->type);
1727 pheader->filesize = BigLong(pinmodel->filesize);
1728 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1729 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1730 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1731 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1732 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1733 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1734 pheader->radius = BigFloat(pinmodel->radius);
1735 pheader->numverts = BigLong(pinmodel->numverts);
1736 pheader->numtris = BigLong(pinmodel->numtris);
1737 pheader->numshaders = BigLong(pinmodel->numshaders);
1738 pheader->numbones = BigLong(pinmodel->numbones);
1739 pheader->numscenes = BigLong(pinmodel->numscenes);
1740 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1741 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1742 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1743 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1744 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1745 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1746 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1747 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1748 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1749 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1750 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1751 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1752 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1753 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1754 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1755 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1756 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1757 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1759 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1761 Con_Printf("%s has no geometry\n", loadmodel->name);
1764 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1766 Con_Printf("%s has no animations\n", loadmodel->name);
1770 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1771 loadmodel->DrawSky = NULL;
1772 loadmodel->DrawAddWaterPlanes = NULL;
1773 loadmodel->Draw = R_Q1BSP_Draw;
1774 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1775 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1776 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1777 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1778 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1779 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1780 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1781 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1782 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1783 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1784 loadmodel->PointSuperContents = NULL;
1786 loadmodel->numframes = pheader->numscenes;
1787 loadmodel->num_surfaces = pheader->numshaders;
1789 skinfiles = Mod_LoadSkinFiles();
1790 if (loadmodel->numskins < 1)
1791 loadmodel->numskins = 1;
1793 // make skinscenes for the skins (no groups)
1794 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1795 for (i = 0;i < loadmodel->numskins;i++)
1797 loadmodel->skinscenes[i].firstframe = i;
1798 loadmodel->skinscenes[i].framecount = 1;
1799 loadmodel->skinscenes[i].loop = true;
1800 loadmodel->skinscenes[i].framerate = 10;
1804 modelradius = pheader->radius;
1805 for (i = 0;i < 3;i++)
1807 loadmodel->normalmins[i] = pheader->mins[i];
1808 loadmodel->normalmaxs[i] = pheader->maxs[i];
1809 loadmodel->rotatedmins[i] = -modelradius;
1810 loadmodel->rotatedmaxs[i] = modelradius;
1812 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1813 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1814 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1815 if (loadmodel->yawmaxs[0] > modelradius)
1816 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1817 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1818 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1819 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1820 loadmodel->radius = modelradius;
1821 loadmodel->radius2 = modelradius * modelradius;
1823 // go through the lumps, swapping things
1825 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1826 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1827 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1828 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1829 for (i = 0;i < pheader->numscenes;i++)
1831 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1832 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1833 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1834 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1835 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1836 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1837 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1838 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1839 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1840 if (loadmodel->animscenes[i].framerate < 0)
1841 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1845 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1846 loadmodel->num_bones = pheader->numbones;
1847 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1848 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1849 for (i = 0;i < pheader->numbones;i++)
1851 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1852 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1853 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1854 if (loadmodel->data_bones[i].parent >= i)
1855 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1858 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1859 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1860 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1861 for (i = 0;i < pheader->numverts;i++)
1863 vertbonecounts[i] = BigLong(bonecount[i]);
1864 if (vertbonecounts[i] != 1)
1865 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1868 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1870 meshvertices = pheader->numverts;
1871 meshtriangles = pheader->numtris;
1873 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1874 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1875 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1876 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]));
1877 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1878 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1879 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1880 loadmodel->surfmesh.num_vertices = meshvertices;
1881 loadmodel->surfmesh.num_triangles = meshtriangles;
1882 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1883 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1884 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1885 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1886 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1887 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1888 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1889 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1890 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1891 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
1892 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1893 if (loadmodel->surfmesh.num_vertices <= 65536)
1894 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1896 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1897 poses = (float *) (pheader->lump_poses.start + pbase);
1898 for (i = 0;i < pheader->lump_poses.length / 4;i++)
1899 loadmodel->data_poses[i] = BigFloat(poses[i]);
1901 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1902 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1903 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1904 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1905 // (converting from weight-blending skeletal animation to
1906 // deformation-based skeletal animation)
1907 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1908 for (i = 0;i < loadmodel->num_bones;i++)
1910 const float *m = loadmodel->data_poses + i * 12;
1911 if (loadmodel->data_bones[i].parent >= 0)
1912 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1914 for (k = 0;k < 12;k++)
1915 bonepose[12*i+k] = m[k];
1917 for (j = 0;j < pheader->numverts;j++)
1919 // this format really should have had a per vertexweight weight value...
1920 // but since it does not, the weighting is completely ignored and
1921 // only one weight is allowed per vertex
1922 int boneindex = BigLong(vertdata[j].bonenum);
1923 const float *m = bonepose + 12 * boneindex;
1924 float relativeorigin[3];
1925 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1926 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1927 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1928 // transform the vertex bone weight into the base mesh
1929 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1930 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1931 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1932 // store the weight as the primary weight on this vertex
1933 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
1934 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = 1;
1937 // normals and tangents are calculated after elements are loaded
1939 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1940 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1941 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1942 for (i = 0;i < pheader->numverts;i++)
1944 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1945 // flip T coordinate for OpenGL
1946 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1949 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1950 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1951 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1953 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1954 //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)
1955 // byteswap, validate, and swap winding order of tris
1956 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1957 if (pheader->lump_render.length != count)
1958 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1959 renderlist = (int *) (pheader->lump_render.start + pbase);
1960 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1962 for (i = 0;i < loadmodel->num_surfaces;i++)
1964 int firstvertex, lastvertex;
1965 if (renderlist >= renderlistend)
1966 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1967 count = BigLong(*renderlist);renderlist++;
1968 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1969 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1971 loadmodel->sortedmodelsurfaces[i] = i;
1972 surface = loadmodel->data_surfaces + i;
1973 surface->texture = loadmodel->data_textures + i;
1974 surface->num_firsttriangle = meshtriangles;
1975 surface->num_triangles = count;
1976 meshtriangles += surface->num_triangles;
1978 // load the elements
1979 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
1980 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
1982 outelements[j*3+2] = BigLong(renderlist[0]);
1983 outelements[j*3+1] = BigLong(renderlist[1]);
1984 outelements[j*3+0] = BigLong(renderlist[2]);
1986 // validate the elements and find the used vertex range
1987 firstvertex = meshvertices;
1989 for (j = 0;j < surface->num_triangles * 3;j++)
1991 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
1992 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
1993 firstvertex = min(firstvertex, outelements[j]);
1994 lastvertex = max(lastvertex, outelements[j]);
1996 surface->num_firstvertex = firstvertex;
1997 surface->num_vertices = lastvertex + 1 - firstvertex;
1999 // since zym models do not have named sections, reuse their shader
2000 // name as the section name
2001 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
2002 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
2004 Mod_FreeSkinFiles(skinfiles);
2005 Mem_Free(vertbonecounts);
2007 Mod_MakeSortedSurfaces(loadmodel);
2009 // compute all the mesh information that was not loaded from the file
2010 if (loadmodel->surfmesh.data_element3s)
2011 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2012 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2013 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2014 Mod_BuildBaseBonePoses();
2015 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2016 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);
2017 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2019 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2022 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2024 dpmheader_t *pheader;
2028 unsigned char *pbase;
2029 int i, j, k, meshvertices, meshtriangles;
2030 skinfile_t *skinfiles;
2031 unsigned char *data;
2034 pheader = (dpmheader_t *)buffer;
2035 pbase = (unsigned char *)buffer;
2036 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2037 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2038 if (BigLong(pheader->type) != 2)
2039 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2041 loadmodel->modeldatatypestring = "DPM";
2043 loadmodel->type = mod_alias;
2044 loadmodel->synctype = ST_RAND;
2047 pheader->type = BigLong(pheader->type);
2048 pheader->filesize = BigLong(pheader->filesize);
2049 pheader->mins[0] = BigFloat(pheader->mins[0]);
2050 pheader->mins[1] = BigFloat(pheader->mins[1]);
2051 pheader->mins[2] = BigFloat(pheader->mins[2]);
2052 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2053 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2054 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2055 pheader->yawradius = BigFloat(pheader->yawradius);
2056 pheader->allradius = BigFloat(pheader->allradius);
2057 pheader->num_bones = BigLong(pheader->num_bones);
2058 pheader->num_meshs = BigLong(pheader->num_meshs);
2059 pheader->num_frames = BigLong(pheader->num_frames);
2060 pheader->ofs_bones = BigLong(pheader->ofs_bones);
2061 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2062 pheader->ofs_frames = BigLong(pheader->ofs_frames);
2064 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2066 Con_Printf("%s has no geometry\n", loadmodel->name);
2069 if (pheader->num_frames < 1)
2071 Con_Printf("%s has no frames\n", loadmodel->name);
2075 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2076 loadmodel->DrawSky = NULL;
2077 loadmodel->DrawAddWaterPlanes = NULL;
2078 loadmodel->Draw = R_Q1BSP_Draw;
2079 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2080 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2081 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2082 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2083 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2084 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2085 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2086 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2087 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2088 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2089 loadmodel->PointSuperContents = NULL;
2092 for (i = 0;i < 3;i++)
2094 loadmodel->normalmins[i] = pheader->mins[i];
2095 loadmodel->normalmaxs[i] = pheader->maxs[i];
2096 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2097 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2098 loadmodel->rotatedmins[i] = -pheader->allradius;
2099 loadmodel->rotatedmaxs[i] = pheader->allradius;
2101 loadmodel->radius = pheader->allradius;
2102 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2104 // load external .skin files if present
2105 skinfiles = Mod_LoadSkinFiles();
2106 if (loadmodel->numskins < 1)
2107 loadmodel->numskins = 1;
2112 // gather combined statistics from the meshes
2113 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2114 for (i = 0;i < (int)pheader->num_meshs;i++)
2116 int numverts = BigLong(dpmmesh->num_verts);
2117 meshvertices += numverts;
2118 meshtriangles += BigLong(dpmmesh->num_tris);
2122 loadmodel->numframes = pheader->num_frames;
2123 loadmodel->num_bones = pheader->num_bones;
2124 loadmodel->num_poses = loadmodel->numframes;
2125 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2126 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2127 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2128 // do most allocations as one merged chunk
2129 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));
2130 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2131 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2132 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2133 loadmodel->surfmesh.num_vertices = meshvertices;
2134 loadmodel->surfmesh.num_triangles = meshtriangles;
2135 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2136 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2137 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2138 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2139 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2140 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2141 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2142 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
2143 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
2144 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
2145 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2146 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2147 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2148 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2149 if (meshvertices <= 65536)
2150 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2152 for (i = 0;i < loadmodel->numskins;i++)
2154 loadmodel->skinscenes[i].firstframe = i;
2155 loadmodel->skinscenes[i].framecount = 1;
2156 loadmodel->skinscenes[i].loop = true;
2157 loadmodel->skinscenes[i].framerate = 10;
2160 // load the bone info
2161 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2162 for (i = 0;i < loadmodel->num_bones;i++)
2164 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2165 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2166 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2167 if (loadmodel->data_bones[i].parent >= i)
2168 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2172 frame = (dpmframe_t *) (pbase + pheader->ofs_frames);
2173 for (i = 0;i < loadmodel->numframes;i++)
2176 memcpy(loadmodel->animscenes[i].name, frame->name, sizeof(frame->name));
2177 loadmodel->animscenes[i].firstframe = i;
2178 loadmodel->animscenes[i].framecount = 1;
2179 loadmodel->animscenes[i].loop = true;
2180 loadmodel->animscenes[i].framerate = 10;
2181 // load the bone poses for this frame
2182 poses = (float *) (pbase + BigLong(frame->ofs_bonepositions));
2183 for (j = 0;j < loadmodel->num_bones*12;j++)
2184 loadmodel->data_poses[i * loadmodel->num_bones*12 + j] = BigFloat(poses[j]);
2185 // stuff not processed here: mins, maxs, yawradius, allradius
2189 // load the meshes now
2190 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2193 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2194 // (converting from weight-blending skeletal animation to
2195 // deformation-based skeletal animation)
2196 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2197 for (i = 0;i < loadmodel->num_bones;i++)
2199 const float *m = loadmodel->data_poses + i * 12;
2200 if (loadmodel->data_bones[i].parent >= 0)
2201 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2203 for (k = 0;k < 12;k++)
2204 bonepose[12*i+k] = m[k];
2206 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2208 const int *inelements;
2210 const float *intexcoord;
2211 msurface_t *surface;
2213 loadmodel->sortedmodelsurfaces[i] = i;
2214 surface = loadmodel->data_surfaces + i;
2215 surface->texture = loadmodel->data_textures + i;
2216 surface->num_firsttriangle = meshtriangles;
2217 surface->num_triangles = BigLong(dpmmesh->num_tris);
2218 surface->num_firstvertex = meshvertices;
2219 surface->num_vertices = BigLong(dpmmesh->num_verts);
2220 meshvertices += surface->num_vertices;
2221 meshtriangles += surface->num_triangles;
2223 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2224 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2225 for (j = 0;j < surface->num_triangles;j++)
2227 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2228 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2229 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2230 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2235 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2236 for (j = 0;j < surface->num_vertices*2;j++)
2237 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2239 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2240 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2244 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2245 data += sizeof(dpmvertex_t);
2246 for (k = 0;k < numweights;k++)
2248 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2249 int boneindex = BigLong(vert->bonenum);
2250 const float *m = bonepose + 12 * boneindex;
2251 float influence = BigFloat(vert->influence);
2252 float relativeorigin[3], relativenormal[3];
2253 relativeorigin[0] = BigFloat(vert->origin[0]);
2254 relativeorigin[1] = BigFloat(vert->origin[1]);
2255 relativeorigin[2] = BigFloat(vert->origin[2]);
2256 relativenormal[0] = BigFloat(vert->normal[0]);
2257 relativenormal[1] = BigFloat(vert->normal[1]);
2258 relativenormal[2] = BigFloat(vert->normal[2]);
2259 // blend the vertex bone weights into the base mesh
2260 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2261 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2262 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2263 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2264 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2265 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2268 // store the first (and often only) weight
2269 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = influence;
2270 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
2274 // sort the new weight into this vertex's weight table
2275 // (which only accepts up to 4 bones per vertex)
2276 for (l = 0;l < 4;l++)
2278 if (loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] < influence)
2280 // move weaker influence weights out of the way first
2282 for (l2 = 3;l2 > l;l2--)
2284 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2-1];
2285 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2-1];
2287 // store the new weight
2288 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] = influence;
2289 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l] = boneindex;
2294 data += sizeof(dpmbonevert_t);
2297 for (l = 0;l < 4;l++)
2298 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l];
2299 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2301 float f = 1.0f / sum;
2302 for (l = 0;l < 4;l++)
2303 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] *= f;
2307 // since dpm models do not have named sections, reuse their shader name as the section name
2308 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2310 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2313 Mod_FreeSkinFiles(skinfiles);
2314 Mod_MakeSortedSurfaces(loadmodel);
2316 // compute all the mesh information that was not loaded from the file
2317 if (loadmodel->surfmesh.data_element3s)
2318 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2319 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2320 Mod_BuildBaseBonePoses();
2321 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);
2322 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2324 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2327 // no idea why PSK/PSA files contain weird quaternions but they do...
2328 #define PSKQUATNEGATIONS
2329 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2331 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2332 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2333 fs_offset_t filesize;
2338 pskboneinfo_t *bones;
2339 pskrawweights_t *rawweights;
2340 pskboneinfo_t *animbones;
2341 pskaniminfo_t *anims;
2342 pskanimkeys_t *animkeys;
2343 void *animfilebuffer, *animbuffer, *animbufferend;
2344 unsigned char *data;
2346 skinfile_t *skinfiles;
2347 char animname[MAX_QPATH];
2350 pchunk = (pskchunk_t *)buffer;
2351 if (strcmp(pchunk->id, "ACTRHEAD"))
2352 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2354 loadmodel->modeldatatypestring = "PSK";
2356 loadmodel->type = mod_alias;
2357 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2358 loadmodel->DrawSky = NULL;
2359 loadmodel->DrawAddWaterPlanes = NULL;
2360 loadmodel->Draw = R_Q1BSP_Draw;
2361 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2362 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2363 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2364 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2365 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2366 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2367 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2368 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2369 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2370 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2371 loadmodel->PointSuperContents = NULL;
2372 loadmodel->synctype = ST_RAND;
2374 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2375 strlcat(animname, ".psa", sizeof(animname));
2376 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2377 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2378 if (animbuffer == NULL)
2379 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2398 while (buffer < bufferend)
2400 pchunk = (pskchunk_t *)buffer;
2401 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2402 version = LittleLong(pchunk->version);
2403 recordsize = LittleLong(pchunk->recordsize);
2404 numrecords = LittleLong(pchunk->numrecords);
2405 if (developer_extra.integer)
2406 Con_DPrintf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2407 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2408 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);
2409 if (!strcmp(pchunk->id, "ACTRHEAD"))
2413 else if (!strcmp(pchunk->id, "PNTS0000"))
2416 if (recordsize != sizeof(*p))
2417 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2418 // byteswap in place and keep the pointer
2419 numpnts = numrecords;
2420 pnts = (pskpnts_t *)buffer;
2421 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2423 p->origin[0] = LittleFloat(p->origin[0]);
2424 p->origin[1] = LittleFloat(p->origin[1]);
2425 p->origin[2] = LittleFloat(p->origin[2]);
2429 else if (!strcmp(pchunk->id, "VTXW0000"))
2432 if (recordsize != sizeof(*p))
2433 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2434 // byteswap in place and keep the pointer
2435 numvtxw = numrecords;
2436 vtxw = (pskvtxw_t *)buffer;
2437 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2439 p->pntsindex = LittleShort(p->pntsindex);
2440 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2441 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2442 if (p->pntsindex >= numpnts)
2444 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2450 else if (!strcmp(pchunk->id, "FACE0000"))
2453 if (recordsize != sizeof(*p))
2454 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2455 // byteswap in place and keep the pointer
2456 numfaces = numrecords;
2457 faces = (pskface_t *)buffer;
2458 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2460 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2461 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2462 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2463 p->group = LittleLong(p->group);
2464 if (p->vtxwindex[0] >= numvtxw)
2466 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2467 p->vtxwindex[0] = 0;
2469 if (p->vtxwindex[1] >= numvtxw)
2471 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2472 p->vtxwindex[1] = 0;
2474 if (p->vtxwindex[2] >= numvtxw)
2476 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2477 p->vtxwindex[2] = 0;
2482 else if (!strcmp(pchunk->id, "MATT0000"))
2485 if (recordsize != sizeof(*p))
2486 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2487 // byteswap in place and keep the pointer
2488 nummatts = numrecords;
2489 matts = (pskmatt_t *)buffer;
2490 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2496 else if (!strcmp(pchunk->id, "REFSKELT"))
2499 if (recordsize != sizeof(*p))
2500 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2501 // byteswap in place and keep the pointer
2502 numbones = numrecords;
2503 bones = (pskboneinfo_t *)buffer;
2504 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2506 p->numchildren = LittleLong(p->numchildren);
2507 p->parent = LittleLong(p->parent);
2508 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2509 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2510 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2511 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2512 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2513 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2514 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2515 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2516 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2517 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2518 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2519 #ifdef PSKQUATNEGATIONS
2522 p->basepose.quat[0] *= -1;
2523 p->basepose.quat[1] *= -1;
2524 p->basepose.quat[2] *= -1;
2528 p->basepose.quat[0] *= 1;
2529 p->basepose.quat[1] *= -1;
2530 p->basepose.quat[2] *= 1;
2533 if (p->parent < 0 || p->parent >= numbones)
2535 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2541 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2544 if (recordsize != sizeof(*p))
2545 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2546 // byteswap in place and keep the pointer
2547 numrawweights = numrecords;
2548 rawweights = (pskrawweights_t *)buffer;
2549 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2551 p->weight = LittleFloat(p->weight);
2552 p->pntsindex = LittleLong(p->pntsindex);
2553 p->boneindex = LittleLong(p->boneindex);
2554 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2556 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2559 if (p->boneindex < 0 || p->boneindex >= numbones)
2561 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2569 while (animbuffer < animbufferend)
2571 pchunk = (pskchunk_t *)animbuffer;
2572 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2573 version = LittleLong(pchunk->version);
2574 recordsize = LittleLong(pchunk->recordsize);
2575 numrecords = LittleLong(pchunk->numrecords);
2576 if (developer_extra.integer)
2577 Con_DPrintf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2578 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2579 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);
2580 if (!strcmp(pchunk->id, "ANIMHEAD"))
2584 else if (!strcmp(pchunk->id, "BONENAMES"))
2587 if (recordsize != sizeof(*p))
2588 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2589 // byteswap in place and keep the pointer
2590 numanimbones = numrecords;
2591 animbones = (pskboneinfo_t *)animbuffer;
2592 // NOTE: supposedly psa does not need to match the psk model, the
2593 // bones missing from the psa would simply use their base
2594 // positions from the psk, but this is hard for me to implement
2595 // and people can easily make animations that match.
2596 if (numanimbones != numbones)
2597 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2598 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2600 p->numchildren = LittleLong(p->numchildren);
2601 p->parent = LittleLong(p->parent);
2602 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2603 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2604 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2605 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2606 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2607 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2608 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2609 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2610 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2611 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2612 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2613 #ifdef PSKQUATNEGATIONS
2616 p->basepose.quat[0] *= -1;
2617 p->basepose.quat[1] *= -1;
2618 p->basepose.quat[2] *= -1;
2622 p->basepose.quat[0] *= 1;
2623 p->basepose.quat[1] *= -1;
2624 p->basepose.quat[2] *= 1;
2627 if (p->parent < 0 || p->parent >= numanimbones)
2629 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2632 // check that bones are the same as in the base
2633 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2634 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2638 else if (!strcmp(pchunk->id, "ANIMINFO"))
2641 if (recordsize != sizeof(*p))
2642 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2643 // byteswap in place and keep the pointer
2644 numanims = numrecords;
2645 anims = (pskaniminfo_t *)animbuffer;
2646 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2648 p->numbones = LittleLong(p->numbones);
2649 p->playtime = LittleFloat(p->playtime);
2650 p->fps = LittleFloat(p->fps);
2651 p->firstframe = LittleLong(p->firstframe);
2652 p->numframes = LittleLong(p->numframes);
2653 if (p->numbones != numbones)
2654 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2658 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2661 if (recordsize != sizeof(*p))
2662 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2663 numanimkeys = numrecords;
2664 animkeys = (pskanimkeys_t *)animbuffer;
2665 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2667 p->origin[0] = LittleFloat(p->origin[0]);
2668 p->origin[1] = LittleFloat(p->origin[1]);
2669 p->origin[2] = LittleFloat(p->origin[2]);
2670 p->quat[0] = LittleFloat(p->quat[0]);
2671 p->quat[1] = LittleFloat(p->quat[1]);
2672 p->quat[2] = LittleFloat(p->quat[2]);
2673 p->quat[3] = LittleFloat(p->quat[3]);
2674 p->frametime = LittleFloat(p->frametime);
2675 #ifdef PSKQUATNEGATIONS
2676 if (index % numbones)
2691 // TODO: allocate bonepose stuff
2694 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2697 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2698 Host_Error("%s: missing required chunks", loadmodel->name);
2700 loadmodel->numframes = 0;
2701 for (index = 0;index < numanims;index++)
2702 loadmodel->numframes += anims[index].numframes;
2704 if (numanimkeys != numbones * loadmodel->numframes)
2705 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2707 meshvertices = numvtxw;
2708 meshtriangles = numfaces;
2710 // load external .skin files if present
2711 skinfiles = Mod_LoadSkinFiles();
2712 if (loadmodel->numskins < 1)
2713 loadmodel->numskins = 1;
2714 loadmodel->num_bones = numbones;
2715 loadmodel->num_poses = loadmodel->numframes;
2716 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2717 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2718 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2719 loadmodel->surfmesh.num_vertices = meshvertices;
2720 loadmodel->surfmesh.num_triangles = meshtriangles;
2721 // do most allocations as one merged chunk
2722 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);
2723 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2724 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2725 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2726 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2727 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2728 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2729 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2730 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2731 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2732 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2733 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2734 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += loadmodel->surfmesh.num_vertices * sizeof(int[4]);
2735 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[4]);
2736 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
2737 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2738 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2739 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2740 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2741 if (loadmodel->surfmesh.num_vertices <= 65536)
2742 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2744 for (i = 0;i < loadmodel->numskins;i++)
2746 loadmodel->skinscenes[i].firstframe = i;
2747 loadmodel->skinscenes[i].framecount = 1;
2748 loadmodel->skinscenes[i].loop = true;
2749 loadmodel->skinscenes[i].framerate = 10;
2753 for (index = 0, i = 0;index < nummatts;index++)
2755 // since psk models do not have named sections, reuse their shader name as the section name
2756 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2757 loadmodel->sortedmodelsurfaces[index] = index;
2758 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2759 loadmodel->data_surfaces[index].num_firstvertex = 0;
2760 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2763 // copy over the vertex locations and texcoords
2764 for (index = 0;index < numvtxw;index++)
2766 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2767 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2768 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2769 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2770 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2773 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2774 for (index = 0;index < numfaces;index++)
2775 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2776 for (index = 0, i = 0;index < nummatts;index++)
2778 loadmodel->data_surfaces[index].num_firsttriangle = i;
2779 i += loadmodel->data_surfaces[index].num_triangles;
2780 loadmodel->data_surfaces[index].num_triangles = 0;
2782 for (index = 0;index < numfaces;index++)
2784 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2785 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2786 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2787 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2790 // copy over the bones
2791 for (index = 0;index < numbones;index++)
2793 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2794 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2795 if (loadmodel->data_bones[index].parent >= index)
2796 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2799 // sort the psk point weights into the vertex weight tables
2800 // (which only accept up to 4 bones per vertex)
2801 for (index = 0;index < numvtxw;index++)
2805 for (j = 0;j < numrawweights;j++)
2807 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2809 int boneindex = rawweights[j].boneindex;
2810 float influence = rawweights[j].weight;
2811 for (l = 0;l < 4;l++)
2813 if (loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] < influence)
2815 // move lower influence weights out of the way first
2817 for (l2 = 3;l2 > l;l2--)
2819 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2-1];
2820 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2-1];
2822 // store the new weight
2823 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] = influence;
2824 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l] = boneindex;
2831 for (l = 0;l < 4;l++)
2832 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l];
2833 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2835 float f = 1.0f / sum;
2836 for (l = 0;l < 4;l++)
2837 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] *= f;
2841 // set up the animscenes based on the anims
2842 for (index = 0, i = 0;index < numanims;index++)
2844 for (j = 0;j < anims[index].numframes;j++, i++)
2846 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2847 loadmodel->animscenes[i].firstframe = i;
2848 loadmodel->animscenes[i].framecount = 1;
2849 loadmodel->animscenes[i].loop = true;
2850 loadmodel->animscenes[i].framerate = 10;
2854 // load the poses from the animkeys
2855 for (index = 0;index < numanimkeys;index++)
2857 pskanimkeys_t *k = animkeys + index;
2859 Matrix4x4_FromOriginQuat(&matrix, k->origin[0], k->origin[1], k->origin[2], k->quat[0], k->quat[1], k->quat[2], k->quat[3]);
2860 Matrix4x4_ToArray12FloatD3D(&matrix, loadmodel->data_poses + index*12);
2862 Mod_FreeSkinFiles(skinfiles);
2863 Mem_Free(animfilebuffer);
2864 Mod_MakeSortedSurfaces(loadmodel);
2866 // compute all the mesh information that was not loaded from the file
2867 // TODO: honor smoothing groups somehow?
2868 if (loadmodel->surfmesh.data_element3s)
2869 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2870 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2871 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2872 Mod_BuildBaseBonePoses();
2873 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2874 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);
2875 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2876 Mod_Alias_CalculateBoundingBox();
2878 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;