2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 cvar_t r_skeletal_debugbone = {0, "r_skeletal_debugbone", "-1", "development cvar for testing skeletal model code"};
26 cvar_t r_skeletal_debugbonecomponent = {0, "r_skeletal_debugbonecomponent", "3", "development cvar for testing skeletal model code"};
27 cvar_t r_skeletal_debugbonevalue = {0, "r_skeletal_debugbonevalue", "100", "development cvar for testing skeletal model code"};
28 cvar_t r_skeletal_debugtranslatex = {0, "r_skeletal_debugtranslatex", "1", "development cvar for testing skeletal model code"};
29 cvar_t r_skeletal_debugtranslatey = {0, "r_skeletal_debugtranslatey", "1", "development cvar for testing skeletal model code"};
30 cvar_t r_skeletal_debugtranslatez = {0, "r_skeletal_debugtranslatez", "1", "development cvar for testing skeletal model code"};
31 cvar_t mod_alias_supporttagscale = {0, "mod_alias_supporttagscale", "1", "support scaling factors in bone/tag attachment matrices as supported by MD3"};
33 float mod_md3_sin[320];
35 void Mod_AliasInit (void)
38 Cvar_RegisterVariable(&r_skeletal_debugbone);
39 Cvar_RegisterVariable(&r_skeletal_debugbonecomponent);
40 Cvar_RegisterVariable(&r_skeletal_debugbonevalue);
41 Cvar_RegisterVariable(&r_skeletal_debugtranslatex);
42 Cvar_RegisterVariable(&r_skeletal_debugtranslatey);
43 Cvar_RegisterVariable(&r_skeletal_debugtranslatez);
44 Cvar_RegisterVariable(&mod_alias_supporttagscale);
45 for (i = 0;i < 320;i++)
46 mod_md3_sin[i] = sin(i * M_PI * 2.0f / 256.0);
49 void Mod_Skeletal_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
52 // vertex weighted skeletal
55 float desiredscale[3];
56 float boneposerelative[MAX_BONES][12];
57 float *matrix, m[12], bonepose[MAX_BONES][12];
59 // interpolate matrices and concatenate them to their parents
60 for (i = 0;i < model->num_bones;i++)
62 for (k = 0;k < 12;k++)
64 VectorClear(desiredscale);
65 for (blends = 0;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++)
67 matrix = model->data_poses + (frameblend[blends].subframe * model->num_bones + i) * 12;
68 for (k = 0;k < 12;k++)
69 m[k] += matrix[k] * frameblend[blends].lerp;
70 desiredscale[0] += frameblend[blends].lerp * VectorLength(matrix );
71 desiredscale[1] += frameblend[blends].lerp * VectorLength(matrix + 4);
72 desiredscale[2] += frameblend[blends].lerp * VectorLength(matrix + 8);
75 VectorNormalize(m + 4);
76 VectorNormalize(m + 8);
77 VectorScale(m , desiredscale[0], m );
78 VectorScale(m + 4, desiredscale[1], m + 4);
79 VectorScale(m + 8, desiredscale[2], m + 8);
80 if (i == r_skeletal_debugbone.integer)
81 m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
82 m[3] *= r_skeletal_debugtranslatex.value;
83 m[7] *= r_skeletal_debugtranslatey.value;
84 m[11] *= r_skeletal_debugtranslatez.value;
85 if (model->data_bones[i].parent >= 0)
86 R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
88 for (k = 0;k < 12;k++)
89 bonepose[i][k] = m[k];
90 // create a relative deformation matrix to describe displacement
91 // from the base mesh, which is used by the actual weighting
92 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]);
94 // blend the vertex bone weights
95 // special case for the extremely common wf[0] == 1 because it saves 3 multiplies per array when compared to the other case (w[0] is always 1 if only one bone controls this vertex, artists only use multiple bones for certain special cases)
96 // special case for the first bone because it avoids the need to memset the arrays before filling
98 const float *v = model->surfmesh.data_vertex3f;
99 const int *wi = model->surfmesh.data_vertexweightindex4i;
100 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
101 memset(vertex3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
102 for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, wi += 4, wf += 4, vertex3f += 3)
106 const float *m = boneposerelative[wi[0]];
107 vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
108 vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
109 vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
113 const float *m = boneposerelative[wi[0]];
115 vertex3f[0] = f * (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
116 vertex3f[1] = f * (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
117 vertex3f[2] = f * (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
118 for (k = 1;k < 4 && wf[k];k++)
120 const float *m = boneposerelative[wi[k]];
122 vertex3f[0] += f * (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
123 vertex3f[1] += f * (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
124 vertex3f[2] += f * (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
131 const float *n = model->surfmesh.data_normal3f;
132 const int *wi = model->surfmesh.data_vertexweightindex4i;
133 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
134 memset(normal3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
135 for (i = 0;i < model->surfmesh.num_vertices;i++, n += 3, wi += 4, wf += 4, normal3f += 3)
139 const float *m = boneposerelative[wi[0]];
140 normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
141 normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
142 normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
146 const float *m = boneposerelative[wi[0]];
148 normal3f[0] = f * (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
149 normal3f[1] = f * (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
150 normal3f[2] = f * (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
151 for (k = 1;k < 4 && wf[k];k++)
153 const float *m = boneposerelative[wi[k]];
155 normal3f[0] += f * (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
156 normal3f[1] += f * (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
157 normal3f[2] += f * (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
164 const float *sv = model->surfmesh.data_svector3f;
165 const int *wi = model->surfmesh.data_vertexweightindex4i;
166 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
167 memset(svector3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
168 for (i = 0;i < model->surfmesh.num_vertices;i++, sv += 3, wi += 4, wf += 4, svector3f += 3)
172 const float *m = boneposerelative[wi[0]];
173 svector3f[0] = (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
174 svector3f[1] = (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
175 svector3f[2] = (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
179 const float *m = boneposerelative[wi[0]];
181 svector3f[0] = f * (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
182 svector3f[1] = f * (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
183 svector3f[2] = f * (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
184 for (k = 1;k < 4 && wf[k];k++)
186 const float *m = boneposerelative[wi[k]];
188 svector3f[0] += f * (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
189 svector3f[1] += f * (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
190 svector3f[2] += f * (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
197 const float *tv = model->surfmesh.data_tvector3f;
198 const int *wi = model->surfmesh.data_vertexweightindex4i;
199 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
200 memset(tvector3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
201 for (i = 0;i < model->surfmesh.num_vertices;i++, tv += 3, wi += 4, wf += 4, tvector3f += 3)
205 const float *m = boneposerelative[wi[0]];
206 tvector3f[0] = (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
207 tvector3f[1] = (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
208 tvector3f[2] = (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
212 const float *m = boneposerelative[wi[0]];
214 tvector3f[0] = f * (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
215 tvector3f[1] = f * (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
216 tvector3f[2] = f * (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
217 for (k = 1;k < 4 && wf[k];k++)
219 const float *m = boneposerelative[wi[k]];
221 tvector3f[0] += f * (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
222 tvector3f[1] += f * (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
223 tvector3f[2] += f * (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
230 void Mod_MD3_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
233 int i, numblends, blendnum;
234 int numverts = model->surfmesh.num_vertices;
236 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
238 //VectorMA(translate, model->surfmesh.num_morphmdlframetranslate, frameblend[blendnum].lerp, translate);
239 if (frameblend[blendnum].lerp > 0)
240 numblends = blendnum + 1;
242 // special case for the first blend because it avoids some adds and the need to memset the arrays first
243 for (blendnum = 0;blendnum < numblends;blendnum++)
245 const md3vertex_t *verts = model->surfmesh.data_morphmd3vertex + numverts * frameblend[blendnum].subframe;
246 float scale = frameblend[blendnum].lerp * (1.0f / 64.0f);
249 for (i = 0;i < numverts;i++)
251 vertex3f[i * 3 + 0] = verts[i].origin[0] * scale;
252 vertex3f[i * 3 + 1] = verts[i].origin[1] * scale;
253 vertex3f[i * 3 + 2] = verts[i].origin[2] * scale;
258 for (i = 0;i < numverts;i++)
260 vertex3f[i * 3 + 0] += verts[i].origin[0] * scale;
261 vertex3f[i * 3 + 1] += verts[i].origin[1] * scale;
262 vertex3f[i * 3 + 2] += verts[i].origin[2] * scale;
265 // the yaw and pitch stored in md3 models are 8bit quantized angles
266 // (0-255), and as such a lookup table is very well suited to
267 // decoding them, and since cosine is equivilant to sine with an
268 // extra 45 degree rotation, this uses one lookup table for both
269 // sine and cosine with a +64 bias to get cosine.
272 float lerp = frameblend[blendnum].lerp;
275 for (i = 0;i < numverts;i++)
277 normal3f[i * 3 + 0] = mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
278 normal3f[i * 3 + 1] = mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
279 normal3f[i * 3 + 2] = mod_md3_sin[verts[i].pitch + 64] * lerp;
284 for (i = 0;i < numverts;i++)
286 normal3f[i * 3 + 0] += mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
287 normal3f[i * 3 + 1] += mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
288 normal3f[i * 3 + 2] += mod_md3_sin[verts[i].pitch + 64] * lerp;
294 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
295 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
298 for (i = 0;i < numverts;i++, texvecvert++)
300 VectorScale(texvecvert->svec, f, svector3f + i*3);
301 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
306 for (i = 0;i < numverts;i++, texvecvert++)
308 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
309 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
316 void Mod_MDL_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
319 int i, numblends, blendnum;
320 int numverts = model->surfmesh.num_vertices;
322 VectorClear(translate);
324 // blend the frame translates to avoid redundantly doing so on each vertex
325 // (a bit of a brain twister but it works)
326 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
328 if (model->surfmesh.data_morphmd2framesize6f)
329 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6 + 3, translate);
331 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.num_morphmdlframetranslate, translate);
332 if (frameblend[blendnum].lerp > 0)
333 numblends = blendnum + 1;
335 // special case for the first blend because it avoids some adds and the need to memset the arrays first
336 for (blendnum = 0;blendnum < numblends;blendnum++)
338 const trivertx_t *verts = model->surfmesh.data_morphmdlvertex + numverts * frameblend[blendnum].subframe;
340 if (model->surfmesh.data_morphmd2framesize6f)
341 VectorScale(model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6, frameblend[blendnum].lerp, scale);
343 VectorScale(model->surfmesh.num_morphmdlframescale, frameblend[blendnum].lerp, scale);
346 for (i = 0;i < numverts;i++)
348 vertex3f[i * 3 + 0] = translate[0] + verts[i].v[0] * scale[0];
349 vertex3f[i * 3 + 1] = translate[1] + verts[i].v[1] * scale[1];
350 vertex3f[i * 3 + 2] = translate[2] + verts[i].v[2] * scale[2];
355 for (i = 0;i < numverts;i++)
357 vertex3f[i * 3 + 0] += verts[i].v[0] * scale[0];
358 vertex3f[i * 3 + 1] += verts[i].v[1] * scale[1];
359 vertex3f[i * 3 + 2] += verts[i].v[2] * scale[2];
362 // the vertex normals in mdl models are an index into a table of
363 // 162 unique values, this very crude quantization reduces the
364 // vertex normal to only one byte, which saves a lot of space but
365 // also makes lighting pretty coarse
368 float lerp = frameblend[blendnum].lerp;
371 for (i = 0;i < numverts;i++)
373 const float *vn = m_bytenormals[verts[i].lightnormalindex];
374 VectorScale(vn, lerp, normal3f + i*3);
379 for (i = 0;i < numverts;i++)
381 const float *vn = m_bytenormals[verts[i].lightnormalindex];
382 VectorMA(normal3f + i*3, lerp, vn, normal3f + i*3);
388 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
389 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
392 for (i = 0;i < numverts;i++, texvecvert++)
394 VectorScale(texvecvert->svec, f, svector3f + i*3);
395 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
400 for (i = 0;i < numverts;i++, texvecvert++)
402 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
403 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
410 int Mod_Alias_GetTagMatrix(const dp_model_t *model, int poseframe, int tagindex, matrix4x4_t *outmatrix)
412 const float *boneframe;
413 float tempbonematrix[12], bonematrix[12];
414 *outmatrix = identitymatrix;
415 if (model->num_bones)
417 if (tagindex < 0 || tagindex >= model->num_bones)
419 if (poseframe >= model->num_poses)
421 boneframe = model->data_poses + poseframe * model->num_bones * 12;
422 memcpy(bonematrix, boneframe + tagindex * 12, sizeof(float[12]));
423 while (model->data_bones[tagindex].parent >= 0)
425 memcpy(tempbonematrix, bonematrix, sizeof(float[12]));
426 R_ConcatTransforms(boneframe + model->data_bones[tagindex].parent * 12, tempbonematrix, bonematrix);
427 tagindex = model->data_bones[tagindex].parent;
429 Matrix4x4_FromArray12FloatD3D(outmatrix, bonematrix);
431 else if (model->num_tags)
433 if (tagindex < 0 || tagindex >= model->num_tags)
435 if (poseframe >= model->num_tagframes)
437 Matrix4x4_FromArray12FloatGL(outmatrix, model->data_tags[poseframe * model->num_tags + tagindex].matrixgl);
440 if(!mod_alias_supporttagscale.integer)
441 Matrix4x4_Normalize3(outmatrix, outmatrix);
446 int Mod_Alias_GetExtendedTagInfoForIndex(const dp_model_t *model, unsigned int skin, int poseframe, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
448 const float *boneframe;
450 if(skin >= (unsigned int)model->numskins)
453 if (model->num_bones)
455 if(tagindex >= model->num_bones || tagindex < 0)
457 if (poseframe >= model->num_poses)
460 boneframe = model->data_poses + poseframe * model->num_bones * 12;
461 *parentindex = model->data_bones[tagindex].parent;
462 *tagname = model->data_bones[tagindex].name;
463 Matrix4x4_FromArray12FloatD3D(tag_localmatrix, boneframe + tagindex * 12);
469 if(tagindex >= model->num_tags || tagindex < 0)
471 if (poseframe >= model->num_tagframes)
473 *tagname = model->data_tags[tagindex].name;
474 Matrix4x4_FromArray12FloatGL(tag_localmatrix, model->data_tags[poseframe * model->num_tags + tagindex].matrixgl);
481 int Mod_Alias_GetTagIndexForName(const dp_model_t *model, unsigned int skin, const char *tagname)
484 if(skin >= (unsigned int)model->numskins)
486 if (model->num_bones)
487 for (i = 0;i < model->num_bones;i++)
488 if (!strcasecmp(tagname, model->data_bones[i].name))
491 for (i = 0;i < model->num_tags;i++)
492 if (!strcasecmp(tagname, model->data_tags[i].name))
497 static void Mod_BuildBaseBonePoses(void)
501 float *basebonepose = (float *) Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(float[12]));
502 float *in12f = loadmodel->data_poses;
503 float *out12f = basebonepose;
504 float *outinv12f = loadmodel->data_baseboneposeinverse;
505 for (i = 0;i < loadmodel->num_bones;i++, in12f += 12, out12f += 12, outinv12f += 12)
507 if (loadmodel->data_bones[i].parent >= 0)
508 R_ConcatTransforms(basebonepose + 12 * loadmodel->data_bones[i].parent, in12f, out12f);
510 for (k = 0;k < 12;k++)
511 out12f[k] = in12f[k];
515 // we only support uniform scaling, so assume the first row is enough
516 // (note the lack of sqrt here, because we're trying to undo the scaling,
517 // this means multiplying by the inverse scale twice - squaring it, which
518 // makes the sqrt a waste of time)
519 scale = 1.0 / (out12f[ 0] * out12f[ 0] + out12f[ 1] * out12f[ 1] + out12f[ 2] * out12f[ 2]);
521 // invert the rotation by transposing and multiplying by the squared
522 // recipricol of the input matrix scale as described above
523 outinv12f[ 0] = (float)(out12f[ 0] * scale);
524 outinv12f[ 1] = (float)(out12f[ 4] * scale);
525 outinv12f[ 2] = (float)(out12f[ 8] * scale);
526 outinv12f[ 4] = (float)(out12f[ 1] * scale);
527 outinv12f[ 5] = (float)(out12f[ 5] * scale);
528 outinv12f[ 6] = (float)(out12f[ 9] * scale);
529 outinv12f[ 8] = (float)(out12f[ 2] * scale);
530 outinv12f[ 9] = (float)(out12f[ 6] * scale);
531 outinv12f[10] = (float)(out12f[10] * scale);
533 // invert the translate
534 outinv12f[ 3] = -(out12f[ 3] * outinv12f[ 0] + out12f[ 7] * outinv12f[ 1] + out12f[11] * outinv12f[ 2]);
535 outinv12f[ 7] = -(out12f[ 3] * outinv12f[ 4] + out12f[ 7] * outinv12f[ 5] + out12f[11] * outinv12f[ 6]);
536 outinv12f[11] = -(out12f[ 3] * outinv12f[ 8] + out12f[ 7] * outinv12f[ 9] + out12f[11] * outinv12f[10]);
538 Mem_Free(basebonepose);
541 static void Mod_Alias_CalculateBoundingBox(void)
544 qboolean firstvertex = true;
545 float dist, yawradius, radius;
548 frameblend_t frameblend[MAX_FRAMEBLENDS];
549 memset(frameblend, 0, sizeof(frameblend));
550 frameblend[0].lerp = 1;
551 vertex3f = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
552 VectorClear(loadmodel->normalmins);
553 VectorClear(loadmodel->normalmaxs);
556 for (frameblend[0].subframe = 0;frameblend[0].subframe < loadmodel->num_poses;frameblend[0].subframe++)
558 loadmodel->AnimateVertices(loadmodel, frameblend, vertex3f, NULL, NULL, NULL);
559 for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
564 VectorCopy(v, loadmodel->normalmins);
565 VectorCopy(v, loadmodel->normalmaxs);
569 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
570 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
571 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
572 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
573 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
574 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
576 dist = v[0] * v[0] + v[1] * v[1];
577 if (yawradius < dist)
586 radius = sqrt(radius);
587 yawradius = sqrt(yawradius);
588 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
589 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
590 loadmodel->yawmins[2] = loadmodel->normalmins[2];
591 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
592 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
593 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
594 loadmodel->radius = radius;
595 loadmodel->radius2 = radius * radius;
598 static void Mod_Alias_MorphMesh_CompileFrames(void)
601 frameblend_t frameblend[MAX_FRAMEBLENDS];
602 unsigned char *datapointer;
603 memset(frameblend, 0, sizeof(frameblend));
604 frameblend[0].lerp = 1;
605 datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
606 loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
607 loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
608 loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
609 loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
610 loadmodel->surfmesh.data_morphtexvecvertex = (texvecvertex_t *)datapointer;datapointer += loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices * sizeof(texvecvertex_t);
611 // this counts down from the last frame to the first so that the final data in surfmesh is for frame zero (which is what the renderer expects to be there)
612 for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
614 frameblend[0].subframe = i;
615 loadmodel->AnimateVertices(loadmodel, frameblend, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
616 Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, r_smoothnormals_areaweighting.integer);
617 // encode the svector and tvector in 3 byte format for permanent storage
618 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
620 VectorScaleCast(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
621 VectorScaleCast(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
626 static void Mod_MDLMD2MD3_TraceBox(dp_model_t *model, int frame, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask)
629 vec3_t shiftstart, shiftend;
630 float segmentmins[3], segmentmaxs[3];
631 frameblend_t frameblend[MAX_FRAMEBLENDS];
633 static int maxvertices = 0;
634 static float *vertex3f = NULL;
635 memset(trace, 0, sizeof(*trace));
637 trace->realfraction = 1;
638 trace->hitsupercontentsmask = hitsupercontentsmask;
639 memset(frameblend, 0, sizeof(frameblend));
640 frameblend[0].subframe = frame;
641 frameblend[0].lerp = 1;
642 if (maxvertices < model->surfmesh.num_vertices)
646 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
647 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
649 if (VectorCompare(boxmins, boxmaxs))
652 VectorAdd(start, boxmins, shiftstart);
653 VectorAdd(end, boxmins, shiftend);
654 segmentmins[0] = min(shiftstart[0], shiftend[0]) - 1;
655 segmentmins[1] = min(shiftstart[1], shiftend[1]) - 1;
656 segmentmins[2] = min(shiftstart[2], shiftend[2]) - 1;
657 segmentmaxs[0] = max(shiftstart[0], shiftend[0]) + 1;
658 segmentmaxs[1] = max(shiftstart[1], shiftend[1]) + 1;
659 segmentmaxs[2] = max(shiftstart[2], shiftend[2]) + 1;
660 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
662 model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL);
663 Collision_TraceLineTriangleMeshFloat(trace, shiftstart, shiftend, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs);
668 // box trace, performed as brush trace
669 colbrushf_t *thisbrush_start, *thisbrush_end;
670 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
671 segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
672 segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
673 segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
674 segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
675 segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
676 segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
677 VectorAdd(start, boxmins, boxstartmins);
678 VectorAdd(start, boxmaxs, boxstartmaxs);
679 VectorAdd(end, boxmins, boxendmins);
680 VectorAdd(end, boxmaxs, boxendmaxs);
681 thisbrush_start = Collision_BrushForBox(&identitymatrix, boxstartmins, boxstartmaxs, 0, 0, NULL);
682 thisbrush_end = Collision_BrushForBox(&identitymatrix, boxendmins, boxendmaxs, 0, 0, NULL);
683 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
685 if (maxvertices < model->surfmesh.num_vertices)
689 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
690 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
692 model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL);
693 Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs);
698 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
701 for (i = 0;i < inverts;i++)
703 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
705 j = vertremap[i]; // not onseam
708 j = vertremap[i+inverts]; // onseam
714 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
716 int i, f, pose, groupframes;
718 daliasframetype_t *pframetype;
719 daliasframe_t *pinframe;
720 daliasgroup_t *group;
721 daliasinterval_t *intervals;
724 scene = loadmodel->animscenes;
725 for (f = 0;f < loadmodel->numframes;f++)
727 pframetype = (daliasframetype_t *)datapointer;
728 datapointer += sizeof(daliasframetype_t);
729 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
731 // a single frame is still treated as a group
738 group = (daliasgroup_t *)datapointer;
739 datapointer += sizeof(daliasgroup_t);
740 groupframes = LittleLong (group->numframes);
742 // intervals (time per frame)
743 intervals = (daliasinterval_t *)datapointer;
744 datapointer += sizeof(daliasinterval_t) * groupframes;
746 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
747 if (interval < 0.01f)
749 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
754 // get scene name from first frame
755 pinframe = (daliasframe_t *)datapointer;
757 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
758 scene->firstframe = pose;
759 scene->framecount = groupframes;
760 scene->framerate = 1.0f / interval;
765 for (i = 0;i < groupframes;i++)
767 pinframe = (daliasframe_t *)datapointer;
768 datapointer += sizeof(daliasframe_t);
769 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
770 datapointer += sizeof(trivertx_t) * inverts;
776 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
778 if (cls.state == ca_dedicated)
782 skinframe = R_SkinFrame_LoadMissing();
783 memset(texture, 0, sizeof(*texture));
784 texture->currentframe = texture;
785 //texture->animated = false;
786 texture->numskinframes = 1;
787 texture->skinframerate = 1;
788 texture->skinframes[0] = skinframe;
789 texture->currentskinframe = skinframe;
790 //texture->backgroundnumskinframes = 0;
791 //texture->customblendfunc[0] = 0;
792 //texture->customblendfunc[1] = 0;
793 //texture->surfaceflags = 0;
794 //texture->supercontents = 0;
795 //texture->surfaceparms = 0;
796 //texture->textureflags = 0;
798 texture->basematerialflags = MATERIALFLAG_WALL;
799 if (texture->currentskinframe->fog)
800 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
801 texture->currentmaterialflags = texture->basematerialflags;
804 static void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
807 skinfileitem_t *skinfileitem;
810 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
811 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
813 memset(skin, 0, sizeof(*skin));
815 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
817 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
818 if (!strcmp(skinfileitem->name, meshname))
820 Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
826 // don't render unmentioned meshes
827 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
828 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
833 Mod_LoadTextureFromQ3Shader(skin, shadername, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
836 #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);
837 #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);
838 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
840 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
841 float scales, scalet, interval;
845 stvert_t *pinstverts;
846 dtriangle_t *pintriangles;
847 daliasskintype_t *pinskintype;
848 daliasskingroup_t *pinskingroup;
849 daliasskininterval_t *pinskinintervals;
850 daliasframetype_t *pinframetype;
851 daliasgroup_t *pinframegroup;
852 unsigned char *datapointer, *startframes, *startskins;
853 char name[MAX_QPATH];
854 skinframe_t *tempskinframe;
855 animscene_t *tempskinscenes;
856 texture_t *tempaliasskins;
858 int *vertonseam, *vertremap;
859 skinfile_t *skinfiles;
861 datapointer = (unsigned char *)buffer;
862 pinmodel = (mdl_t *)datapointer;
863 datapointer += sizeof(mdl_t);
865 version = LittleLong (pinmodel->version);
866 if (version != ALIAS_VERSION)
867 Host_Error ("%s has wrong version number (%i should be %i)",
868 loadmodel->name, version, ALIAS_VERSION);
870 loadmodel->modeldatatypestring = "MDL";
872 loadmodel->type = mod_alias;
873 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
874 loadmodel->DrawSky = NULL;
875 loadmodel->DrawAddWaterPlanes = NULL;
876 loadmodel->Draw = R_Q1BSP_Draw;
877 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
878 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
879 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
880 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
881 loadmodel->DrawLight = R_Q1BSP_DrawLight;
882 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
883 loadmodel->PointSuperContents = NULL;
885 loadmodel->num_surfaces = 1;
886 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
887 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
888 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
889 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
890 loadmodel->sortedmodelsurfaces[0] = 0;
892 loadmodel->numskins = LittleLong(pinmodel->numskins);
893 BOUNDI(loadmodel->numskins,0,65536);
894 skinwidth = LittleLong (pinmodel->skinwidth);
895 BOUNDI(skinwidth,0,65536);
896 skinheight = LittleLong (pinmodel->skinheight);
897 BOUNDI(skinheight,0,65536);
898 numverts = LittleLong(pinmodel->numverts);
899 BOUNDI(numverts,0,65536);
900 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
901 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
902 loadmodel->numframes = LittleLong(pinmodel->numframes);
903 BOUNDI(loadmodel->numframes,0,65536);
904 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
905 BOUNDI(loadmodel->synctype,0,2);
906 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
907 i = LittleLong (pinmodel->flags);
908 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
910 for (i = 0;i < 3;i++)
912 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
913 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
916 startskins = datapointer;
918 for (i = 0;i < loadmodel->numskins;i++)
920 pinskintype = (daliasskintype_t *)datapointer;
921 datapointer += sizeof(daliasskintype_t);
922 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
926 pinskingroup = (daliasskingroup_t *)datapointer;
927 datapointer += sizeof(daliasskingroup_t);
928 groupskins = LittleLong(pinskingroup->numskins);
929 datapointer += sizeof(daliasskininterval_t) * groupskins;
932 for (j = 0;j < groupskins;j++)
934 datapointer += skinwidth * skinheight;
939 pinstverts = (stvert_t *)datapointer;
940 datapointer += sizeof(stvert_t) * numverts;
942 pintriangles = (dtriangle_t *)datapointer;
943 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
945 startframes = datapointer;
946 loadmodel->surfmesh.num_morphframes = 0;
947 for (i = 0;i < loadmodel->numframes;i++)
949 pinframetype = (daliasframetype_t *)datapointer;
950 datapointer += sizeof(daliasframetype_t);
951 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
955 pinframegroup = (daliasgroup_t *)datapointer;
956 datapointer += sizeof(daliasgroup_t);
957 groupframes = LittleLong(pinframegroup->numframes);
958 datapointer += sizeof(daliasinterval_t) * groupframes;
961 for (j = 0;j < groupframes;j++)
963 datapointer += sizeof(daliasframe_t);
964 datapointer += sizeof(trivertx_t) * numverts;
965 loadmodel->surfmesh.num_morphframes++;
968 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
970 // store texture coordinates into temporary array, they will be stored
971 // after usage is determined (triangle data)
972 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
973 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
974 vertonseam = vertremap + numverts * 2;
976 scales = 1.0 / skinwidth;
977 scalet = 1.0 / skinheight;
978 for (i = 0;i < numverts;i++)
980 vertonseam[i] = LittleLong(pinstverts[i].onseam);
981 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
982 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
983 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
984 vertst[(i+numverts)*2+1] = vertst[i*2+1];
987 // load triangle data
988 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
990 // read the triangle elements
991 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
992 for (j = 0;j < 3;j++)
993 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
994 // validate (note numverts is used because this is the original data)
995 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
996 // now butcher the elements according to vertonseam and tri->facesfront
997 // and then compact the vertex set to remove duplicates
998 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
999 if (!LittleLong(pintriangles[i].facesfront)) // backface
1000 for (j = 0;j < 3;j++)
1001 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1002 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1004 // (this uses vertremap to count usage to save some memory)
1005 for (i = 0;i < numverts*2;i++)
1007 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1008 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1009 // build remapping table and compact array
1010 loadmodel->surfmesh.num_vertices = 0;
1011 for (i = 0;i < numverts*2;i++)
1015 vertremap[i] = loadmodel->surfmesh.num_vertices;
1016 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1017 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1018 loadmodel->surfmesh.num_vertices++;
1021 vertremap[i] = -1; // not used at all
1023 // remap the elements to the new vertex set
1024 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1025 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1026 // store the texture coordinates
1027 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1028 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1030 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1031 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1034 // generate ushort elements array if possible
1035 if (loadmodel->surfmesh.num_vertices <= 65536)
1037 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1038 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1039 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1043 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1044 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1045 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1046 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1047 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1048 Mod_Alias_CalculateBoundingBox();
1049 Mod_Alias_MorphMesh_CompileFrames();
1052 Mem_Free(vertremap);
1055 skinfiles = Mod_LoadSkinFiles();
1058 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1059 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1060 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1061 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1062 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1063 Mod_FreeSkinFiles(skinfiles);
1064 for (i = 0;i < loadmodel->numskins;i++)
1066 loadmodel->skinscenes[i].firstframe = i;
1067 loadmodel->skinscenes[i].framecount = 1;
1068 loadmodel->skinscenes[i].loop = true;
1069 loadmodel->skinscenes[i].framerate = 10;
1074 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1075 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1076 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1077 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1079 datapointer = startskins;
1080 for (i = 0;i < loadmodel->numskins;i++)
1082 pinskintype = (daliasskintype_t *)datapointer;
1083 datapointer += sizeof(daliasskintype_t);
1085 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1092 pinskingroup = (daliasskingroup_t *)datapointer;
1093 datapointer += sizeof(daliasskingroup_t);
1095 groupskins = LittleLong (pinskingroup->numskins);
1097 pinskinintervals = (daliasskininterval_t *)datapointer;
1098 datapointer += sizeof(daliasskininterval_t) * groupskins;
1100 interval = LittleFloat(pinskinintervals[0].interval);
1101 if (interval < 0.01f)
1103 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1108 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1109 loadmodel->skinscenes[i].firstframe = totalskins;
1110 loadmodel->skinscenes[i].framecount = groupskins;
1111 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1112 loadmodel->skinscenes[i].loop = true;
1114 for (j = 0;j < groupskins;j++)
1117 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1119 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1120 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))
1121 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));
1122 datapointer += skinwidth * skinheight;
1126 // check for skins that don't exist in the model, but do exist as external images
1127 // (this was added because yummyluv kept pestering me about support for it)
1128 // TODO: support shaders here?
1129 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)))
1131 // expand the arrays to make room
1132 tempskinscenes = loadmodel->skinscenes;
1133 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1134 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1135 Mem_Free(tempskinscenes);
1137 tempaliasskins = loadmodel->data_textures;
1138 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1139 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1140 Mem_Free(tempaliasskins);
1142 // store the info about the new skin
1143 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1144 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1145 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1146 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1147 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1148 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1150 //increase skin counts
1151 loadmodel->numskins++;
1154 // fix up the pointers since they are pointing at the old textures array
1155 // FIXME: this is a hack!
1156 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1157 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1161 surface = loadmodel->data_surfaces;
1162 surface->texture = loadmodel->data_textures;
1163 surface->num_firsttriangle = 0;
1164 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1165 surface->num_firstvertex = 0;
1166 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1168 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1171 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1173 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1174 float iskinwidth, iskinheight;
1175 unsigned char *data;
1176 msurface_t *surface;
1178 unsigned char *base, *datapointer;
1179 md2frame_t *pinframe;
1181 md2triangle_t *intri;
1182 unsigned short *inst;
1183 struct md2verthash_s
1185 struct md2verthash_s *next;
1189 *hash, **md2verthash, *md2verthashdata;
1190 skinfile_t *skinfiles;
1192 pinmodel = (md2_t *)buffer;
1193 base = (unsigned char *)buffer;
1195 version = LittleLong (pinmodel->version);
1196 if (version != MD2ALIAS_VERSION)
1197 Host_Error ("%s has wrong version number (%i should be %i)",
1198 loadmodel->name, version, MD2ALIAS_VERSION);
1200 loadmodel->modeldatatypestring = "MD2";
1202 loadmodel->type = mod_alias;
1203 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1204 loadmodel->DrawSky = NULL;
1205 loadmodel->DrawAddWaterPlanes = NULL;
1206 loadmodel->Draw = R_Q1BSP_Draw;
1207 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1208 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1209 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1210 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1211 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1212 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1213 loadmodel->PointSuperContents = NULL;
1215 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1216 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1217 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1218 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1219 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1220 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1221 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1222 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1224 end = LittleLong(pinmodel->ofs_end);
1225 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1226 Host_Error ("%s is not a valid model", loadmodel->name);
1227 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1228 Host_Error ("%s is not a valid model", loadmodel->name);
1229 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1230 Host_Error ("%s is not a valid model", loadmodel->name);
1231 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1232 Host_Error ("%s is not a valid model", loadmodel->name);
1233 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1234 Host_Error ("%s is not a valid model", loadmodel->name);
1236 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1237 numxyz = LittleLong(pinmodel->num_xyz);
1238 numst = LittleLong(pinmodel->num_st);
1239 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1240 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1241 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1242 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1243 skinwidth = LittleLong(pinmodel->skinwidth);
1244 skinheight = LittleLong(pinmodel->skinheight);
1245 iskinwidth = 1.0f / skinwidth;
1246 iskinheight = 1.0f / skinheight;
1248 loadmodel->num_surfaces = 1;
1249 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1250 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]));
1251 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1252 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1253 loadmodel->sortedmodelsurfaces[0] = 0;
1254 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1255 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1256 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1257 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1259 loadmodel->synctype = ST_RAND;
1262 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1263 skinfiles = Mod_LoadSkinFiles();
1266 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1267 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1268 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1269 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1270 Mod_FreeSkinFiles(skinfiles);
1272 else if (loadmodel->numskins)
1274 // skins found (most likely not a player model)
1275 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1276 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1277 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1278 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1279 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);
1283 // no skins (most likely a player model)
1284 loadmodel->numskins = 1;
1285 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1286 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1287 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1288 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1291 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1292 for (i = 0;i < loadmodel->numskins;i++)
1294 loadmodel->skinscenes[i].firstframe = i;
1295 loadmodel->skinscenes[i].framecount = 1;
1296 loadmodel->skinscenes[i].loop = true;
1297 loadmodel->skinscenes[i].framerate = 10;
1300 // load the triangles and stvert data
1301 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1302 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1303 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1304 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1305 // swap the triangle list
1306 loadmodel->surfmesh.num_vertices = 0;
1307 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1309 for (j = 0;j < 3;j++)
1311 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1312 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1315 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1320 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1323 hashindex = (xyz * 256 + st) & 65535;
1324 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1325 if (hash->xyz == xyz && hash->st == st)
1329 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1332 hash->next = md2verthash[hashindex];
1333 md2verthash[hashindex] = hash;
1335 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1339 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1340 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));
1341 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1342 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1343 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1346 hash = md2verthashdata + i;
1347 vertremap[i] = hash->xyz;
1348 sts = LittleShort(inst[hash->st*2+0]);
1349 stt = LittleShort(inst[hash->st*2+1]);
1350 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1352 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1356 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1357 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1360 Mem_Free(md2verthash);
1361 Mem_Free(md2verthashdata);
1363 // generate ushort elements array if possible
1364 if (loadmodel->surfmesh.num_vertices <= 65536)
1366 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1367 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1368 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1372 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1373 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1378 pinframe = (md2frame_t *)datapointer;
1379 datapointer += sizeof(md2frame_t);
1380 // store the frame scale/translate into the appropriate array
1381 for (j = 0;j < 3;j++)
1383 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1384 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1386 // convert the vertices
1387 v = (trivertx_t *)datapointer;
1388 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1389 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1390 out[k] = v[vertremap[k]];
1391 datapointer += numxyz * sizeof(trivertx_t);
1393 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1394 loadmodel->animscenes[i].firstframe = i;
1395 loadmodel->animscenes[i].framecount = 1;
1396 loadmodel->animscenes[i].framerate = 10;
1397 loadmodel->animscenes[i].loop = true;
1400 Mem_Free(vertremap);
1402 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1403 Mod_Alias_CalculateBoundingBox();
1404 Mod_Alias_MorphMesh_CompileFrames();
1406 surface = loadmodel->data_surfaces;
1407 surface->texture = loadmodel->data_textures;
1408 surface->num_firsttriangle = 0;
1409 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1410 surface->num_firstvertex = 0;
1411 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1413 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1416 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1418 int i, j, k, version, meshvertices, meshtriangles;
1419 unsigned char *data;
1420 msurface_t *surface;
1421 md3modelheader_t *pinmodel;
1422 md3frameinfo_t *pinframe;
1425 skinfile_t *skinfiles;
1427 pinmodel = (md3modelheader_t *)buffer;
1429 if (memcmp(pinmodel->identifier, "IDP3", 4))
1430 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1431 version = LittleLong (pinmodel->version);
1432 if (version != MD3VERSION)
1433 Host_Error ("%s has wrong version number (%i should be %i)",
1434 loadmodel->name, version, MD3VERSION);
1436 skinfiles = Mod_LoadSkinFiles();
1437 if (loadmodel->numskins < 1)
1438 loadmodel->numskins = 1;
1440 loadmodel->modeldatatypestring = "MD3";
1442 loadmodel->type = mod_alias;
1443 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1444 loadmodel->DrawSky = NULL;
1445 loadmodel->DrawAddWaterPlanes = NULL;
1446 loadmodel->Draw = R_Q1BSP_Draw;
1447 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1448 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1449 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1450 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1451 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1452 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1453 loadmodel->PointSuperContents = NULL;
1454 loadmodel->synctype = ST_RAND;
1455 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1456 i = LittleLong (pinmodel->flags);
1457 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1459 // set up some global info about the model
1460 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1461 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1463 // make skinscenes for the skins (no groups)
1464 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1465 for (i = 0;i < loadmodel->numskins;i++)
1467 loadmodel->skinscenes[i].firstframe = i;
1468 loadmodel->skinscenes[i].framecount = 1;
1469 loadmodel->skinscenes[i].loop = true;
1470 loadmodel->skinscenes[i].framerate = 10;
1474 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1475 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1477 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1478 loadmodel->animscenes[i].firstframe = i;
1479 loadmodel->animscenes[i].framecount = 1;
1480 loadmodel->animscenes[i].framerate = 10;
1481 loadmodel->animscenes[i].loop = true;
1485 loadmodel->num_tagframes = loadmodel->numframes;
1486 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1487 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1488 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1490 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1491 for (j = 0;j < 9;j++)
1492 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1493 for (j = 0;j < 3;j++)
1494 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1495 //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);
1501 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)))
1503 if (memcmp(pinmesh->identifier, "IDP3", 4))
1504 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1505 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1506 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1507 meshvertices += LittleLong(pinmesh->num_vertices);
1508 meshtriangles += LittleLong(pinmesh->num_triangles);
1511 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1512 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1513 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1514 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));
1515 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1516 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1517 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1518 loadmodel->surfmesh.num_vertices = meshvertices;
1519 loadmodel->surfmesh.num_triangles = meshtriangles;
1520 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1521 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1522 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1523 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1524 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1525 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1526 if (meshvertices <= 65536)
1528 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1529 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1530 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1535 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)))
1537 if (memcmp(pinmesh->identifier, "IDP3", 4))
1538 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1539 loadmodel->sortedmodelsurfaces[i] = i;
1540 surface = loadmodel->data_surfaces + i;
1541 surface->texture = loadmodel->data_textures + i;
1542 surface->num_firsttriangle = meshtriangles;
1543 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1544 surface->num_firstvertex = meshvertices;
1545 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1546 meshvertices += surface->num_vertices;
1547 meshtriangles += surface->num_triangles;
1549 for (j = 0;j < surface->num_triangles * 3;j++)
1550 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1551 for (j = 0;j < surface->num_vertices;j++)
1553 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1554 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1556 for (j = 0;j < loadmodel->numframes;j++)
1558 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1559 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1560 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1562 out->origin[0] = LittleShort(in->origin[0]);
1563 out->origin[1] = LittleShort(in->origin[1]);
1564 out->origin[2] = LittleShort(in->origin[2]);
1565 out->pitch = in->pitch;
1570 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1572 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1574 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1575 Mod_Alias_MorphMesh_CompileFrames();
1576 Mod_Alias_CalculateBoundingBox();
1577 Mod_FreeSkinFiles(skinfiles);
1578 Mod_MakeSortedSurfaces(loadmodel);
1580 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1581 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1584 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1586 zymtype1header_t *pinmodel, *pheader;
1587 unsigned char *pbase;
1588 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1589 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose;
1590 zymvertex_t *verts, *vertdata;
1594 skinfile_t *skinfiles;
1595 unsigned char *data;
1596 msurface_t *surface;
1598 pinmodel = (zymtype1header_t *)buffer;
1599 pbase = (unsigned char *)buffer;
1600 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1601 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1602 if (BigLong(pinmodel->type) != 1)
1603 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1605 loadmodel->modeldatatypestring = "ZYM";
1607 loadmodel->type = mod_alias;
1608 loadmodel->synctype = ST_RAND;
1612 pheader->type = BigLong(pinmodel->type);
1613 pheader->filesize = BigLong(pinmodel->filesize);
1614 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1615 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1616 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1617 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1618 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1619 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1620 pheader->radius = BigFloat(pinmodel->radius);
1621 pheader->numverts = BigLong(pinmodel->numverts);
1622 pheader->numtris = BigLong(pinmodel->numtris);
1623 pheader->numshaders = BigLong(pinmodel->numshaders);
1624 pheader->numbones = BigLong(pinmodel->numbones);
1625 pheader->numscenes = BigLong(pinmodel->numscenes);
1626 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1627 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1628 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1629 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1630 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1631 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1632 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1633 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1634 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1635 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1636 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1637 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1638 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1639 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1640 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1641 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1642 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1643 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1645 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1647 Con_Printf("%s has no geometry\n", loadmodel->name);
1650 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1652 Con_Printf("%s has no animations\n", loadmodel->name);
1656 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1657 loadmodel->DrawSky = NULL;
1658 loadmodel->DrawAddWaterPlanes = NULL;
1659 loadmodel->Draw = R_Q1BSP_Draw;
1660 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1661 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1662 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1663 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1664 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1665 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1666 loadmodel->PointSuperContents = NULL;
1668 loadmodel->numframes = pheader->numscenes;
1669 loadmodel->num_surfaces = pheader->numshaders;
1671 skinfiles = Mod_LoadSkinFiles();
1672 if (loadmodel->numskins < 1)
1673 loadmodel->numskins = 1;
1675 // make skinscenes for the skins (no groups)
1676 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1677 for (i = 0;i < loadmodel->numskins;i++)
1679 loadmodel->skinscenes[i].firstframe = i;
1680 loadmodel->skinscenes[i].framecount = 1;
1681 loadmodel->skinscenes[i].loop = true;
1682 loadmodel->skinscenes[i].framerate = 10;
1686 modelradius = pheader->radius;
1687 for (i = 0;i < 3;i++)
1689 loadmodel->normalmins[i] = pheader->mins[i];
1690 loadmodel->normalmaxs[i] = pheader->maxs[i];
1691 loadmodel->rotatedmins[i] = -modelradius;
1692 loadmodel->rotatedmaxs[i] = modelradius;
1694 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1695 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1696 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1697 if (loadmodel->yawmaxs[0] > modelradius)
1698 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1699 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1700 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1701 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1702 loadmodel->radius = modelradius;
1703 loadmodel->radius2 = modelradius * modelradius;
1705 // go through the lumps, swapping things
1707 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1708 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1709 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1710 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1711 for (i = 0;i < pheader->numscenes;i++)
1713 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1714 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1715 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1716 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1717 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1718 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1719 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1720 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1721 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1722 if (loadmodel->animscenes[i].framerate < 0)
1723 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1727 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1728 loadmodel->num_bones = pheader->numbones;
1729 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1730 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1731 for (i = 0;i < pheader->numbones;i++)
1733 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1734 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1735 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1736 if (loadmodel->data_bones[i].parent >= i)
1737 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1740 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1741 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1742 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1743 for (i = 0;i < pheader->numverts;i++)
1745 vertbonecounts[i] = BigLong(bonecount[i]);
1746 if (vertbonecounts[i] != 1)
1747 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1750 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1752 meshvertices = pheader->numverts;
1753 meshtriangles = pheader->numtris;
1755 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1756 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1757 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1758 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshvertices * sizeof(float[14]) + meshvertices * sizeof(int[4]) + meshvertices * sizeof(float[4]) + loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]) + loadmodel->num_bones * sizeof(float[12]));
1759 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1760 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1761 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1762 loadmodel->surfmesh.num_vertices = meshvertices;
1763 loadmodel->surfmesh.num_triangles = meshtriangles;
1764 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1765 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1766 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1767 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1768 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1769 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1770 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1771 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1772 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1773 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
1774 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1775 if (loadmodel->surfmesh.num_vertices <= 65536)
1777 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1778 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1779 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1782 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1783 poses = (float *) (pheader->lump_poses.start + pbase);
1784 for (i = 0;i < pheader->lump_poses.length / 4;i++)
1785 loadmodel->data_poses[i] = BigFloat(poses[i]);
1787 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1788 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1789 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1790 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1791 // (converting from weight-blending skeletal animation to
1792 // deformation-based skeletal animation)
1793 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1794 for (i = 0;i < loadmodel->num_bones;i++)
1796 const float *m = loadmodel->data_poses + i * 12;
1797 if (loadmodel->data_bones[i].parent >= 0)
1798 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1800 for (k = 0;k < 12;k++)
1801 bonepose[12*i+k] = m[k];
1803 for (j = 0;j < pheader->numverts;j++)
1805 // this format really should have had a per vertexweight weight value...
1806 // but since it does not, the weighting is completely ignored and
1807 // only one weight is allowed per vertex
1808 int boneindex = BigLong(vertdata[j].bonenum);
1809 const float *m = bonepose + 12 * boneindex;
1810 float relativeorigin[3];
1811 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1812 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1813 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1814 // transform the vertex bone weight into the base mesh
1815 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1816 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1817 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1818 // store the weight as the primary weight on this vertex
1819 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
1820 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = 1;
1823 // normals and tangents are calculated after elements are loaded
1825 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1826 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1827 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1828 for (i = 0;i < pheader->numverts;i++)
1830 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1831 // flip T coordinate for OpenGL
1832 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1835 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1836 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1837 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1839 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1840 //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)
1841 // byteswap, validate, and swap winding order of tris
1842 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1843 if (pheader->lump_render.length != count)
1844 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1845 renderlist = (int *) (pheader->lump_render.start + pbase);
1846 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1848 for (i = 0;i < loadmodel->num_surfaces;i++)
1850 int firstvertex, lastvertex;
1851 if (renderlist >= renderlistend)
1852 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1853 count = BigLong(*renderlist);renderlist++;
1854 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1855 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1857 loadmodel->sortedmodelsurfaces[i] = i;
1858 surface = loadmodel->data_surfaces + i;
1859 surface->texture = loadmodel->data_textures + i;
1860 surface->num_firsttriangle = meshtriangles;
1861 surface->num_triangles = count;
1862 meshtriangles += surface->num_triangles;
1864 // load the elements
1865 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
1866 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
1868 outelements[j*3+2] = BigLong(renderlist[0]);
1869 outelements[j*3+1] = BigLong(renderlist[1]);
1870 outelements[j*3+0] = BigLong(renderlist[2]);
1872 // validate the elements and find the used vertex range
1873 firstvertex = meshvertices;
1875 for (j = 0;j < surface->num_triangles * 3;j++)
1877 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
1878 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
1879 firstvertex = min(firstvertex, outelements[j]);
1880 lastvertex = max(lastvertex, outelements[j]);
1882 surface->num_firstvertex = firstvertex;
1883 surface->num_vertices = lastvertex + 1 - firstvertex;
1885 // since zym models do not have named sections, reuse their shader
1886 // name as the section name
1887 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
1888 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
1890 Mod_FreeSkinFiles(skinfiles);
1891 Mem_Free(vertbonecounts);
1893 Mod_MakeSortedSurfaces(loadmodel);
1895 // compute all the mesh information that was not loaded from the file
1896 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
1897 Mod_BuildBaseBonePoses();
1898 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
1899 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);
1900 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1902 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1905 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1907 dpmheader_t *pheader;
1911 unsigned char *pbase;
1912 int i, j, k, meshvertices, meshtriangles;
1913 skinfile_t *skinfiles;
1914 unsigned char *data;
1917 pheader = (dpmheader_t *)buffer;
1918 pbase = (unsigned char *)buffer;
1919 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
1920 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
1921 if (BigLong(pheader->type) != 2)
1922 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1924 loadmodel->modeldatatypestring = "DPM";
1926 loadmodel->type = mod_alias;
1927 loadmodel->synctype = ST_RAND;
1930 pheader->type = BigLong(pheader->type);
1931 pheader->filesize = BigLong(pheader->filesize);
1932 pheader->mins[0] = BigFloat(pheader->mins[0]);
1933 pheader->mins[1] = BigFloat(pheader->mins[1]);
1934 pheader->mins[2] = BigFloat(pheader->mins[2]);
1935 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
1936 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
1937 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
1938 pheader->yawradius = BigFloat(pheader->yawradius);
1939 pheader->allradius = BigFloat(pheader->allradius);
1940 pheader->num_bones = BigLong(pheader->num_bones);
1941 pheader->num_meshs = BigLong(pheader->num_meshs);
1942 pheader->num_frames = BigLong(pheader->num_frames);
1943 pheader->ofs_bones = BigLong(pheader->ofs_bones);
1944 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
1945 pheader->ofs_frames = BigLong(pheader->ofs_frames);
1947 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
1949 Con_Printf("%s has no geometry\n", loadmodel->name);
1952 if (pheader->num_frames < 1)
1954 Con_Printf("%s has no frames\n", loadmodel->name);
1958 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1959 loadmodel->DrawSky = NULL;
1960 loadmodel->DrawAddWaterPlanes = NULL;
1961 loadmodel->Draw = R_Q1BSP_Draw;
1962 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1963 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1964 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1965 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1966 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1967 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1968 loadmodel->PointSuperContents = NULL;
1971 for (i = 0;i < 3;i++)
1973 loadmodel->normalmins[i] = pheader->mins[i];
1974 loadmodel->normalmaxs[i] = pheader->maxs[i];
1975 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
1976 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
1977 loadmodel->rotatedmins[i] = -pheader->allradius;
1978 loadmodel->rotatedmaxs[i] = pheader->allradius;
1980 loadmodel->radius = pheader->allradius;
1981 loadmodel->radius2 = pheader->allradius * pheader->allradius;
1983 // load external .skin files if present
1984 skinfiles = Mod_LoadSkinFiles();
1985 if (loadmodel->numskins < 1)
1986 loadmodel->numskins = 1;
1991 // gather combined statistics from the meshes
1992 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
1993 for (i = 0;i < (int)pheader->num_meshs;i++)
1995 int numverts = BigLong(dpmmesh->num_verts);
1996 meshvertices += numverts;
1997 meshtriangles += BigLong(dpmmesh->num_tris);
2001 loadmodel->numframes = pheader->num_frames;
2002 loadmodel->num_bones = pheader->num_bones;
2003 loadmodel->num_poses = loadmodel->numframes;
2004 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2005 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2006 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2007 // do most allocations as one merged chunk
2008 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshtriangles * sizeof(int[3]) + meshvertices * (sizeof(float[14]) + sizeof(int[4]) + sizeof(float[4])) + loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
2009 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2010 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2011 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2012 loadmodel->surfmesh.num_vertices = meshvertices;
2013 loadmodel->surfmesh.num_triangles = meshtriangles;
2014 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2015 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2016 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2017 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2018 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2019 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2020 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2021 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
2022 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
2023 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
2024 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2025 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2026 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2027 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2028 if (meshvertices <= 65536)
2030 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2031 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2032 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2035 for (i = 0;i < loadmodel->numskins;i++)
2037 loadmodel->skinscenes[i].firstframe = i;
2038 loadmodel->skinscenes[i].framecount = 1;
2039 loadmodel->skinscenes[i].loop = true;
2040 loadmodel->skinscenes[i].framerate = 10;
2043 // load the bone info
2044 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2045 for (i = 0;i < loadmodel->num_bones;i++)
2047 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2048 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2049 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2050 if (loadmodel->data_bones[i].parent >= i)
2051 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2055 frame = (dpmframe_t *) (pbase + pheader->ofs_frames);
2056 for (i = 0;i < loadmodel->numframes;i++)
2059 memcpy(loadmodel->animscenes[i].name, frame->name, sizeof(frame->name));
2060 loadmodel->animscenes[i].firstframe = i;
2061 loadmodel->animscenes[i].framecount = 1;
2062 loadmodel->animscenes[i].loop = true;
2063 loadmodel->animscenes[i].framerate = 10;
2064 // load the bone poses for this frame
2065 poses = (float *) (pbase + BigLong(frame->ofs_bonepositions));
2066 for (j = 0;j < loadmodel->num_bones*12;j++)
2067 loadmodel->data_poses[i * loadmodel->num_bones*12 + j] = BigFloat(poses[j]);
2068 // stuff not processed here: mins, maxs, yawradius, allradius
2072 // load the meshes now
2073 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2076 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2077 // (converting from weight-blending skeletal animation to
2078 // deformation-based skeletal animation)
2079 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2080 for (i = 0;i < loadmodel->num_bones;i++)
2082 const float *m = loadmodel->data_poses + i * 12;
2083 if (loadmodel->data_bones[i].parent >= 0)
2084 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2086 for (k = 0;k < 12;k++)
2087 bonepose[12*i+k] = m[k];
2089 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2091 const int *inelements;
2093 const float *intexcoord;
2094 msurface_t *surface;
2096 loadmodel->sortedmodelsurfaces[i] = i;
2097 surface = loadmodel->data_surfaces + i;
2098 surface->texture = loadmodel->data_textures + i;
2099 surface->num_firsttriangle = meshtriangles;
2100 surface->num_triangles = BigLong(dpmmesh->num_tris);
2101 surface->num_firstvertex = meshvertices;
2102 surface->num_vertices = BigLong(dpmmesh->num_verts);
2103 meshvertices += surface->num_vertices;
2104 meshtriangles += surface->num_triangles;
2106 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2107 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2108 for (j = 0;j < surface->num_triangles;j++)
2110 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2111 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2112 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2113 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2118 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2119 for (j = 0;j < surface->num_vertices*2;j++)
2120 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2122 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2123 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2127 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2128 data += sizeof(dpmvertex_t);
2129 for (k = 0;k < numweights;k++)
2131 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2132 int boneindex = BigLong(vert->bonenum);
2133 const float *m = bonepose + 12 * boneindex;
2134 float influence = BigFloat(vert->influence);
2135 float relativeorigin[3], relativenormal[3];
2136 relativeorigin[0] = BigFloat(vert->origin[0]);
2137 relativeorigin[1] = BigFloat(vert->origin[1]);
2138 relativeorigin[2] = BigFloat(vert->origin[2]);
2139 relativenormal[0] = BigFloat(vert->normal[0]);
2140 relativenormal[1] = BigFloat(vert->normal[1]);
2141 relativenormal[2] = BigFloat(vert->normal[2]);
2142 // blend the vertex bone weights into the base mesh
2143 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2144 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2145 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2146 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2147 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2148 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2151 // store the first (and often only) weight
2152 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = influence;
2153 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
2157 // sort the new weight into this vertex's weight table
2158 // (which only accepts up to 4 bones per vertex)
2159 for (l = 0;l < 4;l++)
2161 if (loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] < influence)
2163 // move weaker influence weights out of the way first
2165 for (l2 = 3;l2 > l;l2--)
2167 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2-1];
2168 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2-1];
2170 // store the new weight
2171 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] = influence;
2172 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l] = boneindex;
2177 data += sizeof(dpmbonevert_t);
2180 for (l = 0;l < 4;l++)
2181 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l];
2182 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2184 float f = 1.0f / sum;
2185 for (l = 0;l < 4;l++)
2186 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] *= f;
2190 // since dpm models do not have named sections, reuse their shader name as the section name
2191 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2193 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2196 Mod_FreeSkinFiles(skinfiles);
2197 Mod_MakeSortedSurfaces(loadmodel);
2199 // compute all the mesh information that was not loaded from the file
2200 Mod_BuildBaseBonePoses();
2201 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);
2202 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2204 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2207 // no idea why PSK/PSA files contain weird quaternions but they do...
2208 #define PSKQUATNEGATIONS
2209 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2211 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2212 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2213 fs_offset_t filesize;
2218 pskboneinfo_t *bones;
2219 pskrawweights_t *rawweights;
2220 pskboneinfo_t *animbones;
2221 pskaniminfo_t *anims;
2222 pskanimkeys_t *animkeys;
2223 void *animfilebuffer, *animbuffer, *animbufferend;
2224 unsigned char *data;
2226 skinfile_t *skinfiles;
2227 char animname[MAX_QPATH];
2230 pchunk = (pskchunk_t *)buffer;
2231 if (strcmp(pchunk->id, "ACTRHEAD"))
2232 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2234 loadmodel->modeldatatypestring = "PSK";
2236 loadmodel->type = mod_alias;
2237 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2238 loadmodel->DrawSky = NULL;
2239 loadmodel->DrawAddWaterPlanes = NULL;
2240 loadmodel->Draw = R_Q1BSP_Draw;
2241 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2242 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2243 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2244 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2245 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2246 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2247 loadmodel->PointSuperContents = NULL;
2248 loadmodel->synctype = ST_RAND;
2250 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2251 strlcat(animname, ".psa", sizeof(animname));
2252 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2253 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2254 if (animbuffer == NULL)
2255 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2274 while (buffer < bufferend)
2276 pchunk = (pskchunk_t *)buffer;
2277 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2278 version = LittleLong(pchunk->version);
2279 recordsize = LittleLong(pchunk->recordsize);
2280 numrecords = LittleLong(pchunk->numrecords);
2281 if (developer.integer >= 100)
2282 Con_Printf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2283 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2284 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);
2285 if (!strcmp(pchunk->id, "ACTRHEAD"))
2289 else if (!strcmp(pchunk->id, "PNTS0000"))
2292 if (recordsize != sizeof(*p))
2293 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2294 // byteswap in place and keep the pointer
2295 numpnts = numrecords;
2296 pnts = (pskpnts_t *)buffer;
2297 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2299 p->origin[0] = LittleFloat(p->origin[0]);
2300 p->origin[1] = LittleFloat(p->origin[1]);
2301 p->origin[2] = LittleFloat(p->origin[2]);
2305 else if (!strcmp(pchunk->id, "VTXW0000"))
2308 if (recordsize != sizeof(*p))
2309 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2310 // byteswap in place and keep the pointer
2311 numvtxw = numrecords;
2312 vtxw = (pskvtxw_t *)buffer;
2313 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2315 p->pntsindex = LittleShort(p->pntsindex);
2316 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2317 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2318 if (p->pntsindex >= numpnts)
2320 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2326 else if (!strcmp(pchunk->id, "FACE0000"))
2329 if (recordsize != sizeof(*p))
2330 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2331 // byteswap in place and keep the pointer
2332 numfaces = numrecords;
2333 faces = (pskface_t *)buffer;
2334 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2336 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2337 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2338 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2339 p->group = LittleLong(p->group);
2340 if (p->vtxwindex[0] >= numvtxw)
2342 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2343 p->vtxwindex[0] = 0;
2345 if (p->vtxwindex[1] >= numvtxw)
2347 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2348 p->vtxwindex[1] = 0;
2350 if (p->vtxwindex[2] >= numvtxw)
2352 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2353 p->vtxwindex[2] = 0;
2358 else if (!strcmp(pchunk->id, "MATT0000"))
2361 if (recordsize != sizeof(*p))
2362 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2363 // byteswap in place and keep the pointer
2364 nummatts = numrecords;
2365 matts = (pskmatt_t *)buffer;
2366 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2372 else if (!strcmp(pchunk->id, "REFSKELT"))
2375 if (recordsize != sizeof(*p))
2376 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2377 // byteswap in place and keep the pointer
2378 numbones = numrecords;
2379 bones = (pskboneinfo_t *)buffer;
2380 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2382 p->numchildren = LittleLong(p->numchildren);
2383 p->parent = LittleLong(p->parent);
2384 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2385 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2386 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2387 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2388 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2389 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2390 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2391 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2392 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2393 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2394 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2395 #ifdef PSKQUATNEGATIONS
2398 p->basepose.quat[0] *= -1;
2399 p->basepose.quat[1] *= -1;
2400 p->basepose.quat[2] *= -1;
2404 p->basepose.quat[0] *= 1;
2405 p->basepose.quat[1] *= -1;
2406 p->basepose.quat[2] *= 1;
2409 if (p->parent < 0 || p->parent >= numbones)
2411 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2417 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2420 if (recordsize != sizeof(*p))
2421 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2422 // byteswap in place and keep the pointer
2423 numrawweights = numrecords;
2424 rawweights = (pskrawweights_t *)buffer;
2425 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2427 p->weight = LittleFloat(p->weight);
2428 p->pntsindex = LittleLong(p->pntsindex);
2429 p->boneindex = LittleLong(p->boneindex);
2430 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2432 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2435 if (p->boneindex < 0 || p->boneindex >= numbones)
2437 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2445 while (animbuffer < animbufferend)
2447 pchunk = (pskchunk_t *)animbuffer;
2448 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2449 version = LittleLong(pchunk->version);
2450 recordsize = LittleLong(pchunk->recordsize);
2451 numrecords = LittleLong(pchunk->numrecords);
2452 if (developer.integer >= 100)
2453 Con_Printf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2454 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2455 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);
2456 if (!strcmp(pchunk->id, "ANIMHEAD"))
2460 else if (!strcmp(pchunk->id, "BONENAMES"))
2463 if (recordsize != sizeof(*p))
2464 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2465 // byteswap in place and keep the pointer
2466 numanimbones = numrecords;
2467 animbones = (pskboneinfo_t *)animbuffer;
2468 // NOTE: supposedly psa does not need to match the psk model, the
2469 // bones missing from the psa would simply use their base
2470 // positions from the psk, but this is hard for me to implement
2471 // and people can easily make animations that match.
2472 if (numanimbones != numbones)
2473 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2474 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2476 p->numchildren = LittleLong(p->numchildren);
2477 p->parent = LittleLong(p->parent);
2478 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2479 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2480 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2481 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2482 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2483 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2484 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2485 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2486 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2487 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2488 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2489 #ifdef PSKQUATNEGATIONS
2492 p->basepose.quat[0] *= -1;
2493 p->basepose.quat[1] *= -1;
2494 p->basepose.quat[2] *= -1;
2498 p->basepose.quat[0] *= 1;
2499 p->basepose.quat[1] *= -1;
2500 p->basepose.quat[2] *= 1;
2503 if (p->parent < 0 || p->parent >= numanimbones)
2505 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2508 // check that bones are the same as in the base
2509 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2510 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2514 else if (!strcmp(pchunk->id, "ANIMINFO"))
2517 if (recordsize != sizeof(*p))
2518 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2519 // byteswap in place and keep the pointer
2520 numanims = numrecords;
2521 anims = (pskaniminfo_t *)animbuffer;
2522 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2524 p->numbones = LittleLong(p->numbones);
2525 p->playtime = LittleFloat(p->playtime);
2526 p->fps = LittleFloat(p->fps);
2527 p->firstframe = LittleLong(p->firstframe);
2528 p->numframes = LittleLong(p->numframes);
2529 if (p->numbones != numbones)
2530 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2534 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2537 if (recordsize != sizeof(*p))
2538 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2539 numanimkeys = numrecords;
2540 animkeys = (pskanimkeys_t *)animbuffer;
2541 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2543 p->origin[0] = LittleFloat(p->origin[0]);
2544 p->origin[1] = LittleFloat(p->origin[1]);
2545 p->origin[2] = LittleFloat(p->origin[2]);
2546 p->quat[0] = LittleFloat(p->quat[0]);
2547 p->quat[1] = LittleFloat(p->quat[1]);
2548 p->quat[2] = LittleFloat(p->quat[2]);
2549 p->quat[3] = LittleFloat(p->quat[3]);
2550 p->frametime = LittleFloat(p->frametime);
2551 #ifdef PSKQUATNEGATIONS
2552 if (index % numbones)
2567 // TODO: allocate bonepose stuff
2570 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2573 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2574 Host_Error("%s: missing required chunks", loadmodel->name);
2576 loadmodel->numframes = 0;
2577 for (index = 0;index < numanims;index++)
2578 loadmodel->numframes += anims[index].numframes;
2580 if (numanimkeys != numbones * loadmodel->numframes)
2581 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2583 meshvertices = numvtxw;
2584 meshtriangles = numfaces;
2586 // load external .skin files if present
2587 skinfiles = Mod_LoadSkinFiles();
2588 if (loadmodel->numskins < 1)
2589 loadmodel->numskins = 1;
2590 loadmodel->num_bones = numbones;
2591 loadmodel->num_poses = loadmodel->numframes;
2592 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2593 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2594 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2595 loadmodel->surfmesh.num_vertices = meshvertices;
2596 loadmodel->surfmesh.num_triangles = meshtriangles;
2597 // do most allocations as one merged chunk
2598 size = loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + loadmodel->surfmesh.num_triangles * sizeof(int[3]) + loadmodel->surfmesh.num_triangles * sizeof(int[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[2]) + loadmodel->surfmesh.num_vertices * sizeof(int[4]) + loadmodel->surfmesh.num_vertices * sizeof(float[4]) + loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t) + ((loadmodel->surfmesh.num_vertices <= 65536) ? (loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3])) : 0);
2599 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2600 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2601 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2602 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2603 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2604 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2605 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2606 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2607 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2608 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2609 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2610 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += loadmodel->surfmesh.num_vertices * sizeof(int[4]);
2611 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[4]);
2612 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
2613 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2614 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2615 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2616 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2617 if (loadmodel->surfmesh.num_vertices <= 65536)
2619 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2620 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2621 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2624 for (i = 0;i < loadmodel->numskins;i++)
2626 loadmodel->skinscenes[i].firstframe = i;
2627 loadmodel->skinscenes[i].framecount = 1;
2628 loadmodel->skinscenes[i].loop = true;
2629 loadmodel->skinscenes[i].framerate = 10;
2633 for (index = 0, i = 0;index < nummatts;index++)
2635 // since psk models do not have named sections, reuse their shader name as the section name
2636 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2637 loadmodel->sortedmodelsurfaces[index] = index;
2638 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2639 loadmodel->data_surfaces[index].num_firstvertex = 0;
2640 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2643 // copy over the vertex locations and texcoords
2644 for (index = 0;index < numvtxw;index++)
2646 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2647 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2648 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2649 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2650 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2653 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2654 for (index = 0;index < numfaces;index++)
2655 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2656 for (index = 0, i = 0;index < nummatts;index++)
2658 loadmodel->data_surfaces[index].num_firsttriangle = i;
2659 i += loadmodel->data_surfaces[index].num_triangles;
2660 loadmodel->data_surfaces[index].num_triangles = 0;
2662 for (index = 0;index < numfaces;index++)
2664 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2665 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2666 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2667 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2670 // copy over the bones
2671 for (index = 0;index < numbones;index++)
2673 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2674 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2675 if (loadmodel->data_bones[index].parent >= index)
2676 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2679 // sort the psk point weights into the vertex weight tables
2680 // (which only accept up to 4 bones per vertex)
2681 for (index = 0;index < numvtxw;index++)
2685 for (j = 0;j < numrawweights;j++)
2687 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2689 int boneindex = rawweights[j].boneindex;
2690 float influence = rawweights[j].weight;
2691 for (l = 0;l < 4;l++)
2693 if (loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] < influence)
2695 // move lower influence weights out of the way first
2697 for (l2 = 3;l2 > l;l2--)
2699 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2-1];
2700 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2-1];
2702 // store the new weight
2703 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] = influence;
2704 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l] = boneindex;
2711 for (l = 0;l < 4;l++)
2712 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l];
2713 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2715 float f = 1.0f / sum;
2716 for (l = 0;l < 4;l++)
2717 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] *= f;
2721 // set up the animscenes based on the anims
2722 for (index = 0, i = 0;index < numanims;index++)
2724 for (j = 0;j < anims[index].numframes;j++, i++)
2726 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2727 loadmodel->animscenes[i].firstframe = i;
2728 loadmodel->animscenes[i].framecount = 1;
2729 loadmodel->animscenes[i].loop = true;
2730 loadmodel->animscenes[i].framerate = 10;
2734 // load the poses from the animkeys
2735 for (index = 0;index < numanimkeys;index++)
2737 pskanimkeys_t *k = animkeys + index;
2739 Matrix4x4_FromOriginQuat(&matrix, k->origin[0], k->origin[1], k->origin[2], k->quat[0], k->quat[1], k->quat[2], k->quat[3]);
2740 Matrix4x4_ToArray12FloatD3D(&matrix, loadmodel->data_poses + index*12);
2742 Mod_FreeSkinFiles(skinfiles);
2743 Mem_Free(animfilebuffer);
2744 Mod_MakeSortedSurfaces(loadmodel);
2746 // compute all the mesh information that was not loaded from the file
2747 // TODO: honor smoothing groups somehow?
2748 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2749 Mod_BuildBaseBonePoses();
2750 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2751 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);
2752 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2753 Mod_Alias_CalculateBoundingBox();
2755 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2758 void Mod_OBJ_Load(dp_model_t *mod, void *buffer, void *bufferend)
2761 const char *textbase = (char *)buffer, *text = textbase;
2765 char materialname[MAX_QPATH];
2766 int j, index1, index2, index3, first, prev, index;
2769 int numtriangles = 0;
2770 int maxtriangles = 32768;
2771 int *element3i = Mem_Alloc(tempmempool, maxtriangles * sizeof(int[3]));
2773 int numsurfaces = 0;
2774 int maxsurfaces = 0;
2775 msurface_t *surfaces = NULL;
2779 float *oldv, *oldvt, *oldvn;
2780 int maxv = 65536, numv = 1;
2781 int maxvt = 65536, numvt = 1;
2782 int maxvn = 65536, numvn = 1;
2783 int maxverthash = 65536, numverthash = 0;
2784 int numhashindex = 65536;
2785 struct objverthash_s
2787 struct objverthash_s *next;
2793 *hash, **verthash = Mem_Alloc(tempmempool, numhashindex * sizeof(*verthash)), *verthashdata = Mem_Alloc(tempmempool, maxverthash * sizeof(*verthashdata)), *oldverthashdata;
2794 skinfile_t *skinfiles;
2796 dpsnprintf(materialname, sizeof(materialname), "%s", loadmodel->name);
2798 skinfiles = Mod_LoadSkinFiles();
2800 loadmodel->modeldatatypestring = "OBJ";
2802 loadmodel->type = mod_alias;
2803 loadmodel->AnimateVertices = NULL;
2804 loadmodel->DrawSky = NULL;
2805 loadmodel->DrawAddWaterPlanes = NULL;
2806 loadmodel->Draw = R_Q1BSP_Draw;
2807 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2808 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2809 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2810 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2811 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2812 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2813 loadmodel->PointSuperContents = NULL;
2815 // parse the OBJ text now
2822 for (linelen = 0;text[linelen] && text[linelen] != '\r' && text[linelen] != '\n';linelen++)
2823 line[linelen] = text[linelen];
2825 for (argc = 0;argc < (int)(sizeof(argv)/sizeof(argv[0]));argc++)
2829 while (*s == ' ' || *s == '\t')
2839 while (*s == ' ' || *s == '\t')
2844 if (argv[0][0] == '#')
2846 if (!strcmp(argv[0], "v"))
2852 v = Mem_Alloc(tempmempool, maxv * sizeof(float[3]));
2855 memcpy(v, oldv, numv * sizeof(float[3]));
2859 v[numv*3+0] = atof(argv[1]);
2860 v[numv*3+1] = atof(argv[2]);
2861 v[numv*3+2] = atof(argv[3]);
2864 else if (!strcmp(argv[0], "vt"))
2870 vt = Mem_Alloc(tempmempool, maxvt * sizeof(float[2]));
2873 memcpy(vt, oldvt, numvt * sizeof(float[2]));
2877 vt[numvt*2+0] = atof(argv[1]);
2878 vt[numvt*2+1] = atof(argv[2]);
2881 else if (!strcmp(argv[0], "vn"))
2887 vn = Mem_Alloc(tempmempool, maxvn * sizeof(float[3]));
2890 memcpy(vn, oldvn, numvn * sizeof(float[3]));
2894 vn[numvn*3+0] = atof(argv[1]);
2895 vn[numvn*3+1] = atof(argv[2]);
2896 vn[numvn*3+2] = atof(argv[3]);
2899 else if (!strcmp(argv[0], "f"))
2903 if (maxsurfaces <= numsurfaces)
2906 oldsurfaces = surfaces;
2907 surfaces = Mem_Alloc(tempmempool, maxsurfaces * sizeof(*surfaces));
2910 memcpy(surfaces, oldsurfaces, numsurfaces * sizeof(*surfaces));
2911 Mem_Free(oldsurfaces);
2914 surface = surfaces + numsurfaces++;
2917 for (j = 1;j < argc;j++)
2919 index1 = atoi(argv[j]);
2920 while(argv[j][0] && argv[j][0] != '/')
2925 index1 = numv + 1 - index1;
2926 index2 = atoi(argv[j]);
2928 index2 = numvt + 1 - index2;
2929 while(argv[j][0] && argv[j][0] != '/')
2933 index3 = atoi(argv[j]);
2935 index3 = numvn + 1 - index3;
2936 hashindex = (index1 + index2 * 3571 + index3 * 42589) & (numhashindex - 1);
2937 for (hash = verthash[hashindex];hash;hash = hash->next)
2938 if (hash->surface == numsurfaces-1 && hash->v == index1 && hash->vt == index2 && hash->vn == index3)
2942 if (maxverthash <= numverthash)
2945 oldverthashdata = verthashdata;
2946 verthashdata = Mem_Alloc(tempmempool, maxverthash * sizeof(*verthashdata));
2947 if (oldverthashdata)
2949 memcpy(verthashdata, oldverthashdata, numverthash * sizeof(*verthashdata));
2950 Mem_Free(oldverthashdata);
2953 hash = verthashdata + numverthash++;
2954 hash->next = verthash[hashindex];
2955 hash->s = numsurfaces;
2959 verthash[hashindex] = hash;
2961 index = (int)((size_t)(hash - verthashdata));
2966 if (maxtriangles <= numtriangles)
2969 oldelement3i = element3i;
2970 element3i = Mem_Alloc(tempmempool, numtriangles * sizeof(int[3]));
2973 memcpy(element3i, oldelement3i, numtriangles * sizeof(int[3]));
2974 Mem_Free(oldelement3i);
2977 element3i[numtriangles*3+0] = first;
2978 element3i[numtriangles*3+1] = prev;
2979 element3i[numtriangles*3+2] = index;
2985 else if (!strcmp(argv[0], "o") || !strcmp(argv[0], "g"))
2987 else if (!!strcmp(argv[0], "usemtl"))
2990 strlcpy(materialname, argv[1], sizeof(materialname);
3000 Mod_FreeSkinFiles(skinfiles);
3002 // now that we have the OBJ data loaded as-is, we can convert it
3003 loadmodel->numskins = LittleLong(pinmodel->num_skins);
3004 numxyz = LittleLong(pinmodel->num_xyz);
3005 numst = LittleLong(pinmodel->num_st);
3006 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
3007 loadmodel->numframes = LittleLong(pinmodel->num_frames);
3008 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
3009 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
3010 skinwidth = LittleLong(pinmodel->skinwidth);
3011 skinheight = LittleLong(pinmodel->skinheight);
3012 iskinwidth = 1.0f / skinwidth;
3013 iskinheight = 1.0f / skinheight;
3015 loadmodel->num_surfaces = 1;
3016 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
3017 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]));
3018 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
3019 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
3020 loadmodel->sortedmodelsurfaces[0] = 0;
3021 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
3022 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
3023 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
3024 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
3026 loadmodel->synctype = ST_RAND;
3029 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
3030 skinfiles = Mod_LoadSkinFiles();
3033 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3034 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3035 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
3036 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
3037 Mod_FreeSkinFiles(skinfiles);
3039 else if (loadmodel->numskins)
3041 // skins found (most likely not a player model)
3042 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3043 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3044 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
3045 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
3046 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);
3050 // no skins (most likely a player model)
3051 loadmodel->numskins = 1;
3052 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3053 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3054 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
3055 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
3058 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
3059 for (i = 0;i < loadmodel->numskins;i++)
3061 loadmodel->skinscenes[i].firstframe = i;
3062 loadmodel->skinscenes[i].framecount = 1;
3063 loadmodel->skinscenes[i].loop = true;
3064 loadmodel->skinscenes[i].framerate = 10;
3067 // load the triangles and stvert data
3068 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
3069 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
3070 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
3071 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
3072 // swap the triangle list
3073 loadmodel->surfmesh.num_vertices = 0;
3074 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
3076 for (j = 0;j < 3;j++)
3078 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
3079 st = (unsigned short) LittleShort (intri[i].index_st[j]);
3082 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
3087 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
3090 hashindex = (xyz * 256 + st) & 65535;
3091 for (hash = md2verthash[hashindex];hash;hash = hash->next)
3092 if (hash->xyz == xyz && hash->st == st)
3096 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
3099 hash->next = md2verthash[hashindex];
3100 md2verthash[hashindex] = hash;
3102 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
3106 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
3107 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));
3108 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
3109 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
3110 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
3113 hash = md2verthashdata + i;
3114 vertremap[i] = hash->xyz;
3115 sts = LittleShort(inst[hash->st*2+0]);
3116 stt = LittleShort(inst[hash->st*2+1]);
3117 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
3119 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
3123 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
3124 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
3127 Mem_Free(md2verthash);
3128 Mem_Free(md2verthashdata);
3130 // generate ushort elements array if possible
3131 if (loadmodel->surfmesh.num_vertices <= 65536)
3133 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
3134 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3135 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3139 datapointer = (base + LittleLong(pinmodel->ofs_frames));
3140 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
3145 pinframe = (md2frame_t *)datapointer;
3146 datapointer += sizeof(md2frame_t);
3147 // store the frame scale/translate into the appropriate array
3148 for (j = 0;j < 3;j++)
3150 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
3151 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
3153 // convert the vertices
3154 v = (trivertx_t *)datapointer;
3155 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
3156 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
3157 out[k] = v[vertremap[k]];
3158 datapointer += numxyz * sizeof(trivertx_t);
3160 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
3161 loadmodel->animscenes[i].firstframe = i;
3162 loadmodel->animscenes[i].framecount = 1;
3163 loadmodel->animscenes[i].framerate = 10;
3164 loadmodel->animscenes[i].loop = true;
3167 Mem_Free(vertremap);
3169 Mod_MakeSortedSurfaces(loadmodel);
3170 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3171 Mod_Alias_CalculateBoundingBox();
3172 Mod_Alias_MorphMesh_CompileFrames();
3174 surface = loadmodel->data_surfaces;
3175 surface->texture = loadmodel->data_textures;
3176 surface->num_firsttriangle = 0;
3177 surface->num_triangles = loadmodel->surfmesh.num_triangles;
3178 surface->num_firstvertex = 0;
3179 surface->num_vertices = loadmodel->surfmesh.num_vertices;
3181 loadmodel->surfmesh.isanimated = false;