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 || loadmodel->animscenes[0].framecount > 1;
1537 void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer, void *bufferend)
1539 zymtype1header_t *pinmodel, *pheader;
1540 unsigned char *pbase;
1541 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1542 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose;
1543 zymvertex_t *verts, *vertdata;
1547 skinfile_t *skinfiles;
1548 unsigned char *data;
1549 msurface_t *surface;
1551 pinmodel = (zymtype1header_t *)buffer;
1552 pbase = (unsigned char *)buffer;
1553 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1554 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1555 if (BigLong(pinmodel->type) != 1)
1556 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1558 loadmodel->modeldatatypestring = "ZYM";
1560 loadmodel->type = mod_alias;
1561 loadmodel->synctype = ST_RAND;
1565 pheader->type = BigLong(pinmodel->type);
1566 pheader->filesize = BigLong(pinmodel->filesize);
1567 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1568 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1569 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1570 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1571 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1572 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1573 pheader->radius = BigFloat(pinmodel->radius);
1574 pheader->numverts = BigLong(pinmodel->numverts);
1575 pheader->numtris = BigLong(pinmodel->numtris);
1576 pheader->numshaders = BigLong(pinmodel->numshaders);
1577 pheader->numbones = BigLong(pinmodel->numbones);
1578 pheader->numscenes = BigLong(pinmodel->numscenes);
1579 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1580 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1581 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1582 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1583 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1584 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1585 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1586 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1587 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1588 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1589 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1590 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1591 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1592 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1593 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1594 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1595 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1596 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1598 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1600 Con_Printf("%s has no geometry\n", loadmodel->name);
1603 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1605 Con_Printf("%s has no animations\n", loadmodel->name);
1609 loadmodel->DrawSky = NULL;
1610 loadmodel->DrawAddWaterPlanes = NULL;
1611 loadmodel->Draw = R_Q1BSP_Draw;
1612 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1613 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1614 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1615 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1616 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1617 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1618 loadmodel->PointSuperContents = NULL;
1620 loadmodel->numframes = pheader->numscenes;
1621 loadmodel->num_surfaces = pheader->numshaders;
1623 skinfiles = Mod_LoadSkinFiles();
1624 if (loadmodel->numskins < 1)
1625 loadmodel->numskins = 1;
1627 // make skinscenes for the skins (no groups)
1628 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1629 for (i = 0;i < loadmodel->numskins;i++)
1631 loadmodel->skinscenes[i].firstframe = i;
1632 loadmodel->skinscenes[i].framecount = 1;
1633 loadmodel->skinscenes[i].loop = true;
1634 loadmodel->skinscenes[i].framerate = 10;
1638 modelradius = pheader->radius;
1639 for (i = 0;i < 3;i++)
1641 loadmodel->normalmins[i] = pheader->mins[i];
1642 loadmodel->normalmaxs[i] = pheader->maxs[i];
1643 loadmodel->rotatedmins[i] = -modelradius;
1644 loadmodel->rotatedmaxs[i] = modelradius;
1646 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1647 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1648 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1649 if (loadmodel->yawmaxs[0] > modelradius)
1650 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1651 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1652 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1653 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1654 loadmodel->radius = modelradius;
1655 loadmodel->radius2 = modelradius * modelradius;
1657 // go through the lumps, swapping things
1659 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1660 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1661 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1662 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1663 for (i = 0;i < pheader->numscenes;i++)
1665 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1666 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1667 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1668 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1669 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1670 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1671 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1672 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1673 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1674 if (loadmodel->animscenes[i].framerate < 0)
1675 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1679 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1680 loadmodel->num_bones = pheader->numbones;
1681 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, pheader->numbones * sizeof(aliasbone_t));
1682 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1683 for (i = 0;i < pheader->numbones;i++)
1685 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1686 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1687 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1688 if (loadmodel->data_bones[i].parent >= i)
1689 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1692 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1693 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1694 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1695 for (i = 0;i < pheader->numverts;i++)
1697 vertbonecounts[i] = BigLong(bonecount[i]);
1698 if (vertbonecounts[i] != 1)
1699 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1702 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]);
1704 meshvertices = pheader->numverts;
1705 meshtriangles = pheader->numtris;
1707 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1708 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1709 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1710 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]));
1711 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1712 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1713 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1714 loadmodel->surfmesh.num_vertices = meshvertices;
1715 loadmodel->surfmesh.num_triangles = meshtriangles;
1716 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1717 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1718 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1719 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1720 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1721 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1722 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1723 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1724 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1725 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
1726 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1728 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1729 poses = (float *) (pheader->lump_poses.start + pbase);
1730 for (i = 0;i < pheader->lump_poses.length / 4;i++)
1731 loadmodel->data_poses[i] = BigFloat(poses[i]);
1733 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1734 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1735 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1736 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1737 // (converting from weight-blending skeletal animation to
1738 // deformation-based skeletal animation)
1739 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1740 for (i = 0;i < loadmodel->num_bones;i++)
1742 const float *m = loadmodel->data_poses + i * 12;
1743 if (loadmodel->data_bones[i].parent >= 0)
1744 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1746 for (k = 0;k < 12;k++)
1747 bonepose[12*i+k] = m[k];
1749 for (j = 0;j < pheader->numverts;j++)
1751 // this format really should have had a per vertexweight weight value...
1752 // but since it does not, the weighting is completely ignored and
1753 // only one weight is allowed per vertex
1754 int boneindex = BigLong(vertdata[j].bonenum);
1755 const float *m = bonepose + 12 * boneindex;
1756 float relativeorigin[3];
1757 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1758 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1759 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1760 // transform the vertex bone weight into the base mesh
1761 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1762 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1763 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1764 // store the weight as the primary weight on this vertex
1765 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
1766 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = 1;
1769 // normals and tangents are calculated after elements are loaded
1771 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1772 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1773 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1774 for (i = 0;i < pheader->numverts;i++)
1776 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1777 // flip T coordinate for OpenGL
1778 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1781 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1782 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1783 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1785 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1786 //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)
1787 // byteswap, validate, and swap winding order of tris
1788 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1789 if (pheader->lump_render.length != count)
1790 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1791 renderlist = (int *) (pheader->lump_render.start + pbase);
1792 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1794 for (i = 0;i < loadmodel->num_surfaces;i++)
1796 int firstvertex, lastvertex;
1797 if (renderlist >= renderlistend)
1798 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1799 count = BigLong(*renderlist);renderlist++;
1800 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1801 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1803 loadmodel->surfacelist[i] = i;
1804 surface = loadmodel->data_surfaces + i;
1805 surface->texture = loadmodel->data_textures + i;
1806 surface->num_firsttriangle = meshtriangles;
1807 surface->num_triangles = count;
1808 meshtriangles += surface->num_triangles;
1810 // load the elements
1811 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
1812 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
1814 outelements[j*3+2] = BigLong(renderlist[0]);
1815 outelements[j*3+1] = BigLong(renderlist[1]);
1816 outelements[j*3+0] = BigLong(renderlist[2]);
1818 // validate the elements and find the used vertex range
1819 firstvertex = meshvertices;
1821 for (j = 0;j < surface->num_triangles * 3;j++)
1823 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
1824 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
1825 firstvertex = min(firstvertex, outelements[j]);
1826 lastvertex = max(lastvertex, outelements[j]);
1828 surface->num_firstvertex = firstvertex;
1829 surface->num_vertices = lastvertex + 1 - firstvertex;
1831 // since zym models do not have named sections, reuse their shader
1832 // name as the section name
1833 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
1835 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
1837 for (j = 0;j < loadmodel->numskins;j++)
1838 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i + j * loadmodel->num_surfaces, NULL);
1840 Mod_FreeSkinFiles(skinfiles);
1841 Mem_Free(vertbonecounts);
1844 // compute all the mesh information that was not loaded from the file
1845 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
1846 Mod_BuildBaseBonePoses();
1847 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
1848 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);
1849 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1851 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1854 void Mod_DARKPLACESMODEL_Load(model_t *mod, void *buffer, void *bufferend)
1856 dpmheader_t *pheader;
1860 unsigned char *pbase;
1861 int i, j, k, meshvertices, meshtriangles;
1862 skinfile_t *skinfiles;
1863 unsigned char *data;
1866 pheader = (dpmheader_t *)buffer;
1867 pbase = (unsigned char *)buffer;
1868 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
1869 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
1870 if (BigLong(pheader->type) != 2)
1871 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1873 loadmodel->modeldatatypestring = "DPM";
1875 loadmodel->type = mod_alias;
1876 loadmodel->synctype = ST_RAND;
1879 pheader->type = BigLong(pheader->type);
1880 pheader->filesize = BigLong(pheader->filesize);
1881 pheader->mins[0] = BigFloat(pheader->mins[0]);
1882 pheader->mins[1] = BigFloat(pheader->mins[1]);
1883 pheader->mins[2] = BigFloat(pheader->mins[2]);
1884 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
1885 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
1886 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
1887 pheader->yawradius = BigFloat(pheader->yawradius);
1888 pheader->allradius = BigFloat(pheader->allradius);
1889 pheader->num_bones = BigLong(pheader->num_bones);
1890 pheader->num_meshs = BigLong(pheader->num_meshs);
1891 pheader->num_frames = BigLong(pheader->num_frames);
1892 pheader->ofs_bones = BigLong(pheader->ofs_bones);
1893 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
1894 pheader->ofs_frames = BigLong(pheader->ofs_frames);
1896 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
1898 Con_Printf("%s has no geometry\n", loadmodel->name);
1901 if (pheader->num_frames < 1)
1903 Con_Printf("%s has no frames\n", loadmodel->name);
1907 loadmodel->DrawSky = NULL;
1908 loadmodel->DrawAddWaterPlanes = NULL;
1909 loadmodel->Draw = R_Q1BSP_Draw;
1910 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1911 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1912 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1913 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1914 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1915 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1916 loadmodel->PointSuperContents = NULL;
1919 for (i = 0;i < 3;i++)
1921 loadmodel->normalmins[i] = pheader->mins[i];
1922 loadmodel->normalmaxs[i] = pheader->maxs[i];
1923 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
1924 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
1925 loadmodel->rotatedmins[i] = -pheader->allradius;
1926 loadmodel->rotatedmaxs[i] = pheader->allradius;
1928 loadmodel->radius = pheader->allradius;
1929 loadmodel->radius2 = pheader->allradius * pheader->allradius;
1931 // load external .skin files if present
1932 skinfiles = Mod_LoadSkinFiles();
1933 if (loadmodel->numskins < 1)
1934 loadmodel->numskins = 1;
1939 // gather combined statistics from the meshes
1940 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
1941 for (i = 0;i < (int)pheader->num_meshs;i++)
1943 int numverts = BigLong(dpmmesh->num_verts);
1944 meshvertices += numverts;;
1945 meshtriangles += BigLong(dpmmesh->num_tris);
1949 loadmodel->numframes = pheader->num_frames;
1950 loadmodel->num_bones = pheader->num_bones;
1951 loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
1952 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
1953 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1954 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1955 // do most allocations as one merged chunk
1956 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));
1957 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1958 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1959 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1960 loadmodel->surfmesh.num_vertices = meshvertices;
1961 loadmodel->surfmesh.num_triangles = meshtriangles;
1962 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1963 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1964 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1965 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1966 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1967 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1968 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1969 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1970 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1971 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
1972 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1973 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
1974 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
1975 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1977 for (i = 0;i < loadmodel->numskins;i++)
1979 loadmodel->skinscenes[i].firstframe = i;
1980 loadmodel->skinscenes[i].framecount = 1;
1981 loadmodel->skinscenes[i].loop = true;
1982 loadmodel->skinscenes[i].framerate = 10;
1985 // load the bone info
1986 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
1987 for (i = 0;i < loadmodel->num_bones;i++)
1989 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1990 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1991 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1992 if (loadmodel->data_bones[i].parent >= i)
1993 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1997 frame = (dpmframe_t *) (pbase + pheader->ofs_frames);
1998 for (i = 0;i < loadmodel->numframes;i++)
2001 memcpy(loadmodel->animscenes[i].name, frame->name, sizeof(frame->name));
2002 loadmodel->animscenes[i].firstframe = i;
2003 loadmodel->animscenes[i].framecount = 1;
2004 loadmodel->animscenes[i].loop = true;
2005 loadmodel->animscenes[i].framerate = 10;
2006 // load the bone poses for this frame
2007 poses = (float *) (pbase + BigLong(frame->ofs_bonepositions));
2008 for (j = 0;j < loadmodel->num_bones*12;j++)
2009 loadmodel->data_poses[i * loadmodel->num_bones*12 + j] = BigFloat(poses[j]);
2010 // stuff not processed here: mins, maxs, yawradius, allradius
2014 // load the meshes now
2015 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2018 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2019 // (converting from weight-blending skeletal animation to
2020 // deformation-based skeletal animation)
2021 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2022 for (i = 0;i < loadmodel->num_bones;i++)
2024 const float *m = loadmodel->data_poses + i * 12;
2025 if (loadmodel->data_bones[i].parent >= 0)
2026 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2028 for (k = 0;k < 12;k++)
2029 bonepose[12*i+k] = m[k];
2031 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2033 const int *inelements;
2035 const float *intexcoord;
2036 msurface_t *surface;
2038 loadmodel->surfacelist[i] = i;
2039 surface = loadmodel->data_surfaces + i;
2040 surface->texture = loadmodel->data_textures + i;
2041 surface->num_firsttriangle = meshtriangles;
2042 surface->num_triangles = BigLong(dpmmesh->num_tris);
2043 surface->num_firstvertex = meshvertices;
2044 surface->num_vertices = BigLong(dpmmesh->num_verts);
2045 meshvertices += surface->num_vertices;
2046 meshtriangles += surface->num_triangles;
2048 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2049 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2050 for (j = 0;j < surface->num_triangles;j++)
2052 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2053 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2054 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2055 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2060 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2061 for (j = 0;j < surface->num_vertices*2;j++)
2062 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2064 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2065 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2069 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2070 data += sizeof(dpmvertex_t);
2071 for (k = 0;k < numweights;k++)
2073 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2074 int boneindex = BigLong(vert->bonenum);
2075 const float *m = bonepose + 12 * boneindex;
2076 float influence = BigFloat(vert->influence);
2077 float relativeorigin[3], relativenormal[3];
2078 relativeorigin[0] = BigFloat(vert->origin[0]);
2079 relativeorigin[1] = BigFloat(vert->origin[1]);
2080 relativeorigin[2] = BigFloat(vert->origin[2]);
2081 relativenormal[0] = BigFloat(vert->normal[0]);
2082 relativenormal[1] = BigFloat(vert->normal[1]);
2083 relativenormal[2] = BigFloat(vert->normal[2]);
2084 // blend the vertex bone weights into the base mesh
2085 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2086 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2087 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2088 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2089 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2090 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2093 // store the first (and often only) weight
2094 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = influence;
2095 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
2099 // sort the new weight into this vertex's weight table
2100 // (which only accepts up to 4 bones per vertex)
2101 for (l = 0;l < 4;l++)
2103 if (loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] < influence)
2105 // move weaker influence weights out of the way first
2107 for (l2 = 3;l2 > l;l2--)
2109 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2-1];
2110 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2-1];
2112 // store the new weight
2113 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] = influence;
2114 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l] = boneindex;
2119 data += sizeof(dpmbonevert_t);
2122 for (l = 0;l < 4;l++)
2123 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l];
2124 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2126 float f = 1.0f / sum;
2127 for (l = 0;l < 4;l++)
2128 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] *= f;
2132 // since dpm models do not have named sections, reuse their shader name as the section name
2133 if (dpmmesh->shadername[0])
2134 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2136 for (j = 0;j < loadmodel->numskins;j++)
2137 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i + j * loadmodel->num_surfaces, NULL);
2139 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2142 Mod_FreeSkinFiles(skinfiles);
2144 // compute all the mesh information that was not loaded from the file
2145 Mod_BuildBaseBonePoses();
2146 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);
2147 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2149 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2152 // no idea why PSK/PSA files contain weird quaternions but they do...
2153 #define PSKQUATNEGATIONS
2154 void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend)
2156 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2157 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2158 fs_offset_t filesize;
2163 pskboneinfo_t *bones;
2164 pskrawweights_t *rawweights;
2165 pskboneinfo_t *animbones;
2166 pskaniminfo_t *anims;
2167 pskanimkeys_t *animkeys;
2168 void *animfilebuffer, *animbuffer, *animbufferend;
2169 unsigned char *data;
2171 skinfile_t *skinfiles;
2172 char animname[MAX_QPATH];
2174 pchunk = (pskchunk_t *)buffer;
2175 if (strcmp(pchunk->id, "ACTRHEAD"))
2176 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2178 loadmodel->modeldatatypestring = "PSK";
2180 loadmodel->type = mod_alias;
2181 loadmodel->DrawSky = NULL;
2182 loadmodel->DrawAddWaterPlanes = NULL;
2183 loadmodel->Draw = R_Q1BSP_Draw;
2184 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2185 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2186 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2187 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2188 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2189 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2190 loadmodel->PointSuperContents = NULL;
2191 loadmodel->synctype = ST_RAND;
2193 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2194 strlcat(animname, ".psa", sizeof(animname));
2195 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2196 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2197 if (animbuffer == NULL)
2198 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2217 while (buffer < bufferend)
2219 pchunk = (pskchunk_t *)buffer;
2220 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2221 version = LittleLong(pchunk->version);
2222 recordsize = LittleLong(pchunk->recordsize);
2223 numrecords = LittleLong(pchunk->numrecords);
2224 if (developer.integer >= 100)
2225 Con_Printf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2226 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2227 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);
2228 if (!strcmp(pchunk->id, "ACTRHEAD"))
2232 else if (!strcmp(pchunk->id, "PNTS0000"))
2235 if (recordsize != sizeof(*p))
2236 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2237 // byteswap in place and keep the pointer
2238 numpnts = numrecords;
2239 pnts = (pskpnts_t *)buffer;
2240 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2242 p->origin[0] = LittleFloat(p->origin[0]);
2243 p->origin[1] = LittleFloat(p->origin[1]);
2244 p->origin[2] = LittleFloat(p->origin[2]);
2248 else if (!strcmp(pchunk->id, "VTXW0000"))
2251 if (recordsize != sizeof(*p))
2252 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2253 // byteswap in place and keep the pointer
2254 numvtxw = numrecords;
2255 vtxw = (pskvtxw_t *)buffer;
2256 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2258 p->pntsindex = LittleShort(p->pntsindex);
2259 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2260 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2261 if (p->pntsindex >= numpnts)
2263 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2269 else if (!strcmp(pchunk->id, "FACE0000"))
2272 if (recordsize != sizeof(*p))
2273 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2274 // byteswap in place and keep the pointer
2275 numfaces = numrecords;
2276 faces = (pskface_t *)buffer;
2277 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2279 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2280 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2281 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2282 p->group = LittleLong(p->group);
2283 if (p->vtxwindex[0] >= numvtxw)
2285 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2286 p->vtxwindex[0] = 0;
2288 if (p->vtxwindex[1] >= numvtxw)
2290 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2291 p->vtxwindex[1] = 0;
2293 if (p->vtxwindex[2] >= numvtxw)
2295 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2296 p->vtxwindex[2] = 0;
2301 else if (!strcmp(pchunk->id, "MATT0000"))
2304 if (recordsize != sizeof(*p))
2305 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2306 // byteswap in place and keep the pointer
2307 nummatts = numrecords;
2308 matts = (pskmatt_t *)buffer;
2309 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2315 else if (!strcmp(pchunk->id, "REFSKELT"))
2318 if (recordsize != sizeof(*p))
2319 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2320 // byteswap in place and keep the pointer
2321 numbones = numrecords;
2322 bones = (pskboneinfo_t *)buffer;
2323 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2325 p->numchildren = LittleLong(p->numchildren);
2326 p->parent = LittleLong(p->parent);
2327 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2328 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2329 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2330 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2331 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2332 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2333 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2334 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2335 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2336 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2337 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2338 #ifdef PSKQUATNEGATIONS
2341 p->basepose.quat[0] *= -1;
2342 p->basepose.quat[1] *= -1;
2343 p->basepose.quat[2] *= -1;
2347 p->basepose.quat[0] *= 1;
2348 p->basepose.quat[1] *= -1;
2349 p->basepose.quat[2] *= 1;
2352 if (p->parent < 0 || p->parent >= numbones)
2354 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2360 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2363 if (recordsize != sizeof(*p))
2364 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2365 // byteswap in place and keep the pointer
2366 numrawweights = numrecords;
2367 rawweights = (pskrawweights_t *)buffer;
2368 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2370 p->weight = LittleFloat(p->weight);
2371 p->pntsindex = LittleLong(p->pntsindex);
2372 p->boneindex = LittleLong(p->boneindex);
2373 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2375 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2378 if (p->boneindex < 0 || p->boneindex >= numbones)
2380 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2388 while (animbuffer < animbufferend)
2390 pchunk = (pskchunk_t *)animbuffer;
2391 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2392 version = LittleLong(pchunk->version);
2393 recordsize = LittleLong(pchunk->recordsize);
2394 numrecords = LittleLong(pchunk->numrecords);
2395 if (developer.integer >= 100)
2396 Con_Printf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2397 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2398 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);
2399 if (!strcmp(pchunk->id, "ANIMHEAD"))
2403 else if (!strcmp(pchunk->id, "BONENAMES"))
2406 if (recordsize != sizeof(*p))
2407 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2408 // byteswap in place and keep the pointer
2409 numanimbones = numrecords;
2410 animbones = (pskboneinfo_t *)animbuffer;
2411 // NOTE: supposedly psa does not need to match the psk model, the
2412 // bones missing from the psa would simply use their base
2413 // positions from the psk, but this is hard for me to implement
2414 // and people can easily make animations that match.
2415 if (numanimbones != numbones)
2416 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2417 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2419 p->numchildren = LittleLong(p->numchildren);
2420 p->parent = LittleLong(p->parent);
2421 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2422 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2423 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2424 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2425 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2426 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2427 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2428 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2429 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2430 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2431 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2432 #ifdef PSKQUATNEGATIONS
2435 p->basepose.quat[0] *= -1;
2436 p->basepose.quat[1] *= -1;
2437 p->basepose.quat[2] *= -1;
2441 p->basepose.quat[0] *= 1;
2442 p->basepose.quat[1] *= -1;
2443 p->basepose.quat[2] *= 1;
2446 if (p->parent < 0 || p->parent >= numanimbones)
2448 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2451 // check that bones are the same as in the base
2452 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2453 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2457 else if (!strcmp(pchunk->id, "ANIMINFO"))
2460 if (recordsize != sizeof(*p))
2461 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2462 // byteswap in place and keep the pointer
2463 numanims = numrecords;
2464 anims = (pskaniminfo_t *)animbuffer;
2465 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2467 p->numbones = LittleLong(p->numbones);
2468 p->playtime = LittleFloat(p->playtime);
2469 p->fps = LittleFloat(p->fps);
2470 p->firstframe = LittleLong(p->firstframe);
2471 p->numframes = LittleLong(p->numframes);
2472 if (p->numbones != numbones)
2473 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2477 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2480 if (recordsize != sizeof(*p))
2481 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2482 numanimkeys = numrecords;
2483 animkeys = (pskanimkeys_t *)animbuffer;
2484 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2486 p->origin[0] = LittleFloat(p->origin[0]);
2487 p->origin[1] = LittleFloat(p->origin[1]);
2488 p->origin[2] = LittleFloat(p->origin[2]);
2489 p->quat[0] = LittleFloat(p->quat[0]);
2490 p->quat[1] = LittleFloat(p->quat[1]);
2491 p->quat[2] = LittleFloat(p->quat[2]);
2492 p->quat[3] = LittleFloat(p->quat[3]);
2493 p->frametime = LittleFloat(p->frametime);
2494 #ifdef PSKQUATNEGATIONS
2495 if (index % numbones)
2510 // TODO: allocate bonepose stuff
2513 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2516 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2517 Host_Error("%s: missing required chunks", loadmodel->name);
2519 loadmodel->numframes = 0;
2520 for (index = 0;index < numanims;index++)
2521 loadmodel->numframes += anims[index].numframes;
2523 if (numanimkeys != numbones * loadmodel->numframes)
2524 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2526 meshvertices = numvtxw;
2527 meshtriangles = numfaces;
2529 // load external .skin files if present
2530 skinfiles = Mod_LoadSkinFiles();
2531 if (loadmodel->numskins < 1)
2532 loadmodel->numskins = 1;
2533 loadmodel->num_bones = numbones;
2534 loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
2535 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2536 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2537 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2538 // do most allocations as one merged chunk
2539 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));
2540 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2541 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2542 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2543 loadmodel->surfmesh.num_vertices = meshvertices;
2544 loadmodel->surfmesh.num_triangles = meshtriangles;
2545 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2546 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2547 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2548 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2549 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2550 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2551 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2552 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
2553 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
2554 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
2555 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2556 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2557 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2558 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2560 for (i = 0;i < loadmodel->numskins;i++)
2562 loadmodel->skinscenes[i].firstframe = i;
2563 loadmodel->skinscenes[i].framecount = 1;
2564 loadmodel->skinscenes[i].loop = true;
2565 loadmodel->skinscenes[i].framerate = 10;
2569 for (index = 0, i = 0;index < nummatts;index++)
2571 // since psk models do not have named sections, reuse their shader name as the section name
2572 if (matts[index].name[0])
2573 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2575 for (j = 0;j < loadmodel->numskins;j++)
2576 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + index + j * loadmodel->num_surfaces, NULL);
2577 loadmodel->surfacelist[index] = index;
2578 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2579 loadmodel->data_surfaces[index].num_firstvertex = 0;
2580 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2583 // copy over the vertex locations and texcoords
2584 for (index = 0;index < numvtxw;index++)
2586 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2587 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2588 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2589 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2590 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2593 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2594 for (index = 0;index < numfaces;index++)
2595 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2596 for (index = 0, i = 0;index < nummatts;index++)
2598 loadmodel->data_surfaces[index].num_firsttriangle = i;
2599 i += loadmodel->data_surfaces[index].num_triangles;
2600 loadmodel->data_surfaces[index].num_triangles = 0;
2602 for (index = 0;index < numfaces;index++)
2604 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2605 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2606 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2607 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2610 // copy over the bones
2611 for (index = 0;index < numbones;index++)
2613 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2614 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2615 if (loadmodel->data_bones[index].parent >= index)
2616 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2619 // sort the psk point weights into the vertex weight tables
2620 // (which only accept up to 4 bones per vertex)
2621 for (index = 0;index < numvtxw;index++)
2625 for (j = 0;j < numrawweights;j++)
2627 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2629 int boneindex = rawweights[j].boneindex;
2630 float influence = rawweights[j].weight;
2631 for (l = 0;l < 4;l++)
2633 if (loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] < influence)
2635 // move lower influence weights out of the way first
2637 for (l2 = 3;l2 > l;l2--)
2639 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2-1];
2640 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2-1];
2642 // store the new weight
2643 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] = influence;
2644 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l] = boneindex;
2651 for (l = 0;l < 4;l++)
2652 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l];
2653 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2655 float f = 1.0f / sum;
2656 for (l = 0;l < 4;l++)
2657 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] *= f;
2661 // set up the animscenes based on the anims
2662 for (index = 0, i = 0;index < numanims;index++)
2664 for (j = 0;j < anims[index].numframes;j++, i++)
2666 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2667 loadmodel->animscenes[i].firstframe = i;
2668 loadmodel->animscenes[i].framecount = 1;
2669 loadmodel->animscenes[i].loop = true;
2670 loadmodel->animscenes[i].framerate = 10;
2674 // load the poses from the animkeys
2675 for (index = 0;index < numanimkeys;index++)
2677 pskanimkeys_t *k = animkeys + index;
2679 Matrix4x4_FromOriginQuat(&matrix, k->origin[0], k->origin[1], k->origin[2], k->quat[0], k->quat[1], k->quat[2], k->quat[3]);
2680 Matrix4x4_ToArray12FloatD3D(&matrix, loadmodel->data_poses + index*12);
2682 Mod_FreeSkinFiles(skinfiles);
2683 Mem_Free(animfilebuffer);
2685 // compute all the mesh information that was not loaded from the file
2686 // TODO: honor smoothing groups somehow?
2687 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2688 Mod_BuildBaseBonePoses();
2689 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2690 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);
2691 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2692 Mod_Alias_CalculateBoundingBox();
2694 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;