2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 cvar_t r_skeletal_debugbone = {0, "r_skeletal_debugbone", "-1", "development cvar for testing skeletal model code"};
26 cvar_t r_skeletal_debugbonecomponent = {0, "r_skeletal_debugbonecomponent", "3", "development cvar for testing skeletal model code"};
27 cvar_t r_skeletal_debugbonevalue = {0, "r_skeletal_debugbonevalue", "100", "development cvar for testing skeletal model code"};
28 cvar_t r_skeletal_debugtranslatex = {0, "r_skeletal_debugtranslatex", "1", "development cvar for testing skeletal model code"};
29 cvar_t r_skeletal_debugtranslatey = {0, "r_skeletal_debugtranslatey", "1", "development cvar for testing skeletal model code"};
30 cvar_t r_skeletal_debugtranslatez = {0, "r_skeletal_debugtranslatez", "1", "development cvar for testing skeletal model code"};
31 cvar_t mod_alias_supporttagscale = {0, "mod_alias_supporttagscale", "1", "support scaling factors in bone/tag attachment matrices as supported by MD3"};
33 float mod_md3_sin[320];
35 void Mod_AliasInit (void)
38 Cvar_RegisterVariable(&r_skeletal_debugbone);
39 Cvar_RegisterVariable(&r_skeletal_debugbonecomponent);
40 Cvar_RegisterVariable(&r_skeletal_debugbonevalue);
41 Cvar_RegisterVariable(&r_skeletal_debugtranslatex);
42 Cvar_RegisterVariable(&r_skeletal_debugtranslatey);
43 Cvar_RegisterVariable(&r_skeletal_debugtranslatez);
44 Cvar_RegisterVariable(&mod_alias_supporttagscale);
45 for (i = 0;i < 320;i++)
46 mod_md3_sin[i] = sin(i * M_PI * 2.0f / 256.0);
49 void Mod_Skeletal_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
52 // vertex weighted skeletal
55 float desiredscale[3];
56 float boneposerelative[MAX_BONES][12];
57 float *matrix, m[12], bonepose[MAX_BONES][12];
59 // interpolate matrices and concatenate them to their parents
60 for (i = 0;i < model->num_bones;i++)
62 for (k = 0;k < 12;k++)
64 VectorClear(desiredscale);
65 for (blends = 0;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++)
67 matrix = model->data_poses + (frameblend[blends].subframe * model->num_bones + i) * 12;
68 for (k = 0;k < 12;k++)
69 m[k] += matrix[k] * frameblend[blends].lerp;
70 desiredscale[0] += frameblend[blends].lerp * VectorLength(matrix );
71 desiredscale[1] += frameblend[blends].lerp * VectorLength(matrix + 4);
72 desiredscale[2] += frameblend[blends].lerp * VectorLength(matrix + 8);
75 VectorNormalize(m + 4);
76 VectorNormalize(m + 8);
77 VectorScale(m , desiredscale[0], m );
78 VectorScale(m + 4, desiredscale[1], m + 4);
79 VectorScale(m + 8, desiredscale[2], m + 8);
80 if (i == r_skeletal_debugbone.integer)
81 m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
82 m[3] *= r_skeletal_debugtranslatex.value;
83 m[7] *= r_skeletal_debugtranslatey.value;
84 m[11] *= r_skeletal_debugtranslatez.value;
85 if (model->data_bones[i].parent >= 0)
86 R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
88 for (k = 0;k < 12;k++)
89 bonepose[i][k] = m[k];
90 // create a relative deformation matrix to describe displacement
91 // from the base mesh, which is used by the actual weighting
92 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]);
94 // blend the vertex bone weights
95 // special case for the extremely common wf[0] == 1 because it saves 3 multiplies per array when compared to the other case (w[0] is always 1 if only one bone controls this vertex, artists only use multiple bones for certain special cases)
96 // special case for the first bone because it avoids the need to memset the arrays before filling
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 < MAX_FRAMEBLENDS;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].subframe;
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].subframe;
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 < MAX_FRAMEBLENDS;blendnum++)
328 if (model->surfmesh.data_morphmd2framesize6f)
329 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 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].subframe;
340 if (model->surfmesh.data_morphmd2framesize6f)
341 VectorScale(model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 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].subframe;
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[MAX_FRAMEBLENDS];
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].subframe = 0;frameblend[0].subframe < loadmodel->num_poses;frameblend[0].subframe++)
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)
586 radius = sqrt(radius);
587 yawradius = sqrt(yawradius);
588 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
589 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
590 loadmodel->yawmins[2] = loadmodel->normalmins[2];
591 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
592 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
593 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
594 loadmodel->radius = radius;
595 loadmodel->radius2 = radius * radius;
598 static void Mod_Alias_MorphMesh_CompileFrames(void)
601 frameblend_t frameblend[MAX_FRAMEBLENDS];
602 unsigned char *datapointer;
603 memset(frameblend, 0, sizeof(frameblend));
604 frameblend[0].lerp = 1;
605 datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
606 loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
607 loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
608 loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
609 loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
610 loadmodel->surfmesh.data_morphtexvecvertex = (texvecvertex_t *)datapointer;datapointer += loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices * sizeof(texvecvertex_t);
611 // 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)
612 for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
614 frameblend[0].subframe = i;
615 loadmodel->AnimateVertices(loadmodel, frameblend, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
616 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);
617 // encode the svector and tvector in 3 byte format for permanent storage
618 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
620 VectorScaleCast(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
621 VectorScaleCast(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
626 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)
629 float segmentmins[3], segmentmaxs[3];
630 frameblend_t frameblend[MAX_FRAMEBLENDS];
632 static int maxvertices = 0;
633 static float *vertex3f = NULL;
634 memset(trace, 0, sizeof(*trace));
636 trace->realfraction = 1;
637 trace->hitsupercontentsmask = hitsupercontentsmask;
638 memset(frameblend, 0, sizeof(frameblend));
639 frameblend[0].subframe = frame;
640 frameblend[0].lerp = 1;
641 if (maxvertices < model->surfmesh.num_vertices)
645 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
646 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
648 if (VectorLength2(boxmins) + VectorLength2(boxmaxs) == 0)
651 segmentmins[0] = min(start[0], end[0]) - 1;
652 segmentmins[1] = min(start[1], end[1]) - 1;
653 segmentmins[2] = min(start[2], end[2]) - 1;
654 segmentmaxs[0] = max(start[0], end[0]) + 1;
655 segmentmaxs[1] = max(start[1], end[1]) + 1;
656 segmentmaxs[2] = max(start[2], end[2]) + 1;
657 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
659 model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL);
660 Collision_TraceLineTriangleMeshFloat(trace, start, end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs);
665 // box trace, performed as brush trace
666 colbrushf_t *thisbrush_start, *thisbrush_end;
667 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
668 segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
669 segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
670 segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
671 segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
672 segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
673 segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
674 VectorAdd(start, boxmins, boxstartmins);
675 VectorAdd(start, boxmaxs, boxstartmaxs);
676 VectorAdd(end, boxmins, boxendmins);
677 VectorAdd(end, boxmaxs, boxendmaxs);
678 thisbrush_start = Collision_BrushForBox(&identitymatrix, boxstartmins, boxstartmaxs, 0, 0, NULL);
679 thisbrush_end = Collision_BrushForBox(&identitymatrix, boxendmins, boxendmaxs, 0, 0, NULL);
680 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
682 if (maxvertices < model->surfmesh.num_vertices)
686 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
687 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
689 model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL);
690 Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs);
695 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
698 for (i = 0;i < inverts;i++)
700 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
702 j = vertremap[i]; // not onseam
705 j = vertremap[i+inverts]; // onseam
711 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
713 int i, f, pose, groupframes;
715 daliasframetype_t *pframetype;
716 daliasframe_t *pinframe;
717 daliasgroup_t *group;
718 daliasinterval_t *intervals;
721 scene = loadmodel->animscenes;
722 for (f = 0;f < loadmodel->numframes;f++)
724 pframetype = (daliasframetype_t *)datapointer;
725 datapointer += sizeof(daliasframetype_t);
726 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
728 // a single frame is still treated as a group
735 group = (daliasgroup_t *)datapointer;
736 datapointer += sizeof(daliasgroup_t);
737 groupframes = LittleLong (group->numframes);
739 // intervals (time per frame)
740 intervals = (daliasinterval_t *)datapointer;
741 datapointer += sizeof(daliasinterval_t) * groupframes;
743 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
744 if (interval < 0.01f)
746 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
751 // get scene name from first frame
752 pinframe = (daliasframe_t *)datapointer;
754 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
755 scene->firstframe = pose;
756 scene->framecount = groupframes;
757 scene->framerate = 1.0f / interval;
762 for (i = 0;i < groupframes;i++)
764 pinframe = (daliasframe_t *)datapointer;
765 datapointer += sizeof(daliasframe_t);
766 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
767 datapointer += sizeof(trivertx_t) * inverts;
773 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
775 if (cls.state == ca_dedicated)
779 skinframe = R_SkinFrame_LoadMissing();
780 memset(texture, 0, sizeof(*texture));
781 texture->currentframe = texture;
782 //texture->animated = false;
783 texture->numskinframes = 1;
784 texture->skinframerate = 1;
785 texture->skinframes[0] = skinframe;
786 texture->currentskinframe = skinframe;
787 //texture->backgroundnumskinframes = 0;
788 //texture->customblendfunc[0] = 0;
789 //texture->customblendfunc[1] = 0;
790 //texture->surfaceflags = 0;
791 //texture->supercontents = 0;
792 //texture->surfaceparms = 0;
793 //texture->textureflags = 0;
795 texture->basematerialflags = MATERIALFLAG_WALL;
796 if (texture->currentskinframe->fog)
797 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
798 texture->currentmaterialflags = texture->basematerialflags;
801 static void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
804 skinfileitem_t *skinfileitem;
807 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
808 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
810 memset(skin, 0, sizeof(*skin));
812 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
814 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
815 if (!strcmp(skinfileitem->name, meshname))
817 Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
823 // don't render unmentioned meshes
824 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
825 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
830 Mod_LoadTextureFromQ3Shader(skin, shadername, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
833 #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);
834 #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);
835 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
837 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
838 float scales, scalet, interval;
842 stvert_t *pinstverts;
843 dtriangle_t *pintriangles;
844 daliasskintype_t *pinskintype;
845 daliasskingroup_t *pinskingroup;
846 daliasskininterval_t *pinskinintervals;
847 daliasframetype_t *pinframetype;
848 daliasgroup_t *pinframegroup;
849 unsigned char *datapointer, *startframes, *startskins;
850 char name[MAX_QPATH];
851 skinframe_t *tempskinframe;
852 animscene_t *tempskinscenes;
853 texture_t *tempaliasskins;
855 int *vertonseam, *vertremap;
856 skinfile_t *skinfiles;
858 datapointer = (unsigned char *)buffer;
859 pinmodel = (mdl_t *)datapointer;
860 datapointer += sizeof(mdl_t);
862 version = LittleLong (pinmodel->version);
863 if (version != ALIAS_VERSION)
864 Host_Error ("%s has wrong version number (%i should be %i)",
865 loadmodel->name, version, ALIAS_VERSION);
867 loadmodel->modeldatatypestring = "MDL";
869 loadmodel->type = mod_alias;
870 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
871 loadmodel->DrawSky = NULL;
872 loadmodel->DrawAddWaterPlanes = NULL;
873 loadmodel->Draw = R_Q1BSP_Draw;
874 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
875 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
876 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
877 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
878 loadmodel->DrawLight = R_Q1BSP_DrawLight;
879 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
880 loadmodel->PointSuperContents = NULL;
882 loadmodel->num_surfaces = 1;
883 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
884 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
885 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
886 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
887 loadmodel->sortedmodelsurfaces[0] = 0;
889 loadmodel->numskins = LittleLong(pinmodel->numskins);
890 BOUNDI(loadmodel->numskins,0,65536);
891 skinwidth = LittleLong (pinmodel->skinwidth);
892 BOUNDI(skinwidth,0,65536);
893 skinheight = LittleLong (pinmodel->skinheight);
894 BOUNDI(skinheight,0,65536);
895 numverts = LittleLong(pinmodel->numverts);
896 BOUNDI(numverts,0,65536);
897 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
898 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
899 loadmodel->numframes = LittleLong(pinmodel->numframes);
900 BOUNDI(loadmodel->numframes,0,65536);
901 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
902 BOUNDI(loadmodel->synctype,0,2);
903 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
904 i = LittleLong (pinmodel->flags);
905 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
907 for (i = 0;i < 3;i++)
909 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
910 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
913 startskins = datapointer;
915 for (i = 0;i < loadmodel->numskins;i++)
917 pinskintype = (daliasskintype_t *)datapointer;
918 datapointer += sizeof(daliasskintype_t);
919 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
923 pinskingroup = (daliasskingroup_t *)datapointer;
924 datapointer += sizeof(daliasskingroup_t);
925 groupskins = LittleLong(pinskingroup->numskins);
926 datapointer += sizeof(daliasskininterval_t) * groupskins;
929 for (j = 0;j < groupskins;j++)
931 datapointer += skinwidth * skinheight;
936 pinstverts = (stvert_t *)datapointer;
937 datapointer += sizeof(stvert_t) * numverts;
939 pintriangles = (dtriangle_t *)datapointer;
940 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
942 startframes = datapointer;
943 loadmodel->surfmesh.num_morphframes = 0;
944 for (i = 0;i < loadmodel->numframes;i++)
946 pinframetype = (daliasframetype_t *)datapointer;
947 datapointer += sizeof(daliasframetype_t);
948 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
952 pinframegroup = (daliasgroup_t *)datapointer;
953 datapointer += sizeof(daliasgroup_t);
954 groupframes = LittleLong(pinframegroup->numframes);
955 datapointer += sizeof(daliasinterval_t) * groupframes;
958 for (j = 0;j < groupframes;j++)
960 datapointer += sizeof(daliasframe_t);
961 datapointer += sizeof(trivertx_t) * numverts;
962 loadmodel->surfmesh.num_morphframes++;
965 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
967 // store texture coordinates into temporary array, they will be stored
968 // after usage is determined (triangle data)
969 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
970 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
971 vertonseam = vertremap + numverts * 2;
973 scales = 1.0 / skinwidth;
974 scalet = 1.0 / skinheight;
975 for (i = 0;i < numverts;i++)
977 vertonseam[i] = LittleLong(pinstverts[i].onseam);
978 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
979 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
980 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
981 vertst[(i+numverts)*2+1] = vertst[i*2+1];
984 // load triangle data
985 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
987 // read the triangle elements
988 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
989 for (j = 0;j < 3;j++)
990 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
991 // validate (note numverts is used because this is the original data)
992 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
993 // now butcher the elements according to vertonseam and tri->facesfront
994 // and then compact the vertex set to remove duplicates
995 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
996 if (!LittleLong(pintriangles[i].facesfront)) // backface
997 for (j = 0;j < 3;j++)
998 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
999 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1001 // (this uses vertremap to count usage to save some memory)
1002 for (i = 0;i < numverts*2;i++)
1004 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1005 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1006 // build remapping table and compact array
1007 loadmodel->surfmesh.num_vertices = 0;
1008 for (i = 0;i < numverts*2;i++)
1012 vertremap[i] = loadmodel->surfmesh.num_vertices;
1013 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1014 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1015 loadmodel->surfmesh.num_vertices++;
1018 vertremap[i] = -1; // not used at all
1020 // remap the elements to the new vertex set
1021 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1022 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1023 // store the texture coordinates
1024 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1025 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1027 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1028 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1031 // generate ushort elements array if possible
1032 if (loadmodel->surfmesh.num_vertices <= 65536)
1034 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1035 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1036 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1040 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1041 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1042 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1043 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1044 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1045 Mod_Alias_CalculateBoundingBox();
1046 Mod_Alias_MorphMesh_CompileFrames();
1049 Mem_Free(vertremap);
1052 skinfiles = Mod_LoadSkinFiles();
1055 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1056 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1057 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1058 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1059 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1060 Mod_FreeSkinFiles(skinfiles);
1061 for (i = 0;i < loadmodel->numskins;i++)
1063 loadmodel->skinscenes[i].firstframe = i;
1064 loadmodel->skinscenes[i].framecount = 1;
1065 loadmodel->skinscenes[i].loop = true;
1066 loadmodel->skinscenes[i].framerate = 10;
1071 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1072 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1073 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1074 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1076 datapointer = startskins;
1077 for (i = 0;i < loadmodel->numskins;i++)
1079 pinskintype = (daliasskintype_t *)datapointer;
1080 datapointer += sizeof(daliasskintype_t);
1082 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1089 pinskingroup = (daliasskingroup_t *)datapointer;
1090 datapointer += sizeof(daliasskingroup_t);
1092 groupskins = LittleLong (pinskingroup->numskins);
1094 pinskinintervals = (daliasskininterval_t *)datapointer;
1095 datapointer += sizeof(daliasskininterval_t) * groupskins;
1097 interval = LittleFloat(pinskinintervals[0].interval);
1098 if (interval < 0.01f)
1100 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1105 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1106 loadmodel->skinscenes[i].firstframe = totalskins;
1107 loadmodel->skinscenes[i].framecount = groupskins;
1108 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1109 loadmodel->skinscenes[i].loop = true;
1111 for (j = 0;j < groupskins;j++)
1114 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1116 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1117 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))
1118 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));
1119 datapointer += skinwidth * skinheight;
1123 // check for skins that don't exist in the model, but do exist as external images
1124 // (this was added because yummyluv kept pestering me about support for it)
1125 // TODO: support shaders here?
1126 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)))
1128 // expand the arrays to make room
1129 tempskinscenes = loadmodel->skinscenes;
1130 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1131 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1132 Mem_Free(tempskinscenes);
1134 tempaliasskins = loadmodel->data_textures;
1135 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1136 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1137 Mem_Free(tempaliasskins);
1139 // store the info about the new skin
1140 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1141 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1142 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1143 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1144 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1145 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1147 //increase skin counts
1148 loadmodel->numskins++;
1151 // fix up the pointers since they are pointing at the old textures array
1152 // FIXME: this is a hack!
1153 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1154 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1158 surface = loadmodel->data_surfaces;
1159 surface->texture = loadmodel->data_textures;
1160 surface->num_firsttriangle = 0;
1161 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1162 surface->num_firstvertex = 0;
1163 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1165 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1168 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1170 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1171 float iskinwidth, iskinheight;
1172 unsigned char *data;
1173 msurface_t *surface;
1175 unsigned char *base, *datapointer;
1176 md2frame_t *pinframe;
1178 md2triangle_t *intri;
1179 unsigned short *inst;
1180 struct md2verthash_s
1182 struct md2verthash_s *next;
1186 *hash, **md2verthash, *md2verthashdata;
1187 skinfile_t *skinfiles;
1189 pinmodel = (md2_t *)buffer;
1190 base = (unsigned char *)buffer;
1192 version = LittleLong (pinmodel->version);
1193 if (version != MD2ALIAS_VERSION)
1194 Host_Error ("%s has wrong version number (%i should be %i)",
1195 loadmodel->name, version, MD2ALIAS_VERSION);
1197 loadmodel->modeldatatypestring = "MD2";
1199 loadmodel->type = mod_alias;
1200 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1201 loadmodel->DrawSky = NULL;
1202 loadmodel->DrawAddWaterPlanes = NULL;
1203 loadmodel->Draw = R_Q1BSP_Draw;
1204 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1205 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1206 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1207 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1208 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1209 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1210 loadmodel->PointSuperContents = NULL;
1212 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1213 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1214 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1215 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1216 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1217 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1218 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1219 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1221 end = LittleLong(pinmodel->ofs_end);
1222 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1223 Host_Error ("%s is not a valid model", loadmodel->name);
1224 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1225 Host_Error ("%s is not a valid model", loadmodel->name);
1226 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1227 Host_Error ("%s is not a valid model", loadmodel->name);
1228 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1229 Host_Error ("%s is not a valid model", loadmodel->name);
1230 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1231 Host_Error ("%s is not a valid model", loadmodel->name);
1233 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1234 numxyz = LittleLong(pinmodel->num_xyz);
1235 numst = LittleLong(pinmodel->num_st);
1236 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1237 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1238 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1239 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1240 skinwidth = LittleLong(pinmodel->skinwidth);
1241 skinheight = LittleLong(pinmodel->skinheight);
1242 iskinwidth = 1.0f / skinwidth;
1243 iskinheight = 1.0f / skinheight;
1245 loadmodel->num_surfaces = 1;
1246 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1247 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]));
1248 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1249 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1250 loadmodel->sortedmodelsurfaces[0] = 0;
1251 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1252 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1253 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1254 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1256 loadmodel->synctype = ST_RAND;
1259 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1260 skinfiles = Mod_LoadSkinFiles();
1263 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1264 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1265 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1266 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1267 Mod_FreeSkinFiles(skinfiles);
1269 else if (loadmodel->numskins)
1271 // skins found (most likely not a player model)
1272 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1273 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1274 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1275 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1276 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);
1280 // no skins (most likely a player model)
1281 loadmodel->numskins = 1;
1282 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1283 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1284 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1285 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1288 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1289 for (i = 0;i < loadmodel->numskins;i++)
1291 loadmodel->skinscenes[i].firstframe = i;
1292 loadmodel->skinscenes[i].framecount = 1;
1293 loadmodel->skinscenes[i].loop = true;
1294 loadmodel->skinscenes[i].framerate = 10;
1297 // load the triangles and stvert data
1298 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1299 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1300 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1301 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1302 // swap the triangle list
1303 loadmodel->surfmesh.num_vertices = 0;
1304 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1306 for (j = 0;j < 3;j++)
1308 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1309 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1312 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1317 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1320 hashindex = (xyz * 256 + st) & 65535;
1321 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1322 if (hash->xyz == xyz && hash->st == st)
1326 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1329 hash->next = md2verthash[hashindex];
1330 md2verthash[hashindex] = hash;
1332 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1336 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1337 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));
1338 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1339 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1340 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1343 hash = md2verthashdata + i;
1344 vertremap[i] = hash->xyz;
1345 sts = LittleShort(inst[hash->st*2+0]);
1346 stt = LittleShort(inst[hash->st*2+1]);
1347 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1349 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1353 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1354 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1357 Mem_Free(md2verthash);
1358 Mem_Free(md2verthashdata);
1360 // generate ushort elements array if possible
1361 if (loadmodel->surfmesh.num_vertices <= 65536)
1363 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1364 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1365 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1369 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1370 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1375 pinframe = (md2frame_t *)datapointer;
1376 datapointer += sizeof(md2frame_t);
1377 // store the frame scale/translate into the appropriate array
1378 for (j = 0;j < 3;j++)
1380 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1381 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1383 // convert the vertices
1384 v = (trivertx_t *)datapointer;
1385 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1386 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1387 out[k] = v[vertremap[k]];
1388 datapointer += numxyz * sizeof(trivertx_t);
1390 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1391 loadmodel->animscenes[i].firstframe = i;
1392 loadmodel->animscenes[i].framecount = 1;
1393 loadmodel->animscenes[i].framerate = 10;
1394 loadmodel->animscenes[i].loop = true;
1397 Mem_Free(vertremap);
1399 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1400 Mod_Alias_CalculateBoundingBox();
1401 Mod_Alias_MorphMesh_CompileFrames();
1403 surface = loadmodel->data_surfaces;
1404 surface->texture = loadmodel->data_textures;
1405 surface->num_firsttriangle = 0;
1406 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1407 surface->num_firstvertex = 0;
1408 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1410 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1413 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1415 int i, j, k, version, meshvertices, meshtriangles;
1416 unsigned char *data;
1417 msurface_t *surface;
1418 md3modelheader_t *pinmodel;
1419 md3frameinfo_t *pinframe;
1422 skinfile_t *skinfiles;
1424 pinmodel = (md3modelheader_t *)buffer;
1426 if (memcmp(pinmodel->identifier, "IDP3", 4))
1427 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1428 version = LittleLong (pinmodel->version);
1429 if (version != MD3VERSION)
1430 Host_Error ("%s has wrong version number (%i should be %i)",
1431 loadmodel->name, version, MD3VERSION);
1433 skinfiles = Mod_LoadSkinFiles();
1434 if (loadmodel->numskins < 1)
1435 loadmodel->numskins = 1;
1437 loadmodel->modeldatatypestring = "MD3";
1439 loadmodel->type = mod_alias;
1440 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1441 loadmodel->DrawSky = NULL;
1442 loadmodel->DrawAddWaterPlanes = NULL;
1443 loadmodel->Draw = R_Q1BSP_Draw;
1444 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1445 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1446 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1447 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1448 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1449 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1450 loadmodel->PointSuperContents = NULL;
1451 loadmodel->synctype = ST_RAND;
1452 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1453 i = LittleLong (pinmodel->flags);
1454 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1456 // set up some global info about the model
1457 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1458 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1460 // make skinscenes for the skins (no groups)
1461 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1462 for (i = 0;i < loadmodel->numskins;i++)
1464 loadmodel->skinscenes[i].firstframe = i;
1465 loadmodel->skinscenes[i].framecount = 1;
1466 loadmodel->skinscenes[i].loop = true;
1467 loadmodel->skinscenes[i].framerate = 10;
1471 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1472 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1474 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1475 loadmodel->animscenes[i].firstframe = i;
1476 loadmodel->animscenes[i].framecount = 1;
1477 loadmodel->animscenes[i].framerate = 10;
1478 loadmodel->animscenes[i].loop = true;
1482 loadmodel->num_tagframes = loadmodel->numframes;
1483 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1484 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1485 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1487 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1488 for (j = 0;j < 9;j++)
1489 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1490 for (j = 0;j < 3;j++)
1491 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1492 //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);
1498 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)))
1500 if (memcmp(pinmesh->identifier, "IDP3", 4))
1501 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1502 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1503 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1504 meshvertices += LittleLong(pinmesh->num_vertices);
1505 meshtriangles += LittleLong(pinmesh->num_triangles);
1508 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1509 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1510 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1511 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));
1512 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1513 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1514 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1515 loadmodel->surfmesh.num_vertices = meshvertices;
1516 loadmodel->surfmesh.num_triangles = meshtriangles;
1517 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1518 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1519 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1520 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1521 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1522 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1523 if (meshvertices <= 65536)
1525 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1526 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1527 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1532 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)))
1534 if (memcmp(pinmesh->identifier, "IDP3", 4))
1535 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1536 loadmodel->sortedmodelsurfaces[i] = i;
1537 surface = loadmodel->data_surfaces + i;
1538 surface->texture = loadmodel->data_textures + i;
1539 surface->num_firsttriangle = meshtriangles;
1540 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1541 surface->num_firstvertex = meshvertices;
1542 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1543 meshvertices += surface->num_vertices;
1544 meshtriangles += surface->num_triangles;
1546 for (j = 0;j < surface->num_triangles * 3;j++)
1547 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1548 for (j = 0;j < surface->num_vertices;j++)
1550 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1551 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1553 for (j = 0;j < loadmodel->numframes;j++)
1555 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1556 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1557 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1559 out->origin[0] = LittleShort(in->origin[0]);
1560 out->origin[1] = LittleShort(in->origin[1]);
1561 out->origin[2] = LittleShort(in->origin[2]);
1562 out->pitch = in->pitch;
1567 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1569 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1571 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1572 Mod_Alias_MorphMesh_CompileFrames();
1573 Mod_Alias_CalculateBoundingBox();
1574 Mod_FreeSkinFiles(skinfiles);
1575 Mod_MakeSortedSurfaces(loadmodel);
1577 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1578 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1581 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1583 zymtype1header_t *pinmodel, *pheader;
1584 unsigned char *pbase;
1585 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1586 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose;
1587 zymvertex_t *verts, *vertdata;
1591 skinfile_t *skinfiles;
1592 unsigned char *data;
1593 msurface_t *surface;
1595 pinmodel = (zymtype1header_t *)buffer;
1596 pbase = (unsigned char *)buffer;
1597 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1598 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1599 if (BigLong(pinmodel->type) != 1)
1600 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1602 loadmodel->modeldatatypestring = "ZYM";
1604 loadmodel->type = mod_alias;
1605 loadmodel->synctype = ST_RAND;
1609 pheader->type = BigLong(pinmodel->type);
1610 pheader->filesize = BigLong(pinmodel->filesize);
1611 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1612 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1613 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1614 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1615 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1616 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1617 pheader->radius = BigFloat(pinmodel->radius);
1618 pheader->numverts = BigLong(pinmodel->numverts);
1619 pheader->numtris = BigLong(pinmodel->numtris);
1620 pheader->numshaders = BigLong(pinmodel->numshaders);
1621 pheader->numbones = BigLong(pinmodel->numbones);
1622 pheader->numscenes = BigLong(pinmodel->numscenes);
1623 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1624 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1625 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1626 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1627 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1628 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1629 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1630 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1631 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1632 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1633 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1634 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1635 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1636 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1637 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1638 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1639 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1640 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1642 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1644 Con_Printf("%s has no geometry\n", loadmodel->name);
1647 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1649 Con_Printf("%s has no animations\n", loadmodel->name);
1653 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1654 loadmodel->DrawSky = NULL;
1655 loadmodel->DrawAddWaterPlanes = NULL;
1656 loadmodel->Draw = R_Q1BSP_Draw;
1657 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1658 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1659 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1660 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1661 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1662 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1663 loadmodel->PointSuperContents = NULL;
1665 loadmodel->numframes = pheader->numscenes;
1666 loadmodel->num_surfaces = pheader->numshaders;
1668 skinfiles = Mod_LoadSkinFiles();
1669 if (loadmodel->numskins < 1)
1670 loadmodel->numskins = 1;
1672 // make skinscenes for the skins (no groups)
1673 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1674 for (i = 0;i < loadmodel->numskins;i++)
1676 loadmodel->skinscenes[i].firstframe = i;
1677 loadmodel->skinscenes[i].framecount = 1;
1678 loadmodel->skinscenes[i].loop = true;
1679 loadmodel->skinscenes[i].framerate = 10;
1683 modelradius = pheader->radius;
1684 for (i = 0;i < 3;i++)
1686 loadmodel->normalmins[i] = pheader->mins[i];
1687 loadmodel->normalmaxs[i] = pheader->maxs[i];
1688 loadmodel->rotatedmins[i] = -modelradius;
1689 loadmodel->rotatedmaxs[i] = modelradius;
1691 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1692 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1693 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1694 if (loadmodel->yawmaxs[0] > modelradius)
1695 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1696 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1697 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1698 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1699 loadmodel->radius = modelradius;
1700 loadmodel->radius2 = modelradius * modelradius;
1702 // go through the lumps, swapping things
1704 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1705 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1706 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1707 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1708 for (i = 0;i < pheader->numscenes;i++)
1710 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1711 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1712 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1713 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1714 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1715 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1716 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1717 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1718 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1719 if (loadmodel->animscenes[i].framerate < 0)
1720 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1724 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1725 loadmodel->num_bones = pheader->numbones;
1726 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, pheader->numbones * sizeof(aliasbone_t));
1727 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1728 for (i = 0;i < pheader->numbones;i++)
1730 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1731 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1732 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1733 if (loadmodel->data_bones[i].parent >= i)
1734 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1737 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1738 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1739 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1740 for (i = 0;i < pheader->numverts;i++)
1742 vertbonecounts[i] = BigLong(bonecount[i]);
1743 if (vertbonecounts[i] != 1)
1744 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1747 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]);
1749 meshvertices = pheader->numverts;
1750 meshtriangles = pheader->numtris;
1752 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1753 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1754 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1755 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]));
1756 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1757 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1758 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1759 loadmodel->surfmesh.num_vertices = meshvertices;
1760 loadmodel->surfmesh.num_triangles = meshtriangles;
1761 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1762 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1763 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1764 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1765 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1766 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1767 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1768 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1769 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1770 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
1771 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1772 if (loadmodel->surfmesh.num_vertices <= 65536)
1774 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1775 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1776 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1779 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1780 poses = (float *) (pheader->lump_poses.start + pbase);
1781 for (i = 0;i < pheader->lump_poses.length / 4;i++)
1782 loadmodel->data_poses[i] = BigFloat(poses[i]);
1784 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1785 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1786 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1787 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1788 // (converting from weight-blending skeletal animation to
1789 // deformation-based skeletal animation)
1790 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1791 for (i = 0;i < loadmodel->num_bones;i++)
1793 const float *m = loadmodel->data_poses + i * 12;
1794 if (loadmodel->data_bones[i].parent >= 0)
1795 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1797 for (k = 0;k < 12;k++)
1798 bonepose[12*i+k] = m[k];
1800 for (j = 0;j < pheader->numverts;j++)
1802 // this format really should have had a per vertexweight weight value...
1803 // but since it does not, the weighting is completely ignored and
1804 // only one weight is allowed per vertex
1805 int boneindex = BigLong(vertdata[j].bonenum);
1806 const float *m = bonepose + 12 * boneindex;
1807 float relativeorigin[3];
1808 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1809 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1810 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1811 // transform the vertex bone weight into the base mesh
1812 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1813 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1814 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1815 // store the weight as the primary weight on this vertex
1816 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
1817 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = 1;
1820 // normals and tangents are calculated after elements are loaded
1822 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1823 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1824 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1825 for (i = 0;i < pheader->numverts;i++)
1827 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1828 // flip T coordinate for OpenGL
1829 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1832 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1833 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1834 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1836 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1837 //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)
1838 // byteswap, validate, and swap winding order of tris
1839 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1840 if (pheader->lump_render.length != count)
1841 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1842 renderlist = (int *) (pheader->lump_render.start + pbase);
1843 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1845 for (i = 0;i < loadmodel->num_surfaces;i++)
1847 int firstvertex, lastvertex;
1848 if (renderlist >= renderlistend)
1849 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1850 count = BigLong(*renderlist);renderlist++;
1851 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1852 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1854 loadmodel->sortedmodelsurfaces[i] = i;
1855 surface = loadmodel->data_surfaces + i;
1856 surface->texture = loadmodel->data_textures + i;
1857 surface->num_firsttriangle = meshtriangles;
1858 surface->num_triangles = count;
1859 meshtriangles += surface->num_triangles;
1861 // load the elements
1862 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
1863 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
1865 outelements[j*3+2] = BigLong(renderlist[0]);
1866 outelements[j*3+1] = BigLong(renderlist[1]);
1867 outelements[j*3+0] = BigLong(renderlist[2]);
1869 // validate the elements and find the used vertex range
1870 firstvertex = meshvertices;
1872 for (j = 0;j < surface->num_triangles * 3;j++)
1874 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
1875 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
1876 firstvertex = min(firstvertex, outelements[j]);
1877 lastvertex = max(lastvertex, outelements[j]);
1879 surface->num_firstvertex = firstvertex;
1880 surface->num_vertices = lastvertex + 1 - firstvertex;
1882 // since zym models do not have named sections, reuse their shader
1883 // name as the section name
1884 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
1885 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
1887 Mod_FreeSkinFiles(skinfiles);
1888 Mem_Free(vertbonecounts);
1890 Mod_MakeSortedSurfaces(loadmodel);
1892 // compute all the mesh information that was not loaded from the file
1893 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
1894 Mod_BuildBaseBonePoses();
1895 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
1896 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);
1897 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1899 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1902 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1904 dpmheader_t *pheader;
1908 unsigned char *pbase;
1909 int i, j, k, meshvertices, meshtriangles;
1910 skinfile_t *skinfiles;
1911 unsigned char *data;
1914 pheader = (dpmheader_t *)buffer;
1915 pbase = (unsigned char *)buffer;
1916 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
1917 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
1918 if (BigLong(pheader->type) != 2)
1919 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1921 loadmodel->modeldatatypestring = "DPM";
1923 loadmodel->type = mod_alias;
1924 loadmodel->synctype = ST_RAND;
1927 pheader->type = BigLong(pheader->type);
1928 pheader->filesize = BigLong(pheader->filesize);
1929 pheader->mins[0] = BigFloat(pheader->mins[0]);
1930 pheader->mins[1] = BigFloat(pheader->mins[1]);
1931 pheader->mins[2] = BigFloat(pheader->mins[2]);
1932 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
1933 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
1934 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
1935 pheader->yawradius = BigFloat(pheader->yawradius);
1936 pheader->allradius = BigFloat(pheader->allradius);
1937 pheader->num_bones = BigLong(pheader->num_bones);
1938 pheader->num_meshs = BigLong(pheader->num_meshs);
1939 pheader->num_frames = BigLong(pheader->num_frames);
1940 pheader->ofs_bones = BigLong(pheader->ofs_bones);
1941 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
1942 pheader->ofs_frames = BigLong(pheader->ofs_frames);
1944 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
1946 Con_Printf("%s has no geometry\n", loadmodel->name);
1949 if (pheader->num_frames < 1)
1951 Con_Printf("%s has no frames\n", loadmodel->name);
1955 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1956 loadmodel->DrawSky = NULL;
1957 loadmodel->DrawAddWaterPlanes = NULL;
1958 loadmodel->Draw = R_Q1BSP_Draw;
1959 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1960 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1961 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1962 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1963 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1964 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1965 loadmodel->PointSuperContents = NULL;
1968 for (i = 0;i < 3;i++)
1970 loadmodel->normalmins[i] = pheader->mins[i];
1971 loadmodel->normalmaxs[i] = pheader->maxs[i];
1972 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
1973 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
1974 loadmodel->rotatedmins[i] = -pheader->allradius;
1975 loadmodel->rotatedmaxs[i] = pheader->allradius;
1977 loadmodel->radius = pheader->allradius;
1978 loadmodel->radius2 = pheader->allradius * pheader->allradius;
1980 // load external .skin files if present
1981 skinfiles = Mod_LoadSkinFiles();
1982 if (loadmodel->numskins < 1)
1983 loadmodel->numskins = 1;
1988 // gather combined statistics from the meshes
1989 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
1990 for (i = 0;i < (int)pheader->num_meshs;i++)
1992 int numverts = BigLong(dpmmesh->num_verts);
1993 meshvertices += numverts;
1994 meshtriangles += BigLong(dpmmesh->num_tris);
1998 loadmodel->numframes = pheader->num_frames;
1999 loadmodel->num_bones = pheader->num_bones;
2000 loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
2001 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2002 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2003 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2004 // do most allocations as one merged chunk
2005 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));
2006 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2007 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2008 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2009 loadmodel->surfmesh.num_vertices = meshvertices;
2010 loadmodel->surfmesh.num_triangles = meshtriangles;
2011 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2012 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2013 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2014 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2015 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2016 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2017 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2018 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
2019 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
2020 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
2021 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2022 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2023 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2024 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2025 if (meshvertices <= 65536)
2027 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2028 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2029 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2032 for (i = 0;i < loadmodel->numskins;i++)
2034 loadmodel->skinscenes[i].firstframe = i;
2035 loadmodel->skinscenes[i].framecount = 1;
2036 loadmodel->skinscenes[i].loop = true;
2037 loadmodel->skinscenes[i].framerate = 10;
2040 // load the bone info
2041 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2042 for (i = 0;i < loadmodel->num_bones;i++)
2044 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2045 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2046 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2047 if (loadmodel->data_bones[i].parent >= i)
2048 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2052 frame = (dpmframe_t *) (pbase + pheader->ofs_frames);
2053 for (i = 0;i < loadmodel->numframes;i++)
2056 memcpy(loadmodel->animscenes[i].name, frame->name, sizeof(frame->name));
2057 loadmodel->animscenes[i].firstframe = i;
2058 loadmodel->animscenes[i].framecount = 1;
2059 loadmodel->animscenes[i].loop = true;
2060 loadmodel->animscenes[i].framerate = 10;
2061 // load the bone poses for this frame
2062 poses = (float *) (pbase + BigLong(frame->ofs_bonepositions));
2063 for (j = 0;j < loadmodel->num_bones*12;j++)
2064 loadmodel->data_poses[i * loadmodel->num_bones*12 + j] = BigFloat(poses[j]);
2065 // stuff not processed here: mins, maxs, yawradius, allradius
2069 // load the meshes now
2070 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2073 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2074 // (converting from weight-blending skeletal animation to
2075 // deformation-based skeletal animation)
2076 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2077 for (i = 0;i < loadmodel->num_bones;i++)
2079 const float *m = loadmodel->data_poses + i * 12;
2080 if (loadmodel->data_bones[i].parent >= 0)
2081 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2083 for (k = 0;k < 12;k++)
2084 bonepose[12*i+k] = m[k];
2086 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2088 const int *inelements;
2090 const float *intexcoord;
2091 msurface_t *surface;
2093 loadmodel->sortedmodelsurfaces[i] = i;
2094 surface = loadmodel->data_surfaces + i;
2095 surface->texture = loadmodel->data_textures + i;
2096 surface->num_firsttriangle = meshtriangles;
2097 surface->num_triangles = BigLong(dpmmesh->num_tris);
2098 surface->num_firstvertex = meshvertices;
2099 surface->num_vertices = BigLong(dpmmesh->num_verts);
2100 meshvertices += surface->num_vertices;
2101 meshtriangles += surface->num_triangles;
2103 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2104 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2105 for (j = 0;j < surface->num_triangles;j++)
2107 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2108 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2109 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2110 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2115 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2116 for (j = 0;j < surface->num_vertices*2;j++)
2117 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2119 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2120 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2124 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2125 data += sizeof(dpmvertex_t);
2126 for (k = 0;k < numweights;k++)
2128 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2129 int boneindex = BigLong(vert->bonenum);
2130 const float *m = bonepose + 12 * boneindex;
2131 float influence = BigFloat(vert->influence);
2132 float relativeorigin[3], relativenormal[3];
2133 relativeorigin[0] = BigFloat(vert->origin[0]);
2134 relativeorigin[1] = BigFloat(vert->origin[1]);
2135 relativeorigin[2] = BigFloat(vert->origin[2]);
2136 relativenormal[0] = BigFloat(vert->normal[0]);
2137 relativenormal[1] = BigFloat(vert->normal[1]);
2138 relativenormal[2] = BigFloat(vert->normal[2]);
2139 // blend the vertex bone weights into the base mesh
2140 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2141 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2142 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2143 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2144 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2145 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2148 // store the first (and often only) weight
2149 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = influence;
2150 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
2154 // sort the new weight into this vertex's weight table
2155 // (which only accepts up to 4 bones per vertex)
2156 for (l = 0;l < 4;l++)
2158 if (loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] < influence)
2160 // move weaker influence weights out of the way first
2162 for (l2 = 3;l2 > l;l2--)
2164 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2-1];
2165 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2-1];
2167 // store the new weight
2168 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] = influence;
2169 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l] = boneindex;
2174 data += sizeof(dpmbonevert_t);
2177 for (l = 0;l < 4;l++)
2178 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l];
2179 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2181 float f = 1.0f / sum;
2182 for (l = 0;l < 4;l++)
2183 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] *= f;
2187 // since dpm models do not have named sections, reuse their shader name as the section name
2188 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2190 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2193 Mod_FreeSkinFiles(skinfiles);
2194 Mod_MakeSortedSurfaces(loadmodel);
2196 // compute all the mesh information that was not loaded from the file
2197 Mod_BuildBaseBonePoses();
2198 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);
2199 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2201 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2204 // no idea why PSK/PSA files contain weird quaternions but they do...
2205 #define PSKQUATNEGATIONS
2206 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2208 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2209 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2210 fs_offset_t filesize;
2215 pskboneinfo_t *bones;
2216 pskrawweights_t *rawweights;
2217 pskboneinfo_t *animbones;
2218 pskaniminfo_t *anims;
2219 pskanimkeys_t *animkeys;
2220 void *animfilebuffer, *animbuffer, *animbufferend;
2221 unsigned char *data;
2223 skinfile_t *skinfiles;
2224 char animname[MAX_QPATH];
2227 pchunk = (pskchunk_t *)buffer;
2228 if (strcmp(pchunk->id, "ACTRHEAD"))
2229 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2231 loadmodel->modeldatatypestring = "PSK";
2233 loadmodel->type = mod_alias;
2234 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2235 loadmodel->DrawSky = NULL;
2236 loadmodel->DrawAddWaterPlanes = NULL;
2237 loadmodel->Draw = R_Q1BSP_Draw;
2238 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2239 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2240 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2241 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2242 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2243 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2244 loadmodel->PointSuperContents = NULL;
2245 loadmodel->synctype = ST_RAND;
2247 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2248 strlcat(animname, ".psa", sizeof(animname));
2249 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2250 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2251 if (animbuffer == NULL)
2252 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2271 while (buffer < bufferend)
2273 pchunk = (pskchunk_t *)buffer;
2274 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2275 version = LittleLong(pchunk->version);
2276 recordsize = LittleLong(pchunk->recordsize);
2277 numrecords = LittleLong(pchunk->numrecords);
2278 if (developer.integer >= 100)
2279 Con_Printf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2280 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2281 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);
2282 if (!strcmp(pchunk->id, "ACTRHEAD"))
2286 else if (!strcmp(pchunk->id, "PNTS0000"))
2289 if (recordsize != sizeof(*p))
2290 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2291 // byteswap in place and keep the pointer
2292 numpnts = numrecords;
2293 pnts = (pskpnts_t *)buffer;
2294 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2296 p->origin[0] = LittleFloat(p->origin[0]);
2297 p->origin[1] = LittleFloat(p->origin[1]);
2298 p->origin[2] = LittleFloat(p->origin[2]);
2302 else if (!strcmp(pchunk->id, "VTXW0000"))
2305 if (recordsize != sizeof(*p))
2306 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2307 // byteswap in place and keep the pointer
2308 numvtxw = numrecords;
2309 vtxw = (pskvtxw_t *)buffer;
2310 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2312 p->pntsindex = LittleShort(p->pntsindex);
2313 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2314 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2315 if (p->pntsindex >= numpnts)
2317 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2323 else if (!strcmp(pchunk->id, "FACE0000"))
2326 if (recordsize != sizeof(*p))
2327 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2328 // byteswap in place and keep the pointer
2329 numfaces = numrecords;
2330 faces = (pskface_t *)buffer;
2331 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2333 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2334 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2335 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2336 p->group = LittleLong(p->group);
2337 if (p->vtxwindex[0] >= numvtxw)
2339 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2340 p->vtxwindex[0] = 0;
2342 if (p->vtxwindex[1] >= numvtxw)
2344 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2345 p->vtxwindex[1] = 0;
2347 if (p->vtxwindex[2] >= numvtxw)
2349 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2350 p->vtxwindex[2] = 0;
2355 else if (!strcmp(pchunk->id, "MATT0000"))
2358 if (recordsize != sizeof(*p))
2359 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2360 // byteswap in place and keep the pointer
2361 nummatts = numrecords;
2362 matts = (pskmatt_t *)buffer;
2363 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2369 else if (!strcmp(pchunk->id, "REFSKELT"))
2372 if (recordsize != sizeof(*p))
2373 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2374 // byteswap in place and keep the pointer
2375 numbones = numrecords;
2376 bones = (pskboneinfo_t *)buffer;
2377 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2379 p->numchildren = LittleLong(p->numchildren);
2380 p->parent = LittleLong(p->parent);
2381 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2382 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2383 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2384 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2385 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2386 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2387 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2388 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2389 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2390 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2391 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2392 #ifdef PSKQUATNEGATIONS
2395 p->basepose.quat[0] *= -1;
2396 p->basepose.quat[1] *= -1;
2397 p->basepose.quat[2] *= -1;
2401 p->basepose.quat[0] *= 1;
2402 p->basepose.quat[1] *= -1;
2403 p->basepose.quat[2] *= 1;
2406 if (p->parent < 0 || p->parent >= numbones)
2408 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2414 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2417 if (recordsize != sizeof(*p))
2418 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2419 // byteswap in place and keep the pointer
2420 numrawweights = numrecords;
2421 rawweights = (pskrawweights_t *)buffer;
2422 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2424 p->weight = LittleFloat(p->weight);
2425 p->pntsindex = LittleLong(p->pntsindex);
2426 p->boneindex = LittleLong(p->boneindex);
2427 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2429 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2432 if (p->boneindex < 0 || p->boneindex >= numbones)
2434 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2442 while (animbuffer < animbufferend)
2444 pchunk = (pskchunk_t *)animbuffer;
2445 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2446 version = LittleLong(pchunk->version);
2447 recordsize = LittleLong(pchunk->recordsize);
2448 numrecords = LittleLong(pchunk->numrecords);
2449 if (developer.integer >= 100)
2450 Con_Printf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2451 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2452 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);
2453 if (!strcmp(pchunk->id, "ANIMHEAD"))
2457 else if (!strcmp(pchunk->id, "BONENAMES"))
2460 if (recordsize != sizeof(*p))
2461 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2462 // byteswap in place and keep the pointer
2463 numanimbones = numrecords;
2464 animbones = (pskboneinfo_t *)animbuffer;
2465 // NOTE: supposedly psa does not need to match the psk model, the
2466 // bones missing from the psa would simply use their base
2467 // positions from the psk, but this is hard for me to implement
2468 // and people can easily make animations that match.
2469 if (numanimbones != numbones)
2470 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2471 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2473 p->numchildren = LittleLong(p->numchildren);
2474 p->parent = LittleLong(p->parent);
2475 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2476 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2477 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2478 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2479 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2480 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2481 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2482 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2483 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2484 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2485 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2486 #ifdef PSKQUATNEGATIONS
2489 p->basepose.quat[0] *= -1;
2490 p->basepose.quat[1] *= -1;
2491 p->basepose.quat[2] *= -1;
2495 p->basepose.quat[0] *= 1;
2496 p->basepose.quat[1] *= -1;
2497 p->basepose.quat[2] *= 1;
2500 if (p->parent < 0 || p->parent >= numanimbones)
2502 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2505 // check that bones are the same as in the base
2506 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2507 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2511 else if (!strcmp(pchunk->id, "ANIMINFO"))
2514 if (recordsize != sizeof(*p))
2515 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2516 // byteswap in place and keep the pointer
2517 numanims = numrecords;
2518 anims = (pskaniminfo_t *)animbuffer;
2519 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2521 p->numbones = LittleLong(p->numbones);
2522 p->playtime = LittleFloat(p->playtime);
2523 p->fps = LittleFloat(p->fps);
2524 p->firstframe = LittleLong(p->firstframe);
2525 p->numframes = LittleLong(p->numframes);
2526 if (p->numbones != numbones)
2527 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2531 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2534 if (recordsize != sizeof(*p))
2535 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2536 numanimkeys = numrecords;
2537 animkeys = (pskanimkeys_t *)animbuffer;
2538 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2540 p->origin[0] = LittleFloat(p->origin[0]);
2541 p->origin[1] = LittleFloat(p->origin[1]);
2542 p->origin[2] = LittleFloat(p->origin[2]);
2543 p->quat[0] = LittleFloat(p->quat[0]);
2544 p->quat[1] = LittleFloat(p->quat[1]);
2545 p->quat[2] = LittleFloat(p->quat[2]);
2546 p->quat[3] = LittleFloat(p->quat[3]);
2547 p->frametime = LittleFloat(p->frametime);
2548 #ifdef PSKQUATNEGATIONS
2549 if (index % numbones)
2564 // TODO: allocate bonepose stuff
2567 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2570 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2571 Host_Error("%s: missing required chunks", loadmodel->name);
2573 loadmodel->numframes = 0;
2574 for (index = 0;index < numanims;index++)
2575 loadmodel->numframes += anims[index].numframes;
2577 if (numanimkeys != numbones * loadmodel->numframes)
2578 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2580 meshvertices = numvtxw;
2581 meshtriangles = numfaces;
2583 // load external .skin files if present
2584 skinfiles = Mod_LoadSkinFiles();
2585 if (loadmodel->numskins < 1)
2586 loadmodel->numskins = 1;
2587 loadmodel->num_bones = numbones;
2588 loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
2589 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2590 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2591 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2592 loadmodel->surfmesh.num_vertices = meshvertices;
2593 loadmodel->surfmesh.num_triangles = meshtriangles;
2594 // do most allocations as one merged chunk
2595 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);
2596 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2597 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2598 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2599 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2600 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2601 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2602 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2603 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2604 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2605 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2606 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2607 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += loadmodel->surfmesh.num_vertices * sizeof(int[4]);
2608 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[4]);
2609 //loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
2610 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2611 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2612 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2613 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2614 if (loadmodel->surfmesh.num_vertices <= 65536)
2616 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2617 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2618 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2620 loadmodel->data_poses = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->num_poses * sizeof(float[12]));
2622 for (i = 0;i < loadmodel->numskins;i++)
2624 loadmodel->skinscenes[i].firstframe = i;
2625 loadmodel->skinscenes[i].framecount = 1;
2626 loadmodel->skinscenes[i].loop = true;
2627 loadmodel->skinscenes[i].framerate = 10;
2631 for (index = 0, i = 0;index < nummatts;index++)
2633 // since psk models do not have named sections, reuse their shader name as the section name
2634 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2635 loadmodel->sortedmodelsurfaces[index] = index;
2636 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2637 loadmodel->data_surfaces[index].num_firstvertex = 0;
2638 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2641 // copy over the vertex locations and texcoords
2642 for (index = 0;index < numvtxw;index++)
2644 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2645 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2646 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2647 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2648 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2651 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2652 for (index = 0;index < numfaces;index++)
2653 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2654 for (index = 0, i = 0;index < nummatts;index++)
2656 loadmodel->data_surfaces[index].num_firsttriangle = i;
2657 i += loadmodel->data_surfaces[index].num_triangles;
2658 loadmodel->data_surfaces[index].num_triangles = 0;
2660 for (index = 0;index < numfaces;index++)
2662 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2663 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2664 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2665 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2668 // copy over the bones
2669 for (index = 0;index < numbones;index++)
2671 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2672 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2673 if (loadmodel->data_bones[index].parent >= index)
2674 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2677 // sort the psk point weights into the vertex weight tables
2678 // (which only accept up to 4 bones per vertex)
2679 for (index = 0;index < numvtxw;index++)
2683 for (j = 0;j < numrawweights;j++)
2685 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2687 int boneindex = rawweights[j].boneindex;
2688 float influence = rawweights[j].weight;
2689 for (l = 0;l < 4;l++)
2691 if (loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] < influence)
2693 // move lower influence weights out of the way first
2695 for (l2 = 3;l2 > l;l2--)
2697 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2-1];
2698 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2-1];
2700 // store the new weight
2701 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] = influence;
2702 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l] = boneindex;
2709 for (l = 0;l < 4;l++)
2710 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l];
2711 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2713 float f = 1.0f / sum;
2714 for (l = 0;l < 4;l++)
2715 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] *= f;
2719 // set up the animscenes based on the anims
2720 for (index = 0, i = 0;index < numanims;index++)
2722 for (j = 0;j < anims[index].numframes;j++, i++)
2724 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2725 loadmodel->animscenes[i].firstframe = i;
2726 loadmodel->animscenes[i].framecount = 1;
2727 loadmodel->animscenes[i].loop = true;
2728 loadmodel->animscenes[i].framerate = 10;
2732 // load the poses from the animkeys
2733 for (index = 0;index < numanimkeys;index++)
2735 pskanimkeys_t *k = animkeys + index;
2737 Matrix4x4_FromOriginQuat(&matrix, k->origin[0], k->origin[1], k->origin[2], k->quat[0], k->quat[1], k->quat[2], k->quat[3]);
2738 Matrix4x4_ToArray12FloatD3D(&matrix, loadmodel->data_poses + index*12);
2740 Mod_FreeSkinFiles(skinfiles);
2741 Mem_Free(animfilebuffer);
2742 Mod_MakeSortedSurfaces(loadmodel);
2744 // compute all the mesh information that was not loaded from the file
2745 // TODO: honor smoothing groups somehow?
2746 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2747 Mod_BuildBaseBonePoses();
2748 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2749 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);
2750 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2751 Mod_Alias_CalculateBoundingBox();
2753 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2756 void Mod_OBJ_Load(dp_model_t *mod, void *buffer, void *bufferend)
2759 const char *textbase = (char *)buffer, *text = textbase;
2763 char materialname[MAX_QPATH];
2764 int j, index1, index2, index3, first, prev, index;
2767 int numtriangles = 0;
2768 int maxtriangles = 32768;
2769 int *element3i = Mem_Alloc(tempmempool, maxtriangles * sizeof(int[3]));
2771 int numsurfaces = 0;
2772 int maxsurfaces = 0;
2773 msurface_t *surfaces = NULL;
2777 float *oldv, *oldvt, *oldvn;
2778 int maxv = 65536, numv = 1;
2779 int maxvt = 65536, numvt = 1;
2780 int maxvn = 65536, numvn = 1;
2781 int maxverthash = 65536, numverthash = 0;
2782 int numhashindex = 65536;
2783 struct objverthash_s
2785 struct objverthash_s *next;
2791 *hash, **verthash = Mem_Alloc(tempmempool, numhashindex * sizeof(*verthash)), *verthashdata = Mem_Alloc(tempmempool, maxverthash * sizeof(*verthashdata)), *oldverthashdata;
2792 skinfile_t *skinfiles;
2794 dpsnprintf(materialname, sizeof(materialname), "%s", loadmodel->name);
2796 skinfiles = Mod_LoadSkinFiles();
2798 loadmodel->modeldatatypestring = "OBJ";
2800 loadmodel->type = mod_alias;
2801 loadmodel->AnimateVertices = NULL;
2802 loadmodel->DrawSky = NULL;
2803 loadmodel->DrawAddWaterPlanes = NULL;
2804 loadmodel->Draw = R_Q1BSP_Draw;
2805 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2806 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2807 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2808 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2809 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2810 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2811 loadmodel->PointSuperContents = NULL;
2813 // parse the OBJ text now
2820 for (linelen = 0;text[linelen] && text[linelen] != '\r' && text[linelen] != '\n';linelen++)
2821 line[linelen] = text[linelen];
2823 for (argc = 0;argc < (int)(sizeof(argv)/sizeof(argv[0]));argc++)
2827 while (*s == ' ' || *s == '\t')
2837 while (*s == ' ' || *s == '\t')
2842 if (argv[0][0] == '#')
2844 if (!strcmp(argv[0], "v"))
2850 v = Mem_Alloc(tempmempool, maxv * sizeof(float[3]));
2853 memcpy(v, oldv, numv * sizeof(float[3]));
2857 v[numv*3+0] = atof(argv[1]);
2858 v[numv*3+1] = atof(argv[2]);
2859 v[numv*3+2] = atof(argv[3]);
2862 else if (!strcmp(argv[0], "vt"))
2868 vt = Mem_Alloc(tempmempool, maxvt * sizeof(float[2]));
2871 memcpy(vt, oldvt, numvt * sizeof(float[2]));
2875 vt[numvt*2+0] = atof(argv[1]);
2876 vt[numvt*2+1] = atof(argv[2]);
2879 else if (!strcmp(argv[0], "vn"))
2885 vn = Mem_Alloc(tempmempool, maxvn * sizeof(float[3]));
2888 memcpy(vn, oldvn, numvn * sizeof(float[3]));
2892 vn[numvn*3+0] = atof(argv[1]);
2893 vn[numvn*3+1] = atof(argv[2]);
2894 vn[numvn*3+2] = atof(argv[3]);
2897 else if (!strcmp(argv[0], "f"))
2901 if (maxsurfaces <= numsurfaces)
2904 oldsurfaces = surfaces;
2905 surfaces = Mem_Alloc(tempmempool, maxsurfaces * sizeof(*surfaces));
2908 memcpy(surfaces, oldsurfaces, numsurfaces * sizeof(*surfaces));
2909 Mem_Free(oldsurfaces);
2912 surface = surfaces + numsurfaces++;
2915 for (j = 1;j < argc;j++)
2917 index1 = atoi(argv[j]);
2918 while(argv[j][0] && argv[j][0] != '/')
2923 index1 = numv + 1 - index1;
2924 index2 = atoi(argv[j]);
2926 index2 = numvt + 1 - index2;
2927 while(argv[j][0] && argv[j][0] != '/')
2931 index3 = atoi(argv[j]);
2933 index3 = numvn + 1 - index3;
2934 hashindex = (index1 + index2 * 3571 + index3 * 42589) & (numhashindex - 1);
2935 for (hash = verthash[hashindex];hash;hash = hash->next)
2936 if (hash->surface == numsurfaces-1 && hash->v == index1 && hash->vt == index2 && hash->vn == index3)
2940 if (maxverthash <= numverthash)
2943 oldverthashdata = verthashdata;
2944 verthashdata = Mem_Alloc(tempmempool, maxverthash * sizeof(*verthashdata));
2945 if (oldverthashdata)
2947 memcpy(verthashdata, oldverthashdata, numverthash * sizeof(*verthashdata));
2948 Mem_Free(oldverthashdata);
2951 hash = verthashdata + numverthash++;
2952 hash->next = verthash[hashindex];
2953 hash->s = numsurfaces;
2957 verthash[hashindex] = hash;
2959 index = (int)((size_t)(hash - verthashdata));
2964 if (maxtriangles <= numtriangles)
2967 oldelement3i = element3i;
2968 element3i = Mem_Alloc(tempmempool, numtriangles * sizeof(int[3]));
2971 memcpy(element3i, oldelement3i, numtriangles * sizeof(int[3]));
2972 Mem_Free(oldelement3i);
2975 element3i[numtriangles*3+0] = first;
2976 element3i[numtriangles*3+1] = prev;
2977 element3i[numtriangles*3+2] = index;
2983 else if (!strcmp(argv[0], "o") || !strcmp(argv[0], "g"))
2985 else if (!!strcmp(argv[0], "usemtl"))
2988 strlcpy(materialname, argv[1], sizeof(materialname);
2998 Mod_FreeSkinFiles(skinfiles);
3000 // now that we have the OBJ data loaded as-is, we can convert it
3001 loadmodel->numskins = LittleLong(pinmodel->num_skins);
3002 numxyz = LittleLong(pinmodel->num_xyz);
3003 numst = LittleLong(pinmodel->num_st);
3004 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
3005 loadmodel->numframes = LittleLong(pinmodel->num_frames);
3006 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
3007 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
3008 skinwidth = LittleLong(pinmodel->skinwidth);
3009 skinheight = LittleLong(pinmodel->skinheight);
3010 iskinwidth = 1.0f / skinwidth;
3011 iskinheight = 1.0f / skinheight;
3013 loadmodel->num_surfaces = 1;
3014 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
3015 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]));
3016 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
3017 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
3018 loadmodel->sortedmodelsurfaces[0] = 0;
3019 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
3020 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
3021 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
3022 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
3024 loadmodel->synctype = ST_RAND;
3027 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
3028 skinfiles = Mod_LoadSkinFiles();
3031 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3032 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3033 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
3034 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
3035 Mod_FreeSkinFiles(skinfiles);
3037 else if (loadmodel->numskins)
3039 // skins found (most likely not a player model)
3040 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3041 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3042 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
3043 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
3044 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);
3048 // no skins (most likely a player model)
3049 loadmodel->numskins = 1;
3050 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3051 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3052 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
3053 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
3056 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
3057 for (i = 0;i < loadmodel->numskins;i++)
3059 loadmodel->skinscenes[i].firstframe = i;
3060 loadmodel->skinscenes[i].framecount = 1;
3061 loadmodel->skinscenes[i].loop = true;
3062 loadmodel->skinscenes[i].framerate = 10;
3065 // load the triangles and stvert data
3066 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
3067 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
3068 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
3069 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
3070 // swap the triangle list
3071 loadmodel->surfmesh.num_vertices = 0;
3072 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
3074 for (j = 0;j < 3;j++)
3076 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
3077 st = (unsigned short) LittleShort (intri[i].index_st[j]);
3080 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
3085 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
3088 hashindex = (xyz * 256 + st) & 65535;
3089 for (hash = md2verthash[hashindex];hash;hash = hash->next)
3090 if (hash->xyz == xyz && hash->st == st)
3094 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
3097 hash->next = md2verthash[hashindex];
3098 md2verthash[hashindex] = hash;
3100 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
3104 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
3105 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));
3106 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
3107 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
3108 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
3111 hash = md2verthashdata + i;
3112 vertremap[i] = hash->xyz;
3113 sts = LittleShort(inst[hash->st*2+0]);
3114 stt = LittleShort(inst[hash->st*2+1]);
3115 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
3117 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
3121 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
3122 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
3125 Mem_Free(md2verthash);
3126 Mem_Free(md2verthashdata);
3128 // generate ushort elements array if possible
3129 if (loadmodel->surfmesh.num_vertices <= 65536)
3131 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
3132 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3133 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3137 datapointer = (base + LittleLong(pinmodel->ofs_frames));
3138 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
3143 pinframe = (md2frame_t *)datapointer;
3144 datapointer += sizeof(md2frame_t);
3145 // store the frame scale/translate into the appropriate array
3146 for (j = 0;j < 3;j++)
3148 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
3149 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
3151 // convert the vertices
3152 v = (trivertx_t *)datapointer;
3153 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
3154 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
3155 out[k] = v[vertremap[k]];
3156 datapointer += numxyz * sizeof(trivertx_t);
3158 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
3159 loadmodel->animscenes[i].firstframe = i;
3160 loadmodel->animscenes[i].framecount = 1;
3161 loadmodel->animscenes[i].framerate = 10;
3162 loadmodel->animscenes[i].loop = true;
3165 Mem_Free(vertremap);
3167 Mod_MakeSortedSurfaces(loadmodel);
3168 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3169 Mod_Alias_CalculateBoundingBox();
3170 Mod_Alias_MorphMesh_CompileFrames();
3172 surface = loadmodel->data_surfaces;
3173 surface->texture = loadmodel->data_textures;
3174 surface->num_firsttriangle = 0;
3175 surface->num_triangles = loadmodel->surfmesh.num_triangles;
3176 surface->num_firstvertex = 0;
3177 surface->num_vertices = loadmodel->surfmesh.num_vertices;
3179 loadmodel->surfmesh.isanimated = false;