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, 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 // interpolate matrices and concatenate them to their parents
60 for (i = 0;i < model->num_bones;i++)
62 for (k = 0;k < 12;k++)
64 VectorClear(desiredscale);
65 for (blends = 0;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++)
67 matrix = model->data_poses + (frameblend[blends].subframe * model->num_bones + i) * 12;
68 for (k = 0;k < 12;k++)
69 m[k] += matrix[k] * frameblend[blends].lerp;
70 desiredscale[0] += frameblend[blends].lerp * VectorLength(matrix );
71 desiredscale[1] += frameblend[blends].lerp * VectorLength(matrix + 4);
72 desiredscale[2] += frameblend[blends].lerp * VectorLength(matrix + 8);
75 VectorNormalize(m + 4);
76 VectorNormalize(m + 8);
77 VectorScale(m , desiredscale[0], m );
78 VectorScale(m + 4, desiredscale[1], m + 4);
79 VectorScale(m + 8, desiredscale[2], m + 8);
80 if (i == r_skeletal_debugbone.integer)
81 m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
82 m[3] *= r_skeletal_debugtranslatex.value;
83 m[7] *= r_skeletal_debugtranslatey.value;
84 m[11] *= r_skeletal_debugtranslatez.value;
85 if (model->data_bones[i].parent >= 0)
86 R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
88 for (k = 0;k < 12;k++)
89 bonepose[i][k] = m[k];
90 // create a relative deformation matrix to describe displacement
91 // from the base mesh, which is used by the actual weighting
92 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]);
94 // blend the vertex bone weights
95 // 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)
96 // special case for the first bone because it avoids the need to memset the arrays before filling
99 const float *v = model->surfmesh.data_vertex3f;
100 const int *wi = model->surfmesh.data_vertexweightindex4i;
101 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
102 memset(vertex3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
103 for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, wi += 4, wf += 4, vertex3f += 3)
107 const float *m = boneposerelative[wi[0]];
108 vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
109 vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
110 vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
114 const float *m = boneposerelative[wi[0]];
116 vertex3f[0] = f * (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
117 vertex3f[1] = f * (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
118 vertex3f[2] = f * (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
119 for (k = 1;k < 4 && wf[k];k++)
121 const float *m = boneposerelative[wi[k]];
123 vertex3f[0] += f * (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
124 vertex3f[1] += f * (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
125 vertex3f[2] += f * (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
132 const float *n = model->surfmesh.data_normal3f;
133 const int *wi = model->surfmesh.data_vertexweightindex4i;
134 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
135 memset(normal3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
136 for (i = 0;i < model->surfmesh.num_vertices;i++, n += 3, wi += 4, wf += 4, normal3f += 3)
140 const float *m = boneposerelative[wi[0]];
141 normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
142 normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
143 normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
147 const float *m = boneposerelative[wi[0]];
149 normal3f[0] = f * (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
150 normal3f[1] = f * (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
151 normal3f[2] = f * (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
152 for (k = 1;k < 4 && wf[k];k++)
154 const float *m = boneposerelative[wi[k]];
156 normal3f[0] += f * (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
157 normal3f[1] += f * (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
158 normal3f[2] += f * (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
165 const float *sv = model->surfmesh.data_svector3f;
166 const int *wi = model->surfmesh.data_vertexweightindex4i;
167 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
168 memset(svector3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
169 for (i = 0;i < model->surfmesh.num_vertices;i++, sv += 3, wi += 4, wf += 4, svector3f += 3)
173 const float *m = boneposerelative[wi[0]];
174 svector3f[0] = (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
175 svector3f[1] = (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
176 svector3f[2] = (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
180 const float *m = boneposerelative[wi[0]];
182 svector3f[0] = f * (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
183 svector3f[1] = f * (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
184 svector3f[2] = f * (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
185 for (k = 1;k < 4 && wf[k];k++)
187 const float *m = boneposerelative[wi[k]];
189 svector3f[0] += f * (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
190 svector3f[1] += f * (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
191 svector3f[2] += f * (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
198 const float *tv = model->surfmesh.data_tvector3f;
199 const int *wi = model->surfmesh.data_vertexweightindex4i;
200 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
201 memset(tvector3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
202 for (i = 0;i < model->surfmesh.num_vertices;i++, tv += 3, wi += 4, wf += 4, tvector3f += 3)
206 const float *m = boneposerelative[wi[0]];
207 tvector3f[0] = (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
208 tvector3f[1] = (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
209 tvector3f[2] = (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
213 const float *m = boneposerelative[wi[0]];
215 tvector3f[0] = f * (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
216 tvector3f[1] = f * (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
217 tvector3f[2] = f * (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
218 for (k = 1;k < 4 && wf[k];k++)
220 const float *m = boneposerelative[wi[k]];
222 tvector3f[0] += f * (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
223 tvector3f[1] += f * (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
224 tvector3f[2] += f * (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
231 void Mod_MD3_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
234 int i, numblends, blendnum;
235 int numverts = model->surfmesh.num_vertices;
237 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
239 //VectorMA(translate, model->surfmesh.num_morphmdlframetranslate, frameblend[blendnum].lerp, translate);
240 if (frameblend[blendnum].lerp > 0)
241 numblends = blendnum + 1;
243 // special case for the first blend because it avoids some adds and the need to memset the arrays first
244 for (blendnum = 0;blendnum < numblends;blendnum++)
246 const md3vertex_t *verts = model->surfmesh.data_morphmd3vertex + numverts * frameblend[blendnum].subframe;
249 float scale = frameblend[blendnum].lerp * (1.0f / 64.0f);
252 for (i = 0;i < numverts;i++)
254 vertex3f[i * 3 + 0] = verts[i].origin[0] * scale;
255 vertex3f[i * 3 + 1] = verts[i].origin[1] * scale;
256 vertex3f[i * 3 + 2] = verts[i].origin[2] * scale;
261 for (i = 0;i < numverts;i++)
263 vertex3f[i * 3 + 0] += verts[i].origin[0] * scale;
264 vertex3f[i * 3 + 1] += verts[i].origin[1] * scale;
265 vertex3f[i * 3 + 2] += verts[i].origin[2] * scale;
269 // the yaw and pitch stored in md3 models are 8bit quantized angles
270 // (0-255), and as such a lookup table is very well suited to
271 // decoding them, and since cosine is equivilant to sine with an
272 // extra 45 degree rotation, this uses one lookup table for both
273 // sine and cosine with a +64 bias to get cosine.
276 float lerp = frameblend[blendnum].lerp;
279 for (i = 0;i < numverts;i++)
281 normal3f[i * 3 + 0] = mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
282 normal3f[i * 3 + 1] = mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
283 normal3f[i * 3 + 2] = mod_md3_sin[verts[i].pitch + 64] * lerp;
288 for (i = 0;i < numverts;i++)
290 normal3f[i * 3 + 0] += mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
291 normal3f[i * 3 + 1] += mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
292 normal3f[i * 3 + 2] += mod_md3_sin[verts[i].pitch + 64] * lerp;
298 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
299 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
302 for (i = 0;i < numverts;i++, texvecvert++)
304 VectorScale(texvecvert->svec, f, svector3f + i*3);
305 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
310 for (i = 0;i < numverts;i++, texvecvert++)
312 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
313 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
320 void Mod_MDL_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
323 int i, numblends, blendnum;
324 int numverts = model->surfmesh.num_vertices;
326 VectorClear(translate);
328 // blend the frame translates to avoid redundantly doing so on each vertex
329 // (a bit of a brain twister but it works)
330 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
332 if (model->surfmesh.data_morphmd2framesize6f)
333 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6 + 3, translate);
335 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.num_morphmdlframetranslate, translate);
336 if (frameblend[blendnum].lerp > 0)
337 numblends = blendnum + 1;
339 // special case for the first blend because it avoids some adds and the need to memset the arrays first
340 for (blendnum = 0;blendnum < numblends;blendnum++)
342 const trivertx_t *verts = model->surfmesh.data_morphmdlvertex + numverts * frameblend[blendnum].subframe;
346 if (model->surfmesh.data_morphmd2framesize6f)
347 VectorScale(model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6, frameblend[blendnum].lerp, scale);
349 VectorScale(model->surfmesh.num_morphmdlframescale, frameblend[blendnum].lerp, scale);
352 for (i = 0;i < numverts;i++)
354 vertex3f[i * 3 + 0] = translate[0] + verts[i].v[0] * scale[0];
355 vertex3f[i * 3 + 1] = translate[1] + verts[i].v[1] * scale[1];
356 vertex3f[i * 3 + 2] = translate[2] + verts[i].v[2] * scale[2];
361 for (i = 0;i < numverts;i++)
363 vertex3f[i * 3 + 0] += verts[i].v[0] * scale[0];
364 vertex3f[i * 3 + 1] += verts[i].v[1] * scale[1];
365 vertex3f[i * 3 + 2] += verts[i].v[2] * scale[2];
369 // the vertex normals in mdl models are an index into a table of
370 // 162 unique values, this very crude quantization reduces the
371 // vertex normal to only one byte, which saves a lot of space but
372 // also makes lighting pretty coarse
375 float lerp = frameblend[blendnum].lerp;
378 for (i = 0;i < numverts;i++)
380 const float *vn = m_bytenormals[verts[i].lightnormalindex];
381 VectorScale(vn, lerp, normal3f + i*3);
386 for (i = 0;i < numverts;i++)
388 const float *vn = m_bytenormals[verts[i].lightnormalindex];
389 VectorMA(normal3f + i*3, lerp, vn, normal3f + i*3);
395 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
396 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
399 for (i = 0;i < numverts;i++, texvecvert++)
401 VectorScale(texvecvert->svec, f, svector3f + i*3);
402 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
407 for (i = 0;i < numverts;i++, texvecvert++)
409 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
410 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
417 int Mod_Alias_GetTagMatrix(const dp_model_t *model, int poseframe, int tagindex, matrix4x4_t *outmatrix)
419 const float *boneframe;
420 float tempbonematrix[12], bonematrix[12];
421 *outmatrix = identitymatrix;
422 if (model->num_bones)
424 if (tagindex < 0 || tagindex >= model->num_bones)
426 if (poseframe >= model->num_poses)
428 boneframe = model->data_poses + poseframe * model->num_bones * 12;
429 memcpy(bonematrix, boneframe + tagindex * 12, sizeof(float[12]));
430 while (model->data_bones[tagindex].parent >= 0)
432 memcpy(tempbonematrix, bonematrix, sizeof(float[12]));
433 R_ConcatTransforms(boneframe + model->data_bones[tagindex].parent * 12, tempbonematrix, bonematrix);
434 tagindex = model->data_bones[tagindex].parent;
436 Matrix4x4_FromArray12FloatD3D(outmatrix, bonematrix);
438 else if (model->num_tags)
440 if (tagindex < 0 || tagindex >= model->num_tags)
442 if (poseframe >= model->num_tagframes)
444 Matrix4x4_FromArray12FloatGL(outmatrix, model->data_tags[poseframe * model->num_tags + tagindex].matrixgl);
447 if(!mod_alias_supporttagscale.integer)
448 Matrix4x4_Normalize3(outmatrix, outmatrix);
453 int Mod_Alias_GetExtendedTagInfoForIndex(const dp_model_t *model, unsigned int skin, int poseframe, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
455 const float *boneframe;
457 if(skin >= (unsigned int)model->numskins)
460 if (model->num_bones)
462 if(tagindex >= model->num_bones || tagindex < 0)
464 if (poseframe >= model->num_poses)
467 boneframe = model->data_poses + poseframe * model->num_bones * 12;
468 *parentindex = model->data_bones[tagindex].parent;
469 *tagname = model->data_bones[tagindex].name;
470 Matrix4x4_FromArray12FloatD3D(tag_localmatrix, boneframe + tagindex * 12);
476 if(tagindex >= model->num_tags || tagindex < 0)
478 if (poseframe >= model->num_tagframes)
480 *tagname = model->data_tags[tagindex].name;
481 Matrix4x4_FromArray12FloatGL(tag_localmatrix, model->data_tags[poseframe * model->num_tags + tagindex].matrixgl);
488 int Mod_Alias_GetTagIndexForName(const dp_model_t *model, unsigned int skin, const char *tagname)
491 if(skin >= (unsigned int)model->numskins)
493 if (model->num_bones)
494 for (i = 0;i < model->num_bones;i++)
495 if (!strcasecmp(tagname, model->data_bones[i].name))
498 for (i = 0;i < model->num_tags;i++)
499 if (!strcasecmp(tagname, model->data_tags[i].name))
504 static void Mod_BuildBaseBonePoses(void)
509 float *in12f = loadmodel->data_poses;
511 float *outinv12f = loadmodel->data_baseboneposeinverse;
512 if (!loadmodel->num_bones)
514 out12f = basebonepose = (float *) Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(float[12]));
515 for (i = 0;i < loadmodel->num_bones;i++, in12f += 12, out12f += 12, outinv12f += 12)
517 if (loadmodel->data_bones[i].parent >= 0)
518 R_ConcatTransforms(basebonepose + 12 * loadmodel->data_bones[i].parent, in12f, out12f);
520 for (k = 0;k < 12;k++)
521 out12f[k] = in12f[k];
525 // we only support uniform scaling, so assume the first row is enough
526 // (note the lack of sqrt here, because we're trying to undo the scaling,
527 // this means multiplying by the inverse scale twice - squaring it, which
528 // makes the sqrt a waste of time)
529 scale = 1.0 / (out12f[ 0] * out12f[ 0] + out12f[ 1] * out12f[ 1] + out12f[ 2] * out12f[ 2]);
531 // invert the rotation by transposing and multiplying by the squared
532 // recipricol of the input matrix scale as described above
533 outinv12f[ 0] = (float)(out12f[ 0] * scale);
534 outinv12f[ 1] = (float)(out12f[ 4] * scale);
535 outinv12f[ 2] = (float)(out12f[ 8] * scale);
536 outinv12f[ 4] = (float)(out12f[ 1] * scale);
537 outinv12f[ 5] = (float)(out12f[ 5] * scale);
538 outinv12f[ 6] = (float)(out12f[ 9] * scale);
539 outinv12f[ 8] = (float)(out12f[ 2] * scale);
540 outinv12f[ 9] = (float)(out12f[ 6] * scale);
541 outinv12f[10] = (float)(out12f[10] * scale);
543 // invert the translate
544 outinv12f[ 3] = -(out12f[ 3] * outinv12f[ 0] + out12f[ 7] * outinv12f[ 1] + out12f[11] * outinv12f[ 2]);
545 outinv12f[ 7] = -(out12f[ 3] * outinv12f[ 4] + out12f[ 7] * outinv12f[ 5] + out12f[11] * outinv12f[ 6]);
546 outinv12f[11] = -(out12f[ 3] * outinv12f[ 8] + out12f[ 7] * outinv12f[ 9] + out12f[11] * outinv12f[10]);
548 Mem_Free(basebonepose);
551 static void Mod_Alias_CalculateBoundingBox(void)
554 qboolean firstvertex = true;
555 float dist, yawradius, radius;
558 frameblend_t frameblend[MAX_FRAMEBLENDS];
559 memset(frameblend, 0, sizeof(frameblend));
560 frameblend[0].lerp = 1;
561 vertex3f = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
562 VectorClear(loadmodel->normalmins);
563 VectorClear(loadmodel->normalmaxs);
566 for (frameblend[0].subframe = 0;frameblend[0].subframe < loadmodel->num_poses;frameblend[0].subframe++)
568 loadmodel->AnimateVertices(loadmodel, frameblend, vertex3f, NULL, NULL, NULL);
569 for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
574 VectorCopy(v, loadmodel->normalmins);
575 VectorCopy(v, loadmodel->normalmaxs);
579 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
580 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
581 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
582 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
583 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
584 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
586 dist = v[0] * v[0] + v[1] * v[1];
587 if (yawradius < dist)
596 radius = sqrt(radius);
597 yawradius = sqrt(yawradius);
598 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
599 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
600 loadmodel->yawmins[2] = loadmodel->normalmins[2];
601 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
602 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
603 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
604 loadmodel->radius = radius;
605 loadmodel->radius2 = radius * radius;
608 static void Mod_Alias_MorphMesh_CompileFrames(void)
611 frameblend_t frameblend[MAX_FRAMEBLENDS];
612 unsigned char *datapointer;
613 memset(frameblend, 0, sizeof(frameblend));
614 frameblend[0].lerp = 1;
615 datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
616 loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
617 loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
618 loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
619 loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
620 loadmodel->surfmesh.data_morphtexvecvertex = (texvecvertex_t *)datapointer;datapointer += loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices * sizeof(texvecvertex_t);
621 // 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)
622 for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
624 frameblend[0].subframe = i;
625 loadmodel->AnimateVertices(loadmodel, frameblend, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
626 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);
627 // encode the svector and tvector in 3 byte format for permanent storage
628 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
630 VectorScaleCast(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
631 VectorScaleCast(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
636 static void Mod_MDLMD2MD3_TraceLine(dp_model_t *model, int frame, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask)
639 float segmentmins[3], segmentmaxs[3];
640 frameblend_t frameblend[MAX_FRAMEBLENDS];
642 static int maxvertices = 0;
643 static float *vertex3f = NULL;
644 memset(trace, 0, sizeof(*trace));
646 trace->realfraction = 1;
647 trace->hitsupercontentsmask = hitsupercontentsmask;
648 memset(frameblend, 0, sizeof(frameblend));
649 frameblend[0].subframe = frame;
650 frameblend[0].lerp = 1;
651 if (maxvertices < model->surfmesh.num_vertices)
655 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
656 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
658 segmentmins[0] = min(start[0], end[0]) - 1;
659 segmentmins[1] = min(start[1], end[1]) - 1;
660 segmentmins[2] = min(start[2], end[2]) - 1;
661 segmentmaxs[0] = max(start[0], end[0]) + 1;
662 segmentmaxs[1] = max(start[1], end[1]) + 1;
663 segmentmaxs[2] = max(start[2], end[2]) + 1;
664 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
666 model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL);
667 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);
671 static void Mod_MDLMD2MD3_TraceBox(dp_model_t *model, int frame, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask)
674 vec3_t shiftstart, shiftend;
675 float segmentmins[3], segmentmaxs[3];
676 frameblend_t frameblend[MAX_FRAMEBLENDS];
678 static int maxvertices = 0;
679 static float *vertex3f = NULL;
680 colboxbrushf_t thisbrush_start, thisbrush_end;
681 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
683 if (VectorCompare(boxmins, boxmaxs))
685 VectorAdd(start, boxmins, shiftstart);
686 VectorAdd(end, boxmins, shiftend);
687 Mod_MDLMD2MD3_TraceLine(model, frame, trace, start, end, hitsupercontentsmask);
688 VectorSubtract(trace->endpos, boxmins, trace->endpos);
692 // box trace, performed as brush trace
693 memset(trace, 0, sizeof(*trace));
695 trace->realfraction = 1;
696 trace->hitsupercontentsmask = hitsupercontentsmask;
697 memset(frameblend, 0, sizeof(frameblend));
698 frameblend[0].subframe = frame;
699 frameblend[0].lerp = 1;
700 if (maxvertices < model->surfmesh.num_vertices)
704 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
705 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
707 segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
708 segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
709 segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
710 segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
711 segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
712 segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
713 VectorAdd(start, boxmins, boxstartmins);
714 VectorAdd(start, boxmaxs, boxstartmaxs);
715 VectorAdd(end, boxmins, boxendmins);
716 VectorAdd(end, boxmaxs, boxendmaxs);
717 Collision_BrushForBox(&thisbrush_start, boxstartmins, boxstartmaxs, 0, 0, NULL);
718 Collision_BrushForBox(&thisbrush_end, boxendmins, boxendmaxs, 0, 0, NULL);
719 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
721 if (maxvertices < model->surfmesh.num_vertices)
725 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
726 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
728 model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL);
729 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);
733 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
736 for (i = 0;i < inverts;i++)
738 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
740 j = vertremap[i]; // not onseam
743 j = vertremap[i+inverts]; // onseam
749 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
751 int i, f, pose, groupframes;
753 daliasframetype_t *pframetype;
754 daliasframe_t *pinframe;
755 daliasgroup_t *group;
756 daliasinterval_t *intervals;
759 scene = loadmodel->animscenes;
760 for (f = 0;f < loadmodel->numframes;f++)
762 pframetype = (daliasframetype_t *)datapointer;
763 datapointer += sizeof(daliasframetype_t);
764 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
766 // a single frame is still treated as a group
773 group = (daliasgroup_t *)datapointer;
774 datapointer += sizeof(daliasgroup_t);
775 groupframes = LittleLong (group->numframes);
777 // intervals (time per frame)
778 intervals = (daliasinterval_t *)datapointer;
779 datapointer += sizeof(daliasinterval_t) * groupframes;
781 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
782 if (interval < 0.01f)
784 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
789 // get scene name from first frame
790 pinframe = (daliasframe_t *)datapointer;
792 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
793 scene->firstframe = pose;
794 scene->framecount = groupframes;
795 scene->framerate = 1.0f / interval;
800 for (i = 0;i < groupframes;i++)
802 pinframe = (daliasframe_t *)datapointer;
803 datapointer += sizeof(daliasframe_t);
804 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
805 datapointer += sizeof(trivertx_t) * inverts;
811 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
813 if (cls.state == ca_dedicated)
817 skinframe = R_SkinFrame_LoadMissing();
818 memset(texture, 0, sizeof(*texture));
819 texture->currentframe = texture;
820 //texture->animated = false;
821 texture->numskinframes = 1;
822 texture->skinframerate = 1;
823 texture->skinframes[0] = skinframe;
824 texture->currentskinframe = skinframe;
825 //texture->backgroundnumskinframes = 0;
826 //texture->customblendfunc[0] = 0;
827 //texture->customblendfunc[1] = 0;
828 //texture->surfaceflags = 0;
829 //texture->supercontents = 0;
830 //texture->surfaceparms = 0;
831 //texture->textureflags = 0;
833 texture->basematerialflags = MATERIALFLAG_WALL;
834 if (texture->currentskinframe->fog)
835 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
836 texture->currentmaterialflags = texture->basematerialflags;
839 static void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
842 skinfileitem_t *skinfileitem;
845 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
846 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
848 memset(skin, 0, sizeof(*skin));
850 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
852 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
853 if (!strcmp(skinfileitem->name, meshname))
855 Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
861 // don't render unmentioned meshes
862 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
863 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
868 Mod_LoadTextureFromQ3Shader(skin, shadername, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
871 #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);
872 #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);
873 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
875 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
876 float scales, scalet, interval;
880 stvert_t *pinstverts;
881 dtriangle_t *pintriangles;
882 daliasskintype_t *pinskintype;
883 daliasskingroup_t *pinskingroup;
884 daliasskininterval_t *pinskinintervals;
885 daliasframetype_t *pinframetype;
886 daliasgroup_t *pinframegroup;
887 unsigned char *datapointer, *startframes, *startskins;
888 char name[MAX_QPATH];
889 skinframe_t *tempskinframe;
890 animscene_t *tempskinscenes;
891 texture_t *tempaliasskins;
893 int *vertonseam, *vertremap;
894 skinfile_t *skinfiles;
896 datapointer = (unsigned char *)buffer;
897 pinmodel = (mdl_t *)datapointer;
898 datapointer += sizeof(mdl_t);
900 version = LittleLong (pinmodel->version);
901 if (version != ALIAS_VERSION)
902 Host_Error ("%s has wrong version number (%i should be %i)",
903 loadmodel->name, version, ALIAS_VERSION);
905 loadmodel->modeldatatypestring = "MDL";
907 loadmodel->type = mod_alias;
908 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
909 loadmodel->DrawSky = NULL;
910 loadmodel->DrawAddWaterPlanes = NULL;
911 loadmodel->Draw = R_Q1BSP_Draw;
912 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
913 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
914 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
915 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
916 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
917 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
918 loadmodel->DrawLight = R_Q1BSP_DrawLight;
919 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
920 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
921 loadmodel->PointSuperContents = NULL;
923 loadmodel->num_surfaces = 1;
924 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
925 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
926 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
927 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
928 loadmodel->sortedmodelsurfaces[0] = 0;
930 loadmodel->numskins = LittleLong(pinmodel->numskins);
931 BOUNDI(loadmodel->numskins,0,65536);
932 skinwidth = LittleLong (pinmodel->skinwidth);
933 BOUNDI(skinwidth,0,65536);
934 skinheight = LittleLong (pinmodel->skinheight);
935 BOUNDI(skinheight,0,65536);
936 numverts = LittleLong(pinmodel->numverts);
937 BOUNDI(numverts,0,65536);
938 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
939 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
940 loadmodel->numframes = LittleLong(pinmodel->numframes);
941 BOUNDI(loadmodel->numframes,0,65536);
942 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
943 BOUNDI(loadmodel->synctype,0,2);
944 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
945 i = LittleLong (pinmodel->flags);
946 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
948 for (i = 0;i < 3;i++)
950 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
951 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
954 startskins = datapointer;
956 for (i = 0;i < loadmodel->numskins;i++)
958 pinskintype = (daliasskintype_t *)datapointer;
959 datapointer += sizeof(daliasskintype_t);
960 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
964 pinskingroup = (daliasskingroup_t *)datapointer;
965 datapointer += sizeof(daliasskingroup_t);
966 groupskins = LittleLong(pinskingroup->numskins);
967 datapointer += sizeof(daliasskininterval_t) * groupskins;
970 for (j = 0;j < groupskins;j++)
972 datapointer += skinwidth * skinheight;
977 pinstverts = (stvert_t *)datapointer;
978 datapointer += sizeof(stvert_t) * numverts;
980 pintriangles = (dtriangle_t *)datapointer;
981 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
983 startframes = datapointer;
984 loadmodel->surfmesh.num_morphframes = 0;
985 for (i = 0;i < loadmodel->numframes;i++)
987 pinframetype = (daliasframetype_t *)datapointer;
988 datapointer += sizeof(daliasframetype_t);
989 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
993 pinframegroup = (daliasgroup_t *)datapointer;
994 datapointer += sizeof(daliasgroup_t);
995 groupframes = LittleLong(pinframegroup->numframes);
996 datapointer += sizeof(daliasinterval_t) * groupframes;
999 for (j = 0;j < groupframes;j++)
1001 datapointer += sizeof(daliasframe_t);
1002 datapointer += sizeof(trivertx_t) * numverts;
1003 loadmodel->surfmesh.num_morphframes++;
1006 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1008 // store texture coordinates into temporary array, they will be stored
1009 // after usage is determined (triangle data)
1010 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
1011 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
1012 vertonseam = vertremap + numverts * 2;
1014 scales = 1.0 / skinwidth;
1015 scalet = 1.0 / skinheight;
1016 for (i = 0;i < numverts;i++)
1018 vertonseam[i] = LittleLong(pinstverts[i].onseam);
1019 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
1020 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
1021 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
1022 vertst[(i+numverts)*2+1] = vertst[i*2+1];
1025 // load triangle data
1026 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1028 // read the triangle elements
1029 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1030 for (j = 0;j < 3;j++)
1031 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1032 // validate (note numverts is used because this is the original data)
1033 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1034 // now butcher the elements according to vertonseam and tri->facesfront
1035 // and then compact the vertex set to remove duplicates
1036 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1037 if (!LittleLong(pintriangles[i].facesfront)) // backface
1038 for (j = 0;j < 3;j++)
1039 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1040 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1042 // (this uses vertremap to count usage to save some memory)
1043 for (i = 0;i < numverts*2;i++)
1045 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1046 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1047 // build remapping table and compact array
1048 loadmodel->surfmesh.num_vertices = 0;
1049 for (i = 0;i < numverts*2;i++)
1053 vertremap[i] = loadmodel->surfmesh.num_vertices;
1054 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1055 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1056 loadmodel->surfmesh.num_vertices++;
1059 vertremap[i] = -1; // not used at all
1061 // remap the elements to the new vertex set
1062 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1063 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1064 // store the texture coordinates
1065 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1066 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1068 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1069 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1072 // generate ushort elements array if possible
1073 if (loadmodel->surfmesh.num_vertices <= 65536)
1074 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1075 if (loadmodel->surfmesh.data_element3s)
1076 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1077 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1080 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1081 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1082 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1083 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1084 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1085 Mod_Alias_CalculateBoundingBox();
1086 Mod_Alias_MorphMesh_CompileFrames();
1089 Mem_Free(vertremap);
1092 skinfiles = Mod_LoadSkinFiles();
1095 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1096 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1097 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1098 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1099 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1100 Mod_FreeSkinFiles(skinfiles);
1101 for (i = 0;i < loadmodel->numskins;i++)
1103 loadmodel->skinscenes[i].firstframe = i;
1104 loadmodel->skinscenes[i].framecount = 1;
1105 loadmodel->skinscenes[i].loop = true;
1106 loadmodel->skinscenes[i].framerate = 10;
1111 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1112 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1113 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1114 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1116 datapointer = startskins;
1117 for (i = 0;i < loadmodel->numskins;i++)
1119 pinskintype = (daliasskintype_t *)datapointer;
1120 datapointer += sizeof(daliasskintype_t);
1122 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1129 pinskingroup = (daliasskingroup_t *)datapointer;
1130 datapointer += sizeof(daliasskingroup_t);
1132 groupskins = LittleLong (pinskingroup->numskins);
1134 pinskinintervals = (daliasskininterval_t *)datapointer;
1135 datapointer += sizeof(daliasskininterval_t) * groupskins;
1137 interval = LittleFloat(pinskinintervals[0].interval);
1138 if (interval < 0.01f)
1140 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1145 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1146 loadmodel->skinscenes[i].firstframe = totalskins;
1147 loadmodel->skinscenes[i].framecount = groupskins;
1148 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1149 loadmodel->skinscenes[i].loop = true;
1151 for (j = 0;j < groupskins;j++)
1154 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1156 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1157 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))
1158 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));
1159 datapointer += skinwidth * skinheight;
1163 // check for skins that don't exist in the model, but do exist as external images
1164 // (this was added because yummyluv kept pestering me about support for it)
1165 // TODO: support shaders here?
1166 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)))
1168 // expand the arrays to make room
1169 tempskinscenes = loadmodel->skinscenes;
1170 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1171 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1172 Mem_Free(tempskinscenes);
1174 tempaliasskins = loadmodel->data_textures;
1175 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1176 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1177 Mem_Free(tempaliasskins);
1179 // store the info about the new skin
1180 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1181 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1182 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1183 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1184 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1185 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1187 //increase skin counts
1188 loadmodel->numskins++;
1191 // fix up the pointers since they are pointing at the old textures array
1192 // FIXME: this is a hack!
1193 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1194 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1198 surface = loadmodel->data_surfaces;
1199 surface->texture = loadmodel->data_textures;
1200 surface->num_firsttriangle = 0;
1201 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1202 surface->num_firstvertex = 0;
1203 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1205 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1208 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1210 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1211 float iskinwidth, iskinheight;
1212 unsigned char *data;
1213 msurface_t *surface;
1215 unsigned char *base, *datapointer;
1216 md2frame_t *pinframe;
1218 md2triangle_t *intri;
1219 unsigned short *inst;
1220 struct md2verthash_s
1222 struct md2verthash_s *next;
1226 *hash, **md2verthash, *md2verthashdata;
1227 skinfile_t *skinfiles;
1229 pinmodel = (md2_t *)buffer;
1230 base = (unsigned char *)buffer;
1232 version = LittleLong (pinmodel->version);
1233 if (version != MD2ALIAS_VERSION)
1234 Host_Error ("%s has wrong version number (%i should be %i)",
1235 loadmodel->name, version, MD2ALIAS_VERSION);
1237 loadmodel->modeldatatypestring = "MD2";
1239 loadmodel->type = mod_alias;
1240 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1241 loadmodel->DrawSky = NULL;
1242 loadmodel->DrawAddWaterPlanes = NULL;
1243 loadmodel->Draw = R_Q1BSP_Draw;
1244 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1245 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1246 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1247 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1248 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1249 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1250 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1251 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1252 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1253 loadmodel->PointSuperContents = NULL;
1255 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1256 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1257 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1258 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1259 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1260 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1261 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1262 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1264 end = LittleLong(pinmodel->ofs_end);
1265 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1266 Host_Error ("%s is not a valid model", loadmodel->name);
1267 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1268 Host_Error ("%s is not a valid model", loadmodel->name);
1269 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1270 Host_Error ("%s is not a valid model", loadmodel->name);
1271 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1272 Host_Error ("%s is not a valid model", loadmodel->name);
1273 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1274 Host_Error ("%s is not a valid model", loadmodel->name);
1276 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1277 numxyz = LittleLong(pinmodel->num_xyz);
1278 numst = LittleLong(pinmodel->num_st);
1279 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1280 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1281 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1282 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1283 skinwidth = LittleLong(pinmodel->skinwidth);
1284 skinheight = LittleLong(pinmodel->skinheight);
1285 iskinwidth = 1.0f / skinwidth;
1286 iskinheight = 1.0f / skinheight;
1288 loadmodel->num_surfaces = 1;
1289 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1290 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]));
1291 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1292 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1293 loadmodel->sortedmodelsurfaces[0] = 0;
1294 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1295 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1296 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1297 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1299 loadmodel->synctype = ST_RAND;
1302 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1303 skinfiles = Mod_LoadSkinFiles();
1306 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1307 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1308 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1309 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1310 Mod_FreeSkinFiles(skinfiles);
1312 else if (loadmodel->numskins)
1314 // skins found (most likely not a player model)
1315 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1316 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1317 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1318 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1319 Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
1323 // no skins (most likely a player model)
1324 loadmodel->numskins = 1;
1325 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1326 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1327 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1328 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1331 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1332 for (i = 0;i < loadmodel->numskins;i++)
1334 loadmodel->skinscenes[i].firstframe = i;
1335 loadmodel->skinscenes[i].framecount = 1;
1336 loadmodel->skinscenes[i].loop = true;
1337 loadmodel->skinscenes[i].framerate = 10;
1340 // load the triangles and stvert data
1341 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1342 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1343 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1344 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1345 // swap the triangle list
1346 loadmodel->surfmesh.num_vertices = 0;
1347 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1349 for (j = 0;j < 3;j++)
1351 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1352 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1355 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1360 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1363 hashindex = (xyz * 256 + st) & 65535;
1364 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1365 if (hash->xyz == xyz && hash->st == st)
1369 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1372 hash->next = md2verthash[hashindex];
1373 md2verthash[hashindex] = hash;
1375 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1379 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1380 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));
1381 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1382 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1383 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1386 hash = md2verthashdata + i;
1387 vertremap[i] = hash->xyz;
1388 sts = LittleShort(inst[hash->st*2+0]);
1389 stt = LittleShort(inst[hash->st*2+1]);
1390 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1392 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1396 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1397 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1400 Mem_Free(md2verthash);
1401 Mem_Free(md2verthashdata);
1403 // generate ushort elements array if possible
1404 if (loadmodel->surfmesh.num_vertices <= 65536)
1405 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1406 if (loadmodel->surfmesh.data_element3s)
1407 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1408 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1411 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1412 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1417 pinframe = (md2frame_t *)datapointer;
1418 datapointer += sizeof(md2frame_t);
1419 // store the frame scale/translate into the appropriate array
1420 for (j = 0;j < 3;j++)
1422 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1423 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1425 // convert the vertices
1426 v = (trivertx_t *)datapointer;
1427 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1428 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1429 out[k] = v[vertremap[k]];
1430 datapointer += numxyz * sizeof(trivertx_t);
1432 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1433 loadmodel->animscenes[i].firstframe = i;
1434 loadmodel->animscenes[i].framecount = 1;
1435 loadmodel->animscenes[i].framerate = 10;
1436 loadmodel->animscenes[i].loop = true;
1439 Mem_Free(vertremap);
1441 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1442 Mod_Alias_CalculateBoundingBox();
1443 Mod_Alias_MorphMesh_CompileFrames();
1445 surface = loadmodel->data_surfaces;
1446 surface->texture = loadmodel->data_textures;
1447 surface->num_firsttriangle = 0;
1448 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1449 surface->num_firstvertex = 0;
1450 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1452 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1455 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1457 int i, j, k, version, meshvertices, meshtriangles;
1458 unsigned char *data;
1459 msurface_t *surface;
1460 md3modelheader_t *pinmodel;
1461 md3frameinfo_t *pinframe;
1464 skinfile_t *skinfiles;
1466 pinmodel = (md3modelheader_t *)buffer;
1468 if (memcmp(pinmodel->identifier, "IDP3", 4))
1469 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1470 version = LittleLong (pinmodel->version);
1471 if (version != MD3VERSION)
1472 Host_Error ("%s has wrong version number (%i should be %i)",
1473 loadmodel->name, version, MD3VERSION);
1475 skinfiles = Mod_LoadSkinFiles();
1476 if (loadmodel->numskins < 1)
1477 loadmodel->numskins = 1;
1479 loadmodel->modeldatatypestring = "MD3";
1481 loadmodel->type = mod_alias;
1482 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1483 loadmodel->DrawSky = NULL;
1484 loadmodel->DrawAddWaterPlanes = NULL;
1485 loadmodel->Draw = R_Q1BSP_Draw;
1486 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1487 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1488 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1489 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1490 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1491 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1492 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1493 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1494 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1495 loadmodel->PointSuperContents = NULL;
1496 loadmodel->synctype = ST_RAND;
1497 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1498 i = LittleLong (pinmodel->flags);
1499 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1501 // set up some global info about the model
1502 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1503 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1505 // make skinscenes for the skins (no groups)
1506 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1507 for (i = 0;i < loadmodel->numskins;i++)
1509 loadmodel->skinscenes[i].firstframe = i;
1510 loadmodel->skinscenes[i].framecount = 1;
1511 loadmodel->skinscenes[i].loop = true;
1512 loadmodel->skinscenes[i].framerate = 10;
1516 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1517 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1519 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1520 loadmodel->animscenes[i].firstframe = i;
1521 loadmodel->animscenes[i].framecount = 1;
1522 loadmodel->animscenes[i].framerate = 10;
1523 loadmodel->animscenes[i].loop = true;
1527 loadmodel->num_tagframes = loadmodel->numframes;
1528 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1529 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1530 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1532 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1533 for (j = 0;j < 9;j++)
1534 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1535 for (j = 0;j < 3;j++)
1536 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1537 //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);
1543 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)))
1545 if (memcmp(pinmesh->identifier, "IDP3", 4))
1546 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1547 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1548 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1549 meshvertices += LittleLong(pinmesh->num_vertices);
1550 meshtriangles += LittleLong(pinmesh->num_triangles);
1553 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1554 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1555 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1556 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));
1557 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1558 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1559 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1560 loadmodel->surfmesh.num_vertices = meshvertices;
1561 loadmodel->surfmesh.num_triangles = meshtriangles;
1562 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1563 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1564 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1565 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1566 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1567 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1568 if (meshvertices <= 65536)
1569 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1573 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)))
1575 if (memcmp(pinmesh->identifier, "IDP3", 4))
1576 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1577 loadmodel->sortedmodelsurfaces[i] = i;
1578 surface = loadmodel->data_surfaces + i;
1579 surface->texture = loadmodel->data_textures + i;
1580 surface->num_firsttriangle = meshtriangles;
1581 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1582 surface->num_firstvertex = meshvertices;
1583 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1584 meshvertices += surface->num_vertices;
1585 meshtriangles += surface->num_triangles;
1587 for (j = 0;j < surface->num_triangles * 3;j++)
1588 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1589 for (j = 0;j < surface->num_vertices;j++)
1591 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1592 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1594 for (j = 0;j < loadmodel->numframes;j++)
1596 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1597 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1598 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1600 out->origin[0] = LittleShort(in->origin[0]);
1601 out->origin[1] = LittleShort(in->origin[1]);
1602 out->origin[2] = LittleShort(in->origin[2]);
1603 out->pitch = in->pitch;
1608 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1610 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1612 if (loadmodel->surfmesh.data_element3s)
1613 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1614 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1615 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1616 Mod_Alias_MorphMesh_CompileFrames();
1617 Mod_Alias_CalculateBoundingBox();
1618 Mod_FreeSkinFiles(skinfiles);
1619 Mod_MakeSortedSurfaces(loadmodel);
1621 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1622 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1625 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1627 zymtype1header_t *pinmodel, *pheader;
1628 unsigned char *pbase;
1629 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1630 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose;
1631 zymvertex_t *verts, *vertdata;
1635 skinfile_t *skinfiles;
1636 unsigned char *data;
1637 msurface_t *surface;
1639 pinmodel = (zymtype1header_t *)buffer;
1640 pbase = (unsigned char *)buffer;
1641 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1642 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1643 if (BigLong(pinmodel->type) != 1)
1644 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1646 loadmodel->modeldatatypestring = "ZYM";
1648 loadmodel->type = mod_alias;
1649 loadmodel->synctype = ST_RAND;
1653 pheader->type = BigLong(pinmodel->type);
1654 pheader->filesize = BigLong(pinmodel->filesize);
1655 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1656 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1657 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1658 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1659 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1660 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1661 pheader->radius = BigFloat(pinmodel->radius);
1662 pheader->numverts = BigLong(pinmodel->numverts);
1663 pheader->numtris = BigLong(pinmodel->numtris);
1664 pheader->numshaders = BigLong(pinmodel->numshaders);
1665 pheader->numbones = BigLong(pinmodel->numbones);
1666 pheader->numscenes = BigLong(pinmodel->numscenes);
1667 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1668 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1669 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1670 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1671 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1672 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1673 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1674 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1675 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1676 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1677 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1678 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1679 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1680 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1681 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1682 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1683 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1684 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1686 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1688 Con_Printf("%s has no geometry\n", loadmodel->name);
1691 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1693 Con_Printf("%s has no animations\n", loadmodel->name);
1697 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1698 loadmodel->DrawSky = NULL;
1699 loadmodel->DrawAddWaterPlanes = NULL;
1700 loadmodel->Draw = R_Q1BSP_Draw;
1701 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1702 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1703 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1704 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1705 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1706 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1707 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1708 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1709 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1710 loadmodel->PointSuperContents = NULL;
1712 loadmodel->numframes = pheader->numscenes;
1713 loadmodel->num_surfaces = pheader->numshaders;
1715 skinfiles = Mod_LoadSkinFiles();
1716 if (loadmodel->numskins < 1)
1717 loadmodel->numskins = 1;
1719 // make skinscenes for the skins (no groups)
1720 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1721 for (i = 0;i < loadmodel->numskins;i++)
1723 loadmodel->skinscenes[i].firstframe = i;
1724 loadmodel->skinscenes[i].framecount = 1;
1725 loadmodel->skinscenes[i].loop = true;
1726 loadmodel->skinscenes[i].framerate = 10;
1730 modelradius = pheader->radius;
1731 for (i = 0;i < 3;i++)
1733 loadmodel->normalmins[i] = pheader->mins[i];
1734 loadmodel->normalmaxs[i] = pheader->maxs[i];
1735 loadmodel->rotatedmins[i] = -modelradius;
1736 loadmodel->rotatedmaxs[i] = modelradius;
1738 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1739 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1740 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1741 if (loadmodel->yawmaxs[0] > modelradius)
1742 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1743 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1744 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1745 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1746 loadmodel->radius = modelradius;
1747 loadmodel->radius2 = modelradius * modelradius;
1749 // go through the lumps, swapping things
1751 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1752 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1753 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1754 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1755 for (i = 0;i < pheader->numscenes;i++)
1757 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1758 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1759 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1760 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1761 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1762 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1763 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1764 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1765 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1766 if (loadmodel->animscenes[i].framerate < 0)
1767 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1771 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1772 loadmodel->num_bones = pheader->numbones;
1773 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1774 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1775 for (i = 0;i < pheader->numbones;i++)
1777 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1778 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1779 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1780 if (loadmodel->data_bones[i].parent >= i)
1781 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1784 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1785 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1786 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1787 for (i = 0;i < pheader->numverts;i++)
1789 vertbonecounts[i] = BigLong(bonecount[i]);
1790 if (vertbonecounts[i] != 1)
1791 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1794 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1796 meshvertices = pheader->numverts;
1797 meshtriangles = pheader->numtris;
1799 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1800 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1801 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1802 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]));
1803 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1804 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1805 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1806 loadmodel->surfmesh.num_vertices = meshvertices;
1807 loadmodel->surfmesh.num_triangles = meshtriangles;
1808 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1809 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1810 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1811 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1812 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1813 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1814 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1815 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1816 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1817 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
1818 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1819 if (loadmodel->surfmesh.num_vertices <= 65536)
1820 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1822 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1823 poses = (float *) (pheader->lump_poses.start + pbase);
1824 for (i = 0;i < pheader->lump_poses.length / 4;i++)
1825 loadmodel->data_poses[i] = BigFloat(poses[i]);
1827 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1828 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1829 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1830 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1831 // (converting from weight-blending skeletal animation to
1832 // deformation-based skeletal animation)
1833 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1834 for (i = 0;i < loadmodel->num_bones;i++)
1836 const float *m = loadmodel->data_poses + i * 12;
1837 if (loadmodel->data_bones[i].parent >= 0)
1838 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1840 for (k = 0;k < 12;k++)
1841 bonepose[12*i+k] = m[k];
1843 for (j = 0;j < pheader->numverts;j++)
1845 // this format really should have had a per vertexweight weight value...
1846 // but since it does not, the weighting is completely ignored and
1847 // only one weight is allowed per vertex
1848 int boneindex = BigLong(vertdata[j].bonenum);
1849 const float *m = bonepose + 12 * boneindex;
1850 float relativeorigin[3];
1851 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1852 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1853 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1854 // transform the vertex bone weight into the base mesh
1855 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1856 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1857 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1858 // store the weight as the primary weight on this vertex
1859 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
1860 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = 1;
1863 // normals and tangents are calculated after elements are loaded
1865 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1866 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1867 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1868 for (i = 0;i < pheader->numverts;i++)
1870 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1871 // flip T coordinate for OpenGL
1872 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1875 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1876 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1877 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1879 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1880 //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)
1881 // byteswap, validate, and swap winding order of tris
1882 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1883 if (pheader->lump_render.length != count)
1884 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1885 renderlist = (int *) (pheader->lump_render.start + pbase);
1886 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1888 for (i = 0;i < loadmodel->num_surfaces;i++)
1890 int firstvertex, lastvertex;
1891 if (renderlist >= renderlistend)
1892 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1893 count = BigLong(*renderlist);renderlist++;
1894 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1895 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1897 loadmodel->sortedmodelsurfaces[i] = i;
1898 surface = loadmodel->data_surfaces + i;
1899 surface->texture = loadmodel->data_textures + i;
1900 surface->num_firsttriangle = meshtriangles;
1901 surface->num_triangles = count;
1902 meshtriangles += surface->num_triangles;
1904 // load the elements
1905 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
1906 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
1908 outelements[j*3+2] = BigLong(renderlist[0]);
1909 outelements[j*3+1] = BigLong(renderlist[1]);
1910 outelements[j*3+0] = BigLong(renderlist[2]);
1912 // validate the elements and find the used vertex range
1913 firstvertex = meshvertices;
1915 for (j = 0;j < surface->num_triangles * 3;j++)
1917 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
1918 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
1919 firstvertex = min(firstvertex, outelements[j]);
1920 lastvertex = max(lastvertex, outelements[j]);
1922 surface->num_firstvertex = firstvertex;
1923 surface->num_vertices = lastvertex + 1 - firstvertex;
1925 // since zym models do not have named sections, reuse their shader
1926 // name as the section name
1927 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
1928 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
1930 Mod_FreeSkinFiles(skinfiles);
1931 Mem_Free(vertbonecounts);
1933 Mod_MakeSortedSurfaces(loadmodel);
1935 // compute all the mesh information that was not loaded from the file
1936 if (loadmodel->surfmesh.data_element3s)
1937 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1938 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1939 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
1940 Mod_BuildBaseBonePoses();
1941 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
1942 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);
1943 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1945 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1948 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1950 dpmheader_t *pheader;
1954 unsigned char *pbase;
1955 int i, j, k, meshvertices, meshtriangles;
1956 skinfile_t *skinfiles;
1957 unsigned char *data;
1960 pheader = (dpmheader_t *)buffer;
1961 pbase = (unsigned char *)buffer;
1962 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
1963 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
1964 if (BigLong(pheader->type) != 2)
1965 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1967 loadmodel->modeldatatypestring = "DPM";
1969 loadmodel->type = mod_alias;
1970 loadmodel->synctype = ST_RAND;
1973 pheader->type = BigLong(pheader->type);
1974 pheader->filesize = BigLong(pheader->filesize);
1975 pheader->mins[0] = BigFloat(pheader->mins[0]);
1976 pheader->mins[1] = BigFloat(pheader->mins[1]);
1977 pheader->mins[2] = BigFloat(pheader->mins[2]);
1978 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
1979 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
1980 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
1981 pheader->yawradius = BigFloat(pheader->yawradius);
1982 pheader->allradius = BigFloat(pheader->allradius);
1983 pheader->num_bones = BigLong(pheader->num_bones);
1984 pheader->num_meshs = BigLong(pheader->num_meshs);
1985 pheader->num_frames = BigLong(pheader->num_frames);
1986 pheader->ofs_bones = BigLong(pheader->ofs_bones);
1987 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
1988 pheader->ofs_frames = BigLong(pheader->ofs_frames);
1990 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
1992 Con_Printf("%s has no geometry\n", loadmodel->name);
1995 if (pheader->num_frames < 1)
1997 Con_Printf("%s has no frames\n", loadmodel->name);
2001 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2002 loadmodel->DrawSky = NULL;
2003 loadmodel->DrawAddWaterPlanes = NULL;
2004 loadmodel->Draw = R_Q1BSP_Draw;
2005 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2006 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2007 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2008 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2009 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2010 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2011 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2012 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2013 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2014 loadmodel->PointSuperContents = NULL;
2017 for (i = 0;i < 3;i++)
2019 loadmodel->normalmins[i] = pheader->mins[i];
2020 loadmodel->normalmaxs[i] = pheader->maxs[i];
2021 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2022 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2023 loadmodel->rotatedmins[i] = -pheader->allradius;
2024 loadmodel->rotatedmaxs[i] = pheader->allradius;
2026 loadmodel->radius = pheader->allradius;
2027 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2029 // load external .skin files if present
2030 skinfiles = Mod_LoadSkinFiles();
2031 if (loadmodel->numskins < 1)
2032 loadmodel->numskins = 1;
2037 // gather combined statistics from the meshes
2038 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2039 for (i = 0;i < (int)pheader->num_meshs;i++)
2041 int numverts = BigLong(dpmmesh->num_verts);
2042 meshvertices += numverts;
2043 meshtriangles += BigLong(dpmmesh->num_tris);
2047 loadmodel->numframes = pheader->num_frames;
2048 loadmodel->num_bones = pheader->num_bones;
2049 loadmodel->num_poses = loadmodel->numframes;
2050 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2051 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2052 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2053 // do most allocations as one merged chunk
2054 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));
2055 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2056 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2057 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2058 loadmodel->surfmesh.num_vertices = meshvertices;
2059 loadmodel->surfmesh.num_triangles = meshtriangles;
2060 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2061 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2062 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2063 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2064 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2065 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2066 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2067 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
2068 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
2069 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
2070 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2071 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2072 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2073 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2074 if (meshvertices <= 65536)
2075 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2077 for (i = 0;i < loadmodel->numskins;i++)
2079 loadmodel->skinscenes[i].firstframe = i;
2080 loadmodel->skinscenes[i].framecount = 1;
2081 loadmodel->skinscenes[i].loop = true;
2082 loadmodel->skinscenes[i].framerate = 10;
2085 // load the bone info
2086 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2087 for (i = 0;i < loadmodel->num_bones;i++)
2089 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2090 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2091 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2092 if (loadmodel->data_bones[i].parent >= i)
2093 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2097 frame = (dpmframe_t *) (pbase + pheader->ofs_frames);
2098 for (i = 0;i < loadmodel->numframes;i++)
2101 memcpy(loadmodel->animscenes[i].name, frame->name, sizeof(frame->name));
2102 loadmodel->animscenes[i].firstframe = i;
2103 loadmodel->animscenes[i].framecount = 1;
2104 loadmodel->animscenes[i].loop = true;
2105 loadmodel->animscenes[i].framerate = 10;
2106 // load the bone poses for this frame
2107 poses = (float *) (pbase + BigLong(frame->ofs_bonepositions));
2108 for (j = 0;j < loadmodel->num_bones*12;j++)
2109 loadmodel->data_poses[i * loadmodel->num_bones*12 + j] = BigFloat(poses[j]);
2110 // stuff not processed here: mins, maxs, yawradius, allradius
2114 // load the meshes now
2115 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2118 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2119 // (converting from weight-blending skeletal animation to
2120 // deformation-based skeletal animation)
2121 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2122 for (i = 0;i < loadmodel->num_bones;i++)
2124 const float *m = loadmodel->data_poses + i * 12;
2125 if (loadmodel->data_bones[i].parent >= 0)
2126 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2128 for (k = 0;k < 12;k++)
2129 bonepose[12*i+k] = m[k];
2131 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2133 const int *inelements;
2135 const float *intexcoord;
2136 msurface_t *surface;
2138 loadmodel->sortedmodelsurfaces[i] = i;
2139 surface = loadmodel->data_surfaces + i;
2140 surface->texture = loadmodel->data_textures + i;
2141 surface->num_firsttriangle = meshtriangles;
2142 surface->num_triangles = BigLong(dpmmesh->num_tris);
2143 surface->num_firstvertex = meshvertices;
2144 surface->num_vertices = BigLong(dpmmesh->num_verts);
2145 meshvertices += surface->num_vertices;
2146 meshtriangles += surface->num_triangles;
2148 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2149 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2150 for (j = 0;j < surface->num_triangles;j++)
2152 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2153 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2154 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2155 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2160 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2161 for (j = 0;j < surface->num_vertices*2;j++)
2162 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2164 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2165 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2169 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2170 data += sizeof(dpmvertex_t);
2171 for (k = 0;k < numweights;k++)
2173 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2174 int boneindex = BigLong(vert->bonenum);
2175 const float *m = bonepose + 12 * boneindex;
2176 float influence = BigFloat(vert->influence);
2177 float relativeorigin[3], relativenormal[3];
2178 relativeorigin[0] = BigFloat(vert->origin[0]);
2179 relativeorigin[1] = BigFloat(vert->origin[1]);
2180 relativeorigin[2] = BigFloat(vert->origin[2]);
2181 relativenormal[0] = BigFloat(vert->normal[0]);
2182 relativenormal[1] = BigFloat(vert->normal[1]);
2183 relativenormal[2] = BigFloat(vert->normal[2]);
2184 // blend the vertex bone weights into the base mesh
2185 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2186 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2187 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2188 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2189 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2190 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2193 // store the first (and often only) weight
2194 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = influence;
2195 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
2199 // sort the new weight into this vertex's weight table
2200 // (which only accepts up to 4 bones per vertex)
2201 for (l = 0;l < 4;l++)
2203 if (loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] < influence)
2205 // move weaker influence weights out of the way first
2207 for (l2 = 3;l2 > l;l2--)
2209 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2-1];
2210 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2-1];
2212 // store the new weight
2213 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] = influence;
2214 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l] = boneindex;
2219 data += sizeof(dpmbonevert_t);
2222 for (l = 0;l < 4;l++)
2223 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l];
2224 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2226 float f = 1.0f / sum;
2227 for (l = 0;l < 4;l++)
2228 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] *= f;
2232 // since dpm models do not have named sections, reuse their shader name as the section name
2233 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2235 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2238 Mod_FreeSkinFiles(skinfiles);
2239 Mod_MakeSortedSurfaces(loadmodel);
2241 // compute all the mesh information that was not loaded from the file
2242 if (loadmodel->surfmesh.data_element3s)
2243 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2244 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2245 Mod_BuildBaseBonePoses();
2246 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);
2247 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2249 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2252 // no idea why PSK/PSA files contain weird quaternions but they do...
2253 #define PSKQUATNEGATIONS
2254 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2256 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2257 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2258 fs_offset_t filesize;
2263 pskboneinfo_t *bones;
2264 pskrawweights_t *rawweights;
2265 pskboneinfo_t *animbones;
2266 pskaniminfo_t *anims;
2267 pskanimkeys_t *animkeys;
2268 void *animfilebuffer, *animbuffer, *animbufferend;
2269 unsigned char *data;
2271 skinfile_t *skinfiles;
2272 char animname[MAX_QPATH];
2275 pchunk = (pskchunk_t *)buffer;
2276 if (strcmp(pchunk->id, "ACTRHEAD"))
2277 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2279 loadmodel->modeldatatypestring = "PSK";
2281 loadmodel->type = mod_alias;
2282 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2283 loadmodel->DrawSky = NULL;
2284 loadmodel->DrawAddWaterPlanes = NULL;
2285 loadmodel->Draw = R_Q1BSP_Draw;
2286 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2287 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2288 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2289 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2290 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2291 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2292 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2293 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2294 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2295 loadmodel->PointSuperContents = NULL;
2296 loadmodel->synctype = ST_RAND;
2298 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2299 strlcat(animname, ".psa", sizeof(animname));
2300 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2301 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2302 if (animbuffer == NULL)
2303 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2322 while (buffer < bufferend)
2324 pchunk = (pskchunk_t *)buffer;
2325 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2326 version = LittleLong(pchunk->version);
2327 recordsize = LittleLong(pchunk->recordsize);
2328 numrecords = LittleLong(pchunk->numrecords);
2329 if (developer.integer >= 100)
2330 Con_Printf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2331 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2332 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);
2333 if (!strcmp(pchunk->id, "ACTRHEAD"))
2337 else if (!strcmp(pchunk->id, "PNTS0000"))
2340 if (recordsize != sizeof(*p))
2341 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2342 // byteswap in place and keep the pointer
2343 numpnts = numrecords;
2344 pnts = (pskpnts_t *)buffer;
2345 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2347 p->origin[0] = LittleFloat(p->origin[0]);
2348 p->origin[1] = LittleFloat(p->origin[1]);
2349 p->origin[2] = LittleFloat(p->origin[2]);
2353 else if (!strcmp(pchunk->id, "VTXW0000"))
2356 if (recordsize != sizeof(*p))
2357 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2358 // byteswap in place and keep the pointer
2359 numvtxw = numrecords;
2360 vtxw = (pskvtxw_t *)buffer;
2361 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2363 p->pntsindex = LittleShort(p->pntsindex);
2364 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2365 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2366 if (p->pntsindex >= numpnts)
2368 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2374 else if (!strcmp(pchunk->id, "FACE0000"))
2377 if (recordsize != sizeof(*p))
2378 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2379 // byteswap in place and keep the pointer
2380 numfaces = numrecords;
2381 faces = (pskface_t *)buffer;
2382 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2384 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2385 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2386 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2387 p->group = LittleLong(p->group);
2388 if (p->vtxwindex[0] >= numvtxw)
2390 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2391 p->vtxwindex[0] = 0;
2393 if (p->vtxwindex[1] >= numvtxw)
2395 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2396 p->vtxwindex[1] = 0;
2398 if (p->vtxwindex[2] >= numvtxw)
2400 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2401 p->vtxwindex[2] = 0;
2406 else if (!strcmp(pchunk->id, "MATT0000"))
2409 if (recordsize != sizeof(*p))
2410 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2411 // byteswap in place and keep the pointer
2412 nummatts = numrecords;
2413 matts = (pskmatt_t *)buffer;
2414 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2420 else if (!strcmp(pchunk->id, "REFSKELT"))
2423 if (recordsize != sizeof(*p))
2424 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2425 // byteswap in place and keep the pointer
2426 numbones = numrecords;
2427 bones = (pskboneinfo_t *)buffer;
2428 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2430 p->numchildren = LittleLong(p->numchildren);
2431 p->parent = LittleLong(p->parent);
2432 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2433 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2434 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2435 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2436 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2437 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2438 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2439 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2440 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2441 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2442 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2443 #ifdef PSKQUATNEGATIONS
2446 p->basepose.quat[0] *= -1;
2447 p->basepose.quat[1] *= -1;
2448 p->basepose.quat[2] *= -1;
2452 p->basepose.quat[0] *= 1;
2453 p->basepose.quat[1] *= -1;
2454 p->basepose.quat[2] *= 1;
2457 if (p->parent < 0 || p->parent >= numbones)
2459 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2465 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2468 if (recordsize != sizeof(*p))
2469 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2470 // byteswap in place and keep the pointer
2471 numrawweights = numrecords;
2472 rawweights = (pskrawweights_t *)buffer;
2473 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2475 p->weight = LittleFloat(p->weight);
2476 p->pntsindex = LittleLong(p->pntsindex);
2477 p->boneindex = LittleLong(p->boneindex);
2478 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2480 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2483 if (p->boneindex < 0 || p->boneindex >= numbones)
2485 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2493 while (animbuffer < animbufferend)
2495 pchunk = (pskchunk_t *)animbuffer;
2496 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2497 version = LittleLong(pchunk->version);
2498 recordsize = LittleLong(pchunk->recordsize);
2499 numrecords = LittleLong(pchunk->numrecords);
2500 if (developer.integer >= 100)
2501 Con_Printf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2502 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2503 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);
2504 if (!strcmp(pchunk->id, "ANIMHEAD"))
2508 else if (!strcmp(pchunk->id, "BONENAMES"))
2511 if (recordsize != sizeof(*p))
2512 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2513 // byteswap in place and keep the pointer
2514 numanimbones = numrecords;
2515 animbones = (pskboneinfo_t *)animbuffer;
2516 // NOTE: supposedly psa does not need to match the psk model, the
2517 // bones missing from the psa would simply use their base
2518 // positions from the psk, but this is hard for me to implement
2519 // and people can easily make animations that match.
2520 if (numanimbones != numbones)
2521 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2522 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2524 p->numchildren = LittleLong(p->numchildren);
2525 p->parent = LittleLong(p->parent);
2526 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2527 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2528 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2529 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2530 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2531 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2532 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2533 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2534 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2535 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2536 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2537 #ifdef PSKQUATNEGATIONS
2540 p->basepose.quat[0] *= -1;
2541 p->basepose.quat[1] *= -1;
2542 p->basepose.quat[2] *= -1;
2546 p->basepose.quat[0] *= 1;
2547 p->basepose.quat[1] *= -1;
2548 p->basepose.quat[2] *= 1;
2551 if (p->parent < 0 || p->parent >= numanimbones)
2553 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2556 // check that bones are the same as in the base
2557 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2558 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2562 else if (!strcmp(pchunk->id, "ANIMINFO"))
2565 if (recordsize != sizeof(*p))
2566 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2567 // byteswap in place and keep the pointer
2568 numanims = numrecords;
2569 anims = (pskaniminfo_t *)animbuffer;
2570 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2572 p->numbones = LittleLong(p->numbones);
2573 p->playtime = LittleFloat(p->playtime);
2574 p->fps = LittleFloat(p->fps);
2575 p->firstframe = LittleLong(p->firstframe);
2576 p->numframes = LittleLong(p->numframes);
2577 if (p->numbones != numbones)
2578 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2582 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2585 if (recordsize != sizeof(*p))
2586 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2587 numanimkeys = numrecords;
2588 animkeys = (pskanimkeys_t *)animbuffer;
2589 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2591 p->origin[0] = LittleFloat(p->origin[0]);
2592 p->origin[1] = LittleFloat(p->origin[1]);
2593 p->origin[2] = LittleFloat(p->origin[2]);
2594 p->quat[0] = LittleFloat(p->quat[0]);
2595 p->quat[1] = LittleFloat(p->quat[1]);
2596 p->quat[2] = LittleFloat(p->quat[2]);
2597 p->quat[3] = LittleFloat(p->quat[3]);
2598 p->frametime = LittleFloat(p->frametime);
2599 #ifdef PSKQUATNEGATIONS
2600 if (index % numbones)
2615 // TODO: allocate bonepose stuff
2618 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2621 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2622 Host_Error("%s: missing required chunks", loadmodel->name);
2624 loadmodel->numframes = 0;
2625 for (index = 0;index < numanims;index++)
2626 loadmodel->numframes += anims[index].numframes;
2628 if (numanimkeys != numbones * loadmodel->numframes)
2629 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2631 meshvertices = numvtxw;
2632 meshtriangles = numfaces;
2634 // load external .skin files if present
2635 skinfiles = Mod_LoadSkinFiles();
2636 if (loadmodel->numskins < 1)
2637 loadmodel->numskins = 1;
2638 loadmodel->num_bones = numbones;
2639 loadmodel->num_poses = loadmodel->numframes;
2640 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2641 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2642 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2643 loadmodel->surfmesh.num_vertices = meshvertices;
2644 loadmodel->surfmesh.num_triangles = meshtriangles;
2645 // do most allocations as one merged chunk
2646 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);
2647 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2648 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2649 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2650 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2651 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2652 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2653 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2654 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2655 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2656 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2657 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2658 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += loadmodel->surfmesh.num_vertices * sizeof(int[4]);
2659 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[4]);
2660 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
2661 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2662 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2663 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2664 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2665 if (loadmodel->surfmesh.num_vertices <= 65536)
2666 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2668 for (i = 0;i < loadmodel->numskins;i++)
2670 loadmodel->skinscenes[i].firstframe = i;
2671 loadmodel->skinscenes[i].framecount = 1;
2672 loadmodel->skinscenes[i].loop = true;
2673 loadmodel->skinscenes[i].framerate = 10;
2677 for (index = 0, i = 0;index < nummatts;index++)
2679 // since psk models do not have named sections, reuse their shader name as the section name
2680 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2681 loadmodel->sortedmodelsurfaces[index] = index;
2682 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2683 loadmodel->data_surfaces[index].num_firstvertex = 0;
2684 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2687 // copy over the vertex locations and texcoords
2688 for (index = 0;index < numvtxw;index++)
2690 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2691 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2692 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2693 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2694 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2697 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2698 for (index = 0;index < numfaces;index++)
2699 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2700 for (index = 0, i = 0;index < nummatts;index++)
2702 loadmodel->data_surfaces[index].num_firsttriangle = i;
2703 i += loadmodel->data_surfaces[index].num_triangles;
2704 loadmodel->data_surfaces[index].num_triangles = 0;
2706 for (index = 0;index < numfaces;index++)
2708 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2709 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2710 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2711 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2714 // copy over the bones
2715 for (index = 0;index < numbones;index++)
2717 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2718 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2719 if (loadmodel->data_bones[index].parent >= index)
2720 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2723 // sort the psk point weights into the vertex weight tables
2724 // (which only accept up to 4 bones per vertex)
2725 for (index = 0;index < numvtxw;index++)
2729 for (j = 0;j < numrawweights;j++)
2731 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2733 int boneindex = rawweights[j].boneindex;
2734 float influence = rawweights[j].weight;
2735 for (l = 0;l < 4;l++)
2737 if (loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] < influence)
2739 // move lower influence weights out of the way first
2741 for (l2 = 3;l2 > l;l2--)
2743 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2-1];
2744 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2-1];
2746 // store the new weight
2747 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] = influence;
2748 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l] = boneindex;
2755 for (l = 0;l < 4;l++)
2756 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l];
2757 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2759 float f = 1.0f / sum;
2760 for (l = 0;l < 4;l++)
2761 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] *= f;
2765 // set up the animscenes based on the anims
2766 for (index = 0, i = 0;index < numanims;index++)
2768 for (j = 0;j < anims[index].numframes;j++, i++)
2770 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2771 loadmodel->animscenes[i].firstframe = i;
2772 loadmodel->animscenes[i].framecount = 1;
2773 loadmodel->animscenes[i].loop = true;
2774 loadmodel->animscenes[i].framerate = 10;
2778 // load the poses from the animkeys
2779 for (index = 0;index < numanimkeys;index++)
2781 pskanimkeys_t *k = animkeys + index;
2783 Matrix4x4_FromOriginQuat(&matrix, k->origin[0], k->origin[1], k->origin[2], k->quat[0], k->quat[1], k->quat[2], k->quat[3]);
2784 Matrix4x4_ToArray12FloatD3D(&matrix, loadmodel->data_poses + index*12);
2786 Mod_FreeSkinFiles(skinfiles);
2787 Mem_Free(animfilebuffer);
2788 Mod_MakeSortedSurfaces(loadmodel);
2790 // compute all the mesh information that was not loaded from the file
2791 // TODO: honor smoothing groups somehow?
2792 if (loadmodel->surfmesh.data_element3s)
2793 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2794 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2795 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2796 Mod_BuildBaseBonePoses();
2797 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2798 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);
2799 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2800 Mod_Alias_CalculateBoundingBox();
2802 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;