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)
585 radius = sqrt(radius);
586 yawradius = sqrt(yawradius);
587 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
588 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
589 loadmodel->yawmins[2] = loadmodel->normalmins[2];
590 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
591 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
592 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
593 loadmodel->radius = radius;
594 loadmodel->radius2 = radius * radius;
597 static void Mod_Alias_MorphMesh_CompileFrames(void)
600 frameblend_t frameblend[MAX_FRAMEBLENDS];
601 unsigned char *datapointer;
602 memset(frameblend, 0, sizeof(frameblend));
603 frameblend[0].lerp = 1;
604 datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
605 loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
606 loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
607 loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
608 loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
609 loadmodel->surfmesh.data_morphtexvecvertex = (texvecvertex_t *)datapointer;datapointer += loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices * sizeof(texvecvertex_t);
610 // 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)
611 for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
613 frameblend[0].subframe = i;
614 loadmodel->AnimateVertices(loadmodel, frameblend, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
615 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);
616 // encode the svector and tvector in 3 byte format for permanent storage
617 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
619 VectorScaleCast(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
620 VectorScaleCast(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
625 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)
628 float segmentmins[3], segmentmaxs[3];
629 frameblend_t frameblend[MAX_FRAMEBLENDS];
631 static int maxvertices = 0;
632 static float *vertex3f = NULL;
633 memset(trace, 0, sizeof(*trace));
635 trace->realfraction = 1;
636 trace->hitsupercontentsmask = hitsupercontentsmask;
637 memset(frameblend, 0, sizeof(frameblend));
638 frameblend[0].subframe = frame;
639 frameblend[0].lerp = 1;
640 if (maxvertices < model->surfmesh.num_vertices)
644 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
645 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
647 if (VectorLength2(boxmins) + VectorLength2(boxmaxs) == 0)
650 segmentmins[0] = min(start[0], end[0]) - 1;
651 segmentmins[1] = min(start[1], end[1]) - 1;
652 segmentmins[2] = min(start[2], end[2]) - 1;
653 segmentmaxs[0] = max(start[0], end[0]) + 1;
654 segmentmaxs[1] = max(start[1], end[1]) + 1;
655 segmentmaxs[2] = max(start[2], end[2]) + 1;
656 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
658 model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL);
659 Collision_TraceLineTriangleMeshFloat(trace, start, end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, SUPERCONTENTS_SOLID, 0, surface->texture, segmentmins, segmentmaxs);
664 // box trace, performed as brush trace
665 colbrushf_t *thisbrush_start, *thisbrush_end;
666 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
667 segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
668 segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
669 segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
670 segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
671 segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
672 segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
673 VectorAdd(start, boxmins, boxstartmins);
674 VectorAdd(start, boxmaxs, boxstartmaxs);
675 VectorAdd(end, boxmins, boxendmins);
676 VectorAdd(end, boxmaxs, boxendmaxs);
677 thisbrush_start = Collision_BrushForBox(&identitymatrix, boxstartmins, boxstartmaxs, 0, 0, NULL);
678 thisbrush_end = Collision_BrushForBox(&identitymatrix, boxendmins, boxendmaxs, 0, 0, NULL);
679 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
681 if (maxvertices < model->surfmesh.num_vertices)
685 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
686 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
688 model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL);
689 Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, SUPERCONTENTS_SOLID, 0, surface->texture, segmentmins, segmentmaxs);
694 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
697 for (i = 0;i < inverts;i++)
699 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
701 j = vertremap[i]; // not onseam
704 j = vertremap[i+inverts]; // onseam
710 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
712 int i, f, pose, groupframes;
714 daliasframetype_t *pframetype;
715 daliasframe_t *pinframe;
716 daliasgroup_t *group;
717 daliasinterval_t *intervals;
720 scene = loadmodel->animscenes;
721 for (f = 0;f < loadmodel->numframes;f++)
723 pframetype = (daliasframetype_t *)datapointer;
724 datapointer += sizeof(daliasframetype_t);
725 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
727 // a single frame is still treated as a group
734 group = (daliasgroup_t *)datapointer;
735 datapointer += sizeof(daliasgroup_t);
736 groupframes = LittleLong (group->numframes);
738 // intervals (time per frame)
739 intervals = (daliasinterval_t *)datapointer;
740 datapointer += sizeof(daliasinterval_t) * groupframes;
742 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
743 if (interval < 0.01f)
745 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
750 // get scene name from first frame
751 pinframe = (daliasframe_t *)datapointer;
753 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
754 scene->firstframe = pose;
755 scene->framecount = groupframes;
756 scene->framerate = 1.0f / interval;
761 for (i = 0;i < groupframes;i++)
763 pinframe = (daliasframe_t *)datapointer;
764 datapointer += sizeof(daliasframe_t);
765 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
766 datapointer += sizeof(trivertx_t) * inverts;
772 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
774 if (cls.state == ca_dedicated)
778 skinframe = R_SkinFrame_LoadMissing();
779 memset(texture, 0, sizeof(*texture));
780 texture->currentframe = texture;
781 //texture->animated = false;
782 texture->numskinframes = 1;
783 texture->skinframerate = 1;
784 texture->skinframes[0] = skinframe;
785 texture->currentskinframe = skinframe;
786 //texture->backgroundnumskinframes = 0;
787 //texture->customblendfunc[0] = 0;
788 //texture->customblendfunc[1] = 0;
789 //texture->surfaceflags = 0;
790 //texture->supercontents = 0;
791 //texture->surfaceparms = 0;
792 //texture->textureflags = 0;
794 texture->basematerialflags = MATERIALFLAG_WALL;
795 if (texture->currentskinframe->fog)
796 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
797 texture->currentmaterialflags = texture->basematerialflags;
800 static void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
803 skinfileitem_t *skinfileitem;
806 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
807 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
809 memset(skin, 0, sizeof(*skin));
811 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
813 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
814 if (!strcmp(skinfileitem->name, meshname))
816 Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
822 // don't render unmentioned meshes
823 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
824 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
829 Mod_LoadTextureFromQ3Shader(skin, shadername, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
832 #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);
833 #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);
834 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
836 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
837 float scales, scalet, interval;
841 stvert_t *pinstverts;
842 dtriangle_t *pintriangles;
843 daliasskintype_t *pinskintype;
844 daliasskingroup_t *pinskingroup;
845 daliasskininterval_t *pinskinintervals;
846 daliasframetype_t *pinframetype;
847 daliasgroup_t *pinframegroup;
848 unsigned char *datapointer, *startframes, *startskins;
849 char name[MAX_QPATH];
850 skinframe_t *tempskinframe;
851 animscene_t *tempskinscenes;
852 texture_t *tempaliasskins;
854 int *vertonseam, *vertremap;
855 skinfile_t *skinfiles;
857 datapointer = (unsigned char *)buffer;
858 pinmodel = (mdl_t *)datapointer;
859 datapointer += sizeof(mdl_t);
861 version = LittleLong (pinmodel->version);
862 if (version != ALIAS_VERSION)
863 Host_Error ("%s has wrong version number (%i should be %i)",
864 loadmodel->name, version, ALIAS_VERSION);
866 loadmodel->modeldatatypestring = "MDL";
868 loadmodel->type = mod_alias;
869 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
870 loadmodel->DrawSky = NULL;
871 loadmodel->DrawAddWaterPlanes = NULL;
872 loadmodel->Draw = R_Q1BSP_Draw;
873 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
874 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
875 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
876 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
877 loadmodel->DrawLight = R_Q1BSP_DrawLight;
878 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
879 loadmodel->PointSuperContents = NULL;
881 loadmodel->num_surfaces = 1;
882 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
883 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
884 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
885 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
886 loadmodel->sortedmodelsurfaces[0] = 0;
888 loadmodel->numskins = LittleLong(pinmodel->numskins);
889 BOUNDI(loadmodel->numskins,0,65536);
890 skinwidth = LittleLong (pinmodel->skinwidth);
891 BOUNDI(skinwidth,0,65536);
892 skinheight = LittleLong (pinmodel->skinheight);
893 BOUNDI(skinheight,0,65536);
894 numverts = LittleLong(pinmodel->numverts);
895 BOUNDI(numverts,0,65536);
896 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
897 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
898 loadmodel->numframes = LittleLong(pinmodel->numframes);
899 BOUNDI(loadmodel->numframes,0,65536);
900 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
901 BOUNDI(loadmodel->synctype,0,2);
902 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
903 i = LittleLong (pinmodel->flags);
904 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
906 for (i = 0;i < 3;i++)
908 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
909 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
912 startskins = datapointer;
914 for (i = 0;i < loadmodel->numskins;i++)
916 pinskintype = (daliasskintype_t *)datapointer;
917 datapointer += sizeof(daliasskintype_t);
918 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
922 pinskingroup = (daliasskingroup_t *)datapointer;
923 datapointer += sizeof(daliasskingroup_t);
924 groupskins = LittleLong(pinskingroup->numskins);
925 datapointer += sizeof(daliasskininterval_t) * groupskins;
928 for (j = 0;j < groupskins;j++)
930 datapointer += skinwidth * skinheight;
935 pinstverts = (stvert_t *)datapointer;
936 datapointer += sizeof(stvert_t) * numverts;
938 pintriangles = (dtriangle_t *)datapointer;
939 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
941 startframes = datapointer;
942 loadmodel->surfmesh.num_morphframes = 0;
943 for (i = 0;i < loadmodel->numframes;i++)
945 pinframetype = (daliasframetype_t *)datapointer;
946 datapointer += sizeof(daliasframetype_t);
947 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
951 pinframegroup = (daliasgroup_t *)datapointer;
952 datapointer += sizeof(daliasgroup_t);
953 groupframes = LittleLong(pinframegroup->numframes);
954 datapointer += sizeof(daliasinterval_t) * groupframes;
957 for (j = 0;j < groupframes;j++)
959 datapointer += sizeof(daliasframe_t);
960 datapointer += sizeof(trivertx_t) * numverts;
961 loadmodel->surfmesh.num_morphframes++;
964 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
966 // store texture coordinates into temporary array, they will be stored
967 // after usage is determined (triangle data)
968 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
969 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
970 vertonseam = vertremap + numverts * 2;
972 scales = 1.0 / skinwidth;
973 scalet = 1.0 / skinheight;
974 for (i = 0;i < numverts;i++)
976 vertonseam[i] = LittleLong(pinstverts[i].onseam);
977 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
978 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
979 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
980 vertst[(i+numverts)*2+1] = vertst[i*2+1];
983 // load triangle data
984 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
986 // read the triangle elements
987 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
988 for (j = 0;j < 3;j++)
989 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
990 // validate (note numverts is used because this is the original data)
991 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
992 // now butcher the elements according to vertonseam and tri->facesfront
993 // and then compact the vertex set to remove duplicates
994 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
995 if (!LittleLong(pintriangles[i].facesfront)) // backface
996 for (j = 0;j < 3;j++)
997 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
998 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1000 // (this uses vertremap to count usage to save some memory)
1001 for (i = 0;i < numverts*2;i++)
1003 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1004 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1005 // build remapping table and compact array
1006 loadmodel->surfmesh.num_vertices = 0;
1007 for (i = 0;i < numverts*2;i++)
1011 vertremap[i] = loadmodel->surfmesh.num_vertices;
1012 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1013 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1014 loadmodel->surfmesh.num_vertices++;
1017 vertremap[i] = -1; // not used at all
1019 // remap the elements to the new vertex set
1020 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1021 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1022 // store the texture coordinates
1023 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1024 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1026 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1027 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1030 // generate ushort elements array if possible
1031 if (loadmodel->surfmesh.num_vertices <= 65536)
1033 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1034 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1035 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1039 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1040 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1041 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1042 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1043 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1044 Mod_Alias_CalculateBoundingBox();
1045 Mod_Alias_MorphMesh_CompileFrames();
1048 Mem_Free(vertremap);
1051 skinfiles = Mod_LoadSkinFiles();
1054 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1055 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1056 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1057 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1058 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1059 Mod_FreeSkinFiles(skinfiles);
1060 for (i = 0;i < loadmodel->numskins;i++)
1062 loadmodel->skinscenes[i].firstframe = i;
1063 loadmodel->skinscenes[i].framecount = 1;
1064 loadmodel->skinscenes[i].loop = true;
1065 loadmodel->skinscenes[i].framerate = 10;
1070 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1071 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1072 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1073 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1075 datapointer = startskins;
1076 for (i = 0;i < loadmodel->numskins;i++)
1078 pinskintype = (daliasskintype_t *)datapointer;
1079 datapointer += sizeof(daliasskintype_t);
1081 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1088 pinskingroup = (daliasskingroup_t *)datapointer;
1089 datapointer += sizeof(daliasskingroup_t);
1091 groupskins = LittleLong (pinskingroup->numskins);
1093 pinskinintervals = (daliasskininterval_t *)datapointer;
1094 datapointer += sizeof(daliasskininterval_t) * groupskins;
1096 interval = LittleFloat(pinskinintervals[0].interval);
1097 if (interval < 0.01f)
1099 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1104 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1105 loadmodel->skinscenes[i].firstframe = totalskins;
1106 loadmodel->skinscenes[i].framecount = groupskins;
1107 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1108 loadmodel->skinscenes[i].loop = true;
1110 for (j = 0;j < groupskins;j++)
1113 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1115 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1116 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))
1117 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));
1118 datapointer += skinwidth * skinheight;
1122 // check for skins that don't exist in the model, but do exist as external images
1123 // (this was added because yummyluv kept pestering me about support for it)
1124 // TODO: support shaders here?
1125 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)))
1127 // expand the arrays to make room
1128 tempskinscenes = loadmodel->skinscenes;
1129 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1130 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1131 Mem_Free(tempskinscenes);
1133 tempaliasskins = loadmodel->data_textures;
1134 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1135 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1136 Mem_Free(tempaliasskins);
1138 // store the info about the new skin
1139 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1140 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1141 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1142 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1143 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1144 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1146 //increase skin counts
1147 loadmodel->numskins++;
1150 // fix up the pointers since they are pointing at the old textures array
1151 // FIXME: this is a hack!
1152 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1153 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1157 surface = loadmodel->data_surfaces;
1158 surface->texture = loadmodel->data_textures;
1159 surface->num_firsttriangle = 0;
1160 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1161 surface->num_firstvertex = 0;
1162 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1164 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1167 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1169 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1170 float iskinwidth, iskinheight;
1171 unsigned char *data;
1172 msurface_t *surface;
1174 unsigned char *base, *datapointer;
1175 md2frame_t *pinframe;
1177 md2triangle_t *intri;
1178 unsigned short *inst;
1179 struct md2verthash_s
1181 struct md2verthash_s *next;
1185 *hash, **md2verthash, *md2verthashdata;
1186 skinfile_t *skinfiles;
1188 pinmodel = (md2_t *)buffer;
1189 base = (unsigned char *)buffer;
1191 version = LittleLong (pinmodel->version);
1192 if (version != MD2ALIAS_VERSION)
1193 Host_Error ("%s has wrong version number (%i should be %i)",
1194 loadmodel->name, version, MD2ALIAS_VERSION);
1196 loadmodel->modeldatatypestring = "MD2";
1198 loadmodel->type = mod_alias;
1199 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1200 loadmodel->DrawSky = NULL;
1201 loadmodel->DrawAddWaterPlanes = NULL;
1202 loadmodel->Draw = R_Q1BSP_Draw;
1203 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1204 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1205 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1206 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1207 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1208 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1209 loadmodel->PointSuperContents = NULL;
1211 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1212 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1213 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1214 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1215 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1216 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1217 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1218 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1220 end = LittleLong(pinmodel->ofs_end);
1221 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1222 Host_Error ("%s is not a valid model", loadmodel->name);
1223 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1224 Host_Error ("%s is not a valid model", loadmodel->name);
1225 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1226 Host_Error ("%s is not a valid model", loadmodel->name);
1227 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1228 Host_Error ("%s is not a valid model", loadmodel->name);
1229 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1230 Host_Error ("%s is not a valid model", loadmodel->name);
1232 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1233 numxyz = LittleLong(pinmodel->num_xyz);
1234 numst = LittleLong(pinmodel->num_st);
1235 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1236 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1237 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1238 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1239 skinwidth = LittleLong(pinmodel->skinwidth);
1240 skinheight = LittleLong(pinmodel->skinheight);
1241 iskinwidth = 1.0f / skinwidth;
1242 iskinheight = 1.0f / skinheight;
1244 loadmodel->num_surfaces = 1;
1245 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1246 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]));
1247 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1248 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1249 loadmodel->sortedmodelsurfaces[0] = 0;
1250 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1251 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1252 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1253 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1255 loadmodel->synctype = ST_RAND;
1258 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1259 skinfiles = Mod_LoadSkinFiles();
1262 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1263 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1264 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1265 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1266 Mod_FreeSkinFiles(skinfiles);
1268 else if (loadmodel->numskins)
1270 // skins found (most likely not a player model)
1271 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1272 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1273 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1274 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1275 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);
1279 // no skins (most likely a player model)
1280 loadmodel->numskins = 1;
1281 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1282 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1283 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1284 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1287 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1288 for (i = 0;i < loadmodel->numskins;i++)
1290 loadmodel->skinscenes[i].firstframe = i;
1291 loadmodel->skinscenes[i].framecount = 1;
1292 loadmodel->skinscenes[i].loop = true;
1293 loadmodel->skinscenes[i].framerate = 10;
1296 // load the triangles and stvert data
1297 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1298 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1299 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1300 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1301 // swap the triangle list
1302 loadmodel->surfmesh.num_vertices = 0;
1303 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1305 for (j = 0;j < 3;j++)
1307 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1308 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1311 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1316 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1319 hashindex = (xyz * 256 + st) & 65535;
1320 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1321 if (hash->xyz == xyz && hash->st == st)
1325 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1328 hash->next = md2verthash[hashindex];
1329 md2verthash[hashindex] = hash;
1331 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1335 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1336 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));
1337 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1338 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1339 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1342 hash = md2verthashdata + i;
1343 vertremap[i] = hash->xyz;
1344 sts = LittleShort(inst[hash->st*2+0]);
1345 stt = LittleShort(inst[hash->st*2+1]);
1346 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1348 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1352 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1353 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1356 Mem_Free(md2verthash);
1357 Mem_Free(md2verthashdata);
1359 // generate ushort elements array if possible
1360 if (loadmodel->surfmesh.num_vertices <= 65536)
1362 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1363 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1364 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1368 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1369 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1374 pinframe = (md2frame_t *)datapointer;
1375 datapointer += sizeof(md2frame_t);
1376 // store the frame scale/translate into the appropriate array
1377 for (j = 0;j < 3;j++)
1379 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1380 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1382 // convert the vertices
1383 v = (trivertx_t *)datapointer;
1384 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1385 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1386 out[k] = v[vertremap[k]];
1387 datapointer += numxyz * sizeof(trivertx_t);
1389 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1390 loadmodel->animscenes[i].firstframe = i;
1391 loadmodel->animscenes[i].framecount = 1;
1392 loadmodel->animscenes[i].framerate = 10;
1393 loadmodel->animscenes[i].loop = true;
1396 Mem_Free(vertremap);
1398 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1399 Mod_Alias_CalculateBoundingBox();
1400 Mod_Alias_MorphMesh_CompileFrames();
1402 surface = loadmodel->data_surfaces;
1403 surface->texture = loadmodel->data_textures;
1404 surface->num_firsttriangle = 0;
1405 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1406 surface->num_firstvertex = 0;
1407 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1409 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1412 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1414 int i, j, k, version, meshvertices, meshtriangles;
1415 unsigned char *data;
1416 msurface_t *surface;
1417 md3modelheader_t *pinmodel;
1418 md3frameinfo_t *pinframe;
1421 skinfile_t *skinfiles;
1423 pinmodel = (md3modelheader_t *)buffer;
1425 if (memcmp(pinmodel->identifier, "IDP3", 4))
1426 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1427 version = LittleLong (pinmodel->version);
1428 if (version != MD3VERSION)
1429 Host_Error ("%s has wrong version number (%i should be %i)",
1430 loadmodel->name, version, MD3VERSION);
1432 skinfiles = Mod_LoadSkinFiles();
1433 if (loadmodel->numskins < 1)
1434 loadmodel->numskins = 1;
1436 loadmodel->modeldatatypestring = "MD3";
1438 loadmodel->type = mod_alias;
1439 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1440 loadmodel->DrawSky = NULL;
1441 loadmodel->DrawAddWaterPlanes = NULL;
1442 loadmodel->Draw = R_Q1BSP_Draw;
1443 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1444 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1445 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1446 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1447 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1448 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1449 loadmodel->PointSuperContents = NULL;
1450 loadmodel->synctype = ST_RAND;
1451 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1452 i = LittleLong (pinmodel->flags);
1453 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1455 // set up some global info about the model
1456 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1457 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1459 // make skinscenes for the skins (no groups)
1460 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1461 for (i = 0;i < loadmodel->numskins;i++)
1463 loadmodel->skinscenes[i].firstframe = i;
1464 loadmodel->skinscenes[i].framecount = 1;
1465 loadmodel->skinscenes[i].loop = true;
1466 loadmodel->skinscenes[i].framerate = 10;
1470 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1471 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1473 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1474 loadmodel->animscenes[i].firstframe = i;
1475 loadmodel->animscenes[i].framecount = 1;
1476 loadmodel->animscenes[i].framerate = 10;
1477 loadmodel->animscenes[i].loop = true;
1481 loadmodel->num_tagframes = loadmodel->numframes;
1482 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1483 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1484 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1486 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1487 for (j = 0;j < 9;j++)
1488 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1489 for (j = 0;j < 3;j++)
1490 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1491 //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);
1497 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)))
1499 if (memcmp(pinmesh->identifier, "IDP3", 4))
1500 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1501 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1502 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1503 meshvertices += LittleLong(pinmesh->num_vertices);
1504 meshtriangles += LittleLong(pinmesh->num_triangles);
1507 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1508 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1509 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1510 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));
1511 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1512 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1513 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1514 loadmodel->surfmesh.num_vertices = meshvertices;
1515 loadmodel->surfmesh.num_triangles = meshtriangles;
1516 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1517 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1518 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1519 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1520 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1521 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1522 if (meshvertices <= 65536)
1524 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1525 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1526 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1531 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)))
1533 if (memcmp(pinmesh->identifier, "IDP3", 4))
1534 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1535 loadmodel->sortedmodelsurfaces[i] = i;
1536 surface = loadmodel->data_surfaces + i;
1537 surface->texture = loadmodel->data_textures + i;
1538 surface->num_firsttriangle = meshtriangles;
1539 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1540 surface->num_firstvertex = meshvertices;
1541 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1542 meshvertices += surface->num_vertices;
1543 meshtriangles += surface->num_triangles;
1545 for (j = 0;j < surface->num_triangles * 3;j++)
1546 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1547 for (j = 0;j < surface->num_vertices;j++)
1549 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1550 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1552 for (j = 0;j < loadmodel->numframes;j++)
1554 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1555 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1556 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1558 out->origin[0] = LittleShort(in->origin[0]);
1559 out->origin[1] = LittleShort(in->origin[1]);
1560 out->origin[2] = LittleShort(in->origin[2]);
1561 out->pitch = in->pitch;
1566 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1568 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1570 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1571 Mod_Alias_MorphMesh_CompileFrames();
1572 Mod_Alias_CalculateBoundingBox();
1573 Mod_FreeSkinFiles(skinfiles);
1574 Mod_MakeSortedSurfaces(loadmodel);
1576 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1577 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1580 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1582 zymtype1header_t *pinmodel, *pheader;
1583 unsigned char *pbase;
1584 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1585 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose;
1586 zymvertex_t *verts, *vertdata;
1590 skinfile_t *skinfiles;
1591 unsigned char *data;
1592 msurface_t *surface;
1594 pinmodel = (zymtype1header_t *)buffer;
1595 pbase = (unsigned char *)buffer;
1596 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1597 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1598 if (BigLong(pinmodel->type) != 1)
1599 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1601 loadmodel->modeldatatypestring = "ZYM";
1603 loadmodel->type = mod_alias;
1604 loadmodel->synctype = ST_RAND;
1608 pheader->type = BigLong(pinmodel->type);
1609 pheader->filesize = BigLong(pinmodel->filesize);
1610 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1611 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1612 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1613 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1614 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1615 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1616 pheader->radius = BigFloat(pinmodel->radius);
1617 pheader->numverts = BigLong(pinmodel->numverts);
1618 pheader->numtris = BigLong(pinmodel->numtris);
1619 pheader->numshaders = BigLong(pinmodel->numshaders);
1620 pheader->numbones = BigLong(pinmodel->numbones);
1621 pheader->numscenes = BigLong(pinmodel->numscenes);
1622 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1623 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1624 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1625 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1626 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1627 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1628 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1629 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1630 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1631 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1632 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1633 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1634 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1635 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1636 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1637 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1638 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1639 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1641 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1643 Con_Printf("%s has no geometry\n", loadmodel->name);
1646 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1648 Con_Printf("%s has no animations\n", loadmodel->name);
1652 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1653 loadmodel->DrawSky = NULL;
1654 loadmodel->DrawAddWaterPlanes = NULL;
1655 loadmodel->Draw = R_Q1BSP_Draw;
1656 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1657 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1658 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1659 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1660 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1661 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1662 loadmodel->PointSuperContents = NULL;
1664 loadmodel->numframes = pheader->numscenes;
1665 loadmodel->num_surfaces = pheader->numshaders;
1667 skinfiles = Mod_LoadSkinFiles();
1668 if (loadmodel->numskins < 1)
1669 loadmodel->numskins = 1;
1671 // make skinscenes for the skins (no groups)
1672 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1673 for (i = 0;i < loadmodel->numskins;i++)
1675 loadmodel->skinscenes[i].firstframe = i;
1676 loadmodel->skinscenes[i].framecount = 1;
1677 loadmodel->skinscenes[i].loop = true;
1678 loadmodel->skinscenes[i].framerate = 10;
1682 modelradius = pheader->radius;
1683 for (i = 0;i < 3;i++)
1685 loadmodel->normalmins[i] = pheader->mins[i];
1686 loadmodel->normalmaxs[i] = pheader->maxs[i];
1687 loadmodel->rotatedmins[i] = -modelradius;
1688 loadmodel->rotatedmaxs[i] = modelradius;
1690 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1691 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1692 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1693 if (loadmodel->yawmaxs[0] > modelradius)
1694 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1695 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1696 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1697 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1698 loadmodel->radius = modelradius;
1699 loadmodel->radius2 = modelradius * modelradius;
1701 // go through the lumps, swapping things
1703 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1704 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1705 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1706 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1707 for (i = 0;i < pheader->numscenes;i++)
1709 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1710 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1711 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1712 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1713 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1714 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1715 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1716 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1717 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1718 if (loadmodel->animscenes[i].framerate < 0)
1719 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1723 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1724 loadmodel->num_bones = pheader->numbones;
1725 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, pheader->numbones * sizeof(aliasbone_t));
1726 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1727 for (i = 0;i < pheader->numbones;i++)
1729 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1730 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1731 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1732 if (loadmodel->data_bones[i].parent >= i)
1733 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1736 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1737 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1738 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1739 for (i = 0;i < pheader->numverts;i++)
1741 vertbonecounts[i] = BigLong(bonecount[i]);
1742 if (vertbonecounts[i] != 1)
1743 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1746 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]);
1748 meshvertices = pheader->numverts;
1749 meshtriangles = pheader->numtris;
1751 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1752 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1753 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1754 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]));
1755 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1756 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1757 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1758 loadmodel->surfmesh.num_vertices = meshvertices;
1759 loadmodel->surfmesh.num_triangles = meshtriangles;
1760 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1761 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1762 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1763 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1764 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1765 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1766 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1767 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1768 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1769 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
1770 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1771 if (loadmodel->surfmesh.num_vertices <= 65536)
1773 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1774 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1775 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1778 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1779 poses = (float *) (pheader->lump_poses.start + pbase);
1780 for (i = 0;i < pheader->lump_poses.length / 4;i++)
1781 loadmodel->data_poses[i] = BigFloat(poses[i]);
1783 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1784 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1785 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1786 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1787 // (converting from weight-blending skeletal animation to
1788 // deformation-based skeletal animation)
1789 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1790 for (i = 0;i < loadmodel->num_bones;i++)
1792 const float *m = loadmodel->data_poses + i * 12;
1793 if (loadmodel->data_bones[i].parent >= 0)
1794 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1796 for (k = 0;k < 12;k++)
1797 bonepose[12*i+k] = m[k];
1799 for (j = 0;j < pheader->numverts;j++)
1801 // this format really should have had a per vertexweight weight value...
1802 // but since it does not, the weighting is completely ignored and
1803 // only one weight is allowed per vertex
1804 int boneindex = BigLong(vertdata[j].bonenum);
1805 const float *m = bonepose + 12 * boneindex;
1806 float relativeorigin[3];
1807 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1808 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1809 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1810 // transform the vertex bone weight into the base mesh
1811 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1812 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1813 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1814 // store the weight as the primary weight on this vertex
1815 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
1816 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = 1;
1819 // normals and tangents are calculated after elements are loaded
1821 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1822 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1823 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1824 for (i = 0;i < pheader->numverts;i++)
1826 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1827 // flip T coordinate for OpenGL
1828 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1831 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1832 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1833 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1835 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1836 //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)
1837 // byteswap, validate, and swap winding order of tris
1838 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1839 if (pheader->lump_render.length != count)
1840 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1841 renderlist = (int *) (pheader->lump_render.start + pbase);
1842 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1844 for (i = 0;i < loadmodel->num_surfaces;i++)
1846 int firstvertex, lastvertex;
1847 if (renderlist >= renderlistend)
1848 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1849 count = BigLong(*renderlist);renderlist++;
1850 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1851 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1853 loadmodel->sortedmodelsurfaces[i] = i;
1854 surface = loadmodel->data_surfaces + i;
1855 surface->texture = loadmodel->data_textures + i;
1856 surface->num_firsttriangle = meshtriangles;
1857 surface->num_triangles = count;
1858 meshtriangles += surface->num_triangles;
1860 // load the elements
1861 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
1862 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
1864 outelements[j*3+2] = BigLong(renderlist[0]);
1865 outelements[j*3+1] = BigLong(renderlist[1]);
1866 outelements[j*3+0] = BigLong(renderlist[2]);
1868 // validate the elements and find the used vertex range
1869 firstvertex = meshvertices;
1871 for (j = 0;j < surface->num_triangles * 3;j++)
1873 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
1874 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
1875 firstvertex = min(firstvertex, outelements[j]);
1876 lastvertex = max(lastvertex, outelements[j]);
1878 surface->num_firstvertex = firstvertex;
1879 surface->num_vertices = lastvertex + 1 - firstvertex;
1881 // since zym models do not have named sections, reuse their shader
1882 // name as the section name
1883 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
1884 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
1886 Mod_FreeSkinFiles(skinfiles);
1887 Mem_Free(vertbonecounts);
1889 Mod_MakeSortedSurfaces(loadmodel);
1891 // compute all the mesh information that was not loaded from the file
1892 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
1893 Mod_BuildBaseBonePoses();
1894 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
1895 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);
1896 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1898 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1901 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1903 dpmheader_t *pheader;
1907 unsigned char *pbase;
1908 int i, j, k, meshvertices, meshtriangles;
1909 skinfile_t *skinfiles;
1910 unsigned char *data;
1913 pheader = (dpmheader_t *)buffer;
1914 pbase = (unsigned char *)buffer;
1915 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
1916 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
1917 if (BigLong(pheader->type) != 2)
1918 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1920 loadmodel->modeldatatypestring = "DPM";
1922 loadmodel->type = mod_alias;
1923 loadmodel->synctype = ST_RAND;
1926 pheader->type = BigLong(pheader->type);
1927 pheader->filesize = BigLong(pheader->filesize);
1928 pheader->mins[0] = BigFloat(pheader->mins[0]);
1929 pheader->mins[1] = BigFloat(pheader->mins[1]);
1930 pheader->mins[2] = BigFloat(pheader->mins[2]);
1931 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
1932 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
1933 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
1934 pheader->yawradius = BigFloat(pheader->yawradius);
1935 pheader->allradius = BigFloat(pheader->allradius);
1936 pheader->num_bones = BigLong(pheader->num_bones);
1937 pheader->num_meshs = BigLong(pheader->num_meshs);
1938 pheader->num_frames = BigLong(pheader->num_frames);
1939 pheader->ofs_bones = BigLong(pheader->ofs_bones);
1940 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
1941 pheader->ofs_frames = BigLong(pheader->ofs_frames);
1943 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
1945 Con_Printf("%s has no geometry\n", loadmodel->name);
1948 if (pheader->num_frames < 1)
1950 Con_Printf("%s has no frames\n", loadmodel->name);
1954 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1955 loadmodel->DrawSky = NULL;
1956 loadmodel->DrawAddWaterPlanes = NULL;
1957 loadmodel->Draw = R_Q1BSP_Draw;
1958 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1959 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1960 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1961 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1962 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1963 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1964 loadmodel->PointSuperContents = NULL;
1967 for (i = 0;i < 3;i++)
1969 loadmodel->normalmins[i] = pheader->mins[i];
1970 loadmodel->normalmaxs[i] = pheader->maxs[i];
1971 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
1972 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
1973 loadmodel->rotatedmins[i] = -pheader->allradius;
1974 loadmodel->rotatedmaxs[i] = pheader->allradius;
1976 loadmodel->radius = pheader->allradius;
1977 loadmodel->radius2 = pheader->allradius * pheader->allradius;
1979 // load external .skin files if present
1980 skinfiles = Mod_LoadSkinFiles();
1981 if (loadmodel->numskins < 1)
1982 loadmodel->numskins = 1;
1987 // gather combined statistics from the meshes
1988 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
1989 for (i = 0;i < (int)pheader->num_meshs;i++)
1991 int numverts = BigLong(dpmmesh->num_verts);
1992 meshvertices += numverts;
1993 meshtriangles += BigLong(dpmmesh->num_tris);
1997 loadmodel->numframes = pheader->num_frames;
1998 loadmodel->num_bones = pheader->num_bones;
1999 loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
2000 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2001 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2002 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2003 // do most allocations as one merged chunk
2004 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));
2005 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2006 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2007 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2008 loadmodel->surfmesh.num_vertices = meshvertices;
2009 loadmodel->surfmesh.num_triangles = meshtriangles;
2010 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2011 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2012 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2013 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2014 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2015 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2016 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2017 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
2018 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
2019 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
2020 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2021 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2022 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2023 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2024 if (meshvertices <= 65536)
2026 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2027 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2028 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2031 for (i = 0;i < loadmodel->numskins;i++)
2033 loadmodel->skinscenes[i].firstframe = i;
2034 loadmodel->skinscenes[i].framecount = 1;
2035 loadmodel->skinscenes[i].loop = true;
2036 loadmodel->skinscenes[i].framerate = 10;
2039 // load the bone info
2040 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2041 for (i = 0;i < loadmodel->num_bones;i++)
2043 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2044 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2045 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2046 if (loadmodel->data_bones[i].parent >= i)
2047 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2051 frame = (dpmframe_t *) (pbase + pheader->ofs_frames);
2052 for (i = 0;i < loadmodel->numframes;i++)
2055 memcpy(loadmodel->animscenes[i].name, frame->name, sizeof(frame->name));
2056 loadmodel->animscenes[i].firstframe = i;
2057 loadmodel->animscenes[i].framecount = 1;
2058 loadmodel->animscenes[i].loop = true;
2059 loadmodel->animscenes[i].framerate = 10;
2060 // load the bone poses for this frame
2061 poses = (float *) (pbase + BigLong(frame->ofs_bonepositions));
2062 for (j = 0;j < loadmodel->num_bones*12;j++)
2063 loadmodel->data_poses[i * loadmodel->num_bones*12 + j] = BigFloat(poses[j]);
2064 // stuff not processed here: mins, maxs, yawradius, allradius
2068 // load the meshes now
2069 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2072 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2073 // (converting from weight-blending skeletal animation to
2074 // deformation-based skeletal animation)
2075 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2076 for (i = 0;i < loadmodel->num_bones;i++)
2078 const float *m = loadmodel->data_poses + i * 12;
2079 if (loadmodel->data_bones[i].parent >= 0)
2080 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2082 for (k = 0;k < 12;k++)
2083 bonepose[12*i+k] = m[k];
2085 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2087 const int *inelements;
2089 const float *intexcoord;
2090 msurface_t *surface;
2092 loadmodel->sortedmodelsurfaces[i] = i;
2093 surface = loadmodel->data_surfaces + i;
2094 surface->texture = loadmodel->data_textures + i;
2095 surface->num_firsttriangle = meshtriangles;
2096 surface->num_triangles = BigLong(dpmmesh->num_tris);
2097 surface->num_firstvertex = meshvertices;
2098 surface->num_vertices = BigLong(dpmmesh->num_verts);
2099 meshvertices += surface->num_vertices;
2100 meshtriangles += surface->num_triangles;
2102 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2103 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2104 for (j = 0;j < surface->num_triangles;j++)
2106 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2107 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2108 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2109 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2114 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2115 for (j = 0;j < surface->num_vertices*2;j++)
2116 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2118 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2119 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2123 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2124 data += sizeof(dpmvertex_t);
2125 for (k = 0;k < numweights;k++)
2127 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2128 int boneindex = BigLong(vert->bonenum);
2129 const float *m = bonepose + 12 * boneindex;
2130 float influence = BigFloat(vert->influence);
2131 float relativeorigin[3], relativenormal[3];
2132 relativeorigin[0] = BigFloat(vert->origin[0]);
2133 relativeorigin[1] = BigFloat(vert->origin[1]);
2134 relativeorigin[2] = BigFloat(vert->origin[2]);
2135 relativenormal[0] = BigFloat(vert->normal[0]);
2136 relativenormal[1] = BigFloat(vert->normal[1]);
2137 relativenormal[2] = BigFloat(vert->normal[2]);
2138 // blend the vertex bone weights into the base mesh
2139 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2140 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2141 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2142 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2143 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2144 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2147 // store the first (and often only) weight
2148 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = influence;
2149 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
2153 // sort the new weight into this vertex's weight table
2154 // (which only accepts up to 4 bones per vertex)
2155 for (l = 0;l < 4;l++)
2157 if (loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] < influence)
2159 // move weaker influence weights out of the way first
2161 for (l2 = 3;l2 > l;l2--)
2163 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2-1];
2164 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2-1];
2166 // store the new weight
2167 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] = influence;
2168 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l] = boneindex;
2173 data += sizeof(dpmbonevert_t);
2176 for (l = 0;l < 4;l++)
2177 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l];
2178 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2180 float f = 1.0f / sum;
2181 for (l = 0;l < 4;l++)
2182 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] *= f;
2186 // since dpm models do not have named sections, reuse their shader name as the section name
2187 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2189 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2192 Mod_FreeSkinFiles(skinfiles);
2193 Mod_MakeSortedSurfaces(loadmodel);
2195 // compute all the mesh information that was not loaded from the file
2196 Mod_BuildBaseBonePoses();
2197 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);
2198 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2200 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2203 // no idea why PSK/PSA files contain weird quaternions but they do...
2204 #define PSKQUATNEGATIONS
2205 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2207 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2208 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2209 fs_offset_t filesize;
2214 pskboneinfo_t *bones;
2215 pskrawweights_t *rawweights;
2216 pskboneinfo_t *animbones;
2217 pskaniminfo_t *anims;
2218 pskanimkeys_t *animkeys;
2219 void *animfilebuffer, *animbuffer, *animbufferend;
2220 unsigned char *data;
2222 skinfile_t *skinfiles;
2223 char animname[MAX_QPATH];
2226 pchunk = (pskchunk_t *)buffer;
2227 if (strcmp(pchunk->id, "ACTRHEAD"))
2228 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2230 loadmodel->modeldatatypestring = "PSK";
2232 loadmodel->type = mod_alias;
2233 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2234 loadmodel->DrawSky = NULL;
2235 loadmodel->DrawAddWaterPlanes = NULL;
2236 loadmodel->Draw = R_Q1BSP_Draw;
2237 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2238 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2239 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2240 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2241 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2242 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2243 loadmodel->PointSuperContents = NULL;
2244 loadmodel->synctype = ST_RAND;
2246 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2247 strlcat(animname, ".psa", sizeof(animname));
2248 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2249 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2250 if (animbuffer == NULL)
2251 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2270 while (buffer < bufferend)
2272 pchunk = (pskchunk_t *)buffer;
2273 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2274 version = LittleLong(pchunk->version);
2275 recordsize = LittleLong(pchunk->recordsize);
2276 numrecords = LittleLong(pchunk->numrecords);
2277 if (developer.integer >= 100)
2278 Con_Printf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2279 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2280 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);
2281 if (!strcmp(pchunk->id, "ACTRHEAD"))
2285 else if (!strcmp(pchunk->id, "PNTS0000"))
2288 if (recordsize != sizeof(*p))
2289 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2290 // byteswap in place and keep the pointer
2291 numpnts = numrecords;
2292 pnts = (pskpnts_t *)buffer;
2293 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2295 p->origin[0] = LittleFloat(p->origin[0]);
2296 p->origin[1] = LittleFloat(p->origin[1]);
2297 p->origin[2] = LittleFloat(p->origin[2]);
2301 else if (!strcmp(pchunk->id, "VTXW0000"))
2304 if (recordsize != sizeof(*p))
2305 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2306 // byteswap in place and keep the pointer
2307 numvtxw = numrecords;
2308 vtxw = (pskvtxw_t *)buffer;
2309 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2311 p->pntsindex = LittleShort(p->pntsindex);
2312 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2313 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2314 if (p->pntsindex >= numpnts)
2316 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2322 else if (!strcmp(pchunk->id, "FACE0000"))
2325 if (recordsize != sizeof(*p))
2326 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2327 // byteswap in place and keep the pointer
2328 numfaces = numrecords;
2329 faces = (pskface_t *)buffer;
2330 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2332 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2333 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2334 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2335 p->group = LittleLong(p->group);
2336 if (p->vtxwindex[0] >= numvtxw)
2338 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2339 p->vtxwindex[0] = 0;
2341 if (p->vtxwindex[1] >= numvtxw)
2343 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2344 p->vtxwindex[1] = 0;
2346 if (p->vtxwindex[2] >= numvtxw)
2348 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2349 p->vtxwindex[2] = 0;
2354 else if (!strcmp(pchunk->id, "MATT0000"))
2357 if (recordsize != sizeof(*p))
2358 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2359 // byteswap in place and keep the pointer
2360 nummatts = numrecords;
2361 matts = (pskmatt_t *)buffer;
2362 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2368 else if (!strcmp(pchunk->id, "REFSKELT"))
2371 if (recordsize != sizeof(*p))
2372 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2373 // byteswap in place and keep the pointer
2374 numbones = numrecords;
2375 bones = (pskboneinfo_t *)buffer;
2376 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2378 p->numchildren = LittleLong(p->numchildren);
2379 p->parent = LittleLong(p->parent);
2380 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2381 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2382 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2383 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2384 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2385 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2386 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2387 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2388 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2389 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2390 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2391 #ifdef PSKQUATNEGATIONS
2394 p->basepose.quat[0] *= -1;
2395 p->basepose.quat[1] *= -1;
2396 p->basepose.quat[2] *= -1;
2400 p->basepose.quat[0] *= 1;
2401 p->basepose.quat[1] *= -1;
2402 p->basepose.quat[2] *= 1;
2405 if (p->parent < 0 || p->parent >= numbones)
2407 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2413 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2416 if (recordsize != sizeof(*p))
2417 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2418 // byteswap in place and keep the pointer
2419 numrawweights = numrecords;
2420 rawweights = (pskrawweights_t *)buffer;
2421 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2423 p->weight = LittleFloat(p->weight);
2424 p->pntsindex = LittleLong(p->pntsindex);
2425 p->boneindex = LittleLong(p->boneindex);
2426 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2428 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2431 if (p->boneindex < 0 || p->boneindex >= numbones)
2433 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2441 while (animbuffer < animbufferend)
2443 pchunk = (pskchunk_t *)animbuffer;
2444 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2445 version = LittleLong(pchunk->version);
2446 recordsize = LittleLong(pchunk->recordsize);
2447 numrecords = LittleLong(pchunk->numrecords);
2448 if (developer.integer >= 100)
2449 Con_Printf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2450 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2451 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);
2452 if (!strcmp(pchunk->id, "ANIMHEAD"))
2456 else if (!strcmp(pchunk->id, "BONENAMES"))
2459 if (recordsize != sizeof(*p))
2460 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2461 // byteswap in place and keep the pointer
2462 numanimbones = numrecords;
2463 animbones = (pskboneinfo_t *)animbuffer;
2464 // NOTE: supposedly psa does not need to match the psk model, the
2465 // bones missing from the psa would simply use their base
2466 // positions from the psk, but this is hard for me to implement
2467 // and people can easily make animations that match.
2468 if (numanimbones != numbones)
2469 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2470 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2472 p->numchildren = LittleLong(p->numchildren);
2473 p->parent = LittleLong(p->parent);
2474 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2475 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2476 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2477 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2478 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2479 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2480 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2481 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2482 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2483 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2484 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2485 #ifdef PSKQUATNEGATIONS
2488 p->basepose.quat[0] *= -1;
2489 p->basepose.quat[1] *= -1;
2490 p->basepose.quat[2] *= -1;
2494 p->basepose.quat[0] *= 1;
2495 p->basepose.quat[1] *= -1;
2496 p->basepose.quat[2] *= 1;
2499 if (p->parent < 0 || p->parent >= numanimbones)
2501 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2504 // check that bones are the same as in the base
2505 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2506 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2510 else if (!strcmp(pchunk->id, "ANIMINFO"))
2513 if (recordsize != sizeof(*p))
2514 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2515 // byteswap in place and keep the pointer
2516 numanims = numrecords;
2517 anims = (pskaniminfo_t *)animbuffer;
2518 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2520 p->numbones = LittleLong(p->numbones);
2521 p->playtime = LittleFloat(p->playtime);
2522 p->fps = LittleFloat(p->fps);
2523 p->firstframe = LittleLong(p->firstframe);
2524 p->numframes = LittleLong(p->numframes);
2525 if (p->numbones != numbones)
2526 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2530 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2533 if (recordsize != sizeof(*p))
2534 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2535 numanimkeys = numrecords;
2536 animkeys = (pskanimkeys_t *)animbuffer;
2537 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2539 p->origin[0] = LittleFloat(p->origin[0]);
2540 p->origin[1] = LittleFloat(p->origin[1]);
2541 p->origin[2] = LittleFloat(p->origin[2]);
2542 p->quat[0] = LittleFloat(p->quat[0]);
2543 p->quat[1] = LittleFloat(p->quat[1]);
2544 p->quat[2] = LittleFloat(p->quat[2]);
2545 p->quat[3] = LittleFloat(p->quat[3]);
2546 p->frametime = LittleFloat(p->frametime);
2547 #ifdef PSKQUATNEGATIONS
2548 if (index % numbones)
2563 // TODO: allocate bonepose stuff
2566 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2569 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2570 Host_Error("%s: missing required chunks", loadmodel->name);
2572 loadmodel->numframes = 0;
2573 for (index = 0;index < numanims;index++)
2574 loadmodel->numframes += anims[index].numframes;
2576 if (numanimkeys != numbones * loadmodel->numframes)
2577 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2579 meshvertices = numvtxw;
2580 meshtriangles = numfaces;
2582 // load external .skin files if present
2583 skinfiles = Mod_LoadSkinFiles();
2584 if (loadmodel->numskins < 1)
2585 loadmodel->numskins = 1;
2586 loadmodel->num_bones = numbones;
2587 loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
2588 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2589 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2590 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2591 loadmodel->surfmesh.num_vertices = meshvertices;
2592 loadmodel->surfmesh.num_triangles = meshtriangles;
2593 // do most allocations as one merged chunk
2594 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);
2595 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2596 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2597 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2598 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2599 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2600 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2601 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2602 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2603 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2604 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2605 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2606 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += loadmodel->surfmesh.num_vertices * sizeof(int[4]);
2607 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[4]);
2608 //loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
2609 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2610 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2611 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2612 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2613 if (loadmodel->surfmesh.num_vertices <= 65536)
2615 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2616 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2617 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2619 loadmodel->data_poses = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->num_poses * sizeof(float[12]));
2621 for (i = 0;i < loadmodel->numskins;i++)
2623 loadmodel->skinscenes[i].firstframe = i;
2624 loadmodel->skinscenes[i].framecount = 1;
2625 loadmodel->skinscenes[i].loop = true;
2626 loadmodel->skinscenes[i].framerate = 10;
2630 for (index = 0, i = 0;index < nummatts;index++)
2632 // since psk models do not have named sections, reuse their shader name as the section name
2633 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2634 loadmodel->sortedmodelsurfaces[index] = index;
2635 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2636 loadmodel->data_surfaces[index].num_firstvertex = 0;
2637 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2640 // copy over the vertex locations and texcoords
2641 for (index = 0;index < numvtxw;index++)
2643 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2644 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2645 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2646 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2647 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2650 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2651 for (index = 0;index < numfaces;index++)
2652 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2653 for (index = 0, i = 0;index < nummatts;index++)
2655 loadmodel->data_surfaces[index].num_firsttriangle = i;
2656 i += loadmodel->data_surfaces[index].num_triangles;
2657 loadmodel->data_surfaces[index].num_triangles = 0;
2659 for (index = 0;index < numfaces;index++)
2661 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2662 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2663 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2664 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2667 // copy over the bones
2668 for (index = 0;index < numbones;index++)
2670 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2671 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2672 if (loadmodel->data_bones[index].parent >= index)
2673 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2676 // sort the psk point weights into the vertex weight tables
2677 // (which only accept up to 4 bones per vertex)
2678 for (index = 0;index < numvtxw;index++)
2682 for (j = 0;j < numrawweights;j++)
2684 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2686 int boneindex = rawweights[j].boneindex;
2687 float influence = rawweights[j].weight;
2688 for (l = 0;l < 4;l++)
2690 if (loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] < influence)
2692 // move lower influence weights out of the way first
2694 for (l2 = 3;l2 > l;l2--)
2696 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2-1];
2697 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2-1];
2699 // store the new weight
2700 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] = influence;
2701 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l] = boneindex;
2708 for (l = 0;l < 4;l++)
2709 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l];
2710 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2712 float f = 1.0f / sum;
2713 for (l = 0;l < 4;l++)
2714 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] *= f;
2718 // set up the animscenes based on the anims
2719 for (index = 0, i = 0;index < numanims;index++)
2721 for (j = 0;j < anims[index].numframes;j++, i++)
2723 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2724 loadmodel->animscenes[i].firstframe = i;
2725 loadmodel->animscenes[i].framecount = 1;
2726 loadmodel->animscenes[i].loop = true;
2727 loadmodel->animscenes[i].framerate = 10;
2731 // load the poses from the animkeys
2732 for (index = 0;index < numanimkeys;index++)
2734 pskanimkeys_t *k = animkeys + index;
2736 Matrix4x4_FromOriginQuat(&matrix, k->origin[0], k->origin[1], k->origin[2], k->quat[0], k->quat[1], k->quat[2], k->quat[3]);
2737 Matrix4x4_ToArray12FloatD3D(&matrix, loadmodel->data_poses + index*12);
2739 Mod_FreeSkinFiles(skinfiles);
2740 Mem_Free(animfilebuffer);
2741 Mod_MakeSortedSurfaces(loadmodel);
2743 // compute all the mesh information that was not loaded from the file
2744 // TODO: honor smoothing groups somehow?
2745 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2746 Mod_BuildBaseBonePoses();
2747 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2748 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);
2749 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2750 Mod_Alias_CalculateBoundingBox();
2752 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2755 void Mod_OBJ_Load(dp_model_t *mod, void *buffer, void *bufferend)
2758 const char *textbase = (char *)buffer, *text = textbase;
2762 char materialname[MAX_QPATH];
2763 int j, index1, index2, index3, first, prev, index;
2766 int numtriangles = 0;
2767 int maxtriangles = 32768;
2768 int *element3i = Mem_Alloc(tempmempool, maxtriangles * sizeof(int[3]));
2770 int numsurfaces = 0;
2771 int maxsurfaces = 0;
2772 msurface_t *surfaces = NULL;
2776 float *oldv, *oldvt, *oldvn;
2777 int maxv = 65536, numv = 1;
2778 int maxvt = 65536, numvt = 1;
2779 int maxvn = 65536, numvn = 1;
2780 int maxverthash = 65536, numverthash = 0;
2781 int numhashindex = 65536;
2782 struct objverthash_s
2784 struct objverthash_s *next;
2790 *hash, **verthash = Mem_Alloc(tempmempool, numhashindex * sizeof(*verthash)), *verthashdata = Mem_Alloc(tempmempool, maxverthash * sizeof(*verthashdata)), *oldverthashdata;
2791 skinfile_t *skinfiles;
2793 dpsnprintf(materialname, sizeof(materialname), "%s", loadmodel->name);
2795 skinfiles = Mod_LoadSkinFiles();
2797 loadmodel->modeldatatypestring = "OBJ";
2799 loadmodel->type = mod_alias;
2800 loadmodel->AnimateVertices = NULL;
2801 loadmodel->DrawSky = NULL;
2802 loadmodel->DrawAddWaterPlanes = NULL;
2803 loadmodel->Draw = R_Q1BSP_Draw;
2804 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2805 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2806 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2807 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2808 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2809 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2810 loadmodel->PointSuperContents = NULL;
2812 // parse the OBJ text now
2819 for (linelen = 0;text[linelen] && text[linelen] != '\r' && text[linelen] != '\n';linelen++)
2820 line[linelen] = text[linelen];
2822 for (argc = 0;argc < (int)(sizeof(argv)/sizeof(argv[0]));argc++)
2826 while (*s == ' ' || *s == '\t')
2836 while (*s == ' ' || *s == '\t')
2841 if (argv[0][0] == '#')
2843 if (!strcmp(argv[0], "v"))
2849 v = Mem_Alloc(tempmempool, maxv * sizeof(float[3]));
2852 memcpy(v, oldv, numv * sizeof(float[3]));
2856 v[numv*3+0] = atof(argv[1]);
2857 v[numv*3+1] = atof(argv[2]);
2858 v[numv*3+2] = atof(argv[3]);
2861 else if (!strcmp(argv[0], "vt"))
2867 vt = Mem_Alloc(tempmempool, maxvt * sizeof(float[2]));
2870 memcpy(vt, oldvt, numvt * sizeof(float[2]));
2874 vt[numvt*2+0] = atof(argv[1]);
2875 vt[numvt*2+1] = atof(argv[2]);
2878 else if (!strcmp(argv[0], "vn"))
2884 vn = Mem_Alloc(tempmempool, maxvn * sizeof(float[3]));
2887 memcpy(vn, oldvn, numvn * sizeof(float[3]));
2891 vn[numvn*3+0] = atof(argv[1]);
2892 vn[numvn*3+1] = atof(argv[2]);
2893 vn[numvn*3+2] = atof(argv[3]);
2896 else if (!strcmp(argv[0], "f"))
2900 if (maxsurfaces <= numsurfaces)
2903 oldsurfaces = surfaces;
2904 surfaces = Mem_Alloc(tempmempool, maxsurfaces * sizeof(*surfaces));
2907 memcpy(surfaces, oldsurfaces, numsurfaces * sizeof(*surfaces));
2908 Mem_Free(oldsurfaces);
2911 surface = surfaces + numsurfaces++;
2914 for (j = 1;j < argc;j++)
2916 index1 = atoi(argv[j]);
2917 while(argv[j][0] && argv[j][0] != '/')
2922 index1 = numv + 1 - index1;
2923 index2 = atoi(argv[j]);
2925 index2 = numvt + 1 - index2;
2926 while(argv[j][0] && argv[j][0] != '/')
2930 index3 = atoi(argv[j]);
2932 index3 = numvn + 1 - index3;
2933 hashindex = (index1 + index2 * 3571 + index3 * 42589) & (numhashindex - 1);
2934 for (hash = verthash[hashindex];hash;hash = hash->next)
2935 if (hash->surface == numsurfaces-1 && hash->v == index1 && hash->vt == index2 && hash->vn == index3)
2939 if (maxverthash <= numverthash)
2942 oldverthashdata = verthashdata;
2943 verthashdata = Mem_Alloc(tempmempool, maxverthash * sizeof(*verthashdata));
2944 if (oldverthashdata)
2946 memcpy(verthashdata, oldverthashdata, numverthash * sizeof(*verthashdata));
2947 Mem_Free(oldverthashdata);
2950 hash = verthashdata + numverthash++;
2951 hash->next = verthash[hashindex];
2952 hash->s = numsurfaces;
2956 verthash[hashindex] = hash;
2958 index = (int)((size_t)(hash - verthashdata));
2963 if (maxtriangles <= numtriangles)
2966 oldelement3i = element3i;
2967 element3i = Mem_Alloc(tempmempool, numtriangles * sizeof(int[3]));
2970 memcpy(element3i, oldelement3i, numtriangles * sizeof(int[3]));
2971 Mem_Free(oldelement3i);
2974 element3i[numtriangles*3+0] = first;
2975 element3i[numtriangles*3+1] = prev;
2976 element3i[numtriangles*3+2] = index;
2982 else if (!strcmp(argv[0], "o") || !strcmp(argv[0], "g"))
2984 else if (!!strcmp(argv[0], "usemtl"))
2987 strlcpy(materialname, argv[1], sizeof(materialname);
2997 Mod_FreeSkinFiles(skinfiles);
2999 // now that we have the OBJ data loaded as-is, we can convert it
3000 loadmodel->numskins = LittleLong(pinmodel->num_skins);
3001 numxyz = LittleLong(pinmodel->num_xyz);
3002 numst = LittleLong(pinmodel->num_st);
3003 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
3004 loadmodel->numframes = LittleLong(pinmodel->num_frames);
3005 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
3006 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
3007 skinwidth = LittleLong(pinmodel->skinwidth);
3008 skinheight = LittleLong(pinmodel->skinheight);
3009 iskinwidth = 1.0f / skinwidth;
3010 iskinheight = 1.0f / skinheight;
3012 loadmodel->num_surfaces = 1;
3013 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
3014 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]));
3015 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
3016 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
3017 loadmodel->sortedmodelsurfaces[0] = 0;
3018 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
3019 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
3020 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
3021 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
3023 loadmodel->synctype = ST_RAND;
3026 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
3027 skinfiles = Mod_LoadSkinFiles();
3030 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3031 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3032 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
3033 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
3034 Mod_FreeSkinFiles(skinfiles);
3036 else if (loadmodel->numskins)
3038 // skins found (most likely not a player model)
3039 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3040 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3041 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
3042 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
3043 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);
3047 // no skins (most likely a player model)
3048 loadmodel->numskins = 1;
3049 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3050 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3051 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
3052 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
3055 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
3056 for (i = 0;i < loadmodel->numskins;i++)
3058 loadmodel->skinscenes[i].firstframe = i;
3059 loadmodel->skinscenes[i].framecount = 1;
3060 loadmodel->skinscenes[i].loop = true;
3061 loadmodel->skinscenes[i].framerate = 10;
3064 // load the triangles and stvert data
3065 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
3066 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
3067 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
3068 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
3069 // swap the triangle list
3070 loadmodel->surfmesh.num_vertices = 0;
3071 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
3073 for (j = 0;j < 3;j++)
3075 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
3076 st = (unsigned short) LittleShort (intri[i].index_st[j]);
3079 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
3084 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
3087 hashindex = (xyz * 256 + st) & 65535;
3088 for (hash = md2verthash[hashindex];hash;hash = hash->next)
3089 if (hash->xyz == xyz && hash->st == st)
3093 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
3096 hash->next = md2verthash[hashindex];
3097 md2verthash[hashindex] = hash;
3099 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
3103 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
3104 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));
3105 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
3106 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
3107 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
3110 hash = md2verthashdata + i;
3111 vertremap[i] = hash->xyz;
3112 sts = LittleShort(inst[hash->st*2+0]);
3113 stt = LittleShort(inst[hash->st*2+1]);
3114 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
3116 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
3120 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
3121 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
3124 Mem_Free(md2verthash);
3125 Mem_Free(md2verthashdata);
3127 // generate ushort elements array if possible
3128 if (loadmodel->surfmesh.num_vertices <= 65536)
3130 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
3131 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3132 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3136 datapointer = (base + LittleLong(pinmodel->ofs_frames));
3137 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
3142 pinframe = (md2frame_t *)datapointer;
3143 datapointer += sizeof(md2frame_t);
3144 // store the frame scale/translate into the appropriate array
3145 for (j = 0;j < 3;j++)
3147 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
3148 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
3150 // convert the vertices
3151 v = (trivertx_t *)datapointer;
3152 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
3153 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
3154 out[k] = v[vertremap[k]];
3155 datapointer += numxyz * sizeof(trivertx_t);
3157 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
3158 loadmodel->animscenes[i].firstframe = i;
3159 loadmodel->animscenes[i].framecount = 1;
3160 loadmodel->animscenes[i].framerate = 10;
3161 loadmodel->animscenes[i].loop = true;
3164 Mem_Free(vertremap);
3166 Mod_MakeSortedSurfaces(loadmodel);
3167 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3168 Mod_Alias_CalculateBoundingBox();
3169 Mod_Alias_MorphMesh_CompileFrames();
3171 surface = loadmodel->data_surfaces;
3172 surface->texture = loadmodel->data_textures;
3173 surface->num_firsttriangle = 0;
3174 surface->num_triangles = loadmodel->surfmesh.num_triangles;
3175 surface->num_firstvertex = 0;
3176 surface->num_vertices = loadmodel->surfmesh.num_vertices;
3178 loadmodel->surfmesh.isanimated = false;