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->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
884 loadmodel->sortedmodelsurfaces[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->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1247 loadmodel->sortedmodelsurfaces[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->sortedmodelsurfaces = (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->sortedmodelsurfaces[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);
1572 Mod_MakeSortedSurfaces(loadmodel);
1574 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1575 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1578 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1580 zymtype1header_t *pinmodel, *pheader;
1581 unsigned char *pbase;
1582 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1583 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose;
1584 zymvertex_t *verts, *vertdata;
1588 skinfile_t *skinfiles;
1589 unsigned char *data;
1590 msurface_t *surface;
1592 pinmodel = (zymtype1header_t *)buffer;
1593 pbase = (unsigned char *)buffer;
1594 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1595 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1596 if (BigLong(pinmodel->type) != 1)
1597 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1599 loadmodel->modeldatatypestring = "ZYM";
1601 loadmodel->type = mod_alias;
1602 loadmodel->synctype = ST_RAND;
1606 pheader->type = BigLong(pinmodel->type);
1607 pheader->filesize = BigLong(pinmodel->filesize);
1608 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1609 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1610 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1611 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1612 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1613 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1614 pheader->radius = BigFloat(pinmodel->radius);
1615 pheader->numverts = BigLong(pinmodel->numverts);
1616 pheader->numtris = BigLong(pinmodel->numtris);
1617 pheader->numshaders = BigLong(pinmodel->numshaders);
1618 pheader->numbones = BigLong(pinmodel->numbones);
1619 pheader->numscenes = BigLong(pinmodel->numscenes);
1620 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1621 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1622 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1623 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1624 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1625 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1626 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1627 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1628 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1629 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1630 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1631 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1632 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1633 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1634 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1635 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1636 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1637 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1639 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1641 Con_Printf("%s has no geometry\n", loadmodel->name);
1644 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1646 Con_Printf("%s has no animations\n", loadmodel->name);
1650 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1651 loadmodel->DrawSky = NULL;
1652 loadmodel->DrawAddWaterPlanes = NULL;
1653 loadmodel->Draw = R_Q1BSP_Draw;
1654 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1655 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1656 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1657 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1658 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1659 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1660 loadmodel->PointSuperContents = NULL;
1662 loadmodel->numframes = pheader->numscenes;
1663 loadmodel->num_surfaces = pheader->numshaders;
1665 skinfiles = Mod_LoadSkinFiles();
1666 if (loadmodel->numskins < 1)
1667 loadmodel->numskins = 1;
1669 // make skinscenes for the skins (no groups)
1670 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1671 for (i = 0;i < loadmodel->numskins;i++)
1673 loadmodel->skinscenes[i].firstframe = i;
1674 loadmodel->skinscenes[i].framecount = 1;
1675 loadmodel->skinscenes[i].loop = true;
1676 loadmodel->skinscenes[i].framerate = 10;
1680 modelradius = pheader->radius;
1681 for (i = 0;i < 3;i++)
1683 loadmodel->normalmins[i] = pheader->mins[i];
1684 loadmodel->normalmaxs[i] = pheader->maxs[i];
1685 loadmodel->rotatedmins[i] = -modelradius;
1686 loadmodel->rotatedmaxs[i] = modelradius;
1688 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1689 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1690 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1691 if (loadmodel->yawmaxs[0] > modelradius)
1692 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1693 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1694 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1695 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1696 loadmodel->radius = modelradius;
1697 loadmodel->radius2 = modelradius * modelradius;
1699 // go through the lumps, swapping things
1701 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1702 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1703 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1704 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1705 for (i = 0;i < pheader->numscenes;i++)
1707 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1708 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1709 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1710 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1711 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1712 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1713 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1714 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1715 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1716 if (loadmodel->animscenes[i].framerate < 0)
1717 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1721 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1722 loadmodel->num_bones = pheader->numbones;
1723 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, pheader->numbones * sizeof(aliasbone_t));
1724 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1725 for (i = 0;i < pheader->numbones;i++)
1727 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1728 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1729 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1730 if (loadmodel->data_bones[i].parent >= i)
1731 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1734 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1735 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1736 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1737 for (i = 0;i < pheader->numverts;i++)
1739 vertbonecounts[i] = BigLong(bonecount[i]);
1740 if (vertbonecounts[i] != 1)
1741 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1744 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]);
1746 meshvertices = pheader->numverts;
1747 meshtriangles = pheader->numtris;
1749 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1750 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1751 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1752 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]));
1753 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1754 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1755 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1756 loadmodel->surfmesh.num_vertices = meshvertices;
1757 loadmodel->surfmesh.num_triangles = meshtriangles;
1758 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1759 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1760 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1761 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1762 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1763 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1764 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1765 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1766 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1767 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
1768 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1769 if (loadmodel->surfmesh.num_vertices <= 65536)
1771 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1772 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1773 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1776 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1777 poses = (float *) (pheader->lump_poses.start + pbase);
1778 for (i = 0;i < pheader->lump_poses.length / 4;i++)
1779 loadmodel->data_poses[i] = BigFloat(poses[i]);
1781 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1782 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1783 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1784 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1785 // (converting from weight-blending skeletal animation to
1786 // deformation-based skeletal animation)
1787 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1788 for (i = 0;i < loadmodel->num_bones;i++)
1790 const float *m = loadmodel->data_poses + i * 12;
1791 if (loadmodel->data_bones[i].parent >= 0)
1792 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1794 for (k = 0;k < 12;k++)
1795 bonepose[12*i+k] = m[k];
1797 for (j = 0;j < pheader->numverts;j++)
1799 // this format really should have had a per vertexweight weight value...
1800 // but since it does not, the weighting is completely ignored and
1801 // only one weight is allowed per vertex
1802 int boneindex = BigLong(vertdata[j].bonenum);
1803 const float *m = bonepose + 12 * boneindex;
1804 float relativeorigin[3];
1805 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1806 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1807 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1808 // transform the vertex bone weight into the base mesh
1809 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1810 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1811 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1812 // store the weight as the primary weight on this vertex
1813 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
1814 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = 1;
1817 // normals and tangents are calculated after elements are loaded
1819 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1820 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1821 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1822 for (i = 0;i < pheader->numverts;i++)
1824 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1825 // flip T coordinate for OpenGL
1826 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1829 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1830 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1831 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1833 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1834 //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)
1835 // byteswap, validate, and swap winding order of tris
1836 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1837 if (pheader->lump_render.length != count)
1838 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1839 renderlist = (int *) (pheader->lump_render.start + pbase);
1840 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1842 for (i = 0;i < loadmodel->num_surfaces;i++)
1844 int firstvertex, lastvertex;
1845 if (renderlist >= renderlistend)
1846 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1847 count = BigLong(*renderlist);renderlist++;
1848 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1849 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1851 loadmodel->sortedmodelsurfaces[i] = i;
1852 surface = loadmodel->data_surfaces + i;
1853 surface->texture = loadmodel->data_textures + i;
1854 surface->num_firsttriangle = meshtriangles;
1855 surface->num_triangles = count;
1856 meshtriangles += surface->num_triangles;
1858 // load the elements
1859 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
1860 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
1862 outelements[j*3+2] = BigLong(renderlist[0]);
1863 outelements[j*3+1] = BigLong(renderlist[1]);
1864 outelements[j*3+0] = BigLong(renderlist[2]);
1866 // validate the elements and find the used vertex range
1867 firstvertex = meshvertices;
1869 for (j = 0;j < surface->num_triangles * 3;j++)
1871 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
1872 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
1873 firstvertex = min(firstvertex, outelements[j]);
1874 lastvertex = max(lastvertex, outelements[j]);
1876 surface->num_firstvertex = firstvertex;
1877 surface->num_vertices = lastvertex + 1 - firstvertex;
1879 // since zym models do not have named sections, reuse their shader
1880 // name as the section name
1881 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
1882 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
1884 Mod_FreeSkinFiles(skinfiles);
1885 Mem_Free(vertbonecounts);
1887 Mod_MakeSortedSurfaces(loadmodel);
1889 // compute all the mesh information that was not loaded from the file
1890 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
1891 Mod_BuildBaseBonePoses();
1892 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
1893 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);
1894 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1896 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1899 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1901 dpmheader_t *pheader;
1905 unsigned char *pbase;
1906 int i, j, k, meshvertices, meshtriangles;
1907 skinfile_t *skinfiles;
1908 unsigned char *data;
1911 pheader = (dpmheader_t *)buffer;
1912 pbase = (unsigned char *)buffer;
1913 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
1914 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
1915 if (BigLong(pheader->type) != 2)
1916 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1918 loadmodel->modeldatatypestring = "DPM";
1920 loadmodel->type = mod_alias;
1921 loadmodel->synctype = ST_RAND;
1924 pheader->type = BigLong(pheader->type);
1925 pheader->filesize = BigLong(pheader->filesize);
1926 pheader->mins[0] = BigFloat(pheader->mins[0]);
1927 pheader->mins[1] = BigFloat(pheader->mins[1]);
1928 pheader->mins[2] = BigFloat(pheader->mins[2]);
1929 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
1930 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
1931 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
1932 pheader->yawradius = BigFloat(pheader->yawradius);
1933 pheader->allradius = BigFloat(pheader->allradius);
1934 pheader->num_bones = BigLong(pheader->num_bones);
1935 pheader->num_meshs = BigLong(pheader->num_meshs);
1936 pheader->num_frames = BigLong(pheader->num_frames);
1937 pheader->ofs_bones = BigLong(pheader->ofs_bones);
1938 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
1939 pheader->ofs_frames = BigLong(pheader->ofs_frames);
1941 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
1943 Con_Printf("%s has no geometry\n", loadmodel->name);
1946 if (pheader->num_frames < 1)
1948 Con_Printf("%s has no frames\n", loadmodel->name);
1952 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1953 loadmodel->DrawSky = NULL;
1954 loadmodel->DrawAddWaterPlanes = NULL;
1955 loadmodel->Draw = R_Q1BSP_Draw;
1956 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1957 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1958 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1959 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1960 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1961 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1962 loadmodel->PointSuperContents = NULL;
1965 for (i = 0;i < 3;i++)
1967 loadmodel->normalmins[i] = pheader->mins[i];
1968 loadmodel->normalmaxs[i] = pheader->maxs[i];
1969 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
1970 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
1971 loadmodel->rotatedmins[i] = -pheader->allradius;
1972 loadmodel->rotatedmaxs[i] = pheader->allradius;
1974 loadmodel->radius = pheader->allradius;
1975 loadmodel->radius2 = pheader->allradius * pheader->allradius;
1977 // load external .skin files if present
1978 skinfiles = Mod_LoadSkinFiles();
1979 if (loadmodel->numskins < 1)
1980 loadmodel->numskins = 1;
1985 // gather combined statistics from the meshes
1986 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
1987 for (i = 0;i < (int)pheader->num_meshs;i++)
1989 int numverts = BigLong(dpmmesh->num_verts);
1990 meshvertices += numverts;
1991 meshtriangles += BigLong(dpmmesh->num_tris);
1995 loadmodel->numframes = pheader->num_frames;
1996 loadmodel->num_bones = pheader->num_bones;
1997 loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
1998 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
1999 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2000 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2001 // do most allocations as one merged chunk
2002 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));
2003 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2004 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2005 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2006 loadmodel->surfmesh.num_vertices = meshvertices;
2007 loadmodel->surfmesh.num_triangles = meshtriangles;
2008 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2009 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2010 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2011 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2012 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2013 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2014 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2015 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
2016 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
2017 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
2018 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2019 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2020 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2021 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2022 if (meshvertices <= 65536)
2024 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2025 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2026 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2029 for (i = 0;i < loadmodel->numskins;i++)
2031 loadmodel->skinscenes[i].firstframe = i;
2032 loadmodel->skinscenes[i].framecount = 1;
2033 loadmodel->skinscenes[i].loop = true;
2034 loadmodel->skinscenes[i].framerate = 10;
2037 // load the bone info
2038 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2039 for (i = 0;i < loadmodel->num_bones;i++)
2041 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2042 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2043 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2044 if (loadmodel->data_bones[i].parent >= i)
2045 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2049 frame = (dpmframe_t *) (pbase + pheader->ofs_frames);
2050 for (i = 0;i < loadmodel->numframes;i++)
2053 memcpy(loadmodel->animscenes[i].name, frame->name, sizeof(frame->name));
2054 loadmodel->animscenes[i].firstframe = i;
2055 loadmodel->animscenes[i].framecount = 1;
2056 loadmodel->animscenes[i].loop = true;
2057 loadmodel->animscenes[i].framerate = 10;
2058 // load the bone poses for this frame
2059 poses = (float *) (pbase + BigLong(frame->ofs_bonepositions));
2060 for (j = 0;j < loadmodel->num_bones*12;j++)
2061 loadmodel->data_poses[i * loadmodel->num_bones*12 + j] = BigFloat(poses[j]);
2062 // stuff not processed here: mins, maxs, yawradius, allradius
2066 // load the meshes now
2067 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2070 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2071 // (converting from weight-blending skeletal animation to
2072 // deformation-based skeletal animation)
2073 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2074 for (i = 0;i < loadmodel->num_bones;i++)
2076 const float *m = loadmodel->data_poses + i * 12;
2077 if (loadmodel->data_bones[i].parent >= 0)
2078 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2080 for (k = 0;k < 12;k++)
2081 bonepose[12*i+k] = m[k];
2083 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2085 const int *inelements;
2087 const float *intexcoord;
2088 msurface_t *surface;
2090 loadmodel->sortedmodelsurfaces[i] = i;
2091 surface = loadmodel->data_surfaces + i;
2092 surface->texture = loadmodel->data_textures + i;
2093 surface->num_firsttriangle = meshtriangles;
2094 surface->num_triangles = BigLong(dpmmesh->num_tris);
2095 surface->num_firstvertex = meshvertices;
2096 surface->num_vertices = BigLong(dpmmesh->num_verts);
2097 meshvertices += surface->num_vertices;
2098 meshtriangles += surface->num_triangles;
2100 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2101 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2102 for (j = 0;j < surface->num_triangles;j++)
2104 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2105 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2106 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2107 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2112 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2113 for (j = 0;j < surface->num_vertices*2;j++)
2114 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2116 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2117 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2121 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2122 data += sizeof(dpmvertex_t);
2123 for (k = 0;k < numweights;k++)
2125 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2126 int boneindex = BigLong(vert->bonenum);
2127 const float *m = bonepose + 12 * boneindex;
2128 float influence = BigFloat(vert->influence);
2129 float relativeorigin[3], relativenormal[3];
2130 relativeorigin[0] = BigFloat(vert->origin[0]);
2131 relativeorigin[1] = BigFloat(vert->origin[1]);
2132 relativeorigin[2] = BigFloat(vert->origin[2]);
2133 relativenormal[0] = BigFloat(vert->normal[0]);
2134 relativenormal[1] = BigFloat(vert->normal[1]);
2135 relativenormal[2] = BigFloat(vert->normal[2]);
2136 // blend the vertex bone weights into the base mesh
2137 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2138 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2139 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2140 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2141 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2142 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2145 // store the first (and often only) weight
2146 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = influence;
2147 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
2151 // sort the new weight into this vertex's weight table
2152 // (which only accepts up to 4 bones per vertex)
2153 for (l = 0;l < 4;l++)
2155 if (loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] < influence)
2157 // move weaker influence weights out of the way first
2159 for (l2 = 3;l2 > l;l2--)
2161 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2-1];
2162 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2-1];
2164 // store the new weight
2165 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] = influence;
2166 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l] = boneindex;
2171 data += sizeof(dpmbonevert_t);
2174 for (l = 0;l < 4;l++)
2175 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l];
2176 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2178 float f = 1.0f / sum;
2179 for (l = 0;l < 4;l++)
2180 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] *= f;
2184 // since dpm models do not have named sections, reuse their shader name as the section name
2185 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2187 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2190 Mod_FreeSkinFiles(skinfiles);
2191 Mod_MakeSortedSurfaces(loadmodel);
2193 // compute all the mesh information that was not loaded from the file
2194 Mod_BuildBaseBonePoses();
2195 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);
2196 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2198 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2201 // no idea why PSK/PSA files contain weird quaternions but they do...
2202 #define PSKQUATNEGATIONS
2203 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2205 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2206 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2207 fs_offset_t filesize;
2212 pskboneinfo_t *bones;
2213 pskrawweights_t *rawweights;
2214 pskboneinfo_t *animbones;
2215 pskaniminfo_t *anims;
2216 pskanimkeys_t *animkeys;
2217 void *animfilebuffer, *animbuffer, *animbufferend;
2218 unsigned char *data;
2220 skinfile_t *skinfiles;
2221 char animname[MAX_QPATH];
2224 pchunk = (pskchunk_t *)buffer;
2225 if (strcmp(pchunk->id, "ACTRHEAD"))
2226 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2228 loadmodel->modeldatatypestring = "PSK";
2230 loadmodel->type = mod_alias;
2231 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2232 loadmodel->DrawSky = NULL;
2233 loadmodel->DrawAddWaterPlanes = NULL;
2234 loadmodel->Draw = R_Q1BSP_Draw;
2235 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2236 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2237 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2238 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2239 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2240 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2241 loadmodel->PointSuperContents = NULL;
2242 loadmodel->synctype = ST_RAND;
2244 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2245 strlcat(animname, ".psa", sizeof(animname));
2246 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2247 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2248 if (animbuffer == NULL)
2249 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2268 while (buffer < bufferend)
2270 pchunk = (pskchunk_t *)buffer;
2271 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2272 version = LittleLong(pchunk->version);
2273 recordsize = LittleLong(pchunk->recordsize);
2274 numrecords = LittleLong(pchunk->numrecords);
2275 if (developer.integer >= 100)
2276 Con_Printf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2277 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2278 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);
2279 if (!strcmp(pchunk->id, "ACTRHEAD"))
2283 else if (!strcmp(pchunk->id, "PNTS0000"))
2286 if (recordsize != sizeof(*p))
2287 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2288 // byteswap in place and keep the pointer
2289 numpnts = numrecords;
2290 pnts = (pskpnts_t *)buffer;
2291 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2293 p->origin[0] = LittleFloat(p->origin[0]);
2294 p->origin[1] = LittleFloat(p->origin[1]);
2295 p->origin[2] = LittleFloat(p->origin[2]);
2299 else if (!strcmp(pchunk->id, "VTXW0000"))
2302 if (recordsize != sizeof(*p))
2303 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2304 // byteswap in place and keep the pointer
2305 numvtxw = numrecords;
2306 vtxw = (pskvtxw_t *)buffer;
2307 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2309 p->pntsindex = LittleShort(p->pntsindex);
2310 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2311 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2312 if (p->pntsindex >= numpnts)
2314 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2320 else if (!strcmp(pchunk->id, "FACE0000"))
2323 if (recordsize != sizeof(*p))
2324 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2325 // byteswap in place and keep the pointer
2326 numfaces = numrecords;
2327 faces = (pskface_t *)buffer;
2328 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2330 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2331 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2332 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2333 p->group = LittleLong(p->group);
2334 if (p->vtxwindex[0] >= numvtxw)
2336 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2337 p->vtxwindex[0] = 0;
2339 if (p->vtxwindex[1] >= numvtxw)
2341 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2342 p->vtxwindex[1] = 0;
2344 if (p->vtxwindex[2] >= numvtxw)
2346 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2347 p->vtxwindex[2] = 0;
2352 else if (!strcmp(pchunk->id, "MATT0000"))
2355 if (recordsize != sizeof(*p))
2356 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2357 // byteswap in place and keep the pointer
2358 nummatts = numrecords;
2359 matts = (pskmatt_t *)buffer;
2360 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2366 else if (!strcmp(pchunk->id, "REFSKELT"))
2369 if (recordsize != sizeof(*p))
2370 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2371 // byteswap in place and keep the pointer
2372 numbones = numrecords;
2373 bones = (pskboneinfo_t *)buffer;
2374 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2376 p->numchildren = LittleLong(p->numchildren);
2377 p->parent = LittleLong(p->parent);
2378 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2379 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2380 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2381 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2382 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2383 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2384 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2385 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2386 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2387 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2388 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2389 #ifdef PSKQUATNEGATIONS
2392 p->basepose.quat[0] *= -1;
2393 p->basepose.quat[1] *= -1;
2394 p->basepose.quat[2] *= -1;
2398 p->basepose.quat[0] *= 1;
2399 p->basepose.quat[1] *= -1;
2400 p->basepose.quat[2] *= 1;
2403 if (p->parent < 0 || p->parent >= numbones)
2405 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2411 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2414 if (recordsize != sizeof(*p))
2415 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2416 // byteswap in place and keep the pointer
2417 numrawweights = numrecords;
2418 rawweights = (pskrawweights_t *)buffer;
2419 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2421 p->weight = LittleFloat(p->weight);
2422 p->pntsindex = LittleLong(p->pntsindex);
2423 p->boneindex = LittleLong(p->boneindex);
2424 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2426 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2429 if (p->boneindex < 0 || p->boneindex >= numbones)
2431 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2439 while (animbuffer < animbufferend)
2441 pchunk = (pskchunk_t *)animbuffer;
2442 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2443 version = LittleLong(pchunk->version);
2444 recordsize = LittleLong(pchunk->recordsize);
2445 numrecords = LittleLong(pchunk->numrecords);
2446 if (developer.integer >= 100)
2447 Con_Printf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2448 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2449 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);
2450 if (!strcmp(pchunk->id, "ANIMHEAD"))
2454 else if (!strcmp(pchunk->id, "BONENAMES"))
2457 if (recordsize != sizeof(*p))
2458 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2459 // byteswap in place and keep the pointer
2460 numanimbones = numrecords;
2461 animbones = (pskboneinfo_t *)animbuffer;
2462 // NOTE: supposedly psa does not need to match the psk model, the
2463 // bones missing from the psa would simply use their base
2464 // positions from the psk, but this is hard for me to implement
2465 // and people can easily make animations that match.
2466 if (numanimbones != numbones)
2467 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2468 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2470 p->numchildren = LittleLong(p->numchildren);
2471 p->parent = LittleLong(p->parent);
2472 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2473 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2474 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2475 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2476 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2477 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2478 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2479 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2480 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2481 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2482 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2483 #ifdef PSKQUATNEGATIONS
2486 p->basepose.quat[0] *= -1;
2487 p->basepose.quat[1] *= -1;
2488 p->basepose.quat[2] *= -1;
2492 p->basepose.quat[0] *= 1;
2493 p->basepose.quat[1] *= -1;
2494 p->basepose.quat[2] *= 1;
2497 if (p->parent < 0 || p->parent >= numanimbones)
2499 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2502 // check that bones are the same as in the base
2503 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2504 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2508 else if (!strcmp(pchunk->id, "ANIMINFO"))
2511 if (recordsize != sizeof(*p))
2512 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2513 // byteswap in place and keep the pointer
2514 numanims = numrecords;
2515 anims = (pskaniminfo_t *)animbuffer;
2516 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2518 p->numbones = LittleLong(p->numbones);
2519 p->playtime = LittleFloat(p->playtime);
2520 p->fps = LittleFloat(p->fps);
2521 p->firstframe = LittleLong(p->firstframe);
2522 p->numframes = LittleLong(p->numframes);
2523 if (p->numbones != numbones)
2524 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2528 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2531 if (recordsize != sizeof(*p))
2532 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2533 numanimkeys = numrecords;
2534 animkeys = (pskanimkeys_t *)animbuffer;
2535 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2537 p->origin[0] = LittleFloat(p->origin[0]);
2538 p->origin[1] = LittleFloat(p->origin[1]);
2539 p->origin[2] = LittleFloat(p->origin[2]);
2540 p->quat[0] = LittleFloat(p->quat[0]);
2541 p->quat[1] = LittleFloat(p->quat[1]);
2542 p->quat[2] = LittleFloat(p->quat[2]);
2543 p->quat[3] = LittleFloat(p->quat[3]);
2544 p->frametime = LittleFloat(p->frametime);
2545 #ifdef PSKQUATNEGATIONS
2546 if (index % numbones)
2561 // TODO: allocate bonepose stuff
2564 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2567 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2568 Host_Error("%s: missing required chunks", loadmodel->name);
2570 loadmodel->numframes = 0;
2571 for (index = 0;index < numanims;index++)
2572 loadmodel->numframes += anims[index].numframes;
2574 if (numanimkeys != numbones * loadmodel->numframes)
2575 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2577 meshvertices = numvtxw;
2578 meshtriangles = numfaces;
2580 // load external .skin files if present
2581 skinfiles = Mod_LoadSkinFiles();
2582 if (loadmodel->numskins < 1)
2583 loadmodel->numskins = 1;
2584 loadmodel->num_bones = numbones;
2585 loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
2586 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2587 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2588 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2589 loadmodel->surfmesh.num_vertices = meshvertices;
2590 loadmodel->surfmesh.num_triangles = meshtriangles;
2591 // do most allocations as one merged chunk
2592 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);
2593 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2594 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2595 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2596 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2597 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2598 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2599 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2600 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2601 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2602 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2603 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2604 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += loadmodel->surfmesh.num_vertices * sizeof(int[4]);
2605 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[4]);
2606 //loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
2607 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2608 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2609 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2610 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2611 if (loadmodel->surfmesh.num_vertices <= 65536)
2613 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2614 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2615 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2617 loadmodel->data_poses = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->num_poses * sizeof(float[12]));
2619 for (i = 0;i < loadmodel->numskins;i++)
2621 loadmodel->skinscenes[i].firstframe = i;
2622 loadmodel->skinscenes[i].framecount = 1;
2623 loadmodel->skinscenes[i].loop = true;
2624 loadmodel->skinscenes[i].framerate = 10;
2628 for (index = 0, i = 0;index < nummatts;index++)
2630 // since psk models do not have named sections, reuse their shader name as the section name
2631 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2632 loadmodel->sortedmodelsurfaces[index] = index;
2633 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2634 loadmodel->data_surfaces[index].num_firstvertex = 0;
2635 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2638 // copy over the vertex locations and texcoords
2639 for (index = 0;index < numvtxw;index++)
2641 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2642 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2643 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2644 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2645 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2648 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2649 for (index = 0;index < numfaces;index++)
2650 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2651 for (index = 0, i = 0;index < nummatts;index++)
2653 loadmodel->data_surfaces[index].num_firsttriangle = i;
2654 i += loadmodel->data_surfaces[index].num_triangles;
2655 loadmodel->data_surfaces[index].num_triangles = 0;
2657 for (index = 0;index < numfaces;index++)
2659 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2660 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2661 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2662 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2665 // copy over the bones
2666 for (index = 0;index < numbones;index++)
2668 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2669 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2670 if (loadmodel->data_bones[index].parent >= index)
2671 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2674 // sort the psk point weights into the vertex weight tables
2675 // (which only accept up to 4 bones per vertex)
2676 for (index = 0;index < numvtxw;index++)
2680 for (j = 0;j < numrawweights;j++)
2682 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2684 int boneindex = rawweights[j].boneindex;
2685 float influence = rawweights[j].weight;
2686 for (l = 0;l < 4;l++)
2688 if (loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] < influence)
2690 // move lower influence weights out of the way first
2692 for (l2 = 3;l2 > l;l2--)
2694 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2-1];
2695 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2-1];
2697 // store the new weight
2698 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] = influence;
2699 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l] = boneindex;
2706 for (l = 0;l < 4;l++)
2707 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l];
2708 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2710 float f = 1.0f / sum;
2711 for (l = 0;l < 4;l++)
2712 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] *= f;
2716 // set up the animscenes based on the anims
2717 for (index = 0, i = 0;index < numanims;index++)
2719 for (j = 0;j < anims[index].numframes;j++, i++)
2721 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2722 loadmodel->animscenes[i].firstframe = i;
2723 loadmodel->animscenes[i].framecount = 1;
2724 loadmodel->animscenes[i].loop = true;
2725 loadmodel->animscenes[i].framerate = 10;
2729 // load the poses from the animkeys
2730 for (index = 0;index < numanimkeys;index++)
2732 pskanimkeys_t *k = animkeys + index;
2734 Matrix4x4_FromOriginQuat(&matrix, k->origin[0], k->origin[1], k->origin[2], k->quat[0], k->quat[1], k->quat[2], k->quat[3]);
2735 Matrix4x4_ToArray12FloatD3D(&matrix, loadmodel->data_poses + index*12);
2737 Mod_FreeSkinFiles(skinfiles);
2738 Mem_Free(animfilebuffer);
2739 Mod_MakeSortedSurfaces(loadmodel);
2741 // compute all the mesh information that was not loaded from the file
2742 // TODO: honor smoothing groups somehow?
2743 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2744 Mod_BuildBaseBonePoses();
2745 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2746 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);
2747 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2748 Mod_Alias_CalculateBoundingBox();
2750 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2753 void Mod_OBJ_Load(dp_model_t *mod, void *buffer, void *bufferend)
2756 const char *textbase = (char *)buffer, *text = textbase;
2760 char materialname[MAX_QPATH];
2761 int j, index1, index2, index3, first, prev, index;
2764 int numtriangles = 0;
2765 int maxtriangles = 32768;
2766 int *element3i = Mem_Alloc(tempmempool, maxtriangles * sizeof(int[3]));
2768 int numsurfaces = 0;
2769 int maxsurfaces = 0;
2770 msurface_t *surfaces = NULL;
2774 float *oldv, *oldvt, *oldvn;
2775 int maxv = 65536, numv = 1;
2776 int maxvt = 65536, numvt = 1;
2777 int maxvn = 65536, numvn = 1;
2778 int maxverthash = 65536, numverthash = 0;
2779 int numhashindex = 65536;
2780 struct objverthash_s
2782 struct objverthash_s *next;
2788 *hash, **verthash = Mem_Alloc(tempmempool, numhashindex * sizeof(*verthash)), *verthashdata = Mem_Alloc(tempmempool, maxverthash * sizeof(*verthashdata)), *oldverthashdata;
2789 skinfile_t *skinfiles;
2791 dpsnprintf(materialname, sizeof(materialname), "%s", loadmodel->name);
2793 skinfiles = Mod_LoadSkinFiles();
2795 loadmodel->modeldatatypestring = "OBJ";
2797 loadmodel->type = mod_alias;
2798 loadmodel->AnimateVertices = NULL;
2799 loadmodel->DrawSky = NULL;
2800 loadmodel->DrawAddWaterPlanes = NULL;
2801 loadmodel->Draw = R_Q1BSP_Draw;
2802 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2803 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2804 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2805 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2806 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2807 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2808 loadmodel->PointSuperContents = NULL;
2810 // parse the OBJ text now
2817 for (linelen = 0;text[linelen] && text[linelen] != '\r' && text[linelen] != '\n';linelen++)
2818 line[linelen] = text[linelen];
2820 for (argc = 0;argc < (int)(sizeof(argv)/sizeof(argv[0]));argc++)
2824 while (*s == ' ' || *s == '\t')
2834 while (*s == ' ' || *s == '\t')
2839 if (argv[0][0] == '#')
2841 if (!strcmp(argv[0], "v"))
2847 v = Mem_Alloc(tempmempool, maxv * sizeof(float[3]));
2850 memcpy(v, oldv, numv * sizeof(float[3]));
2854 v[numv*3+0] = atof(argv[1]);
2855 v[numv*3+1] = atof(argv[2]);
2856 v[numv*3+2] = atof(argv[3]);
2859 else if (!strcmp(argv[0], "vt"))
2865 vt = Mem_Alloc(tempmempool, maxvt * sizeof(float[2]));
2868 memcpy(vt, oldvt, numvt * sizeof(float[2]));
2872 vt[numvt*2+0] = atof(argv[1]);
2873 vt[numvt*2+1] = atof(argv[2]);
2876 else if (!strcmp(argv[0], "vn"))
2882 vn = Mem_Alloc(tempmempool, maxvn * sizeof(float[3]));
2885 memcpy(vn, oldvn, numvn * sizeof(float[3]));
2889 vn[numvn*3+0] = atof(argv[1]);
2890 vn[numvn*3+1] = atof(argv[2]);
2891 vn[numvn*3+2] = atof(argv[3]);
2894 else if (!strcmp(argv[0], "f"))
2898 if (maxsurfaces <= numsurfaces)
2901 oldsurfaces = surfaces;
2902 surfaces = Mem_Alloc(tempmempool, maxsurfaces * sizeof(*surfaces));
2905 memcpy(surfaces, oldsurfaces, numsurfaces * sizeof(*surfaces));
2906 Mem_Free(oldsurfaces);
2909 surface = surfaces + numsurfaces++;
2912 for (j = 1;j < argc;j++)
2914 index1 = atoi(argv[j]);
2915 while(argv[j][0] && argv[j][0] != '/')
2920 index1 = numv + 1 - index1;
2921 index2 = atoi(argv[j]);
2923 index2 = numvt + 1 - index2;
2924 while(argv[j][0] && argv[j][0] != '/')
2928 index3 = atoi(argv[j]);
2930 index3 = numvn + 1 - index3;
2931 hashindex = (index1 + index2 * 3571 + index3 * 42589) & (numhashindex - 1);
2932 for (hash = verthash[hashindex];hash;hash = hash->next)
2933 if (hash->surface == numsurfaces-1 && hash->v == index1 && hash->vt == index2 && hash->vn == index3)
2937 if (maxverthash <= numverthash)
2940 oldverthashdata = verthashdata;
2941 verthashdata = Mem_Alloc(tempmempool, maxverthash * sizeof(*verthashdata));
2942 if (oldverthashdata)
2944 memcpy(verthashdata, oldverthashdata, numverthash * sizeof(*verthashdata));
2945 Mem_Free(oldverthashdata);
2948 hash = verthashdata + numverthash++;
2949 hash->next = verthash[hashindex];
2950 hash->s = numsurfaces;
2954 verthash[hashindex] = hash;
2956 index = (int)((size_t)(hash - verthashdata));
2961 if (maxtriangles <= numtriangles)
2964 oldelement3i = element3i;
2965 element3i = Mem_Alloc(tempmempool, numtriangles * sizeof(int[3]));
2968 memcpy(element3i, oldelement3i, numtriangles * sizeof(int[3]));
2969 Mem_Free(oldelement3i);
2972 element3i[numtriangles*3+0] = first;
2973 element3i[numtriangles*3+1] = prev;
2974 element3i[numtriangles*3+2] = index;
2980 else if (!strcmp(argv[0], "o") || !strcmp(argv[0], "g"))
2982 else if (!!strcmp(argv[0], "usemtl"))
2985 strlcpy(materialname, argv[1], sizeof(materialname);
2995 Mod_FreeSkinFiles(skinfiles);
2997 // now that we have the OBJ data loaded as-is, we can convert it
2998 loadmodel->numskins = LittleLong(pinmodel->num_skins);
2999 numxyz = LittleLong(pinmodel->num_xyz);
3000 numst = LittleLong(pinmodel->num_st);
3001 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
3002 loadmodel->numframes = LittleLong(pinmodel->num_frames);
3003 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
3004 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
3005 skinwidth = LittleLong(pinmodel->skinwidth);
3006 skinheight = LittleLong(pinmodel->skinheight);
3007 iskinwidth = 1.0f / skinwidth;
3008 iskinheight = 1.0f / skinheight;
3010 loadmodel->num_surfaces = 1;
3011 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
3012 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]));
3013 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
3014 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
3015 loadmodel->sortedmodelsurfaces[0] = 0;
3016 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
3017 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
3018 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
3019 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
3021 loadmodel->synctype = ST_RAND;
3024 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
3025 skinfiles = Mod_LoadSkinFiles();
3028 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3029 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3030 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
3031 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
3032 Mod_FreeSkinFiles(skinfiles);
3034 else if (loadmodel->numskins)
3036 // skins found (most likely not a player model)
3037 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3038 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3039 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
3040 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
3041 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);
3045 // no skins (most likely a player model)
3046 loadmodel->numskins = 1;
3047 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3048 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3049 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
3050 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
3053 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
3054 for (i = 0;i < loadmodel->numskins;i++)
3056 loadmodel->skinscenes[i].firstframe = i;
3057 loadmodel->skinscenes[i].framecount = 1;
3058 loadmodel->skinscenes[i].loop = true;
3059 loadmodel->skinscenes[i].framerate = 10;
3062 // load the triangles and stvert data
3063 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
3064 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
3065 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
3066 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
3067 // swap the triangle list
3068 loadmodel->surfmesh.num_vertices = 0;
3069 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
3071 for (j = 0;j < 3;j++)
3073 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
3074 st = (unsigned short) LittleShort (intri[i].index_st[j]);
3077 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
3082 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
3085 hashindex = (xyz * 256 + st) & 65535;
3086 for (hash = md2verthash[hashindex];hash;hash = hash->next)
3087 if (hash->xyz == xyz && hash->st == st)
3091 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
3094 hash->next = md2verthash[hashindex];
3095 md2verthash[hashindex] = hash;
3097 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
3101 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
3102 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));
3103 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
3104 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
3105 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
3108 hash = md2verthashdata + i;
3109 vertremap[i] = hash->xyz;
3110 sts = LittleShort(inst[hash->st*2+0]);
3111 stt = LittleShort(inst[hash->st*2+1]);
3112 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
3114 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
3118 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
3119 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
3122 Mem_Free(md2verthash);
3123 Mem_Free(md2verthashdata);
3125 // generate ushort elements array if possible
3126 if (loadmodel->surfmesh.num_vertices <= 65536)
3128 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
3129 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3130 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3134 datapointer = (base + LittleLong(pinmodel->ofs_frames));
3135 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
3140 pinframe = (md2frame_t *)datapointer;
3141 datapointer += sizeof(md2frame_t);
3142 // store the frame scale/translate into the appropriate array
3143 for (j = 0;j < 3;j++)
3145 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
3146 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
3148 // convert the vertices
3149 v = (trivertx_t *)datapointer;
3150 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
3151 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
3152 out[k] = v[vertremap[k]];
3153 datapointer += numxyz * sizeof(trivertx_t);
3155 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
3156 loadmodel->animscenes[i].firstframe = i;
3157 loadmodel->animscenes[i].framecount = 1;
3158 loadmodel->animscenes[i].framerate = 10;
3159 loadmodel->animscenes[i].loop = true;
3162 Mem_Free(vertremap);
3164 Mod_MakeSortedSurfaces(loadmodel);
3165 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3166 Mod_Alias_CalculateBoundingBox();
3167 Mod_Alias_MorphMesh_CompileFrames();
3169 surface = loadmodel->data_surfaces;
3170 surface->texture = loadmodel->data_textures;
3171 surface->num_firsttriangle = 0;
3172 surface->num_triangles = loadmodel->surfmesh.num_triangles;
3173 surface->num_firstvertex = 0;
3174 surface->num_vertices = loadmodel->surfmesh.num_vertices;
3176 loadmodel->surfmesh.isanimated = false;