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 < 4 && frameblend[blends].lerp > 0;blends++)
67 matrix = model->data_poses + (frameblend[blends].frame * 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
98 const float *v = model->surfmesh.data_vertex3f;
99 const int *wi = model->surfmesh.data_vertexweightindex4i;
100 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
101 memset(vertex3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
102 for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, wi += 4, wf += 4, vertex3f += 3)
106 const float *m = boneposerelative[wi[0]];
107 vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
108 vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
109 vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
113 const float *m = boneposerelative[wi[0]];
115 vertex3f[0] = f * (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
116 vertex3f[1] = f * (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
117 vertex3f[2] = f * (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
118 for (k = 1;k < 4 && wf[k];k++)
120 const float *m = boneposerelative[wi[k]];
122 vertex3f[0] += f * (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
123 vertex3f[1] += f * (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
124 vertex3f[2] += f * (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
131 const float *n = model->surfmesh.data_normal3f;
132 const int *wi = model->surfmesh.data_vertexweightindex4i;
133 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
134 memset(normal3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
135 for (i = 0;i < model->surfmesh.num_vertices;i++, n += 3, wi += 4, wf += 4, normal3f += 3)
139 const float *m = boneposerelative[wi[0]];
140 normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
141 normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
142 normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
146 const float *m = boneposerelative[wi[0]];
148 normal3f[0] = f * (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
149 normal3f[1] = f * (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
150 normal3f[2] = f * (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
151 for (k = 1;k < 4 && wf[k];k++)
153 const float *m = boneposerelative[wi[k]];
155 normal3f[0] += f * (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
156 normal3f[1] += f * (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
157 normal3f[2] += f * (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
164 const float *sv = model->surfmesh.data_svector3f;
165 const int *wi = model->surfmesh.data_vertexweightindex4i;
166 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
167 memset(svector3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
168 for (i = 0;i < model->surfmesh.num_vertices;i++, sv += 3, wi += 4, wf += 4, svector3f += 3)
172 const float *m = boneposerelative[wi[0]];
173 svector3f[0] = (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
174 svector3f[1] = (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
175 svector3f[2] = (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
179 const float *m = boneposerelative[wi[0]];
181 svector3f[0] = f * (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
182 svector3f[1] = f * (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
183 svector3f[2] = f * (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
184 for (k = 1;k < 4 && wf[k];k++)
186 const float *m = boneposerelative[wi[k]];
188 svector3f[0] += f * (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
189 svector3f[1] += f * (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
190 svector3f[2] += f * (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
197 const float *tv = model->surfmesh.data_tvector3f;
198 const int *wi = model->surfmesh.data_vertexweightindex4i;
199 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
200 memset(tvector3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
201 for (i = 0;i < model->surfmesh.num_vertices;i++, tv += 3, wi += 4, wf += 4, tvector3f += 3)
205 const float *m = boneposerelative[wi[0]];
206 tvector3f[0] = (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
207 tvector3f[1] = (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
208 tvector3f[2] = (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
212 const float *m = boneposerelative[wi[0]];
214 tvector3f[0] = f * (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
215 tvector3f[1] = f * (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
216 tvector3f[2] = f * (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
217 for (k = 1;k < 4 && wf[k];k++)
219 const float *m = boneposerelative[wi[k]];
221 tvector3f[0] += f * (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
222 tvector3f[1] += f * (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
223 tvector3f[2] += f * (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
230 void Mod_MD3_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
233 int i, numblends, blendnum;
234 int numverts = model->surfmesh.num_vertices;
236 for (blendnum = 0;blendnum < 4;blendnum++)
238 //VectorMA(translate, model->surfmesh.num_morphmdlframetranslate, frameblend[blendnum].lerp, translate);
239 if (frameblend[blendnum].lerp > 0)
240 numblends = blendnum + 1;
242 // special case for the first blend because it avoids some adds and the need to memset the arrays first
243 for (blendnum = 0;blendnum < numblends;blendnum++)
245 const md3vertex_t *verts = model->surfmesh.data_morphmd3vertex + numverts * frameblend[blendnum].frame;
246 float scale = frameblend[blendnum].lerp * (1.0f / 64.0f);
249 for (i = 0;i < numverts;i++)
251 vertex3f[i * 3 + 0] = verts[i].origin[0] * scale;
252 vertex3f[i * 3 + 1] = verts[i].origin[1] * scale;
253 vertex3f[i * 3 + 2] = verts[i].origin[2] * scale;
258 for (i = 0;i < numverts;i++)
260 vertex3f[i * 3 + 0] += verts[i].origin[0] * scale;
261 vertex3f[i * 3 + 1] += verts[i].origin[1] * scale;
262 vertex3f[i * 3 + 2] += verts[i].origin[2] * scale;
265 // the yaw and pitch stored in md3 models are 8bit quantized angles
266 // (0-255), and as such a lookup table is very well suited to
267 // decoding them, and since cosine is equivilant to sine with an
268 // extra 45 degree rotation, this uses one lookup table for both
269 // sine and cosine with a +64 bias to get cosine.
272 float lerp = frameblend[blendnum].lerp;
275 for (i = 0;i < numverts;i++)
277 normal3f[i * 3 + 0] = mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
278 normal3f[i * 3 + 1] = mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
279 normal3f[i * 3 + 2] = mod_md3_sin[verts[i].pitch + 64] * lerp;
284 for (i = 0;i < numverts;i++)
286 normal3f[i * 3 + 0] += mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
287 normal3f[i * 3 + 1] += mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
288 normal3f[i * 3 + 2] += mod_md3_sin[verts[i].pitch + 64] * lerp;
294 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].frame;
295 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
298 for (i = 0;i < numverts;i++, texvecvert++)
300 VectorScale(texvecvert->svec, f, svector3f + i*3);
301 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
306 for (i = 0;i < numverts;i++, texvecvert++)
308 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
309 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
316 void Mod_MDL_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
319 int i, numblends, blendnum;
320 int numverts = model->surfmesh.num_vertices;
322 VectorClear(translate);
324 // blend the frame translates to avoid redundantly doing so on each vertex
325 // (a bit of a brain twister but it works)
326 for (blendnum = 0;blendnum < 4;blendnum++)
328 if (model->surfmesh.data_morphmd2framesize6f)
329 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].frame * 6 + 3, translate);
331 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.num_morphmdlframetranslate, translate);
332 if (frameblend[blendnum].lerp > 0)
333 numblends = blendnum + 1;
335 // special case for the first blend because it avoids some adds and the need to memset the arrays first
336 for (blendnum = 0;blendnum < numblends;blendnum++)
338 const trivertx_t *verts = model->surfmesh.data_morphmdlvertex + numverts * frameblend[blendnum].frame;
340 if (model->surfmesh.data_morphmd2framesize6f)
341 VectorScale(model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].frame * 6, frameblend[blendnum].lerp, scale);
343 VectorScale(model->surfmesh.num_morphmdlframescale, frameblend[blendnum].lerp, scale);
346 for (i = 0;i < numverts;i++)
348 vertex3f[i * 3 + 0] = translate[0] + verts[i].v[0] * scale[0];
349 vertex3f[i * 3 + 1] = translate[1] + verts[i].v[1] * scale[1];
350 vertex3f[i * 3 + 2] = translate[2] + verts[i].v[2] * scale[2];
355 for (i = 0;i < numverts;i++)
357 vertex3f[i * 3 + 0] += verts[i].v[0] * scale[0];
358 vertex3f[i * 3 + 1] += verts[i].v[1] * scale[1];
359 vertex3f[i * 3 + 2] += verts[i].v[2] * scale[2];
362 // the vertex normals in mdl models are an index into a table of
363 // 162 unique values, this very crude quantization reduces the
364 // vertex normal to only one byte, which saves a lot of space but
365 // also makes lighting pretty coarse
368 float lerp = frameblend[blendnum].lerp;
371 for (i = 0;i < numverts;i++)
373 const float *vn = m_bytenormals[verts[i].lightnormalindex];
374 VectorScale(vn, lerp, normal3f + i*3);
379 for (i = 0;i < numverts;i++)
381 const float *vn = m_bytenormals[verts[i].lightnormalindex];
382 VectorMA(normal3f + i*3, lerp, vn, normal3f + i*3);
388 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].frame;
389 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
392 for (i = 0;i < numverts;i++, texvecvert++)
394 VectorScale(texvecvert->svec, f, svector3f + i*3);
395 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
400 for (i = 0;i < numverts;i++, texvecvert++)
402 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
403 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
410 int Mod_Alias_GetTagMatrix(const dp_model_t *model, int poseframe, int tagindex, matrix4x4_t *outmatrix)
412 const float *boneframe;
413 float tempbonematrix[12], bonematrix[12];
414 *outmatrix = identitymatrix;
415 if (model->num_bones)
417 if (tagindex < 0 || tagindex >= model->num_bones)
419 if (poseframe >= model->num_poses)
421 boneframe = model->data_poses + poseframe * model->num_bones * 12;
422 memcpy(bonematrix, boneframe + tagindex * 12, sizeof(float[12]));
423 while (model->data_bones[tagindex].parent >= 0)
425 memcpy(tempbonematrix, bonematrix, sizeof(float[12]));
426 R_ConcatTransforms(boneframe + model->data_bones[tagindex].parent * 12, tempbonematrix, bonematrix);
427 tagindex = model->data_bones[tagindex].parent;
429 Matrix4x4_FromArray12FloatD3D(outmatrix, bonematrix);
431 else if (model->num_tags)
433 if (tagindex < 0 || tagindex >= model->num_tags)
435 if (poseframe >= model->num_tagframes)
437 Matrix4x4_FromArray12FloatGL(outmatrix, model->data_tags[poseframe * model->num_tags + tagindex].matrixgl);
440 if(!mod_alias_supporttagscale.integer)
441 Matrix4x4_Normalize3(outmatrix, outmatrix);
446 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)
448 const float *boneframe;
450 if(skin >= (unsigned int)model->numskins)
453 if (model->num_bones)
455 if(tagindex >= model->num_bones || tagindex < 0)
457 if (poseframe >= model->num_poses)
460 boneframe = model->data_poses + poseframe * model->num_bones * 12;
461 *parentindex = model->data_bones[tagindex].parent;
462 *tagname = model->data_bones[tagindex].name;
463 Matrix4x4_FromArray12FloatD3D(tag_localmatrix, boneframe + tagindex * 12);
469 if(tagindex >= model->num_tags || tagindex < 0)
471 if (poseframe >= model->num_tagframes)
473 *tagname = model->data_tags[tagindex].name;
474 Matrix4x4_FromArray12FloatGL(tag_localmatrix, model->data_tags[poseframe * model->num_tags + tagindex].matrixgl);
481 int Mod_Alias_GetTagIndexForName(const dp_model_t *model, unsigned int skin, const char *tagname)
484 if(skin >= (unsigned int)model->numskins)
486 if (model->num_bones)
487 for (i = 0;i < model->num_bones;i++)
488 if (!strcasecmp(tagname, model->data_bones[i].name))
491 for (i = 0;i < model->num_tags;i++)
492 if (!strcasecmp(tagname, model->data_tags[i].name))
497 static void Mod_BuildBaseBonePoses(void)
501 float *basebonepose = (float *) Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(float[12]));
502 float *in12f = loadmodel->data_poses;
503 float *out12f = basebonepose;
504 float *outinv12f = loadmodel->data_baseboneposeinverse;
505 for (i = 0;i < loadmodel->num_bones;i++, in12f += 12, out12f += 12, outinv12f += 12)
507 if (loadmodel->data_bones[i].parent >= 0)
508 R_ConcatTransforms(basebonepose + 12 * loadmodel->data_bones[i].parent, in12f, out12f);
510 for (k = 0;k < 12;k++)
511 out12f[k] = in12f[k];
515 // we only support uniform scaling, so assume the first row is enough
516 // (note the lack of sqrt here, because we're trying to undo the scaling,
517 // this means multiplying by the inverse scale twice - squaring it, which
518 // makes the sqrt a waste of time)
519 scale = 1.0 / (out12f[ 0] * out12f[ 0] + out12f[ 1] * out12f[ 1] + out12f[ 2] * out12f[ 2]);
521 // invert the rotation by transposing and multiplying by the squared
522 // recipricol of the input matrix scale as described above
523 outinv12f[ 0] = (float)(out12f[ 0] * scale);
524 outinv12f[ 1] = (float)(out12f[ 4] * scale);
525 outinv12f[ 2] = (float)(out12f[ 8] * scale);
526 outinv12f[ 4] = (float)(out12f[ 1] * scale);
527 outinv12f[ 5] = (float)(out12f[ 5] * scale);
528 outinv12f[ 6] = (float)(out12f[ 9] * scale);
529 outinv12f[ 8] = (float)(out12f[ 2] * scale);
530 outinv12f[ 9] = (float)(out12f[ 6] * scale);
531 outinv12f[10] = (float)(out12f[10] * scale);
533 // invert the translate
534 outinv12f[ 3] = -(out12f[ 3] * outinv12f[ 0] + out12f[ 7] * outinv12f[ 1] + out12f[11] * outinv12f[ 2]);
535 outinv12f[ 7] = -(out12f[ 3] * outinv12f[ 4] + out12f[ 7] * outinv12f[ 5] + out12f[11] * outinv12f[ 6]);
536 outinv12f[11] = -(out12f[ 3] * outinv12f[ 8] + out12f[ 7] * outinv12f[ 9] + out12f[11] * outinv12f[10]);
538 Mem_Free(basebonepose);
541 static void Mod_Alias_CalculateBoundingBox(void)
544 qboolean firstvertex = true;
545 float dist, yawradius, radius;
548 frameblend_t frameblend[4];
549 memset(frameblend, 0, sizeof(frameblend));
550 frameblend[0].lerp = 1;
551 vertex3f = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
552 VectorClear(loadmodel->normalmins);
553 VectorClear(loadmodel->normalmaxs);
556 for (frameblend[0].frame = 0;frameblend[0].frame < loadmodel->num_poses;frameblend[0].frame++)
558 loadmodel->AnimateVertices(loadmodel, frameblend, vertex3f, NULL, NULL, NULL);
559 for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
564 VectorCopy(v, loadmodel->normalmins);
565 VectorCopy(v, loadmodel->normalmaxs);
569 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
570 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
571 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
572 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
573 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
574 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
576 dist = v[0] * v[0] + v[1] * v[1];
577 if (yawradius < dist)
585 radius = sqrt(radius);
586 yawradius = sqrt(yawradius);
587 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
588 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
589 loadmodel->yawmins[2] = loadmodel->normalmins[2];
590 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
591 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
592 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
593 loadmodel->radius = radius;
594 loadmodel->radius2 = radius * radius;
597 static void Mod_Alias_MorphMesh_CompileFrames(void)
600 frameblend_t frameblend[4] = {{0, 1}, {0, 0}, {0, 0}, {0, 0}};
601 unsigned char *datapointer;
602 datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
603 loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
604 loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
605 loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
606 loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
607 loadmodel->surfmesh.data_morphtexvecvertex = (texvecvertex_t *)datapointer;datapointer += loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices * sizeof(texvecvertex_t);
608 // 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)
609 for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
611 frameblend[0].frame = i;
612 loadmodel->AnimateVertices(loadmodel, frameblend, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
613 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);
614 // encode the svector and tvector in 3 byte format for permanent storage
615 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
617 VectorScaleCast(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
618 VectorScaleCast(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
623 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)
626 float segmentmins[3], segmentmaxs[3];
627 frameblend_t frameblend[4];
629 static int maxvertices = 0;
630 static float *vertex3f = NULL;
631 memset(trace, 0, sizeof(*trace));
633 trace->realfraction = 1;
634 trace->hitsupercontentsmask = hitsupercontentsmask;
635 memset(frameblend, 0, sizeof(frameblend));
636 frameblend[0].frame = frame;
637 frameblend[0].lerp = 1;
638 if (maxvertices < model->surfmesh.num_vertices)
642 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
643 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
645 if (VectorLength2(boxmins) + VectorLength2(boxmaxs) == 0)
648 segmentmins[0] = min(start[0], end[0]) - 1;
649 segmentmins[1] = min(start[1], end[1]) - 1;
650 segmentmins[2] = min(start[2], end[2]) - 1;
651 segmentmaxs[0] = max(start[0], end[0]) + 1;
652 segmentmaxs[1] = max(start[1], end[1]) + 1;
653 segmentmaxs[2] = max(start[2], end[2]) + 1;
654 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
656 model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL);
657 Collision_TraceLineTriangleMeshFloat(trace, start, end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, SUPERCONTENTS_SOLID, 0, surface->texture, segmentmins, segmentmaxs);
662 // box trace, performed as brush trace
663 colbrushf_t *thisbrush_start, *thisbrush_end;
664 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
665 segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
666 segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
667 segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
668 segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
669 segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
670 segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
671 VectorAdd(start, boxmins, boxstartmins);
672 VectorAdd(start, boxmaxs, boxstartmaxs);
673 VectorAdd(end, boxmins, boxendmins);
674 VectorAdd(end, boxmaxs, boxendmaxs);
675 thisbrush_start = Collision_BrushForBox(&identitymatrix, boxstartmins, boxstartmaxs, 0, 0, NULL);
676 thisbrush_end = Collision_BrushForBox(&identitymatrix, boxendmins, boxendmaxs, 0, 0, NULL);
677 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
679 if (maxvertices < model->surfmesh.num_vertices)
683 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
684 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
686 model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL);
687 Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, SUPERCONTENTS_SOLID, 0, surface->texture, segmentmins, segmentmaxs);
692 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
695 for (i = 0;i < inverts;i++)
697 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
699 j = vertremap[i]; // not onseam
702 j = vertremap[i+inverts]; // onseam
708 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
710 int i, f, pose, groupframes;
712 daliasframetype_t *pframetype;
713 daliasframe_t *pinframe;
714 daliasgroup_t *group;
715 daliasinterval_t *intervals;
718 scene = loadmodel->animscenes;
719 for (f = 0;f < loadmodel->numframes;f++)
721 pframetype = (daliasframetype_t *)datapointer;
722 datapointer += sizeof(daliasframetype_t);
723 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
725 // a single frame is still treated as a group
732 group = (daliasgroup_t *)datapointer;
733 datapointer += sizeof(daliasgroup_t);
734 groupframes = LittleLong (group->numframes);
736 // intervals (time per frame)
737 intervals = (daliasinterval_t *)datapointer;
738 datapointer += sizeof(daliasinterval_t) * groupframes;
740 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
741 if (interval < 0.01f)
743 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
748 // get scene name from first frame
749 pinframe = (daliasframe_t *)datapointer;
751 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
752 scene->firstframe = pose;
753 scene->framecount = groupframes;
754 scene->framerate = 1.0f / interval;
759 for (i = 0;i < groupframes;i++)
761 pinframe = (daliasframe_t *)datapointer;
762 datapointer += sizeof(daliasframe_t);
763 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
764 datapointer += sizeof(trivertx_t) * inverts;
770 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
772 if (cls.state == ca_dedicated)
776 skinframe = R_SkinFrame_LoadMissing();
777 memset(texture, 0, sizeof(*texture));
778 texture->currentframe = texture;
779 //texture->animated = false;
780 texture->numskinframes = 1;
781 texture->skinframerate = 1;
782 texture->skinframes[0] = skinframe;
783 texture->currentskinframe = skinframe;
784 //texture->backgroundnumskinframes = 0;
785 //texture->customblendfunc[0] = 0;
786 //texture->customblendfunc[1] = 0;
787 //texture->surfaceflags = 0;
788 //texture->supercontents = 0;
789 //texture->surfaceparms = 0;
790 //texture->textureflags = 0;
792 texture->basematerialflags = MATERIALFLAG_WALL;
793 if (texture->currentskinframe->fog)
794 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
795 texture->currentmaterialflags = texture->basematerialflags;
798 static void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
801 skinfileitem_t *skinfileitem;
804 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
805 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
807 memset(skin, 0, sizeof(*skin));
809 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
811 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
812 if (!strcmp(skinfileitem->name, meshname))
814 Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
820 // don't render unmentioned meshes
821 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
822 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
827 Mod_LoadTextureFromQ3Shader(skin, shadername, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
830 #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);
831 #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);
832 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
834 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
835 float scales, scalet, interval;
839 stvert_t *pinstverts;
840 dtriangle_t *pintriangles;
841 daliasskintype_t *pinskintype;
842 daliasskingroup_t *pinskingroup;
843 daliasskininterval_t *pinskinintervals;
844 daliasframetype_t *pinframetype;
845 daliasgroup_t *pinframegroup;
846 unsigned char *datapointer, *startframes, *startskins;
847 char name[MAX_QPATH];
848 skinframe_t *tempskinframe;
849 animscene_t *tempskinscenes;
850 texture_t *tempaliasskins;
852 int *vertonseam, *vertremap;
853 skinfile_t *skinfiles;
855 datapointer = (unsigned char *)buffer;
856 pinmodel = (mdl_t *)datapointer;
857 datapointer += sizeof(mdl_t);
859 version = LittleLong (pinmodel->version);
860 if (version != ALIAS_VERSION)
861 Host_Error ("%s has wrong version number (%i should be %i)",
862 loadmodel->name, version, ALIAS_VERSION);
864 loadmodel->modeldatatypestring = "MDL";
866 loadmodel->type = mod_alias;
867 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
868 loadmodel->DrawSky = NULL;
869 loadmodel->DrawAddWaterPlanes = NULL;
870 loadmodel->Draw = R_Q1BSP_Draw;
871 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
872 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
873 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
874 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
875 loadmodel->DrawLight = R_Q1BSP_DrawLight;
876 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
877 loadmodel->PointSuperContents = NULL;
879 loadmodel->num_surfaces = 1;
880 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
881 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
882 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
883 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
884 loadmodel->surfacelist[0] = 0;
886 loadmodel->numskins = LittleLong(pinmodel->numskins);
887 BOUNDI(loadmodel->numskins,0,65536);
888 skinwidth = LittleLong (pinmodel->skinwidth);
889 BOUNDI(skinwidth,0,65536);
890 skinheight = LittleLong (pinmodel->skinheight);
891 BOUNDI(skinheight,0,65536);
892 numverts = LittleLong(pinmodel->numverts);
893 BOUNDI(numverts,0,65536);
894 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
895 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
896 loadmodel->numframes = LittleLong(pinmodel->numframes);
897 BOUNDI(loadmodel->numframes,0,65536);
898 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
899 BOUNDI(loadmodel->synctype,0,2);
900 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
901 i = LittleLong (pinmodel->flags);
902 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
904 for (i = 0;i < 3;i++)
906 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
907 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
910 startskins = datapointer;
912 for (i = 0;i < loadmodel->numskins;i++)
914 pinskintype = (daliasskintype_t *)datapointer;
915 datapointer += sizeof(daliasskintype_t);
916 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
920 pinskingroup = (daliasskingroup_t *)datapointer;
921 datapointer += sizeof(daliasskingroup_t);
922 groupskins = LittleLong(pinskingroup->numskins);
923 datapointer += sizeof(daliasskininterval_t) * groupskins;
926 for (j = 0;j < groupskins;j++)
928 datapointer += skinwidth * skinheight;
933 pinstverts = (stvert_t *)datapointer;
934 datapointer += sizeof(stvert_t) * numverts;
936 pintriangles = (dtriangle_t *)datapointer;
937 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
939 startframes = datapointer;
940 loadmodel->surfmesh.num_morphframes = 0;
941 for (i = 0;i < loadmodel->numframes;i++)
943 pinframetype = (daliasframetype_t *)datapointer;
944 datapointer += sizeof(daliasframetype_t);
945 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
949 pinframegroup = (daliasgroup_t *)datapointer;
950 datapointer += sizeof(daliasgroup_t);
951 groupframes = LittleLong(pinframegroup->numframes);
952 datapointer += sizeof(daliasinterval_t) * groupframes;
955 for (j = 0;j < groupframes;j++)
957 datapointer += sizeof(daliasframe_t);
958 datapointer += sizeof(trivertx_t) * numverts;
959 loadmodel->surfmesh.num_morphframes++;
962 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
964 // store texture coordinates into temporary array, they will be stored
965 // after usage is determined (triangle data)
966 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
967 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
968 vertonseam = vertremap + numverts * 2;
970 scales = 1.0 / skinwidth;
971 scalet = 1.0 / skinheight;
972 for (i = 0;i < numverts;i++)
974 vertonseam[i] = LittleLong(pinstverts[i].onseam);
975 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
976 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
977 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
978 vertst[(i+numverts)*2+1] = vertst[i*2+1];
981 // load triangle data
982 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
984 // read the triangle elements
985 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
986 for (j = 0;j < 3;j++)
987 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
988 // validate (note numverts is used because this is the original data)
989 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
990 // now butcher the elements according to vertonseam and tri->facesfront
991 // and then compact the vertex set to remove duplicates
992 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
993 if (!LittleLong(pintriangles[i].facesfront)) // backface
994 for (j = 0;j < 3;j++)
995 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
996 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
998 // (this uses vertremap to count usage to save some memory)
999 for (i = 0;i < numverts*2;i++)
1001 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1002 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1003 // build remapping table and compact array
1004 loadmodel->surfmesh.num_vertices = 0;
1005 for (i = 0;i < numverts*2;i++)
1009 vertremap[i] = loadmodel->surfmesh.num_vertices;
1010 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1011 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1012 loadmodel->surfmesh.num_vertices++;
1015 vertremap[i] = -1; // not used at all
1017 // remap the elements to the new vertex set
1018 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1019 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1020 // store the texture coordinates
1021 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1022 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1024 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1025 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1028 // generate ushort elements array if possible
1029 if (loadmodel->surfmesh.num_vertices <= 65536)
1031 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1032 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1033 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1037 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1038 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1039 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1040 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1041 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1042 Mod_Alias_CalculateBoundingBox();
1043 Mod_Alias_MorphMesh_CompileFrames();
1046 Mem_Free(vertremap);
1049 skinfiles = Mod_LoadSkinFiles();
1052 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1053 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1054 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1055 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1056 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1057 Mod_FreeSkinFiles(skinfiles);
1058 for (i = 0;i < loadmodel->numskins;i++)
1060 loadmodel->skinscenes[i].firstframe = i;
1061 loadmodel->skinscenes[i].framecount = 1;
1062 loadmodel->skinscenes[i].loop = true;
1063 loadmodel->skinscenes[i].framerate = 10;
1068 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1069 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1070 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1071 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1073 datapointer = startskins;
1074 for (i = 0;i < loadmodel->numskins;i++)
1076 pinskintype = (daliasskintype_t *)datapointer;
1077 datapointer += sizeof(daliasskintype_t);
1079 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1086 pinskingroup = (daliasskingroup_t *)datapointer;
1087 datapointer += sizeof(daliasskingroup_t);
1089 groupskins = LittleLong (pinskingroup->numskins);
1091 pinskinintervals = (daliasskininterval_t *)datapointer;
1092 datapointer += sizeof(daliasskininterval_t) * groupskins;
1094 interval = LittleFloat(pinskinintervals[0].interval);
1095 if (interval < 0.01f)
1097 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1102 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1103 loadmodel->skinscenes[i].firstframe = totalskins;
1104 loadmodel->skinscenes[i].framecount = groupskins;
1105 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1106 loadmodel->skinscenes[i].loop = true;
1108 for (j = 0;j < groupskins;j++)
1111 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1113 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1114 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))
1115 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));
1116 datapointer += skinwidth * skinheight;
1120 // check for skins that don't exist in the model, but do exist as external images
1121 // (this was added because yummyluv kept pestering me about support for it)
1122 // TODO: support shaders here?
1123 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)))
1125 // expand the arrays to make room
1126 tempskinscenes = loadmodel->skinscenes;
1127 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1128 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1129 Mem_Free(tempskinscenes);
1131 tempaliasskins = loadmodel->data_textures;
1132 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1133 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1134 Mem_Free(tempaliasskins);
1136 // store the info about the new skin
1137 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1138 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1139 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1140 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1141 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1142 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1144 //increase skin counts
1145 loadmodel->numskins++;
1148 // fix up the pointers since they are pointing at the old textures array
1149 // FIXME: this is a hack!
1150 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1151 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1155 surface = loadmodel->data_surfaces;
1156 surface->texture = loadmodel->data_textures;
1157 surface->num_firsttriangle = 0;
1158 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1159 surface->num_firstvertex = 0;
1160 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1162 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1165 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1167 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1168 float iskinwidth, iskinheight;
1169 unsigned char *data;
1170 msurface_t *surface;
1172 unsigned char *base, *datapointer;
1173 md2frame_t *pinframe;
1175 md2triangle_t *intri;
1176 unsigned short *inst;
1177 struct md2verthash_s
1179 struct md2verthash_s *next;
1183 *hash, **md2verthash, *md2verthashdata;
1184 skinfile_t *skinfiles;
1186 pinmodel = (md2_t *)buffer;
1187 base = (unsigned char *)buffer;
1189 version = LittleLong (pinmodel->version);
1190 if (version != MD2ALIAS_VERSION)
1191 Host_Error ("%s has wrong version number (%i should be %i)",
1192 loadmodel->name, version, MD2ALIAS_VERSION);
1194 loadmodel->modeldatatypestring = "MD2";
1196 loadmodel->type = mod_alias;
1197 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1198 loadmodel->DrawSky = NULL;
1199 loadmodel->DrawAddWaterPlanes = NULL;
1200 loadmodel->Draw = R_Q1BSP_Draw;
1201 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1202 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1203 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1204 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1205 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1206 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1207 loadmodel->PointSuperContents = NULL;
1209 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1210 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1211 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1212 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1213 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1214 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1215 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1216 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1218 end = LittleLong(pinmodel->ofs_end);
1219 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1220 Host_Error ("%s is not a valid model", loadmodel->name);
1221 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1222 Host_Error ("%s is not a valid model", loadmodel->name);
1223 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1224 Host_Error ("%s is not a valid model", loadmodel->name);
1225 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1226 Host_Error ("%s is not a valid model", loadmodel->name);
1227 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1228 Host_Error ("%s is not a valid model", loadmodel->name);
1230 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1231 numxyz = LittleLong(pinmodel->num_xyz);
1232 numst = LittleLong(pinmodel->num_st);
1233 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1234 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1235 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1236 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1237 skinwidth = LittleLong(pinmodel->skinwidth);
1238 skinheight = LittleLong(pinmodel->skinheight);
1239 iskinwidth = 1.0f / skinwidth;
1240 iskinheight = 1.0f / skinheight;
1242 loadmodel->num_surfaces = 1;
1243 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1244 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]));
1245 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1246 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1247 loadmodel->surfacelist[0] = 0;
1248 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1249 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1250 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1251 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1253 loadmodel->synctype = ST_RAND;
1256 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1257 skinfiles = Mod_LoadSkinFiles();
1260 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1261 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1262 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1263 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1264 Mod_FreeSkinFiles(skinfiles);
1266 else if (loadmodel->numskins)
1268 // skins found (most likely not a player model)
1269 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1270 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1271 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1272 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1273 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);
1277 // no skins (most likely a player model)
1278 loadmodel->numskins = 1;
1279 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1280 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1281 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1282 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1285 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1286 for (i = 0;i < loadmodel->numskins;i++)
1288 loadmodel->skinscenes[i].firstframe = i;
1289 loadmodel->skinscenes[i].framecount = 1;
1290 loadmodel->skinscenes[i].loop = true;
1291 loadmodel->skinscenes[i].framerate = 10;
1294 // load the triangles and stvert data
1295 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1296 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1297 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1298 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1299 // swap the triangle list
1300 loadmodel->surfmesh.num_vertices = 0;
1301 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1303 for (j = 0;j < 3;j++)
1305 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1306 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1309 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1314 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1317 hashindex = (xyz * 256 + st) & 65535;
1318 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1319 if (hash->xyz == xyz && hash->st == st)
1323 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1326 hash->next = md2verthash[hashindex];
1327 md2verthash[hashindex] = hash;
1329 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1333 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1334 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));
1335 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1336 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1337 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1340 hash = md2verthashdata + i;
1341 vertremap[i] = hash->xyz;
1342 sts = LittleShort(inst[hash->st*2+0]);
1343 stt = LittleShort(inst[hash->st*2+1]);
1344 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1346 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1350 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1351 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1354 Mem_Free(md2verthash);
1355 Mem_Free(md2verthashdata);
1357 // generate ushort elements array if possible
1358 if (loadmodel->surfmesh.num_vertices <= 65536)
1360 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1361 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1362 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1366 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1367 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1372 pinframe = (md2frame_t *)datapointer;
1373 datapointer += sizeof(md2frame_t);
1374 // store the frame scale/translate into the appropriate array
1375 for (j = 0;j < 3;j++)
1377 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1378 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1380 // convert the vertices
1381 v = (trivertx_t *)datapointer;
1382 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1383 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1384 out[k] = v[vertremap[k]];
1385 datapointer += numxyz * sizeof(trivertx_t);
1387 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1388 loadmodel->animscenes[i].firstframe = i;
1389 loadmodel->animscenes[i].framecount = 1;
1390 loadmodel->animscenes[i].framerate = 10;
1391 loadmodel->animscenes[i].loop = true;
1394 Mem_Free(vertremap);
1396 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1397 Mod_Alias_CalculateBoundingBox();
1398 Mod_Alias_MorphMesh_CompileFrames();
1400 surface = loadmodel->data_surfaces;
1401 surface->texture = loadmodel->data_textures;
1402 surface->num_firsttriangle = 0;
1403 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1404 surface->num_firstvertex = 0;
1405 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1407 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1410 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1412 int i, j, k, version, meshvertices, meshtriangles;
1413 unsigned char *data;
1414 msurface_t *surface;
1415 md3modelheader_t *pinmodel;
1416 md3frameinfo_t *pinframe;
1419 skinfile_t *skinfiles;
1421 pinmodel = (md3modelheader_t *)buffer;
1423 if (memcmp(pinmodel->identifier, "IDP3", 4))
1424 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1425 version = LittleLong (pinmodel->version);
1426 if (version != MD3VERSION)
1427 Host_Error ("%s has wrong version number (%i should be %i)",
1428 loadmodel->name, version, MD3VERSION);
1430 skinfiles = Mod_LoadSkinFiles();
1431 if (loadmodel->numskins < 1)
1432 loadmodel->numskins = 1;
1434 loadmodel->modeldatatypestring = "MD3";
1436 loadmodel->type = mod_alias;
1437 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1438 loadmodel->DrawSky = NULL;
1439 loadmodel->DrawAddWaterPlanes = NULL;
1440 loadmodel->Draw = R_Q1BSP_Draw;
1441 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1442 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1443 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1444 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1445 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1446 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1447 loadmodel->PointSuperContents = NULL;
1448 loadmodel->synctype = ST_RAND;
1449 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1450 i = LittleLong (pinmodel->flags);
1451 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1453 // set up some global info about the model
1454 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1455 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1457 // make skinscenes for the skins (no groups)
1458 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1459 for (i = 0;i < loadmodel->numskins;i++)
1461 loadmodel->skinscenes[i].firstframe = i;
1462 loadmodel->skinscenes[i].framecount = 1;
1463 loadmodel->skinscenes[i].loop = true;
1464 loadmodel->skinscenes[i].framerate = 10;
1468 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1469 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1471 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1472 loadmodel->animscenes[i].firstframe = i;
1473 loadmodel->animscenes[i].framecount = 1;
1474 loadmodel->animscenes[i].framerate = 10;
1475 loadmodel->animscenes[i].loop = true;
1479 loadmodel->num_tagframes = loadmodel->numframes;
1480 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1481 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1482 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1484 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1485 for (j = 0;j < 9;j++)
1486 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1487 for (j = 0;j < 3;j++)
1488 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1489 //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);
1495 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)))
1497 if (memcmp(pinmesh->identifier, "IDP3", 4))
1498 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1499 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1500 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1501 meshvertices += LittleLong(pinmesh->num_vertices);
1502 meshtriangles += LittleLong(pinmesh->num_triangles);
1505 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1506 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1507 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1508 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));
1509 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1510 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1511 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1512 loadmodel->surfmesh.num_vertices = meshvertices;
1513 loadmodel->surfmesh.num_triangles = meshtriangles;
1514 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1515 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1516 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1517 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1518 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1519 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1520 if (meshvertices <= 65536)
1522 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1523 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1524 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1529 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)))
1531 if (memcmp(pinmesh->identifier, "IDP3", 4))
1532 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1533 loadmodel->surfacelist[i] = i;
1534 surface = loadmodel->data_surfaces + i;
1535 surface->texture = loadmodel->data_textures + i;
1536 surface->num_firsttriangle = meshtriangles;
1537 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1538 surface->num_firstvertex = meshvertices;
1539 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1540 meshvertices += surface->num_vertices;
1541 meshtriangles += surface->num_triangles;
1543 for (j = 0;j < surface->num_triangles * 3;j++)
1544 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1545 for (j = 0;j < surface->num_vertices;j++)
1547 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1548 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1550 for (j = 0;j < loadmodel->numframes;j++)
1552 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1553 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1554 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1556 out->origin[0] = LittleShort(in->origin[0]);
1557 out->origin[1] = LittleShort(in->origin[1]);
1558 out->origin[2] = LittleShort(in->origin[2]);
1559 out->pitch = in->pitch;
1564 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1566 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1568 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1569 Mod_Alias_MorphMesh_CompileFrames();
1570 Mod_Alias_CalculateBoundingBox();
1571 Mod_FreeSkinFiles(skinfiles);
1573 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1574 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1577 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1579 zymtype1header_t *pinmodel, *pheader;
1580 unsigned char *pbase;
1581 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1582 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose;
1583 zymvertex_t *verts, *vertdata;
1587 skinfile_t *skinfiles;
1588 unsigned char *data;
1589 msurface_t *surface;
1591 pinmodel = (zymtype1header_t *)buffer;
1592 pbase = (unsigned char *)buffer;
1593 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1594 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1595 if (BigLong(pinmodel->type) != 1)
1596 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1598 loadmodel->modeldatatypestring = "ZYM";
1600 loadmodel->type = mod_alias;
1601 loadmodel->synctype = ST_RAND;
1605 pheader->type = BigLong(pinmodel->type);
1606 pheader->filesize = BigLong(pinmodel->filesize);
1607 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1608 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1609 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1610 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1611 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1612 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1613 pheader->radius = BigFloat(pinmodel->radius);
1614 pheader->numverts = BigLong(pinmodel->numverts);
1615 pheader->numtris = BigLong(pinmodel->numtris);
1616 pheader->numshaders = BigLong(pinmodel->numshaders);
1617 pheader->numbones = BigLong(pinmodel->numbones);
1618 pheader->numscenes = BigLong(pinmodel->numscenes);
1619 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1620 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1621 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1622 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1623 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1624 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1625 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1626 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1627 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1628 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1629 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1630 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1631 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1632 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1633 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1634 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1635 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1636 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1638 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1640 Con_Printf("%s has no geometry\n", loadmodel->name);
1643 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1645 Con_Printf("%s has no animations\n", loadmodel->name);
1649 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1650 loadmodel->DrawSky = NULL;
1651 loadmodel->DrawAddWaterPlanes = NULL;
1652 loadmodel->Draw = R_Q1BSP_Draw;
1653 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1654 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1655 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1656 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1657 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1658 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1659 loadmodel->PointSuperContents = NULL;
1661 loadmodel->numframes = pheader->numscenes;
1662 loadmodel->num_surfaces = pheader->numshaders;
1664 skinfiles = Mod_LoadSkinFiles();
1665 if (loadmodel->numskins < 1)
1666 loadmodel->numskins = 1;
1668 // make skinscenes for the skins (no groups)
1669 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1670 for (i = 0;i < loadmodel->numskins;i++)
1672 loadmodel->skinscenes[i].firstframe = i;
1673 loadmodel->skinscenes[i].framecount = 1;
1674 loadmodel->skinscenes[i].loop = true;
1675 loadmodel->skinscenes[i].framerate = 10;
1679 modelradius = pheader->radius;
1680 for (i = 0;i < 3;i++)
1682 loadmodel->normalmins[i] = pheader->mins[i];
1683 loadmodel->normalmaxs[i] = pheader->maxs[i];
1684 loadmodel->rotatedmins[i] = -modelradius;
1685 loadmodel->rotatedmaxs[i] = modelradius;
1687 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1688 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1689 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1690 if (loadmodel->yawmaxs[0] > modelradius)
1691 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1692 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1693 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1694 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1695 loadmodel->radius = modelradius;
1696 loadmodel->radius2 = modelradius * modelradius;
1698 // go through the lumps, swapping things
1700 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1701 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1702 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1703 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1704 for (i = 0;i < pheader->numscenes;i++)
1706 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1707 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1708 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1709 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1710 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1711 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1712 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1713 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1714 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1715 if (loadmodel->animscenes[i].framerate < 0)
1716 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1720 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1721 loadmodel->num_bones = pheader->numbones;
1722 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, pheader->numbones * sizeof(aliasbone_t));
1723 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1724 for (i = 0;i < pheader->numbones;i++)
1726 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1727 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1728 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1729 if (loadmodel->data_bones[i].parent >= i)
1730 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1733 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1734 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1735 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1736 for (i = 0;i < pheader->numverts;i++)
1738 vertbonecounts[i] = BigLong(bonecount[i]);
1739 if (vertbonecounts[i] != 1)
1740 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1743 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]);
1745 meshvertices = pheader->numverts;
1746 meshtriangles = pheader->numtris;
1748 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1749 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1750 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1751 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 * sizeof(float[12]) + loadmodel->num_bones * sizeof(float[12]));
1752 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1753 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1754 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1755 loadmodel->surfmesh.num_vertices = meshvertices;
1756 loadmodel->surfmesh.num_triangles = meshtriangles;
1757 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1758 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1759 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1760 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1761 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1762 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1763 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1764 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1765 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1766 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
1767 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1768 if (loadmodel->surfmesh.num_vertices <= 65536)
1770 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1771 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1772 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1775 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1776 poses = (float *) (pheader->lump_poses.start + pbase);
1777 for (i = 0;i < pheader->lump_poses.length / 4;i++)
1778 loadmodel->data_poses[i] = BigFloat(poses[i]);
1780 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1781 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1782 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1783 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1784 // (converting from weight-blending skeletal animation to
1785 // deformation-based skeletal animation)
1786 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1787 for (i = 0;i < loadmodel->num_bones;i++)
1789 const float *m = loadmodel->data_poses + i * 12;
1790 if (loadmodel->data_bones[i].parent >= 0)
1791 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1793 for (k = 0;k < 12;k++)
1794 bonepose[12*i+k] = m[k];
1796 for (j = 0;j < pheader->numverts;j++)
1798 // this format really should have had a per vertexweight weight value...
1799 // but since it does not, the weighting is completely ignored and
1800 // only one weight is allowed per vertex
1801 int boneindex = BigLong(vertdata[j].bonenum);
1802 const float *m = bonepose + 12 * boneindex;
1803 float relativeorigin[3];
1804 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1805 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1806 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1807 // transform the vertex bone weight into the base mesh
1808 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1809 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1810 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1811 // store the weight as the primary weight on this vertex
1812 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
1813 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = 1;
1816 // normals and tangents are calculated after elements are loaded
1818 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1819 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1820 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1821 for (i = 0;i < pheader->numverts;i++)
1823 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1824 // flip T coordinate for OpenGL
1825 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1828 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1829 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1830 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1832 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1833 //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)
1834 // byteswap, validate, and swap winding order of tris
1835 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1836 if (pheader->lump_render.length != count)
1837 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1838 renderlist = (int *) (pheader->lump_render.start + pbase);
1839 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1841 for (i = 0;i < loadmodel->num_surfaces;i++)
1843 int firstvertex, lastvertex;
1844 if (renderlist >= renderlistend)
1845 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1846 count = BigLong(*renderlist);renderlist++;
1847 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1848 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1850 loadmodel->surfacelist[i] = i;
1851 surface = loadmodel->data_surfaces + i;
1852 surface->texture = loadmodel->data_textures + i;
1853 surface->num_firsttriangle = meshtriangles;
1854 surface->num_triangles = count;
1855 meshtriangles += surface->num_triangles;
1857 // load the elements
1858 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
1859 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
1861 outelements[j*3+2] = BigLong(renderlist[0]);
1862 outelements[j*3+1] = BigLong(renderlist[1]);
1863 outelements[j*3+0] = BigLong(renderlist[2]);
1865 // validate the elements and find the used vertex range
1866 firstvertex = meshvertices;
1868 for (j = 0;j < surface->num_triangles * 3;j++)
1870 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
1871 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
1872 firstvertex = min(firstvertex, outelements[j]);
1873 lastvertex = max(lastvertex, outelements[j]);
1875 surface->num_firstvertex = firstvertex;
1876 surface->num_vertices = lastvertex + 1 - firstvertex;
1878 // since zym models do not have named sections, reuse their shader
1879 // name as the section name
1880 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
1881 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
1883 Mod_FreeSkinFiles(skinfiles);
1884 Mem_Free(vertbonecounts);
1887 // compute all the mesh information that was not loaded from the file
1888 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
1889 Mod_BuildBaseBonePoses();
1890 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
1891 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);
1892 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1894 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1897 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1899 dpmheader_t *pheader;
1903 unsigned char *pbase;
1904 int i, j, k, meshvertices, meshtriangles;
1905 skinfile_t *skinfiles;
1906 unsigned char *data;
1909 pheader = (dpmheader_t *)buffer;
1910 pbase = (unsigned char *)buffer;
1911 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
1912 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
1913 if (BigLong(pheader->type) != 2)
1914 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1916 loadmodel->modeldatatypestring = "DPM";
1918 loadmodel->type = mod_alias;
1919 loadmodel->synctype = ST_RAND;
1922 pheader->type = BigLong(pheader->type);
1923 pheader->filesize = BigLong(pheader->filesize);
1924 pheader->mins[0] = BigFloat(pheader->mins[0]);
1925 pheader->mins[1] = BigFloat(pheader->mins[1]);
1926 pheader->mins[2] = BigFloat(pheader->mins[2]);
1927 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
1928 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
1929 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
1930 pheader->yawradius = BigFloat(pheader->yawradius);
1931 pheader->allradius = BigFloat(pheader->allradius);
1932 pheader->num_bones = BigLong(pheader->num_bones);
1933 pheader->num_meshs = BigLong(pheader->num_meshs);
1934 pheader->num_frames = BigLong(pheader->num_frames);
1935 pheader->ofs_bones = BigLong(pheader->ofs_bones);
1936 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
1937 pheader->ofs_frames = BigLong(pheader->ofs_frames);
1939 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
1941 Con_Printf("%s has no geometry\n", loadmodel->name);
1944 if (pheader->num_frames < 1)
1946 Con_Printf("%s has no frames\n", loadmodel->name);
1950 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1951 loadmodel->DrawSky = NULL;
1952 loadmodel->DrawAddWaterPlanes = NULL;
1953 loadmodel->Draw = R_Q1BSP_Draw;
1954 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1955 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1956 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1957 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1958 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1959 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1960 loadmodel->PointSuperContents = NULL;
1963 for (i = 0;i < 3;i++)
1965 loadmodel->normalmins[i] = pheader->mins[i];
1966 loadmodel->normalmaxs[i] = pheader->maxs[i];
1967 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
1968 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
1969 loadmodel->rotatedmins[i] = -pheader->allradius;
1970 loadmodel->rotatedmaxs[i] = pheader->allradius;
1972 loadmodel->radius = pheader->allradius;
1973 loadmodel->radius2 = pheader->allradius * pheader->allradius;
1975 // load external .skin files if present
1976 skinfiles = Mod_LoadSkinFiles();
1977 if (loadmodel->numskins < 1)
1978 loadmodel->numskins = 1;
1983 // gather combined statistics from the meshes
1984 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
1985 for (i = 0;i < (int)pheader->num_meshs;i++)
1987 int numverts = BigLong(dpmmesh->num_verts);
1988 meshvertices += numverts;
1989 meshtriangles += BigLong(dpmmesh->num_tris);
1993 loadmodel->numframes = pheader->num_frames;
1994 loadmodel->num_bones = pheader->num_bones;
1995 loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
1996 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
1997 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1998 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1999 // do most allocations as one merged chunk
2000 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 * 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));
2001 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2002 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2003 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2004 loadmodel->surfmesh.num_vertices = meshvertices;
2005 loadmodel->surfmesh.num_triangles = meshtriangles;
2006 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2007 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2008 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2009 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2010 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2011 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2012 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2013 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
2014 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
2015 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
2016 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2017 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2018 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2019 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2020 if (meshvertices <= 65536)
2022 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2023 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2024 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2027 for (i = 0;i < loadmodel->numskins;i++)
2029 loadmodel->skinscenes[i].firstframe = i;
2030 loadmodel->skinscenes[i].framecount = 1;
2031 loadmodel->skinscenes[i].loop = true;
2032 loadmodel->skinscenes[i].framerate = 10;
2035 // load the bone info
2036 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2037 for (i = 0;i < loadmodel->num_bones;i++)
2039 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2040 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2041 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2042 if (loadmodel->data_bones[i].parent >= i)
2043 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2047 frame = (dpmframe_t *) (pbase + pheader->ofs_frames);
2048 for (i = 0;i < loadmodel->numframes;i++)
2051 memcpy(loadmodel->animscenes[i].name, frame->name, sizeof(frame->name));
2052 loadmodel->animscenes[i].firstframe = i;
2053 loadmodel->animscenes[i].framecount = 1;
2054 loadmodel->animscenes[i].loop = true;
2055 loadmodel->animscenes[i].framerate = 10;
2056 // load the bone poses for this frame
2057 poses = (float *) (pbase + BigLong(frame->ofs_bonepositions));
2058 for (j = 0;j < loadmodel->num_bones*12;j++)
2059 loadmodel->data_poses[i * loadmodel->num_bones*12 + j] = BigFloat(poses[j]);
2060 // stuff not processed here: mins, maxs, yawradius, allradius
2064 // load the meshes now
2065 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2068 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2069 // (converting from weight-blending skeletal animation to
2070 // deformation-based skeletal animation)
2071 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2072 for (i = 0;i < loadmodel->num_bones;i++)
2074 const float *m = loadmodel->data_poses + i * 12;
2075 if (loadmodel->data_bones[i].parent >= 0)
2076 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2078 for (k = 0;k < 12;k++)
2079 bonepose[12*i+k] = m[k];
2081 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2083 const int *inelements;
2085 const float *intexcoord;
2086 msurface_t *surface;
2088 loadmodel->surfacelist[i] = i;
2089 surface = loadmodel->data_surfaces + i;
2090 surface->texture = loadmodel->data_textures + i;
2091 surface->num_firsttriangle = meshtriangles;
2092 surface->num_triangles = BigLong(dpmmesh->num_tris);
2093 surface->num_firstvertex = meshvertices;
2094 surface->num_vertices = BigLong(dpmmesh->num_verts);
2095 meshvertices += surface->num_vertices;
2096 meshtriangles += surface->num_triangles;
2098 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2099 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2100 for (j = 0;j < surface->num_triangles;j++)
2102 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2103 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2104 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2105 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2110 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2111 for (j = 0;j < surface->num_vertices*2;j++)
2112 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2114 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2115 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2119 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2120 data += sizeof(dpmvertex_t);
2121 for (k = 0;k < numweights;k++)
2123 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2124 int boneindex = BigLong(vert->bonenum);
2125 const float *m = bonepose + 12 * boneindex;
2126 float influence = BigFloat(vert->influence);
2127 float relativeorigin[3], relativenormal[3];
2128 relativeorigin[0] = BigFloat(vert->origin[0]);
2129 relativeorigin[1] = BigFloat(vert->origin[1]);
2130 relativeorigin[2] = BigFloat(vert->origin[2]);
2131 relativenormal[0] = BigFloat(vert->normal[0]);
2132 relativenormal[1] = BigFloat(vert->normal[1]);
2133 relativenormal[2] = BigFloat(vert->normal[2]);
2134 // blend the vertex bone weights into the base mesh
2135 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2136 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2137 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2138 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2139 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2140 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2143 // store the first (and often only) weight
2144 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = influence;
2145 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
2149 // sort the new weight into this vertex's weight table
2150 // (which only accepts up to 4 bones per vertex)
2151 for (l = 0;l < 4;l++)
2153 if (loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] < influence)
2155 // move weaker influence weights out of the way first
2157 for (l2 = 3;l2 > l;l2--)
2159 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2-1];
2160 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2-1];
2162 // store the new weight
2163 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] = influence;
2164 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l] = boneindex;
2169 data += sizeof(dpmbonevert_t);
2172 for (l = 0;l < 4;l++)
2173 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l];
2174 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2176 float f = 1.0f / sum;
2177 for (l = 0;l < 4;l++)
2178 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] *= f;
2182 // since dpm models do not have named sections, reuse their shader name as the section name
2183 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2185 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2188 Mod_FreeSkinFiles(skinfiles);
2190 // compute all the mesh information that was not loaded from the file
2191 Mod_BuildBaseBonePoses();
2192 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);
2193 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2195 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2198 // no idea why PSK/PSA files contain weird quaternions but they do...
2199 #define PSKQUATNEGATIONS
2200 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2202 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2203 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2204 fs_offset_t filesize;
2209 pskboneinfo_t *bones;
2210 pskrawweights_t *rawweights;
2211 pskboneinfo_t *animbones;
2212 pskaniminfo_t *anims;
2213 pskanimkeys_t *animkeys;
2214 void *animfilebuffer, *animbuffer, *animbufferend;
2215 unsigned char *data;
2217 skinfile_t *skinfiles;
2218 char animname[MAX_QPATH];
2221 pchunk = (pskchunk_t *)buffer;
2222 if (strcmp(pchunk->id, "ACTRHEAD"))
2223 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2225 loadmodel->modeldatatypestring = "PSK";
2227 loadmodel->type = mod_alias;
2228 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2229 loadmodel->DrawSky = NULL;
2230 loadmodel->DrawAddWaterPlanes = NULL;
2231 loadmodel->Draw = R_Q1BSP_Draw;
2232 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2233 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2234 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2235 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2236 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2237 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2238 loadmodel->PointSuperContents = NULL;
2239 loadmodel->synctype = ST_RAND;
2241 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2242 strlcat(animname, ".psa", sizeof(animname));
2243 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2244 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2245 if (animbuffer == NULL)
2246 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2265 while (buffer < bufferend)
2267 pchunk = (pskchunk_t *)buffer;
2268 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2269 version = LittleLong(pchunk->version);
2270 recordsize = LittleLong(pchunk->recordsize);
2271 numrecords = LittleLong(pchunk->numrecords);
2272 if (developer.integer >= 100)
2273 Con_Printf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2274 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2275 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);
2276 if (!strcmp(pchunk->id, "ACTRHEAD"))
2280 else if (!strcmp(pchunk->id, "PNTS0000"))
2283 if (recordsize != sizeof(*p))
2284 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2285 // byteswap in place and keep the pointer
2286 numpnts = numrecords;
2287 pnts = (pskpnts_t *)buffer;
2288 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2290 p->origin[0] = LittleFloat(p->origin[0]);
2291 p->origin[1] = LittleFloat(p->origin[1]);
2292 p->origin[2] = LittleFloat(p->origin[2]);
2296 else if (!strcmp(pchunk->id, "VTXW0000"))
2299 if (recordsize != sizeof(*p))
2300 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2301 // byteswap in place and keep the pointer
2302 numvtxw = numrecords;
2303 vtxw = (pskvtxw_t *)buffer;
2304 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2306 p->pntsindex = LittleShort(p->pntsindex);
2307 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2308 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2309 if (p->pntsindex >= numpnts)
2311 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2317 else if (!strcmp(pchunk->id, "FACE0000"))
2320 if (recordsize != sizeof(*p))
2321 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2322 // byteswap in place and keep the pointer
2323 numfaces = numrecords;
2324 faces = (pskface_t *)buffer;
2325 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2327 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2328 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2329 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2330 p->group = LittleLong(p->group);
2331 if (p->vtxwindex[0] >= numvtxw)
2333 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2334 p->vtxwindex[0] = 0;
2336 if (p->vtxwindex[1] >= numvtxw)
2338 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2339 p->vtxwindex[1] = 0;
2341 if (p->vtxwindex[2] >= numvtxw)
2343 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2344 p->vtxwindex[2] = 0;
2349 else if (!strcmp(pchunk->id, "MATT0000"))
2352 if (recordsize != sizeof(*p))
2353 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2354 // byteswap in place and keep the pointer
2355 nummatts = numrecords;
2356 matts = (pskmatt_t *)buffer;
2357 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2363 else if (!strcmp(pchunk->id, "REFSKELT"))
2366 if (recordsize != sizeof(*p))
2367 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2368 // byteswap in place and keep the pointer
2369 numbones = numrecords;
2370 bones = (pskboneinfo_t *)buffer;
2371 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2373 p->numchildren = LittleLong(p->numchildren);
2374 p->parent = LittleLong(p->parent);
2375 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2376 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2377 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2378 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2379 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2380 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2381 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2382 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2383 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2384 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2385 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2386 #ifdef PSKQUATNEGATIONS
2389 p->basepose.quat[0] *= -1;
2390 p->basepose.quat[1] *= -1;
2391 p->basepose.quat[2] *= -1;
2395 p->basepose.quat[0] *= 1;
2396 p->basepose.quat[1] *= -1;
2397 p->basepose.quat[2] *= 1;
2400 if (p->parent < 0 || p->parent >= numbones)
2402 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2408 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2411 if (recordsize != sizeof(*p))
2412 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2413 // byteswap in place and keep the pointer
2414 numrawweights = numrecords;
2415 rawweights = (pskrawweights_t *)buffer;
2416 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2418 p->weight = LittleFloat(p->weight);
2419 p->pntsindex = LittleLong(p->pntsindex);
2420 p->boneindex = LittleLong(p->boneindex);
2421 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2423 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2426 if (p->boneindex < 0 || p->boneindex >= numbones)
2428 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2436 while (animbuffer < animbufferend)
2438 pchunk = (pskchunk_t *)animbuffer;
2439 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2440 version = LittleLong(pchunk->version);
2441 recordsize = LittleLong(pchunk->recordsize);
2442 numrecords = LittleLong(pchunk->numrecords);
2443 if (developer.integer >= 100)
2444 Con_Printf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2445 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2446 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);
2447 if (!strcmp(pchunk->id, "ANIMHEAD"))
2451 else if (!strcmp(pchunk->id, "BONENAMES"))
2454 if (recordsize != sizeof(*p))
2455 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2456 // byteswap in place and keep the pointer
2457 numanimbones = numrecords;
2458 animbones = (pskboneinfo_t *)animbuffer;
2459 // NOTE: supposedly psa does not need to match the psk model, the
2460 // bones missing from the psa would simply use their base
2461 // positions from the psk, but this is hard for me to implement
2462 // and people can easily make animations that match.
2463 if (numanimbones != numbones)
2464 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2465 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2467 p->numchildren = LittleLong(p->numchildren);
2468 p->parent = LittleLong(p->parent);
2469 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2470 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2471 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2472 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2473 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2474 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2475 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2476 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2477 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2478 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2479 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2480 #ifdef PSKQUATNEGATIONS
2483 p->basepose.quat[0] *= -1;
2484 p->basepose.quat[1] *= -1;
2485 p->basepose.quat[2] *= -1;
2489 p->basepose.quat[0] *= 1;
2490 p->basepose.quat[1] *= -1;
2491 p->basepose.quat[2] *= 1;
2494 if (p->parent < 0 || p->parent >= numanimbones)
2496 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2499 // check that bones are the same as in the base
2500 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2501 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2505 else if (!strcmp(pchunk->id, "ANIMINFO"))
2508 if (recordsize != sizeof(*p))
2509 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2510 // byteswap in place and keep the pointer
2511 numanims = numrecords;
2512 anims = (pskaniminfo_t *)animbuffer;
2513 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2515 p->numbones = LittleLong(p->numbones);
2516 p->playtime = LittleFloat(p->playtime);
2517 p->fps = LittleFloat(p->fps);
2518 p->firstframe = LittleLong(p->firstframe);
2519 p->numframes = LittleLong(p->numframes);
2520 if (p->numbones != numbones)
2521 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2525 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2528 if (recordsize != sizeof(*p))
2529 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2530 numanimkeys = numrecords;
2531 animkeys = (pskanimkeys_t *)animbuffer;
2532 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2534 p->origin[0] = LittleFloat(p->origin[0]);
2535 p->origin[1] = LittleFloat(p->origin[1]);
2536 p->origin[2] = LittleFloat(p->origin[2]);
2537 p->quat[0] = LittleFloat(p->quat[0]);
2538 p->quat[1] = LittleFloat(p->quat[1]);
2539 p->quat[2] = LittleFloat(p->quat[2]);
2540 p->quat[3] = LittleFloat(p->quat[3]);
2541 p->frametime = LittleFloat(p->frametime);
2542 #ifdef PSKQUATNEGATIONS
2543 if (index % numbones)
2558 // TODO: allocate bonepose stuff
2561 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2564 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2565 Host_Error("%s: missing required chunks", loadmodel->name);
2567 loadmodel->numframes = 0;
2568 for (index = 0;index < numanims;index++)
2569 loadmodel->numframes += anims[index].numframes;
2571 if (numanimkeys != numbones * loadmodel->numframes)
2572 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2574 meshvertices = numvtxw;
2575 meshtriangles = numfaces;
2577 // load external .skin files if present
2578 skinfiles = Mod_LoadSkinFiles();
2579 if (loadmodel->numskins < 1)
2580 loadmodel->numskins = 1;
2581 loadmodel->num_bones = numbones;
2582 loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
2583 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2584 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2585 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2586 loadmodel->surfmesh.num_vertices = meshvertices;
2587 loadmodel->surfmesh.num_triangles = meshtriangles;
2588 // do most allocations as one merged chunk
2589 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 * 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);
2590 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2591 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2592 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2593 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2594 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2595 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2596 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2597 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2598 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2599 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2600 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2601 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += loadmodel->surfmesh.num_vertices * sizeof(int[4]);
2602 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[4]);
2603 //loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
2604 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2605 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2606 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2607 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2608 if (loadmodel->surfmesh.num_vertices <= 65536)
2610 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2611 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2612 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2614 loadmodel->data_poses = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->num_poses * sizeof(float[12]));
2616 for (i = 0;i < loadmodel->numskins;i++)
2618 loadmodel->skinscenes[i].firstframe = i;
2619 loadmodel->skinscenes[i].framecount = 1;
2620 loadmodel->skinscenes[i].loop = true;
2621 loadmodel->skinscenes[i].framerate = 10;
2625 for (index = 0, i = 0;index < nummatts;index++)
2627 // since psk models do not have named sections, reuse their shader name as the section name
2628 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2629 loadmodel->surfacelist[index] = index;
2630 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2631 loadmodel->data_surfaces[index].num_firstvertex = 0;
2632 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2635 // copy over the vertex locations and texcoords
2636 for (index = 0;index < numvtxw;index++)
2638 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2639 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2640 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2641 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2642 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2645 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2646 for (index = 0;index < numfaces;index++)
2647 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2648 for (index = 0, i = 0;index < nummatts;index++)
2650 loadmodel->data_surfaces[index].num_firsttriangle = i;
2651 i += loadmodel->data_surfaces[index].num_triangles;
2652 loadmodel->data_surfaces[index].num_triangles = 0;
2654 for (index = 0;index < numfaces;index++)
2656 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2657 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2658 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2659 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2662 // copy over the bones
2663 for (index = 0;index < numbones;index++)
2665 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2666 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2667 if (loadmodel->data_bones[index].parent >= index)
2668 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2671 // sort the psk point weights into the vertex weight tables
2672 // (which only accept up to 4 bones per vertex)
2673 for (index = 0;index < numvtxw;index++)
2677 for (j = 0;j < numrawweights;j++)
2679 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2681 int boneindex = rawweights[j].boneindex;
2682 float influence = rawweights[j].weight;
2683 for (l = 0;l < 4;l++)
2685 if (loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] < influence)
2687 // move lower influence weights out of the way first
2689 for (l2 = 3;l2 > l;l2--)
2691 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2-1];
2692 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2-1];
2694 // store the new weight
2695 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] = influence;
2696 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l] = boneindex;
2703 for (l = 0;l < 4;l++)
2704 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l];
2705 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2707 float f = 1.0f / sum;
2708 for (l = 0;l < 4;l++)
2709 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] *= f;
2713 // set up the animscenes based on the anims
2714 for (index = 0, i = 0;index < numanims;index++)
2716 for (j = 0;j < anims[index].numframes;j++, i++)
2718 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2719 loadmodel->animscenes[i].firstframe = i;
2720 loadmodel->animscenes[i].framecount = 1;
2721 loadmodel->animscenes[i].loop = true;
2722 loadmodel->animscenes[i].framerate = 10;
2726 // load the poses from the animkeys
2727 for (index = 0;index < numanimkeys;index++)
2729 pskanimkeys_t *k = animkeys + index;
2731 Matrix4x4_FromOriginQuat(&matrix, k->origin[0], k->origin[1], k->origin[2], k->quat[0], k->quat[1], k->quat[2], k->quat[3]);
2732 Matrix4x4_ToArray12FloatD3D(&matrix, loadmodel->data_poses + index*12);
2734 Mod_FreeSkinFiles(skinfiles);
2735 Mem_Free(animfilebuffer);
2737 // compute all the mesh information that was not loaded from the file
2738 // TODO: honor smoothing groups somehow?
2739 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2740 Mod_BuildBaseBonePoses();
2741 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2742 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);
2743 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2744 Mod_Alias_CalculateBoundingBox();
2746 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;