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"};
32 float mod_md3_sin[320];
34 void Mod_AliasInit (void)
37 Cvar_RegisterVariable(&r_skeletal_debugbone);
38 Cvar_RegisterVariable(&r_skeletal_debugbonecomponent);
39 Cvar_RegisterVariable(&r_skeletal_debugbonevalue);
40 Cvar_RegisterVariable(&r_skeletal_debugtranslatex);
41 Cvar_RegisterVariable(&r_skeletal_debugtranslatey);
42 Cvar_RegisterVariable(&r_skeletal_debugtranslatez);
43 for (i = 0;i < 320;i++)
44 mod_md3_sin[i] = sin(i * M_PI * 2.0f / 256.0);
47 void Mod_Alias_GetMesh_Vertices(const model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
50 if (model->surfmesh.data_vertexweightindex4i)
52 // vertex weighted skeletal
54 float boneposerelative[MAX_BONES][12];
55 // interpolate matrices and concatenate them to their parents
56 for (i = 0;i < model->num_bones;i++)
59 float *matrix, m[12], bonepose[MAX_BONES][12];
60 for (k = 0;k < 12;k++)
62 for (blends = 0;blends < 4 && frameblend[blends].lerp > 0;blends++)
64 matrix = model->data_poses + (frameblend[blends].frame * model->num_bones + i) * 12;
65 for (k = 0;k < 12;k++)
66 m[k] += matrix[k] * frameblend[blends].lerp;
68 if (i == r_skeletal_debugbone.integer)
69 m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
70 m[3] *= r_skeletal_debugtranslatex.value;
71 m[7] *= r_skeletal_debugtranslatey.value;
72 m[11] *= r_skeletal_debugtranslatez.value;
73 if (model->data_bones[i].parent >= 0)
74 R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
76 for (k = 0;k < 12;k++)
77 bonepose[i][k] = m[k];
78 // create a relative deformation matrix to describe displacement
79 // from the base mesh, which is used by the actual weighting
80 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]);
82 // blend the vertex bone weights
83 // 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)
84 // special case for the first bone because it avoids the need to memset the arrays before filling
86 const float *v = model->surfmesh.data_vertex3f;
87 const int *wi = model->surfmesh.data_vertexweightindex4i;
88 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
89 memset(vertex3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
90 for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, wi += 4, wf += 4, vertex3f += 3)
94 const float *m = boneposerelative[wi[0]];
95 vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
96 vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
97 vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
101 const float *m = boneposerelative[wi[0]];
103 vertex3f[0] = f * (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
104 vertex3f[1] = f * (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
105 vertex3f[2] = f * (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
106 for (k = 1;k < 4 && wf[k];k++)
108 const float *m = boneposerelative[wi[k]];
110 vertex3f[0] += f * (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
111 vertex3f[1] += f * (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
112 vertex3f[2] += f * (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
119 const float *n = model->surfmesh.data_normal3f;
120 const int *wi = model->surfmesh.data_vertexweightindex4i;
121 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
122 memset(normal3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
123 for (i = 0;i < model->surfmesh.num_vertices;i++, n += 3, wi += 4, wf += 4, normal3f += 3)
127 const float *m = boneposerelative[wi[0]];
128 normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
129 normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
130 normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
134 const float *m = boneposerelative[wi[0]];
136 normal3f[0] = f * (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
137 normal3f[1] = f * (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
138 normal3f[2] = f * (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
139 for (k = 1;k < 4 && wf[k];k++)
141 const float *m = boneposerelative[wi[k]];
143 normal3f[0] += f * (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
144 normal3f[1] += f * (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
145 normal3f[2] += f * (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
152 const float *sv = model->surfmesh.data_svector3f;
153 const int *wi = model->surfmesh.data_vertexweightindex4i;
154 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
155 memset(svector3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
156 for (i = 0;i < model->surfmesh.num_vertices;i++, sv += 3, wi += 4, wf += 4, svector3f += 3)
160 const float *m = boneposerelative[wi[0]];
161 svector3f[0] = (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
162 svector3f[1] = (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
163 svector3f[2] = (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
167 const float *m = boneposerelative[wi[0]];
169 svector3f[0] = f * (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
170 svector3f[1] = f * (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
171 svector3f[2] = f * (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
172 for (k = 1;k < 4 && wf[k];k++)
174 const float *m = boneposerelative[wi[k]];
176 svector3f[0] += f * (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
177 svector3f[1] += f * (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
178 svector3f[2] += f * (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
185 const float *tv = model->surfmesh.data_tvector3f;
186 const int *wi = model->surfmesh.data_vertexweightindex4i;
187 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
188 memset(tvector3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
189 for (i = 0;i < model->surfmesh.num_vertices;i++, tv += 3, wi += 4, wf += 4, tvector3f += 3)
193 const float *m = boneposerelative[wi[0]];
194 tvector3f[0] = (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
195 tvector3f[1] = (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
196 tvector3f[2] = (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
200 const float *m = boneposerelative[wi[0]];
202 tvector3f[0] = f * (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
203 tvector3f[1] = f * (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
204 tvector3f[2] = f * (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
205 for (k = 1;k < 4 && wf[k];k++)
207 const float *m = boneposerelative[wi[k]];
209 tvector3f[0] += f * (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
210 tvector3f[1] += f * (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
211 tvector3f[2] += f * (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
217 else if (model->surfmesh.data_morphmd3vertex)
220 int i, numblends, blendnum;
221 int numverts = model->surfmesh.num_vertices;
223 for (blendnum = 0;blendnum < 4;blendnum++)
225 //VectorMA(translate, model->surfmesh.num_morphmdlframetranslate, frameblend[blendnum].lerp, translate);
226 if (frameblend[blendnum].lerp > 0)
227 numblends = blendnum + 1;
229 // special case for the first blend because it avoids some adds and the need to memset the arrays first
230 for (blendnum = 0;blendnum < numblends;blendnum++)
232 const md3vertex_t *verts = model->surfmesh.data_morphmd3vertex + numverts * frameblend[blendnum].frame;
233 float scale = frameblend[blendnum].lerp * (1.0f / 64.0f);
236 for (i = 0;i < numverts;i++)
238 vertex3f[i * 3 + 0] = verts[i].origin[0] * scale;
239 vertex3f[i * 3 + 1] = verts[i].origin[1] * scale;
240 vertex3f[i * 3 + 2] = verts[i].origin[2] * scale;
245 for (i = 0;i < numverts;i++)
247 vertex3f[i * 3 + 0] += verts[i].origin[0] * scale;
248 vertex3f[i * 3 + 1] += verts[i].origin[1] * scale;
249 vertex3f[i * 3 + 2] += verts[i].origin[2] * scale;
252 // the yaw and pitch stored in md3 models are 8bit quantized angles
253 // (0-255), and as such a lookup table is very well suited to
254 // decoding them, and since cosine is equivilant to sine with an
255 // extra 45 degree rotation, this uses one lookup table for both
256 // sine and cosine with a +64 bias to get cosine.
259 float lerp = frameblend[blendnum].lerp;
262 for (i = 0;i < numverts;i++)
264 normal3f[i * 3 + 0] = mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
265 normal3f[i * 3 + 1] = mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
266 normal3f[i * 3 + 2] = mod_md3_sin[verts[i].pitch + 64] * lerp;
271 for (i = 0;i < numverts;i++)
273 normal3f[i * 3 + 0] += mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
274 normal3f[i * 3 + 1] += mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
275 normal3f[i * 3 + 2] += mod_md3_sin[verts[i].pitch + 64] * lerp;
281 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].frame;
282 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
285 for (i = 0;i < numverts;i++, texvecvert++)
287 VectorScale(texvecvert->svec, f, svector3f + i*3);
288 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
293 for (i = 0;i < numverts;i++, texvecvert++)
295 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
296 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
302 else if (model->surfmesh.data_morphmdlvertex)
305 int i, numblends, blendnum;
306 int numverts = model->surfmesh.num_vertices;
308 VectorClear(translate);
310 // blend the frame translates to avoid redundantly doing so on each vertex
311 // (a bit of a brain twister but it works)
312 for (blendnum = 0;blendnum < 4;blendnum++)
314 if (model->surfmesh.data_morphmd2framesize6f)
315 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].frame * 6 + 3, translate);
317 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.num_morphmdlframetranslate, translate);
318 if (frameblend[blendnum].lerp > 0)
319 numblends = blendnum + 1;
321 // special case for the first blend because it avoids some adds and the need to memset the arrays first
322 for (blendnum = 0;blendnum < numblends;blendnum++)
324 const trivertx_t *verts = model->surfmesh.data_morphmdlvertex + numverts * frameblend[blendnum].frame;
326 if (model->surfmesh.data_morphmd2framesize6f)
327 VectorScale(model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].frame * 6, frameblend[blendnum].lerp, scale);
329 VectorScale(model->surfmesh.num_morphmdlframescale, frameblend[blendnum].lerp, scale);
332 for (i = 0;i < numverts;i++)
334 vertex3f[i * 3 + 0] = translate[0] + verts[i].v[0] * scale[0];
335 vertex3f[i * 3 + 1] = translate[1] + verts[i].v[1] * scale[1];
336 vertex3f[i * 3 + 2] = translate[2] + verts[i].v[2] * scale[2];
341 for (i = 0;i < numverts;i++)
343 vertex3f[i * 3 + 0] += verts[i].v[0] * scale[0];
344 vertex3f[i * 3 + 1] += verts[i].v[1] * scale[1];
345 vertex3f[i * 3 + 2] += verts[i].v[2] * scale[2];
348 // the vertex normals in mdl models are an index into a table of
349 // 162 unique values, this very crude quantization reduces the
350 // vertex normal to only one byte, which saves a lot of space but
351 // also makes lighting pretty coarse
354 float lerp = frameblend[blendnum].lerp;
357 for (i = 0;i < numverts;i++)
359 const float *vn = m_bytenormals[verts[i].lightnormalindex];
360 VectorScale(vn, lerp, normal3f + i*3);
365 for (i = 0;i < numverts;i++)
367 const float *vn = m_bytenormals[verts[i].lightnormalindex];
368 VectorMA(normal3f + i*3, lerp, vn, normal3f + i*3);
374 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].frame;
375 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
378 for (i = 0;i < numverts;i++, texvecvert++)
380 VectorScale(texvecvert->svec, f, svector3f + i*3);
381 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
386 for (i = 0;i < numverts;i++, texvecvert++)
388 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
389 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
396 Host_Error("model %s has no skeletal or vertex morph animation data", model->name);
399 int Mod_Alias_GetTagMatrix(const model_t *model, int poseframe, int tagindex, matrix4x4_t *outmatrix)
401 const float *boneframe;
402 float tempbonematrix[12], bonematrix[12];
403 *outmatrix = identitymatrix;
404 if (model->num_bones)
406 if (tagindex < 0 || tagindex >= model->num_bones)
408 if (poseframe >= model->num_poses)
410 boneframe = model->data_poses + poseframe * model->num_bones * 12;
411 memcpy(bonematrix, boneframe + tagindex * 12, sizeof(float[12]));
412 while (model->data_bones[tagindex].parent >= 0)
414 memcpy(tempbonematrix, bonematrix, sizeof(float[12]));
415 R_ConcatTransforms(boneframe + model->data_bones[tagindex].parent * 12, tempbonematrix, bonematrix);
416 tagindex = model->data_bones[tagindex].parent;
418 Matrix4x4_FromArray12FloatD3D(outmatrix, bonematrix);
420 else if (model->num_tags)
422 if (tagindex < 0 || tagindex >= model->num_tags)
424 if (poseframe >= model->num_tagframes)
426 Matrix4x4_FromArray12FloatGL(outmatrix, model->data_tags[poseframe * model->num_tags + tagindex].matrixgl);
431 int Mod_Alias_GetTagIndexForName(const model_t *model, unsigned int skin, const char *tagname)
434 if(skin >= (unsigned int)model->numskins)
436 if (model->data_overridetagnamesforskin && skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)skin].num_overridetagnames)
437 for (i = 0;i < model->data_overridetagnamesforskin[skin].num_overridetagnames;i++)
438 if (!strcasecmp(tagname, model->data_overridetagnamesforskin[skin].data_overridetagnames[i].name))
440 if (model->num_bones)
441 for (i = 0;i < model->num_bones;i++)
442 if (!strcasecmp(tagname, model->data_bones[i].name))
445 for (i = 0;i < model->num_tags;i++)
446 if (!strcasecmp(tagname, model->data_tags[i].name))
451 static void Mod_BuildBaseBonePoses(void)
455 float *basebonepose = Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(float[12]));
456 float *in12f = loadmodel->data_poses;
457 float *out12f = basebonepose;
458 float *outinv12f = loadmodel->data_baseboneposeinverse;
459 for (i = 0;i < loadmodel->num_bones;i++, in12f += 12, out12f += 12, outinv12f += 12)
461 if (loadmodel->data_bones[i].parent >= 0)
462 R_ConcatTransforms(basebonepose + 12 * loadmodel->data_bones[i].parent, in12f, out12f);
464 for (k = 0;k < 12;k++)
465 out12f[k] = in12f[k];
469 // we only support uniform scaling, so assume the first row is enough
470 // (note the lack of sqrt here, because we're trying to undo the scaling,
471 // this means multiplying by the inverse scale twice - squaring it, which
472 // makes the sqrt a waste of time)
473 scale = 1.0 / (out12f[ 0] * out12f[ 0] + out12f[ 1] * out12f[ 1] + out12f[ 2] * out12f[ 2]);
475 // invert the rotation by transposing and multiplying by the squared
476 // recipricol of the input matrix scale as described above
477 outinv12f[ 0] = (float)(out12f[ 0] * scale);
478 outinv12f[ 1] = (float)(out12f[ 4] * scale);
479 outinv12f[ 2] = (float)(out12f[ 8] * scale);
480 outinv12f[ 4] = (float)(out12f[ 1] * scale);
481 outinv12f[ 5] = (float)(out12f[ 5] * scale);
482 outinv12f[ 6] = (float)(out12f[ 9] * scale);
483 outinv12f[ 8] = (float)(out12f[ 2] * scale);
484 outinv12f[ 9] = (float)(out12f[ 6] * scale);
485 outinv12f[10] = (float)(out12f[10] * scale);
487 // invert the translate
488 outinv12f[ 3] = -(out12f[ 3] * outinv12f[ 0] + out12f[ 7] * outinv12f[ 1] + out12f[11] * outinv12f[ 2]);
489 outinv12f[ 7] = -(out12f[ 3] * outinv12f[ 4] + out12f[ 7] * outinv12f[ 5] + out12f[11] * outinv12f[ 6]);
490 outinv12f[11] = -(out12f[ 3] * outinv12f[ 8] + out12f[ 7] * outinv12f[ 9] + out12f[11] * outinv12f[10]);
492 Mem_Free(basebonepose);
495 static void Mod_Alias_CalculateBoundingBox(void)
499 qboolean firstvertex = true;
500 float dist, yawradius, radius;
503 frameblend_t frameblend[4];
504 memset(frameblend, 0, sizeof(frameblend));
505 frameblend[0].lerp = 1;
506 vertex3f = Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
507 VectorClear(loadmodel->normalmins);
508 VectorClear(loadmodel->normalmaxs);
511 for (i = 0;i < loadmodel->numframes;i++)
513 for (j = 0, frameblend[0].frame = loadmodel->animscenes[i].firstframe;j < loadmodel->animscenes[i].framecount;j++, frameblend[0].frame++)
515 Mod_Alias_GetMesh_Vertices(loadmodel, frameblend, vertex3f, NULL, NULL, NULL);
516 for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
521 VectorCopy(v, loadmodel->normalmins);
522 VectorCopy(v, loadmodel->normalmaxs);
526 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
527 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
528 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
529 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
530 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
531 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
533 dist = v[0] * v[0] + v[1] * v[1];
534 if (yawradius < dist)
543 radius = sqrt(radius);
544 yawradius = sqrt(yawradius);
545 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
546 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
547 loadmodel->yawmins[2] = loadmodel->normalmins[2];
548 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
549 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
550 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
551 loadmodel->radius = radius;
552 loadmodel->radius2 = radius * radius;
555 static void Mod_Alias_MorphMesh_CompileFrames(void)
558 frameblend_t frameblend[4] = {{0, 1}, {0, 0}, {0, 0}, {0, 0}};
559 unsigned char *datapointer;
560 datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
561 loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
562 loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
563 loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
564 loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
565 loadmodel->surfmesh.data_morphtexvecvertex = (texvecvertex_t *)datapointer;datapointer += loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices * sizeof(texvecvertex_t);
566 // 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)
567 for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
569 frameblend[0].frame = i;
570 Mod_Alias_GetMesh_Vertices(loadmodel, frameblend, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
571 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);
572 // encode the svector and tvector in 3 byte format for permanent storage
573 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
575 VectorScale(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
576 VectorScale(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
581 static void Mod_MDLMD2MD3_TraceBox(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)
584 float segmentmins[3], segmentmaxs[3];
585 frameblend_t frameblend[4];
587 static int maxvertices = 0;
588 static float *vertex3f = NULL;
589 memset(trace, 0, sizeof(*trace));
591 trace->realfraction = 1;
592 trace->hitsupercontentsmask = hitsupercontentsmask;
593 memset(frameblend, 0, sizeof(frameblend));
594 frameblend[0].frame = frame;
595 frameblend[0].lerp = 1;
596 if (maxvertices < model->surfmesh.num_vertices)
600 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
601 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
603 if (VectorLength2(boxmins) + VectorLength2(boxmaxs) == 0)
606 segmentmins[0] = min(start[0], end[0]) - 1;
607 segmentmins[1] = min(start[1], end[1]) - 1;
608 segmentmins[2] = min(start[2], end[2]) - 1;
609 segmentmaxs[0] = max(start[0], end[0]) + 1;
610 segmentmaxs[1] = max(start[1], end[1]) + 1;
611 segmentmaxs[2] = max(start[2], end[2]) + 1;
612 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
614 Mod_Alias_GetMesh_Vertices(model, frameblend, vertex3f, NULL, NULL, NULL);
615 Collision_TraceLineTriangleMeshFloat(trace, start, end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, SUPERCONTENTS_SOLID, 0, surface->texture, segmentmins, segmentmaxs);
620 // box trace, performed as brush trace
621 colbrushf_t *thisbrush_start, *thisbrush_end;
622 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
623 segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
624 segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
625 segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
626 segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
627 segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
628 segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
629 VectorAdd(start, boxmins, boxstartmins);
630 VectorAdd(start, boxmaxs, boxstartmaxs);
631 VectorAdd(end, boxmins, boxendmins);
632 VectorAdd(end, boxmaxs, boxendmaxs);
633 thisbrush_start = Collision_BrushForBox(&identitymatrix, boxstartmins, boxstartmaxs, 0, 0, NULL);
634 thisbrush_end = Collision_BrushForBox(&identitymatrix, boxendmins, boxendmaxs, 0, 0, NULL);
635 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
637 if (maxvertices < model->surfmesh.num_vertices)
641 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
642 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
644 Mod_Alias_GetMesh_Vertices(model, frameblend, vertex3f, NULL, NULL, NULL);
645 Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, SUPERCONTENTS_SOLID, 0, surface->texture, segmentmins, segmentmaxs);
650 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
653 for (i = 0;i < inverts;i++)
655 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
657 j = vertremap[i]; // not onseam
660 j = vertremap[i+inverts]; // onseam
666 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
668 int i, f, pose, groupframes;
670 daliasframetype_t *pframetype;
671 daliasframe_t *pinframe;
672 daliasgroup_t *group;
673 daliasinterval_t *intervals;
676 scene = loadmodel->animscenes;
677 for (f = 0;f < loadmodel->numframes;f++)
679 pframetype = (daliasframetype_t *)datapointer;
680 datapointer += sizeof(daliasframetype_t);
681 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
683 // a single frame is still treated as a group
690 group = (daliasgroup_t *)datapointer;
691 datapointer += sizeof(daliasgroup_t);
692 groupframes = LittleLong (group->numframes);
694 // intervals (time per frame)
695 intervals = (daliasinterval_t *)datapointer;
696 datapointer += sizeof(daliasinterval_t) * groupframes;
698 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
699 if (interval < 0.01f)
701 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
706 // get scene name from first frame
707 pinframe = (daliasframe_t *)datapointer;
709 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
710 scene->firstframe = pose;
711 scene->framecount = groupframes;
712 scene->framerate = 1.0f / interval;
717 for (i = 0;i < groupframes;i++)
719 pinframe = (daliasframe_t *)datapointer;
720 datapointer += sizeof(daliasframe_t);
721 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
722 datapointer += sizeof(trivertx_t) * inverts;
728 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
730 if (cls.state == ca_dedicated)
734 skinframe = R_SkinFrame_LoadMissing();
735 memset(texture, 0, sizeof(*texture));
736 texture->currentframe = texture;
737 //texture->animated = false;
738 texture->numskinframes = 1;
739 texture->skinframerate = 1;
740 texture->skinframes[0] = skinframe;
741 texture->currentskinframe = skinframe;
742 //texture->backgroundnumskinframes = 0;
743 //texture->customblendfunc[0] = 0;
744 //texture->customblendfunc[1] = 0;
745 //texture->surfaceflags = 0;
746 //texture->supercontents = 0;
747 //texture->surfaceparms = 0;
748 //texture->textureflags = 0;
750 texture->basematerialflags = MATERIALFLAG_WALL;
751 if (texture->currentskinframe->fog)
752 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
753 texture->currentmaterialflags = texture->basematerialflags;
756 static void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, char *meshname, char *shadername)
759 skinfileitem_t *skinfileitem;
760 skinframe_t *tempskinframe;
763 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
764 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
766 memset(skin, 0, sizeof(*skin));
768 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
770 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
771 if (!strcmp(skinfileitem->name, meshname) && strcmp(skinfileitem->replacement, "common/nodraw") && strcmp(skinfileitem->replacement, "textures/common/nodraw"))
773 if (!Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, false, false, true))
775 tempskinframe = R_SkinFrame_LoadExternal(skinfileitem->replacement, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS, false);
777 if (cls.state != ca_dedicated)
778 Con_Printf("mesh \"%s\": failed to load skin #%i \"%s\"\n", meshname, i, skinfileitem->replacement);
779 Mod_BuildAliasSkinFromSkinFrame(skin, tempskinframe);
786 // don't render unmentioned meshes
787 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
788 skin->basematerialflags = skin->currentmaterialflags = 0;
794 if (!Mod_LoadTextureFromQ3Shader(skin, shadername, false, false, true))
796 tempskinframe = R_SkinFrame_LoadExternal(shadername, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS, false);
798 if (cls.state != ca_dedicated)
799 Con_Printf("Can't find texture \"%s\" for mesh \"%s\", using grey checkerboard\n", shadername, meshname);
800 Mod_BuildAliasSkinFromSkinFrame(skin, tempskinframe);
805 #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);
806 #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);
807 void Mod_IDP0_Load(model_t *mod, void *buffer, void *bufferend)
809 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
810 float scales, scalet, interval;
814 stvert_t *pinstverts;
815 dtriangle_t *pintriangles;
816 daliasskintype_t *pinskintype;
817 daliasskingroup_t *pinskingroup;
818 daliasskininterval_t *pinskinintervals;
819 daliasframetype_t *pinframetype;
820 daliasgroup_t *pinframegroup;
821 unsigned char *datapointer, *startframes, *startskins;
822 char name[MAX_QPATH];
823 skinframe_t *tempskinframe;
824 animscene_t *tempskinscenes;
825 texture_t *tempaliasskins;
827 int *vertonseam, *vertremap;
828 skinfile_t *skinfiles;
830 datapointer = (unsigned char *)buffer;
831 pinmodel = (mdl_t *)datapointer;
832 datapointer += sizeof(mdl_t);
834 version = LittleLong (pinmodel->version);
835 if (version != ALIAS_VERSION)
836 Host_Error ("%s has wrong version number (%i should be %i)",
837 loadmodel->name, version, ALIAS_VERSION);
839 loadmodel->modeldatatypestring = "MDL";
841 loadmodel->type = mod_alias;
842 loadmodel->DrawSky = NULL;
843 loadmodel->DrawAddWaterPlanes = NULL;
844 loadmodel->Draw = R_Q1BSP_Draw;
845 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
846 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
847 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
848 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
849 loadmodel->DrawLight = R_Q1BSP_DrawLight;
850 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
851 loadmodel->PointSuperContents = NULL;
853 loadmodel->num_surfaces = 1;
854 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
855 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
856 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
857 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
858 loadmodel->surfacelist[0] = 0;
860 loadmodel->numskins = LittleLong(pinmodel->numskins);
861 BOUNDI(loadmodel->numskins,0,65536);
862 skinwidth = LittleLong (pinmodel->skinwidth);
863 BOUNDI(skinwidth,0,65536);
864 skinheight = LittleLong (pinmodel->skinheight);
865 BOUNDI(skinheight,0,65536);
866 numverts = LittleLong(pinmodel->numverts);
867 BOUNDI(numverts,0,65536);
868 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
869 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
870 loadmodel->numframes = LittleLong(pinmodel->numframes);
871 BOUNDI(loadmodel->numframes,0,65536);
872 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
873 BOUNDI(loadmodel->synctype,0,2);
874 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
875 i = LittleLong (pinmodel->flags);
876 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
878 for (i = 0;i < 3;i++)
880 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
881 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
884 startskins = datapointer;
886 for (i = 0;i < loadmodel->numskins;i++)
888 pinskintype = (daliasskintype_t *)datapointer;
889 datapointer += sizeof(daliasskintype_t);
890 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
894 pinskingroup = (daliasskingroup_t *)datapointer;
895 datapointer += sizeof(daliasskingroup_t);
896 groupskins = LittleLong(pinskingroup->numskins);
897 datapointer += sizeof(daliasskininterval_t) * groupskins;
900 for (j = 0;j < groupskins;j++)
902 datapointer += skinwidth * skinheight;
907 pinstverts = (stvert_t *)datapointer;
908 datapointer += sizeof(stvert_t) * numverts;
910 pintriangles = (dtriangle_t *)datapointer;
911 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
913 startframes = datapointer;
914 loadmodel->surfmesh.num_morphframes = 0;
915 for (i = 0;i < loadmodel->numframes;i++)
917 pinframetype = (daliasframetype_t *)datapointer;
918 datapointer += sizeof(daliasframetype_t);
919 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
923 pinframegroup = (daliasgroup_t *)datapointer;
924 datapointer += sizeof(daliasgroup_t);
925 groupframes = LittleLong(pinframegroup->numframes);
926 datapointer += sizeof(daliasinterval_t) * groupframes;
929 for (j = 0;j < groupframes;j++)
931 datapointer += sizeof(daliasframe_t);
932 datapointer += sizeof(trivertx_t) * numverts;
933 loadmodel->surfmesh.num_morphframes++;
937 // store texture coordinates into temporary array, they will be stored
938 // after usage is determined (triangle data)
939 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
940 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
941 vertonseam = vertremap + numverts * 2;
943 scales = 1.0 / skinwidth;
944 scalet = 1.0 / skinheight;
945 for (i = 0;i < numverts;i++)
947 vertonseam[i] = LittleLong(pinstverts[i].onseam);
948 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
949 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
950 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
951 vertst[(i+numverts)*2+1] = vertst[i*2+1];
954 // load triangle data
955 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
957 // read the triangle elements
958 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
959 for (j = 0;j < 3;j++)
960 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
961 // validate (note numverts is used because this is the original data)
962 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
963 // now butcher the elements according to vertonseam and tri->facesfront
964 // and then compact the vertex set to remove duplicates
965 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
966 if (!LittleLong(pintriangles[i].facesfront)) // backface
967 for (j = 0;j < 3;j++)
968 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
969 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
971 // (this uses vertremap to count usage to save some memory)
972 for (i = 0;i < numverts*2;i++)
974 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
975 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
976 // build remapping table and compact array
977 loadmodel->surfmesh.num_vertices = 0;
978 for (i = 0;i < numverts*2;i++)
982 vertremap[i] = loadmodel->surfmesh.num_vertices;
983 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
984 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
985 loadmodel->surfmesh.num_vertices++;
988 vertremap[i] = -1; // not used at all
990 // remap the elements to the new vertex set
991 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
992 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
993 // store the texture coordinates
994 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
995 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
997 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
998 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1002 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1003 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1004 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1005 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1006 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1007 Mod_Alias_CalculateBoundingBox();
1008 Mod_Alias_MorphMesh_CompileFrames();
1011 Mem_Free(vertremap);
1014 skinfiles = Mod_LoadSkinFiles();
1015 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1016 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1017 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1018 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1021 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1022 Mod_FreeSkinFiles(skinfiles);
1023 for (i = 0;i < loadmodel->numskins;i++)
1025 loadmodel->skinscenes[i].firstframe = i;
1026 loadmodel->skinscenes[i].framecount = 1;
1027 loadmodel->skinscenes[i].loop = true;
1028 loadmodel->skinscenes[i].framerate = 10;
1034 datapointer = startskins;
1035 for (i = 0;i < loadmodel->numskins;i++)
1037 pinskintype = (daliasskintype_t *)datapointer;
1038 datapointer += sizeof(daliasskintype_t);
1040 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1047 pinskingroup = (daliasskingroup_t *)datapointer;
1048 datapointer += sizeof(daliasskingroup_t);
1050 groupskins = LittleLong (pinskingroup->numskins);
1052 pinskinintervals = (daliasskininterval_t *)datapointer;
1053 datapointer += sizeof(daliasskininterval_t) * groupskins;
1055 interval = LittleFloat(pinskinintervals[0].interval);
1056 if (interval < 0.01f)
1058 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1063 sprintf(loadmodel->skinscenes[i].name, "skin %i", i);
1064 loadmodel->skinscenes[i].firstframe = totalskins;
1065 loadmodel->skinscenes[i].framecount = groupskins;
1066 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1067 loadmodel->skinscenes[i].loop = true;
1069 for (j = 0;j < groupskins;j++)
1072 sprintf (name, "%s_%i_%i", loadmodel->name, i, j);
1074 sprintf (name, "%s_%i", loadmodel->name, i);
1075 if (!Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, name, false, false, true))
1077 tempskinframe = R_SkinFrame_LoadExternal(name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS, false);
1079 tempskinframe = R_SkinFrame_LoadInternalQuake(name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP, true, r_fullbrights.integer, (unsigned char *)datapointer, skinwidth, skinheight);
1080 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1082 datapointer += skinwidth * skinheight;
1086 // check for skins that don't exist in the model, but do exist as external images
1087 // (this was added because yummyluv kept pestering me about support for it)
1088 // TODO: support shaders here?
1089 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)))
1091 // expand the arrays to make room
1092 tempskinscenes = loadmodel->skinscenes;
1093 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1094 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1095 Mem_Free(tempskinscenes);
1097 tempaliasskins = loadmodel->data_textures;
1098 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1099 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1100 Mem_Free(tempaliasskins);
1102 // store the info about the new skin
1103 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1104 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1105 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1106 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1107 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1108 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1110 //increase skin counts
1111 loadmodel->numskins++;
1114 // fix up the pointers since they are pointing at the old textures array
1115 // FIXME: this is a hack!
1116 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1117 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1121 surface = loadmodel->data_surfaces;
1122 surface->texture = loadmodel->data_textures;
1123 surface->num_firsttriangle = 0;
1124 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1125 surface->num_firstvertex = 0;
1126 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1128 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1131 void Mod_IDP2_Load(model_t *mod, void *buffer, void *bufferend)
1133 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1134 float iskinwidth, iskinheight;
1135 unsigned char *data;
1136 msurface_t *surface;
1138 unsigned char *base, *datapointer;
1139 md2frame_t *pinframe;
1141 md2triangle_t *intri;
1142 unsigned short *inst;
1143 struct md2verthash_s
1145 struct md2verthash_s *next;
1149 *hash, **md2verthash, *md2verthashdata;
1150 skinframe_t *tempskinframe;
1151 skinfile_t *skinfiles;
1153 pinmodel = (md2_t *)buffer;
1154 base = (unsigned char *)buffer;
1156 version = LittleLong (pinmodel->version);
1157 if (version != MD2ALIAS_VERSION)
1158 Host_Error ("%s has wrong version number (%i should be %i)",
1159 loadmodel->name, version, MD2ALIAS_VERSION);
1161 loadmodel->modeldatatypestring = "MD2";
1163 loadmodel->type = mod_alias;
1164 loadmodel->DrawSky = NULL;
1165 loadmodel->DrawAddWaterPlanes = NULL;
1166 loadmodel->Draw = R_Q1BSP_Draw;
1167 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1168 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1169 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1170 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1171 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1172 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1173 loadmodel->PointSuperContents = NULL;
1175 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1176 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1177 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1178 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1179 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1180 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1181 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1182 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1184 end = LittleLong(pinmodel->ofs_end);
1185 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1186 Host_Error ("%s is not a valid model", loadmodel->name);
1187 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1188 Host_Error ("%s is not a valid model", loadmodel->name);
1189 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1190 Host_Error ("%s is not a valid model", loadmodel->name);
1191 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1192 Host_Error ("%s is not a valid model", loadmodel->name);
1193 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1194 Host_Error ("%s is not a valid model", loadmodel->name);
1196 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1197 numxyz = LittleLong(pinmodel->num_xyz);
1198 numst = LittleLong(pinmodel->num_st);
1199 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1200 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1201 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1202 skinwidth = LittleLong(pinmodel->skinwidth);
1203 skinheight = LittleLong(pinmodel->skinheight);
1204 iskinwidth = 1.0f / skinwidth;
1205 iskinheight = 1.0f / skinheight;
1207 loadmodel->num_surfaces = 1;
1208 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1209 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]));
1210 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1211 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1212 loadmodel->surfacelist[0] = 0;
1213 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1214 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1215 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1216 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1218 loadmodel->synctype = ST_RAND;
1221 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1222 skinfiles = Mod_LoadSkinFiles();
1225 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1226 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1227 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1228 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1229 Mod_FreeSkinFiles(skinfiles);
1231 else if (loadmodel->numskins)
1233 // skins found (most likely not a player model)
1234 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1235 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1236 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1237 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1239 if (!Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, false, false, true))
1241 tempskinframe = R_SkinFrame_LoadExternal(inskin, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS, false);
1243 Con_Printf("%s is missing skin \"%s\"\n", loadmodel->name, inskin);
1244 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i * loadmodel->num_surfaces, tempskinframe);
1250 // no skins (most likely a player model)
1251 loadmodel->numskins = 1;
1252 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1253 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1254 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1255 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1258 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1259 for (i = 0;i < loadmodel->numskins;i++)
1261 loadmodel->skinscenes[i].firstframe = i;
1262 loadmodel->skinscenes[i].framecount = 1;
1263 loadmodel->skinscenes[i].loop = true;
1264 loadmodel->skinscenes[i].framerate = 10;
1267 // load the triangles and stvert data
1268 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1269 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1270 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1271 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1272 // swap the triangle list
1273 loadmodel->surfmesh.num_vertices = 0;
1274 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1276 for (j = 0;j < 3;j++)
1278 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1279 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1282 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1287 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1290 hashindex = (xyz * 256 + st) & 65535;
1291 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1292 if (hash->xyz == xyz && hash->st == st)
1296 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1299 hash->next = md2verthash[hashindex];
1300 md2verthash[hashindex] = hash;
1302 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1306 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1307 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));
1308 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1309 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1310 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1313 hash = md2verthashdata + i;
1314 vertremap[i] = hash->xyz;
1315 sts = LittleShort(inst[hash->st*2+0]);
1316 stt = LittleShort(inst[hash->st*2+1]);
1317 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1319 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1323 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1324 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1327 Mem_Free(md2verthash);
1328 Mem_Free(md2verthashdata);
1331 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1332 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1337 pinframe = (md2frame_t *)datapointer;
1338 datapointer += sizeof(md2frame_t);
1339 // store the frame scale/translate into the appropriate array
1340 for (j = 0;j < 3;j++)
1342 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1343 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1345 // convert the vertices
1346 v = (trivertx_t *)datapointer;
1347 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1348 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1349 out[k] = v[vertremap[k]];
1350 datapointer += numxyz * sizeof(trivertx_t);
1352 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1353 loadmodel->animscenes[i].firstframe = i;
1354 loadmodel->animscenes[i].framecount = 1;
1355 loadmodel->animscenes[i].framerate = 10;
1356 loadmodel->animscenes[i].loop = true;
1359 Mem_Free(vertremap);
1361 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1362 Mod_Alias_CalculateBoundingBox();
1363 Mod_Alias_MorphMesh_CompileFrames();
1365 surface = loadmodel->data_surfaces;
1366 surface->texture = loadmodel->data_textures;
1367 surface->num_firsttriangle = 0;
1368 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1369 surface->num_firstvertex = 0;
1370 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1372 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1375 void Mod_IDP3_Load(model_t *mod, void *buffer, void *bufferend)
1377 int i, j, k, version, meshvertices, meshtriangles;
1378 unsigned char *data;
1379 msurface_t *surface;
1380 md3modelheader_t *pinmodel;
1381 md3frameinfo_t *pinframe;
1384 skinfile_t *skinfiles;
1386 pinmodel = (md3modelheader_t *)buffer;
1388 if (memcmp(pinmodel->identifier, "IDP3", 4))
1389 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1390 version = LittleLong (pinmodel->version);
1391 if (version != MD3VERSION)
1392 Host_Error ("%s has wrong version number (%i should be %i)",
1393 loadmodel->name, version, MD3VERSION);
1395 skinfiles = Mod_LoadSkinFiles();
1396 if (loadmodel->numskins < 1)
1397 loadmodel->numskins = 1;
1399 loadmodel->modeldatatypestring = "MD3";
1401 loadmodel->type = mod_alias;
1402 loadmodel->DrawSky = NULL;
1403 loadmodel->DrawAddWaterPlanes = NULL;
1404 loadmodel->Draw = R_Q1BSP_Draw;
1405 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1406 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1407 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1408 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1409 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1410 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1411 loadmodel->PointSuperContents = NULL;
1412 loadmodel->synctype = ST_RAND;
1413 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1414 i = LittleLong (pinmodel->flags);
1415 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1417 // set up some global info about the model
1418 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1419 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1421 // make skinscenes for the skins (no groups)
1422 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1423 for (i = 0;i < loadmodel->numskins;i++)
1425 loadmodel->skinscenes[i].firstframe = i;
1426 loadmodel->skinscenes[i].framecount = 1;
1427 loadmodel->skinscenes[i].loop = true;
1428 loadmodel->skinscenes[i].framerate = 10;
1432 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1433 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1435 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1436 loadmodel->animscenes[i].firstframe = i;
1437 loadmodel->animscenes[i].framecount = 1;
1438 loadmodel->animscenes[i].framerate = 10;
1439 loadmodel->animscenes[i].loop = true;
1443 loadmodel->num_tagframes = loadmodel->numframes;
1444 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1445 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1446 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1448 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1449 for (j = 0;j < 9;j++)
1450 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1451 for (j = 0;j < 3;j++)
1452 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1453 //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);
1459 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)))
1461 if (memcmp(pinmesh->identifier, "IDP3", 4))
1462 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1463 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1464 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1465 meshvertices += LittleLong(pinmesh->num_vertices);
1466 meshtriangles += LittleLong(pinmesh->num_triangles);
1469 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1470 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1471 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1472 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 * sizeof(float[2]) + meshvertices * loadmodel->numframes * sizeof(md3vertex_t));
1473 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1474 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1475 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1476 loadmodel->surfmesh.num_vertices = meshvertices;
1477 loadmodel->surfmesh.num_triangles = meshtriangles;
1478 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1479 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1480 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1481 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1482 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1486 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)))
1488 if (memcmp(pinmesh->identifier, "IDP3", 4))
1489 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1490 loadmodel->surfacelist[i] = i;
1491 surface = loadmodel->data_surfaces + i;
1492 surface->texture = loadmodel->data_textures + i;
1493 surface->num_firsttriangle = meshtriangles;
1494 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1495 surface->num_firstvertex = meshvertices;
1496 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1497 meshvertices += surface->num_vertices;
1498 meshtriangles += surface->num_triangles;
1500 for (j = 0;j < surface->num_triangles * 3;j++)
1501 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1502 for (j = 0;j < surface->num_vertices;j++)
1504 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1505 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1507 for (j = 0;j < loadmodel->numframes;j++)
1509 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1510 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1511 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1513 out->origin[0] = LittleShort(in->origin[0]);
1514 out->origin[1] = LittleShort(in->origin[1]);
1515 out->origin[2] = LittleShort(in->origin[2]);
1516 out->pitch = in->pitch;
1521 if (LittleLong(pinmesh->num_shaders) >= 1)
1522 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name);
1524 for (j = 0;j < loadmodel->numskins;j++)
1525 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i + j * loadmodel->num_surfaces, NULL);
1527 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1529 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1530 Mod_Alias_MorphMesh_CompileFrames();
1531 Mod_Alias_CalculateBoundingBox();
1532 Mod_FreeSkinFiles(skinfiles);
1534 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1535 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1538 void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer, void *bufferend)
1540 zymtype1header_t *pinmodel, *pheader;
1541 unsigned char *pbase;
1542 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1543 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose;
1544 zymvertex_t *verts, *vertdata;
1548 skinfile_t *skinfiles;
1549 unsigned char *data;
1550 msurface_t *surface;
1552 pinmodel = (zymtype1header_t *)buffer;
1553 pbase = (unsigned char *)buffer;
1554 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1555 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1556 if (BigLong(pinmodel->type) != 1)
1557 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1559 loadmodel->modeldatatypestring = "ZYM";
1561 loadmodel->type = mod_alias;
1562 loadmodel->synctype = ST_RAND;
1566 pheader->type = BigLong(pinmodel->type);
1567 pheader->filesize = BigLong(pinmodel->filesize);
1568 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1569 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1570 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1571 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1572 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1573 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1574 pheader->radius = BigFloat(pinmodel->radius);
1575 pheader->numverts = BigLong(pinmodel->numverts);
1576 pheader->numtris = BigLong(pinmodel->numtris);
1577 pheader->numshaders = BigLong(pinmodel->numshaders);
1578 pheader->numbones = BigLong(pinmodel->numbones);
1579 pheader->numscenes = BigLong(pinmodel->numscenes);
1580 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1581 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1582 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1583 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1584 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1585 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1586 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1587 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1588 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1589 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1590 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1591 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1592 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1593 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1594 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1595 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1596 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1597 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1599 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1601 Con_Printf("%s has no geometry\n", loadmodel->name);
1604 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1606 Con_Printf("%s has no animations\n", loadmodel->name);
1610 loadmodel->DrawSky = NULL;
1611 loadmodel->DrawAddWaterPlanes = NULL;
1612 loadmodel->Draw = R_Q1BSP_Draw;
1613 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1614 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1615 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1616 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1617 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1618 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1619 loadmodel->PointSuperContents = NULL;
1621 loadmodel->numframes = pheader->numscenes;
1622 loadmodel->num_surfaces = pheader->numshaders;
1624 skinfiles = Mod_LoadSkinFiles();
1625 if (loadmodel->numskins < 1)
1626 loadmodel->numskins = 1;
1628 // make skinscenes for the skins (no groups)
1629 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1630 for (i = 0;i < loadmodel->numskins;i++)
1632 loadmodel->skinscenes[i].firstframe = i;
1633 loadmodel->skinscenes[i].framecount = 1;
1634 loadmodel->skinscenes[i].loop = true;
1635 loadmodel->skinscenes[i].framerate = 10;
1639 modelradius = pheader->radius;
1640 for (i = 0;i < 3;i++)
1642 loadmodel->normalmins[i] = pheader->mins[i];
1643 loadmodel->normalmaxs[i] = pheader->maxs[i];
1644 loadmodel->rotatedmins[i] = -modelradius;
1645 loadmodel->rotatedmaxs[i] = modelradius;
1647 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1648 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1649 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1650 if (loadmodel->yawmaxs[0] > modelradius)
1651 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1652 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1653 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1654 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1655 loadmodel->radius = modelradius;
1656 loadmodel->radius2 = modelradius * modelradius;
1658 // go through the lumps, swapping things
1660 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1661 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1662 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1663 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1664 for (i = 0;i < pheader->numscenes;i++)
1666 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1667 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1668 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1669 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1670 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1671 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1672 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1673 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1674 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1675 if (loadmodel->animscenes[i].framerate < 0)
1676 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1680 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1681 loadmodel->num_bones = pheader->numbones;
1682 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, pheader->numbones * sizeof(aliasbone_t));
1683 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1684 for (i = 0;i < pheader->numbones;i++)
1686 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1687 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1688 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1689 if (loadmodel->data_bones[i].parent >= i)
1690 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1693 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1694 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1695 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1696 for (i = 0;i < pheader->numverts;i++)
1698 vertbonecounts[i] = BigLong(bonecount[i]);
1699 if (vertbonecounts[i] != 1)
1700 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1703 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]);
1705 meshvertices = pheader->numverts;
1706 meshtriangles = pheader->numtris;
1708 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1709 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1710 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1711 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 * sizeof(float[14]) + meshvertices * sizeof(int[4]) + meshvertices * sizeof(float[4]) + loadmodel->num_poses * sizeof(float[12]) + loadmodel->num_bones * sizeof(float[12]));
1712 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1713 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1714 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1715 loadmodel->surfmesh.num_vertices = meshvertices;
1716 loadmodel->surfmesh.num_triangles = meshtriangles;
1717 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1718 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1719 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1720 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1721 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1722 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1723 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1724 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1725 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1726 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
1727 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1729 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1730 poses = (float *) (pheader->lump_poses.start + pbase);
1731 for (i = 0;i < pheader->lump_poses.length / 4;i++)
1732 loadmodel->data_poses[i] = BigFloat(poses[i]);
1734 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1735 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1736 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1737 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1738 // (converting from weight-blending skeletal animation to
1739 // deformation-based skeletal animation)
1740 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1741 for (i = 0;i < loadmodel->num_bones;i++)
1743 const float *m = loadmodel->data_poses + i * 12;
1744 if (loadmodel->data_bones[i].parent >= 0)
1745 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1747 for (k = 0;k < 12;k++)
1748 bonepose[12*i+k] = m[k];
1750 for (j = 0;j < pheader->numverts;j++)
1752 // this format really should have had a per vertexweight weight value...
1753 // but since it does not, the weighting is completely ignored and
1754 // only one weight is allowed per vertex
1755 int boneindex = BigLong(vertdata[j].bonenum);
1756 const float *m = bonepose + 12 * boneindex;
1757 float relativeorigin[3];
1758 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1759 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1760 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1761 // transform the vertex bone weight into the base mesh
1762 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1763 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1764 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1765 // store the weight as the primary weight on this vertex
1766 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
1767 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = 1;
1770 // normals and tangents are calculated after elements are loaded
1772 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1773 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1774 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1775 for (i = 0;i < pheader->numverts;i++)
1777 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1778 // flip T coordinate for OpenGL
1779 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1782 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1783 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1784 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1786 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1787 //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)
1788 // byteswap, validate, and swap winding order of tris
1789 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1790 if (pheader->lump_render.length != count)
1791 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1792 renderlist = (int *) (pheader->lump_render.start + pbase);
1793 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1795 for (i = 0;i < loadmodel->num_surfaces;i++)
1797 int firstvertex, lastvertex;
1798 if (renderlist >= renderlistend)
1799 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1800 count = BigLong(*renderlist);renderlist++;
1801 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1802 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1804 loadmodel->surfacelist[i] = i;
1805 surface = loadmodel->data_surfaces + i;
1806 surface->texture = loadmodel->data_textures + i;
1807 surface->num_firsttriangle = meshtriangles;
1808 surface->num_triangles = count;
1809 meshtriangles += surface->num_triangles;
1811 // load the elements
1812 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
1813 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
1815 outelements[j*3+2] = BigLong(renderlist[0]);
1816 outelements[j*3+1] = BigLong(renderlist[1]);
1817 outelements[j*3+0] = BigLong(renderlist[2]);
1819 // validate the elements and find the used vertex range
1820 firstvertex = meshvertices;
1822 for (j = 0;j < surface->num_triangles * 3;j++)
1824 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
1825 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
1826 firstvertex = min(firstvertex, outelements[j]);
1827 lastvertex = max(lastvertex, outelements[j]);
1829 surface->num_firstvertex = firstvertex;
1830 surface->num_vertices = lastvertex + 1 - firstvertex;
1832 // since zym models do not have named sections, reuse their shader
1833 // name as the section name
1834 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
1836 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
1838 for (j = 0;j < loadmodel->numskins;j++)
1839 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i + j * loadmodel->num_surfaces, NULL);
1841 Mod_FreeSkinFiles(skinfiles);
1842 Mem_Free(vertbonecounts);
1845 // compute all the mesh information that was not loaded from the file
1846 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
1847 Mod_BuildBaseBonePoses();
1848 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
1849 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);
1850 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1852 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1855 void Mod_DARKPLACESMODEL_Load(model_t *mod, void *buffer, void *bufferend)
1857 dpmheader_t *pheader;
1861 unsigned char *pbase;
1862 int i, j, k, meshvertices, meshtriangles;
1863 skinfile_t *skinfiles;
1864 unsigned char *data;
1867 pheader = (dpmheader_t *)buffer;
1868 pbase = (unsigned char *)buffer;
1869 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
1870 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
1871 if (BigLong(pheader->type) != 2)
1872 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1874 loadmodel->modeldatatypestring = "DPM";
1876 loadmodel->type = mod_alias;
1877 loadmodel->synctype = ST_RAND;
1880 pheader->type = BigLong(pheader->type);
1881 pheader->filesize = BigLong(pheader->filesize);
1882 pheader->mins[0] = BigFloat(pheader->mins[0]);
1883 pheader->mins[1] = BigFloat(pheader->mins[1]);
1884 pheader->mins[2] = BigFloat(pheader->mins[2]);
1885 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
1886 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
1887 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
1888 pheader->yawradius = BigFloat(pheader->yawradius);
1889 pheader->allradius = BigFloat(pheader->allradius);
1890 pheader->num_bones = BigLong(pheader->num_bones);
1891 pheader->num_meshs = BigLong(pheader->num_meshs);
1892 pheader->num_frames = BigLong(pheader->num_frames);
1893 pheader->ofs_bones = BigLong(pheader->ofs_bones);
1894 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
1895 pheader->ofs_frames = BigLong(pheader->ofs_frames);
1897 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
1899 Con_Printf("%s has no geometry\n", loadmodel->name);
1902 if (pheader->num_frames < 1)
1904 Con_Printf("%s has no frames\n", loadmodel->name);
1908 loadmodel->DrawSky = NULL;
1909 loadmodel->DrawAddWaterPlanes = NULL;
1910 loadmodel->Draw = R_Q1BSP_Draw;
1911 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1912 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1913 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1914 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1915 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1916 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1917 loadmodel->PointSuperContents = NULL;
1920 for (i = 0;i < 3;i++)
1922 loadmodel->normalmins[i] = pheader->mins[i];
1923 loadmodel->normalmaxs[i] = pheader->maxs[i];
1924 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
1925 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
1926 loadmodel->rotatedmins[i] = -pheader->allradius;
1927 loadmodel->rotatedmaxs[i] = pheader->allradius;
1929 loadmodel->radius = pheader->allradius;
1930 loadmodel->radius2 = pheader->allradius * pheader->allradius;
1932 // load external .skin files if present
1933 skinfiles = Mod_LoadSkinFiles();
1934 if (loadmodel->numskins < 1)
1935 loadmodel->numskins = 1;
1940 // gather combined statistics from the meshes
1941 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
1942 for (i = 0;i < (int)pheader->num_meshs;i++)
1944 int numverts = BigLong(dpmmesh->num_verts);
1945 meshvertices += numverts;;
1946 meshtriangles += BigLong(dpmmesh->num_tris);
1950 loadmodel->numframes = pheader->num_frames;
1951 loadmodel->num_bones = pheader->num_bones;
1952 loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
1953 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
1954 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1955 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1956 // do most allocations as one merged chunk
1957 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 * (sizeof(float[14]) + sizeof(int[4]) + sizeof(float[4])) + loadmodel->num_poses * sizeof(float[12]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
1958 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1959 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1960 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1961 loadmodel->surfmesh.num_vertices = meshvertices;
1962 loadmodel->surfmesh.num_triangles = meshtriangles;
1963 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1964 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1965 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1966 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1967 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1968 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1969 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1970 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1971 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1972 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
1973 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1974 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
1975 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
1976 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1978 for (i = 0;i < loadmodel->numskins;i++)
1980 loadmodel->skinscenes[i].firstframe = i;
1981 loadmodel->skinscenes[i].framecount = 1;
1982 loadmodel->skinscenes[i].loop = true;
1983 loadmodel->skinscenes[i].framerate = 10;
1986 // load the bone info
1987 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
1988 for (i = 0;i < loadmodel->num_bones;i++)
1990 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1991 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1992 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1993 if (loadmodel->data_bones[i].parent >= i)
1994 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1998 frame = (dpmframe_t *) (pbase + pheader->ofs_frames);
1999 for (i = 0;i < loadmodel->numframes;i++)
2002 memcpy(loadmodel->animscenes[i].name, frame->name, sizeof(frame->name));
2003 loadmodel->animscenes[i].firstframe = i;
2004 loadmodel->animscenes[i].framecount = 1;
2005 loadmodel->animscenes[i].loop = true;
2006 loadmodel->animscenes[i].framerate = 10;
2007 // load the bone poses for this frame
2008 poses = (float *) (pbase + BigLong(frame->ofs_bonepositions));
2009 for (j = 0;j < loadmodel->num_bones*12;j++)
2010 loadmodel->data_poses[i * loadmodel->num_bones*12 + j] = BigFloat(poses[j]);
2011 // stuff not processed here: mins, maxs, yawradius, allradius
2015 // load the meshes now
2016 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2019 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2020 // (converting from weight-blending skeletal animation to
2021 // deformation-based skeletal animation)
2022 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2023 for (i = 0;i < loadmodel->num_bones;i++)
2025 const float *m = loadmodel->data_poses + i * 12;
2026 if (loadmodel->data_bones[i].parent >= 0)
2027 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2029 for (k = 0;k < 12;k++)
2030 bonepose[12*i+k] = m[k];
2032 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2034 const int *inelements;
2036 const float *intexcoord;
2037 msurface_t *surface;
2039 loadmodel->surfacelist[i] = i;
2040 surface = loadmodel->data_surfaces + i;
2041 surface->texture = loadmodel->data_textures + i;
2042 surface->num_firsttriangle = meshtriangles;
2043 surface->num_triangles = BigLong(dpmmesh->num_tris);
2044 surface->num_firstvertex = meshvertices;
2045 surface->num_vertices = BigLong(dpmmesh->num_verts);
2046 meshvertices += surface->num_vertices;
2047 meshtriangles += surface->num_triangles;
2049 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2050 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2051 for (j = 0;j < surface->num_triangles;j++)
2053 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2054 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2055 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2056 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2061 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2062 for (j = 0;j < surface->num_vertices*2;j++)
2063 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2065 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2066 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2070 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2071 data += sizeof(dpmvertex_t);
2072 for (k = 0;k < numweights;k++)
2074 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2075 int boneindex = BigLong(vert->bonenum);
2076 const float *m = bonepose + 12 * boneindex;
2077 float influence = BigFloat(vert->influence);
2078 float relativeorigin[3], relativenormal[3];
2079 relativeorigin[0] = BigFloat(vert->origin[0]);
2080 relativeorigin[1] = BigFloat(vert->origin[1]);
2081 relativeorigin[2] = BigFloat(vert->origin[2]);
2082 relativenormal[0] = BigFloat(vert->normal[0]);
2083 relativenormal[1] = BigFloat(vert->normal[1]);
2084 relativenormal[2] = BigFloat(vert->normal[2]);
2085 // blend the vertex bone weights into the base mesh
2086 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2087 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2088 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2089 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2090 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2091 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2094 // store the first (and often only) weight
2095 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = influence;
2096 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
2100 // sort the new weight into this vertex's weight table
2101 // (which only accepts up to 4 bones per vertex)
2102 for (l = 0;l < 4;l++)
2104 if (loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] < influence)
2106 // move weaker influence weights out of the way first
2108 for (l2 = 3;l2 > l;l2--)
2110 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2-1];
2111 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2-1];
2113 // store the new weight
2114 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] = influence;
2115 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l] = boneindex;
2120 data += sizeof(dpmbonevert_t);
2123 for (l = 0;l < 4;l++)
2124 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l];
2125 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2127 float f = 1.0f / sum;
2128 for (l = 0;l < 4;l++)
2129 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] *= f;
2133 // since dpm models do not have named sections, reuse their shader name as the section name
2134 if (dpmmesh->shadername[0])
2135 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2137 for (j = 0;j < loadmodel->numskins;j++)
2138 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i + j * loadmodel->num_surfaces, NULL);
2140 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2143 Mod_FreeSkinFiles(skinfiles);
2145 // compute all the mesh information that was not loaded from the file
2146 Mod_BuildBaseBonePoses();
2147 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);
2148 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2150 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2153 // no idea why PSK/PSA files contain weird quaternions but they do...
2154 #define PSKQUATNEGATIONS
2155 void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend)
2157 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2158 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2159 fs_offset_t filesize;
2164 pskboneinfo_t *bones;
2165 pskrawweights_t *rawweights;
2166 pskboneinfo_t *animbones;
2167 pskaniminfo_t *anims;
2168 pskanimkeys_t *animkeys;
2169 void *animfilebuffer, *animbuffer, *animbufferend;
2170 unsigned char *data;
2172 skinfile_t *skinfiles;
2173 char animname[MAX_QPATH];
2175 pchunk = (pskchunk_t *)buffer;
2176 if (strcmp(pchunk->id, "ACTRHEAD"))
2177 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2179 loadmodel->modeldatatypestring = "PSK";
2181 loadmodel->type = mod_alias;
2182 loadmodel->DrawSky = NULL;
2183 loadmodel->DrawAddWaterPlanes = NULL;
2184 loadmodel->Draw = R_Q1BSP_Draw;
2185 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2186 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2187 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2188 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2189 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2190 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2191 loadmodel->PointSuperContents = NULL;
2192 loadmodel->synctype = ST_RAND;
2194 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2195 strlcat(animname, ".psa", sizeof(animname));
2196 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2197 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2198 if (animbuffer == NULL)
2199 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2218 while (buffer < bufferend)
2220 pchunk = (pskchunk_t *)buffer;
2221 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2222 version = LittleLong(pchunk->version);
2223 recordsize = LittleLong(pchunk->recordsize);
2224 numrecords = LittleLong(pchunk->numrecords);
2225 if (developer.integer >= 100)
2226 Con_Printf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2227 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2228 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);
2229 if (!strcmp(pchunk->id, "ACTRHEAD"))
2233 else if (!strcmp(pchunk->id, "PNTS0000"))
2236 if (recordsize != sizeof(*p))
2237 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2238 // byteswap in place and keep the pointer
2239 numpnts = numrecords;
2240 pnts = (pskpnts_t *)buffer;
2241 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2243 p->origin[0] = LittleFloat(p->origin[0]);
2244 p->origin[1] = LittleFloat(p->origin[1]);
2245 p->origin[2] = LittleFloat(p->origin[2]);
2249 else if (!strcmp(pchunk->id, "VTXW0000"))
2252 if (recordsize != sizeof(*p))
2253 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2254 // byteswap in place and keep the pointer
2255 numvtxw = numrecords;
2256 vtxw = (pskvtxw_t *)buffer;
2257 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2259 p->pntsindex = LittleShort(p->pntsindex);
2260 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2261 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2262 if (p->pntsindex >= numpnts)
2264 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2270 else if (!strcmp(pchunk->id, "FACE0000"))
2273 if (recordsize != sizeof(*p))
2274 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2275 // byteswap in place and keep the pointer
2276 numfaces = numrecords;
2277 faces = (pskface_t *)buffer;
2278 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2280 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2281 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2282 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2283 p->group = LittleLong(p->group);
2284 if (p->vtxwindex[0] >= numvtxw)
2286 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2287 p->vtxwindex[0] = 0;
2289 if (p->vtxwindex[1] >= numvtxw)
2291 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2292 p->vtxwindex[1] = 0;
2294 if (p->vtxwindex[2] >= numvtxw)
2296 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2297 p->vtxwindex[2] = 0;
2302 else if (!strcmp(pchunk->id, "MATT0000"))
2305 if (recordsize != sizeof(*p))
2306 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2307 // byteswap in place and keep the pointer
2308 nummatts = numrecords;
2309 matts = (pskmatt_t *)buffer;
2310 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2316 else if (!strcmp(pchunk->id, "REFSKELT"))
2319 if (recordsize != sizeof(*p))
2320 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2321 // byteswap in place and keep the pointer
2322 numbones = numrecords;
2323 bones = (pskboneinfo_t *)buffer;
2324 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2326 p->numchildren = LittleLong(p->numchildren);
2327 p->parent = LittleLong(p->parent);
2328 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2329 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2330 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2331 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2332 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2333 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2334 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2335 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2336 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2337 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2338 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2339 #ifdef PSKQUATNEGATIONS
2342 p->basepose.quat[0] *= -1;
2343 p->basepose.quat[1] *= -1;
2344 p->basepose.quat[2] *= -1;
2348 p->basepose.quat[0] *= 1;
2349 p->basepose.quat[1] *= -1;
2350 p->basepose.quat[2] *= 1;
2353 if (p->parent < 0 || p->parent >= numbones)
2355 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2361 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2364 if (recordsize != sizeof(*p))
2365 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2366 // byteswap in place and keep the pointer
2367 numrawweights = numrecords;
2368 rawweights = (pskrawweights_t *)buffer;
2369 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2371 p->weight = LittleFloat(p->weight);
2372 p->pntsindex = LittleLong(p->pntsindex);
2373 p->boneindex = LittleLong(p->boneindex);
2374 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2376 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2379 if (p->boneindex < 0 || p->boneindex >= numbones)
2381 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2389 while (animbuffer < animbufferend)
2391 pchunk = (pskchunk_t *)animbuffer;
2392 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2393 version = LittleLong(pchunk->version);
2394 recordsize = LittleLong(pchunk->recordsize);
2395 numrecords = LittleLong(pchunk->numrecords);
2396 if (developer.integer >= 100)
2397 Con_Printf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2398 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2399 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);
2400 if (!strcmp(pchunk->id, "ANIMHEAD"))
2404 else if (!strcmp(pchunk->id, "BONENAMES"))
2407 if (recordsize != sizeof(*p))
2408 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2409 // byteswap in place and keep the pointer
2410 numanimbones = numrecords;
2411 animbones = (pskboneinfo_t *)animbuffer;
2412 // NOTE: supposedly psa does not need to match the psk model, the
2413 // bones missing from the psa would simply use their base
2414 // positions from the psk, but this is hard for me to implement
2415 // and people can easily make animations that match.
2416 if (numanimbones != numbones)
2417 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2418 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2420 p->numchildren = LittleLong(p->numchildren);
2421 p->parent = LittleLong(p->parent);
2422 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2423 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2424 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2425 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2426 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2427 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2428 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2429 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2430 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2431 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2432 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2433 #ifdef PSKQUATNEGATIONS
2436 p->basepose.quat[0] *= -1;
2437 p->basepose.quat[1] *= -1;
2438 p->basepose.quat[2] *= -1;
2442 p->basepose.quat[0] *= 1;
2443 p->basepose.quat[1] *= -1;
2444 p->basepose.quat[2] *= 1;
2447 if (p->parent < 0 || p->parent >= numanimbones)
2449 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2452 // check that bones are the same as in the base
2453 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2454 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2458 else if (!strcmp(pchunk->id, "ANIMINFO"))
2461 if (recordsize != sizeof(*p))
2462 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2463 // byteswap in place and keep the pointer
2464 numanims = numrecords;
2465 anims = (pskaniminfo_t *)animbuffer;
2466 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2468 p->numbones = LittleLong(p->numbones);
2469 p->playtime = LittleFloat(p->playtime);
2470 p->fps = LittleFloat(p->fps);
2471 p->firstframe = LittleLong(p->firstframe);
2472 p->numframes = LittleLong(p->numframes);
2473 if (p->numbones != numbones)
2474 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2478 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2481 if (recordsize != sizeof(*p))
2482 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2483 numanimkeys = numrecords;
2484 animkeys = (pskanimkeys_t *)animbuffer;
2485 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2487 p->origin[0] = LittleFloat(p->origin[0]);
2488 p->origin[1] = LittleFloat(p->origin[1]);
2489 p->origin[2] = LittleFloat(p->origin[2]);
2490 p->quat[0] = LittleFloat(p->quat[0]);
2491 p->quat[1] = LittleFloat(p->quat[1]);
2492 p->quat[2] = LittleFloat(p->quat[2]);
2493 p->quat[3] = LittleFloat(p->quat[3]);
2494 p->frametime = LittleFloat(p->frametime);
2495 #ifdef PSKQUATNEGATIONS
2496 if (index % numbones)
2511 // TODO: allocate bonepose stuff
2514 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2517 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2518 Host_Error("%s: missing required chunks", loadmodel->name);
2520 loadmodel->numframes = 0;
2521 for (index = 0;index < numanims;index++)
2522 loadmodel->numframes += anims[index].numframes;
2524 if (numanimkeys != numbones * loadmodel->numframes)
2525 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2527 meshvertices = numvtxw;
2528 meshtriangles = numfaces;
2530 // load external .skin files if present
2531 skinfiles = Mod_LoadSkinFiles();
2532 if (loadmodel->numskins < 1)
2533 loadmodel->numskins = 1;
2534 loadmodel->num_bones = numbones;
2535 loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
2536 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2537 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2538 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2539 // do most allocations as one merged chunk
2540 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 * (sizeof(float[14]) + sizeof(int[4]) + sizeof(float[4])) + loadmodel->num_poses * sizeof(float[12]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
2541 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2542 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2543 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2544 loadmodel->surfmesh.num_vertices = meshvertices;
2545 loadmodel->surfmesh.num_triangles = meshtriangles;
2546 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2547 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2548 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2549 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2550 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2551 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2552 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2553 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
2554 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
2555 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
2556 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2557 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2558 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2559 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2561 for (i = 0;i < loadmodel->numskins;i++)
2563 loadmodel->skinscenes[i].firstframe = i;
2564 loadmodel->skinscenes[i].framecount = 1;
2565 loadmodel->skinscenes[i].loop = true;
2566 loadmodel->skinscenes[i].framerate = 10;
2570 for (index = 0, i = 0;index < nummatts;index++)
2572 // since psk models do not have named sections, reuse their shader name as the section name
2573 if (matts[index].name[0])
2574 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2576 for (j = 0;j < loadmodel->numskins;j++)
2577 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + index + j * loadmodel->num_surfaces, NULL);
2578 loadmodel->surfacelist[index] = index;
2579 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2580 loadmodel->data_surfaces[index].num_firstvertex = 0;
2581 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2584 // copy over the vertex locations and texcoords
2585 for (index = 0;index < numvtxw;index++)
2587 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2588 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2589 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2590 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2591 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2594 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2595 for (index = 0;index < numfaces;index++)
2596 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2597 for (index = 0, i = 0;index < nummatts;index++)
2599 loadmodel->data_surfaces[index].num_firsttriangle = i;
2600 i += loadmodel->data_surfaces[index].num_triangles;
2601 loadmodel->data_surfaces[index].num_triangles = 0;
2603 for (index = 0;index < numfaces;index++)
2605 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2606 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2607 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2608 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2611 // copy over the bones
2612 for (index = 0;index < numbones;index++)
2614 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2615 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2616 if (loadmodel->data_bones[index].parent >= index)
2617 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2620 // sort the psk point weights into the vertex weight tables
2621 // (which only accept up to 4 bones per vertex)
2622 for (index = 0;index < numvtxw;index++)
2626 for (j = 0;j < numrawweights;j++)
2628 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2630 int boneindex = rawweights[j].boneindex;
2631 float influence = rawweights[j].weight;
2632 for (l = 0;l < 4;l++)
2634 if (loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] < influence)
2636 // move lower influence weights out of the way first
2638 for (l2 = 3;l2 > l;l2--)
2640 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2-1];
2641 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2-1];
2643 // store the new weight
2644 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] = influence;
2645 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l] = boneindex;
2652 for (l = 0;l < 4;l++)
2653 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l];
2654 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2656 float f = 1.0f / sum;
2657 for (l = 0;l < 4;l++)
2658 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] *= f;
2662 // set up the animscenes based on the anims
2663 for (index = 0, i = 0;index < numanims;index++)
2665 for (j = 0;j < anims[index].numframes;j++, i++)
2667 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2668 loadmodel->animscenes[i].firstframe = i;
2669 loadmodel->animscenes[i].framecount = 1;
2670 loadmodel->animscenes[i].loop = true;
2671 loadmodel->animscenes[i].framerate = 10;
2675 // load the poses from the animkeys
2676 for (index = 0;index < numanimkeys;index++)
2678 pskanimkeys_t *k = animkeys + index;
2680 Matrix4x4_FromOriginQuat(&matrix, k->origin[0], k->origin[1], k->origin[2], k->quat[0], k->quat[1], k->quat[2], k->quat[3]);
2681 Matrix4x4_ToArray12FloatD3D(&matrix, loadmodel->data_poses + index*12);
2683 Mod_FreeSkinFiles(skinfiles);
2684 Mem_Free(animfilebuffer);
2686 // compute all the mesh information that was not loaded from the file
2687 // TODO: honor smoothing groups somehow?
2688 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2689 Mod_BuildBaseBonePoses();
2690 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2691 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);
2692 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2693 Mod_Alias_CalculateBoundingBox();
2695 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;