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;
762 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
763 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
765 memset(skin, 0, sizeof(*skin));
767 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
769 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
770 if (!strcmp(skinfileitem->name, meshname))
772 Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
778 // don't render unmentioned meshes
779 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
780 skin->basematerialflags = skin->currentmaterialflags = 0;
785 Mod_LoadTextureFromQ3Shader(skin, shadername, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
788 #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);
789 #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);
790 void Mod_IDP0_Load(model_t *mod, void *buffer, void *bufferend)
792 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
793 float scales, scalet, interval;
797 stvert_t *pinstverts;
798 dtriangle_t *pintriangles;
799 daliasskintype_t *pinskintype;
800 daliasskingroup_t *pinskingroup;
801 daliasskininterval_t *pinskinintervals;
802 daliasframetype_t *pinframetype;
803 daliasgroup_t *pinframegroup;
804 unsigned char *datapointer, *startframes, *startskins;
805 char name[MAX_QPATH];
806 skinframe_t *tempskinframe;
807 animscene_t *tempskinscenes;
808 texture_t *tempaliasskins;
810 int *vertonseam, *vertremap;
811 skinfile_t *skinfiles;
813 datapointer = (unsigned char *)buffer;
814 pinmodel = (mdl_t *)datapointer;
815 datapointer += sizeof(mdl_t);
817 version = LittleLong (pinmodel->version);
818 if (version != ALIAS_VERSION)
819 Host_Error ("%s has wrong version number (%i should be %i)",
820 loadmodel->name, version, ALIAS_VERSION);
822 loadmodel->modeldatatypestring = "MDL";
824 loadmodel->type = mod_alias;
825 loadmodel->DrawSky = NULL;
826 loadmodel->DrawAddWaterPlanes = NULL;
827 loadmodel->Draw = R_Q1BSP_Draw;
828 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
829 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
830 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
831 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
832 loadmodel->DrawLight = R_Q1BSP_DrawLight;
833 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
834 loadmodel->PointSuperContents = NULL;
836 loadmodel->num_surfaces = 1;
837 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
838 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
839 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
840 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
841 loadmodel->surfacelist[0] = 0;
843 loadmodel->numskins = LittleLong(pinmodel->numskins);
844 BOUNDI(loadmodel->numskins,0,65536);
845 skinwidth = LittleLong (pinmodel->skinwidth);
846 BOUNDI(skinwidth,0,65536);
847 skinheight = LittleLong (pinmodel->skinheight);
848 BOUNDI(skinheight,0,65536);
849 numverts = LittleLong(pinmodel->numverts);
850 BOUNDI(numverts,0,65536);
851 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
852 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
853 loadmodel->numframes = LittleLong(pinmodel->numframes);
854 BOUNDI(loadmodel->numframes,0,65536);
855 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
856 BOUNDI(loadmodel->synctype,0,2);
857 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
858 i = LittleLong (pinmodel->flags);
859 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
861 for (i = 0;i < 3;i++)
863 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
864 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
867 startskins = datapointer;
869 for (i = 0;i < loadmodel->numskins;i++)
871 pinskintype = (daliasskintype_t *)datapointer;
872 datapointer += sizeof(daliasskintype_t);
873 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
877 pinskingroup = (daliasskingroup_t *)datapointer;
878 datapointer += sizeof(daliasskingroup_t);
879 groupskins = LittleLong(pinskingroup->numskins);
880 datapointer += sizeof(daliasskininterval_t) * groupskins;
883 for (j = 0;j < groupskins;j++)
885 datapointer += skinwidth * skinheight;
890 pinstverts = (stvert_t *)datapointer;
891 datapointer += sizeof(stvert_t) * numverts;
893 pintriangles = (dtriangle_t *)datapointer;
894 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
896 startframes = datapointer;
897 loadmodel->surfmesh.num_morphframes = 0;
898 for (i = 0;i < loadmodel->numframes;i++)
900 pinframetype = (daliasframetype_t *)datapointer;
901 datapointer += sizeof(daliasframetype_t);
902 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
906 pinframegroup = (daliasgroup_t *)datapointer;
907 datapointer += sizeof(daliasgroup_t);
908 groupframes = LittleLong(pinframegroup->numframes);
909 datapointer += sizeof(daliasinterval_t) * groupframes;
912 for (j = 0;j < groupframes;j++)
914 datapointer += sizeof(daliasframe_t);
915 datapointer += sizeof(trivertx_t) * numverts;
916 loadmodel->surfmesh.num_morphframes++;
920 // store texture coordinates into temporary array, they will be stored
921 // after usage is determined (triangle data)
922 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
923 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
924 vertonseam = vertremap + numverts * 2;
926 scales = 1.0 / skinwidth;
927 scalet = 1.0 / skinheight;
928 for (i = 0;i < numverts;i++)
930 vertonseam[i] = LittleLong(pinstverts[i].onseam);
931 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
932 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
933 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
934 vertst[(i+numverts)*2+1] = vertst[i*2+1];
937 // load triangle data
938 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
940 // read the triangle elements
941 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
942 for (j = 0;j < 3;j++)
943 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
944 // validate (note numverts is used because this is the original data)
945 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
946 // now butcher the elements according to vertonseam and tri->facesfront
947 // and then compact the vertex set to remove duplicates
948 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
949 if (!LittleLong(pintriangles[i].facesfront)) // backface
950 for (j = 0;j < 3;j++)
951 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
952 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
954 // (this uses vertremap to count usage to save some memory)
955 for (i = 0;i < numverts*2;i++)
957 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
958 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
959 // build remapping table and compact array
960 loadmodel->surfmesh.num_vertices = 0;
961 for (i = 0;i < numverts*2;i++)
965 vertremap[i] = loadmodel->surfmesh.num_vertices;
966 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
967 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
968 loadmodel->surfmesh.num_vertices++;
971 vertremap[i] = -1; // not used at all
973 // remap the elements to the new vertex set
974 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
975 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
976 // store the texture coordinates
977 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
978 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
980 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
981 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
985 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
986 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
987 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
988 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
989 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
990 Mod_Alias_CalculateBoundingBox();
991 Mod_Alias_MorphMesh_CompileFrames();
997 skinfiles = Mod_LoadSkinFiles();
998 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
999 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1000 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1001 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1004 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1005 Mod_FreeSkinFiles(skinfiles);
1006 for (i = 0;i < loadmodel->numskins;i++)
1008 loadmodel->skinscenes[i].firstframe = i;
1009 loadmodel->skinscenes[i].framecount = 1;
1010 loadmodel->skinscenes[i].loop = true;
1011 loadmodel->skinscenes[i].framerate = 10;
1017 datapointer = startskins;
1018 for (i = 0;i < loadmodel->numskins;i++)
1020 pinskintype = (daliasskintype_t *)datapointer;
1021 datapointer += sizeof(daliasskintype_t);
1023 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1030 pinskingroup = (daliasskingroup_t *)datapointer;
1031 datapointer += sizeof(daliasskingroup_t);
1033 groupskins = LittleLong (pinskingroup->numskins);
1035 pinskinintervals = (daliasskininterval_t *)datapointer;
1036 datapointer += sizeof(daliasskininterval_t) * groupskins;
1038 interval = LittleFloat(pinskinintervals[0].interval);
1039 if (interval < 0.01f)
1041 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1046 sprintf(loadmodel->skinscenes[i].name, "skin %i", i);
1047 loadmodel->skinscenes[i].firstframe = totalskins;
1048 loadmodel->skinscenes[i].framecount = groupskins;
1049 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1050 loadmodel->skinscenes[i].loop = true;
1052 for (j = 0;j < groupskins;j++)
1055 sprintf (name, "%s_%i_%i", loadmodel->name, i, j);
1057 sprintf (name, "%s_%i", loadmodel->name, i);
1058 if (!Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, name, false, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS))
1059 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, R_SkinFrame_LoadInternalQuake(name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP, true, r_fullbrights.integer, (unsigned char *)datapointer, skinwidth, skinheight));
1060 datapointer += skinwidth * skinheight;
1064 // check for skins that don't exist in the model, but do exist as external images
1065 // (this was added because yummyluv kept pestering me about support for it)
1066 // TODO: support shaders here?
1067 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)))
1069 // expand the arrays to make room
1070 tempskinscenes = loadmodel->skinscenes;
1071 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1072 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1073 Mem_Free(tempskinscenes);
1075 tempaliasskins = loadmodel->data_textures;
1076 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1077 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1078 Mem_Free(tempaliasskins);
1080 // store the info about the new skin
1081 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1082 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1083 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1084 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1085 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1086 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1088 //increase skin counts
1089 loadmodel->numskins++;
1092 // fix up the pointers since they are pointing at the old textures array
1093 // FIXME: this is a hack!
1094 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1095 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1099 surface = loadmodel->data_surfaces;
1100 surface->texture = loadmodel->data_textures;
1101 surface->num_firsttriangle = 0;
1102 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1103 surface->num_firstvertex = 0;
1104 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1106 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1109 void Mod_IDP2_Load(model_t *mod, void *buffer, void *bufferend)
1111 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1112 float iskinwidth, iskinheight;
1113 unsigned char *data;
1114 msurface_t *surface;
1116 unsigned char *base, *datapointer;
1117 md2frame_t *pinframe;
1119 md2triangle_t *intri;
1120 unsigned short *inst;
1121 struct md2verthash_s
1123 struct md2verthash_s *next;
1127 *hash, **md2verthash, *md2verthashdata;
1128 skinfile_t *skinfiles;
1130 pinmodel = (md2_t *)buffer;
1131 base = (unsigned char *)buffer;
1133 version = LittleLong (pinmodel->version);
1134 if (version != MD2ALIAS_VERSION)
1135 Host_Error ("%s has wrong version number (%i should be %i)",
1136 loadmodel->name, version, MD2ALIAS_VERSION);
1138 loadmodel->modeldatatypestring = "MD2";
1140 loadmodel->type = mod_alias;
1141 loadmodel->DrawSky = NULL;
1142 loadmodel->DrawAddWaterPlanes = NULL;
1143 loadmodel->Draw = R_Q1BSP_Draw;
1144 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1145 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1146 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1147 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1148 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1149 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1150 loadmodel->PointSuperContents = NULL;
1152 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1153 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1154 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1155 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1156 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1157 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1158 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1159 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1161 end = LittleLong(pinmodel->ofs_end);
1162 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1163 Host_Error ("%s is not a valid model", loadmodel->name);
1164 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1165 Host_Error ("%s is not a valid model", loadmodel->name);
1166 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1167 Host_Error ("%s is not a valid model", loadmodel->name);
1168 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1169 Host_Error ("%s is not a valid model", loadmodel->name);
1170 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1171 Host_Error ("%s is not a valid model", loadmodel->name);
1173 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1174 numxyz = LittleLong(pinmodel->num_xyz);
1175 numst = LittleLong(pinmodel->num_st);
1176 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1177 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1178 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1179 skinwidth = LittleLong(pinmodel->skinwidth);
1180 skinheight = LittleLong(pinmodel->skinheight);
1181 iskinwidth = 1.0f / skinwidth;
1182 iskinheight = 1.0f / skinheight;
1184 loadmodel->num_surfaces = 1;
1185 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1186 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]));
1187 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1188 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1189 loadmodel->surfacelist[0] = 0;
1190 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1191 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1192 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1193 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1195 loadmodel->synctype = ST_RAND;
1198 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1199 skinfiles = Mod_LoadSkinFiles();
1202 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1203 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1204 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1205 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1206 Mod_FreeSkinFiles(skinfiles);
1208 else if (loadmodel->numskins)
1210 // skins found (most likely not a player model)
1211 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1212 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1213 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1214 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1215 Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
1219 // no skins (most likely a player model)
1220 loadmodel->numskins = 1;
1221 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1222 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1223 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1224 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1227 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1228 for (i = 0;i < loadmodel->numskins;i++)
1230 loadmodel->skinscenes[i].firstframe = i;
1231 loadmodel->skinscenes[i].framecount = 1;
1232 loadmodel->skinscenes[i].loop = true;
1233 loadmodel->skinscenes[i].framerate = 10;
1236 // load the triangles and stvert data
1237 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1238 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1239 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1240 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1241 // swap the triangle list
1242 loadmodel->surfmesh.num_vertices = 0;
1243 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1245 for (j = 0;j < 3;j++)
1247 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1248 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1251 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1256 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1259 hashindex = (xyz * 256 + st) & 65535;
1260 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1261 if (hash->xyz == xyz && hash->st == st)
1265 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1268 hash->next = md2verthash[hashindex];
1269 md2verthash[hashindex] = hash;
1271 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1275 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1276 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));
1277 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1278 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1279 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1282 hash = md2verthashdata + i;
1283 vertremap[i] = hash->xyz;
1284 sts = LittleShort(inst[hash->st*2+0]);
1285 stt = LittleShort(inst[hash->st*2+1]);
1286 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1288 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1292 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1293 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1296 Mem_Free(md2verthash);
1297 Mem_Free(md2verthashdata);
1300 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1301 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1306 pinframe = (md2frame_t *)datapointer;
1307 datapointer += sizeof(md2frame_t);
1308 // store the frame scale/translate into the appropriate array
1309 for (j = 0;j < 3;j++)
1311 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1312 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1314 // convert the vertices
1315 v = (trivertx_t *)datapointer;
1316 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1317 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1318 out[k] = v[vertremap[k]];
1319 datapointer += numxyz * sizeof(trivertx_t);
1321 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1322 loadmodel->animscenes[i].firstframe = i;
1323 loadmodel->animscenes[i].framecount = 1;
1324 loadmodel->animscenes[i].framerate = 10;
1325 loadmodel->animscenes[i].loop = true;
1328 Mem_Free(vertremap);
1330 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1331 Mod_Alias_CalculateBoundingBox();
1332 Mod_Alias_MorphMesh_CompileFrames();
1334 surface = loadmodel->data_surfaces;
1335 surface->texture = loadmodel->data_textures;
1336 surface->num_firsttriangle = 0;
1337 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1338 surface->num_firstvertex = 0;
1339 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1341 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1344 void Mod_IDP3_Load(model_t *mod, void *buffer, void *bufferend)
1346 int i, j, k, version, meshvertices, meshtriangles;
1347 unsigned char *data;
1348 msurface_t *surface;
1349 md3modelheader_t *pinmodel;
1350 md3frameinfo_t *pinframe;
1353 skinfile_t *skinfiles;
1355 pinmodel = (md3modelheader_t *)buffer;
1357 if (memcmp(pinmodel->identifier, "IDP3", 4))
1358 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1359 version = LittleLong (pinmodel->version);
1360 if (version != MD3VERSION)
1361 Host_Error ("%s has wrong version number (%i should be %i)",
1362 loadmodel->name, version, MD3VERSION);
1364 skinfiles = Mod_LoadSkinFiles();
1365 if (loadmodel->numskins < 1)
1366 loadmodel->numskins = 1;
1368 loadmodel->modeldatatypestring = "MD3";
1370 loadmodel->type = mod_alias;
1371 loadmodel->DrawSky = NULL;
1372 loadmodel->DrawAddWaterPlanes = NULL;
1373 loadmodel->Draw = R_Q1BSP_Draw;
1374 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1375 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1376 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1377 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1378 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1379 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1380 loadmodel->PointSuperContents = NULL;
1381 loadmodel->synctype = ST_RAND;
1382 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1383 i = LittleLong (pinmodel->flags);
1384 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1386 // set up some global info about the model
1387 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1388 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1390 // make skinscenes for the skins (no groups)
1391 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1392 for (i = 0;i < loadmodel->numskins;i++)
1394 loadmodel->skinscenes[i].firstframe = i;
1395 loadmodel->skinscenes[i].framecount = 1;
1396 loadmodel->skinscenes[i].loop = true;
1397 loadmodel->skinscenes[i].framerate = 10;
1401 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1402 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1404 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1405 loadmodel->animscenes[i].firstframe = i;
1406 loadmodel->animscenes[i].framecount = 1;
1407 loadmodel->animscenes[i].framerate = 10;
1408 loadmodel->animscenes[i].loop = true;
1412 loadmodel->num_tagframes = loadmodel->numframes;
1413 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1414 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1415 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1417 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1418 for (j = 0;j < 9;j++)
1419 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1420 for (j = 0;j < 3;j++)
1421 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1422 //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);
1428 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)))
1430 if (memcmp(pinmesh->identifier, "IDP3", 4))
1431 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1432 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1433 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1434 meshvertices += LittleLong(pinmesh->num_vertices);
1435 meshtriangles += LittleLong(pinmesh->num_triangles);
1438 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1439 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1440 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1441 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));
1442 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1443 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1444 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1445 loadmodel->surfmesh.num_vertices = meshvertices;
1446 loadmodel->surfmesh.num_triangles = meshtriangles;
1447 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1448 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1449 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1450 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1451 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1455 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)))
1457 if (memcmp(pinmesh->identifier, "IDP3", 4))
1458 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1459 loadmodel->surfacelist[i] = i;
1460 surface = loadmodel->data_surfaces + i;
1461 surface->texture = loadmodel->data_textures + i;
1462 surface->num_firsttriangle = meshtriangles;
1463 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1464 surface->num_firstvertex = meshvertices;
1465 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1466 meshvertices += surface->num_vertices;
1467 meshtriangles += surface->num_triangles;
1469 for (j = 0;j < surface->num_triangles * 3;j++)
1470 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1471 for (j = 0;j < surface->num_vertices;j++)
1473 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1474 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1476 for (j = 0;j < loadmodel->numframes;j++)
1478 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1479 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1480 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1482 out->origin[0] = LittleShort(in->origin[0]);
1483 out->origin[1] = LittleShort(in->origin[1]);
1484 out->origin[2] = LittleShort(in->origin[2]);
1485 out->pitch = in->pitch;
1490 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1492 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1494 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1495 Mod_Alias_MorphMesh_CompileFrames();
1496 Mod_Alias_CalculateBoundingBox();
1497 Mod_FreeSkinFiles(skinfiles);
1499 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1500 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1503 void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer, void *bufferend)
1505 zymtype1header_t *pinmodel, *pheader;
1506 unsigned char *pbase;
1507 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1508 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose;
1509 zymvertex_t *verts, *vertdata;
1513 skinfile_t *skinfiles;
1514 unsigned char *data;
1515 msurface_t *surface;
1517 pinmodel = (zymtype1header_t *)buffer;
1518 pbase = (unsigned char *)buffer;
1519 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1520 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1521 if (BigLong(pinmodel->type) != 1)
1522 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1524 loadmodel->modeldatatypestring = "ZYM";
1526 loadmodel->type = mod_alias;
1527 loadmodel->synctype = ST_RAND;
1531 pheader->type = BigLong(pinmodel->type);
1532 pheader->filesize = BigLong(pinmodel->filesize);
1533 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1534 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1535 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1536 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1537 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1538 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1539 pheader->radius = BigFloat(pinmodel->radius);
1540 pheader->numverts = BigLong(pinmodel->numverts);
1541 pheader->numtris = BigLong(pinmodel->numtris);
1542 pheader->numshaders = BigLong(pinmodel->numshaders);
1543 pheader->numbones = BigLong(pinmodel->numbones);
1544 pheader->numscenes = BigLong(pinmodel->numscenes);
1545 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1546 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1547 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1548 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1549 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1550 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1551 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1552 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1553 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1554 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1555 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1556 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1557 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1558 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1559 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1560 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1561 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1562 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1564 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1566 Con_Printf("%s has no geometry\n", loadmodel->name);
1569 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1571 Con_Printf("%s has no animations\n", loadmodel->name);
1575 loadmodel->DrawSky = NULL;
1576 loadmodel->DrawAddWaterPlanes = NULL;
1577 loadmodel->Draw = R_Q1BSP_Draw;
1578 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1579 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1580 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1581 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1582 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1583 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1584 loadmodel->PointSuperContents = NULL;
1586 loadmodel->numframes = pheader->numscenes;
1587 loadmodel->num_surfaces = pheader->numshaders;
1589 skinfiles = Mod_LoadSkinFiles();
1590 if (loadmodel->numskins < 1)
1591 loadmodel->numskins = 1;
1593 // make skinscenes for the skins (no groups)
1594 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1595 for (i = 0;i < loadmodel->numskins;i++)
1597 loadmodel->skinscenes[i].firstframe = i;
1598 loadmodel->skinscenes[i].framecount = 1;
1599 loadmodel->skinscenes[i].loop = true;
1600 loadmodel->skinscenes[i].framerate = 10;
1604 modelradius = pheader->radius;
1605 for (i = 0;i < 3;i++)
1607 loadmodel->normalmins[i] = pheader->mins[i];
1608 loadmodel->normalmaxs[i] = pheader->maxs[i];
1609 loadmodel->rotatedmins[i] = -modelradius;
1610 loadmodel->rotatedmaxs[i] = modelradius;
1612 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1613 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1614 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1615 if (loadmodel->yawmaxs[0] > modelradius)
1616 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1617 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1618 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1619 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1620 loadmodel->radius = modelradius;
1621 loadmodel->radius2 = modelradius * modelradius;
1623 // go through the lumps, swapping things
1625 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1626 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1627 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1628 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1629 for (i = 0;i < pheader->numscenes;i++)
1631 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1632 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1633 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1634 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1635 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1636 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1637 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1638 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1639 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1640 if (loadmodel->animscenes[i].framerate < 0)
1641 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1645 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1646 loadmodel->num_bones = pheader->numbones;
1647 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, pheader->numbones * sizeof(aliasbone_t));
1648 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1649 for (i = 0;i < pheader->numbones;i++)
1651 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1652 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1653 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1654 if (loadmodel->data_bones[i].parent >= i)
1655 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1658 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1659 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1660 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1661 for (i = 0;i < pheader->numverts;i++)
1663 vertbonecounts[i] = BigLong(bonecount[i]);
1664 if (vertbonecounts[i] != 1)
1665 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1668 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]);
1670 meshvertices = pheader->numverts;
1671 meshtriangles = pheader->numtris;
1673 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1674 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1675 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1676 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]));
1677 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1678 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1679 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1680 loadmodel->surfmesh.num_vertices = meshvertices;
1681 loadmodel->surfmesh.num_triangles = meshtriangles;
1682 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1683 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1684 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1685 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1686 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1687 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1688 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1689 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1690 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1691 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
1692 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1694 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1695 poses = (float *) (pheader->lump_poses.start + pbase);
1696 for (i = 0;i < pheader->lump_poses.length / 4;i++)
1697 loadmodel->data_poses[i] = BigFloat(poses[i]);
1699 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1700 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1701 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1702 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1703 // (converting from weight-blending skeletal animation to
1704 // deformation-based skeletal animation)
1705 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1706 for (i = 0;i < loadmodel->num_bones;i++)
1708 const float *m = loadmodel->data_poses + i * 12;
1709 if (loadmodel->data_bones[i].parent >= 0)
1710 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1712 for (k = 0;k < 12;k++)
1713 bonepose[12*i+k] = m[k];
1715 for (j = 0;j < pheader->numverts;j++)
1717 // this format really should have had a per vertexweight weight value...
1718 // but since it does not, the weighting is completely ignored and
1719 // only one weight is allowed per vertex
1720 int boneindex = BigLong(vertdata[j].bonenum);
1721 const float *m = bonepose + 12 * boneindex;
1722 float relativeorigin[3];
1723 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1724 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1725 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1726 // transform the vertex bone weight into the base mesh
1727 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1728 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1729 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1730 // store the weight as the primary weight on this vertex
1731 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
1732 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = 1;
1735 // normals and tangents are calculated after elements are loaded
1737 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1738 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1739 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1740 for (i = 0;i < pheader->numverts;i++)
1742 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1743 // flip T coordinate for OpenGL
1744 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1747 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1748 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1749 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1751 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1752 //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)
1753 // byteswap, validate, and swap winding order of tris
1754 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1755 if (pheader->lump_render.length != count)
1756 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1757 renderlist = (int *) (pheader->lump_render.start + pbase);
1758 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1760 for (i = 0;i < loadmodel->num_surfaces;i++)
1762 int firstvertex, lastvertex;
1763 if (renderlist >= renderlistend)
1764 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1765 count = BigLong(*renderlist);renderlist++;
1766 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1767 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1769 loadmodel->surfacelist[i] = i;
1770 surface = loadmodel->data_surfaces + i;
1771 surface->texture = loadmodel->data_textures + i;
1772 surface->num_firsttriangle = meshtriangles;
1773 surface->num_triangles = count;
1774 meshtriangles += surface->num_triangles;
1776 // load the elements
1777 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
1778 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
1780 outelements[j*3+2] = BigLong(renderlist[0]);
1781 outelements[j*3+1] = BigLong(renderlist[1]);
1782 outelements[j*3+0] = BigLong(renderlist[2]);
1784 // validate the elements and find the used vertex range
1785 firstvertex = meshvertices;
1787 for (j = 0;j < surface->num_triangles * 3;j++)
1789 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
1790 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
1791 firstvertex = min(firstvertex, outelements[j]);
1792 lastvertex = max(lastvertex, outelements[j]);
1794 surface->num_firstvertex = firstvertex;
1795 surface->num_vertices = lastvertex + 1 - firstvertex;
1797 // since zym models do not have named sections, reuse their shader
1798 // name as the section name
1799 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
1800 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
1802 Mod_FreeSkinFiles(skinfiles);
1803 Mem_Free(vertbonecounts);
1806 // compute all the mesh information that was not loaded from the file
1807 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
1808 Mod_BuildBaseBonePoses();
1809 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
1810 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);
1811 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1813 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1816 void Mod_DARKPLACESMODEL_Load(model_t *mod, void *buffer, void *bufferend)
1818 dpmheader_t *pheader;
1822 unsigned char *pbase;
1823 int i, j, k, meshvertices, meshtriangles;
1824 skinfile_t *skinfiles;
1825 unsigned char *data;
1828 pheader = (dpmheader_t *)buffer;
1829 pbase = (unsigned char *)buffer;
1830 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
1831 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
1832 if (BigLong(pheader->type) != 2)
1833 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1835 loadmodel->modeldatatypestring = "DPM";
1837 loadmodel->type = mod_alias;
1838 loadmodel->synctype = ST_RAND;
1841 pheader->type = BigLong(pheader->type);
1842 pheader->filesize = BigLong(pheader->filesize);
1843 pheader->mins[0] = BigFloat(pheader->mins[0]);
1844 pheader->mins[1] = BigFloat(pheader->mins[1]);
1845 pheader->mins[2] = BigFloat(pheader->mins[2]);
1846 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
1847 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
1848 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
1849 pheader->yawradius = BigFloat(pheader->yawradius);
1850 pheader->allradius = BigFloat(pheader->allradius);
1851 pheader->num_bones = BigLong(pheader->num_bones);
1852 pheader->num_meshs = BigLong(pheader->num_meshs);
1853 pheader->num_frames = BigLong(pheader->num_frames);
1854 pheader->ofs_bones = BigLong(pheader->ofs_bones);
1855 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
1856 pheader->ofs_frames = BigLong(pheader->ofs_frames);
1858 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
1860 Con_Printf("%s has no geometry\n", loadmodel->name);
1863 if (pheader->num_frames < 1)
1865 Con_Printf("%s has no frames\n", loadmodel->name);
1869 loadmodel->DrawSky = NULL;
1870 loadmodel->DrawAddWaterPlanes = NULL;
1871 loadmodel->Draw = R_Q1BSP_Draw;
1872 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1873 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1874 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1875 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1876 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1877 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1878 loadmodel->PointSuperContents = NULL;
1881 for (i = 0;i < 3;i++)
1883 loadmodel->normalmins[i] = pheader->mins[i];
1884 loadmodel->normalmaxs[i] = pheader->maxs[i];
1885 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
1886 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
1887 loadmodel->rotatedmins[i] = -pheader->allradius;
1888 loadmodel->rotatedmaxs[i] = pheader->allradius;
1890 loadmodel->radius = pheader->allradius;
1891 loadmodel->radius2 = pheader->allradius * pheader->allradius;
1893 // load external .skin files if present
1894 skinfiles = Mod_LoadSkinFiles();
1895 if (loadmodel->numskins < 1)
1896 loadmodel->numskins = 1;
1901 // gather combined statistics from the meshes
1902 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
1903 for (i = 0;i < (int)pheader->num_meshs;i++)
1905 int numverts = BigLong(dpmmesh->num_verts);
1906 meshvertices += numverts;;
1907 meshtriangles += BigLong(dpmmesh->num_tris);
1911 loadmodel->numframes = pheader->num_frames;
1912 loadmodel->num_bones = pheader->num_bones;
1913 loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
1914 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
1915 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1916 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1917 // do most allocations as one merged chunk
1918 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));
1919 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1920 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1921 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1922 loadmodel->surfmesh.num_vertices = meshvertices;
1923 loadmodel->surfmesh.num_triangles = meshtriangles;
1924 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1925 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1926 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1927 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1928 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1929 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1930 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1931 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1932 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1933 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
1934 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1935 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
1936 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
1937 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1939 for (i = 0;i < loadmodel->numskins;i++)
1941 loadmodel->skinscenes[i].firstframe = i;
1942 loadmodel->skinscenes[i].framecount = 1;
1943 loadmodel->skinscenes[i].loop = true;
1944 loadmodel->skinscenes[i].framerate = 10;
1947 // load the bone info
1948 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
1949 for (i = 0;i < loadmodel->num_bones;i++)
1951 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1952 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1953 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1954 if (loadmodel->data_bones[i].parent >= i)
1955 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1959 frame = (dpmframe_t *) (pbase + pheader->ofs_frames);
1960 for (i = 0;i < loadmodel->numframes;i++)
1963 memcpy(loadmodel->animscenes[i].name, frame->name, sizeof(frame->name));
1964 loadmodel->animscenes[i].firstframe = i;
1965 loadmodel->animscenes[i].framecount = 1;
1966 loadmodel->animscenes[i].loop = true;
1967 loadmodel->animscenes[i].framerate = 10;
1968 // load the bone poses for this frame
1969 poses = (float *) (pbase + BigLong(frame->ofs_bonepositions));
1970 for (j = 0;j < loadmodel->num_bones*12;j++)
1971 loadmodel->data_poses[i * loadmodel->num_bones*12 + j] = BigFloat(poses[j]);
1972 // stuff not processed here: mins, maxs, yawradius, allradius
1976 // load the meshes now
1977 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
1980 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1981 // (converting from weight-blending skeletal animation to
1982 // deformation-based skeletal animation)
1983 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1984 for (i = 0;i < loadmodel->num_bones;i++)
1986 const float *m = loadmodel->data_poses + i * 12;
1987 if (loadmodel->data_bones[i].parent >= 0)
1988 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1990 for (k = 0;k < 12;k++)
1991 bonepose[12*i+k] = m[k];
1993 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
1995 const int *inelements;
1997 const float *intexcoord;
1998 msurface_t *surface;
2000 loadmodel->surfacelist[i] = i;
2001 surface = loadmodel->data_surfaces + i;
2002 surface->texture = loadmodel->data_textures + i;
2003 surface->num_firsttriangle = meshtriangles;
2004 surface->num_triangles = BigLong(dpmmesh->num_tris);
2005 surface->num_firstvertex = meshvertices;
2006 surface->num_vertices = BigLong(dpmmesh->num_verts);
2007 meshvertices += surface->num_vertices;
2008 meshtriangles += surface->num_triangles;
2010 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2011 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2012 for (j = 0;j < surface->num_triangles;j++)
2014 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2015 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2016 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2017 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2022 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2023 for (j = 0;j < surface->num_vertices*2;j++)
2024 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2026 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2027 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2031 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2032 data += sizeof(dpmvertex_t);
2033 for (k = 0;k < numweights;k++)
2035 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2036 int boneindex = BigLong(vert->bonenum);
2037 const float *m = bonepose + 12 * boneindex;
2038 float influence = BigFloat(vert->influence);
2039 float relativeorigin[3], relativenormal[3];
2040 relativeorigin[0] = BigFloat(vert->origin[0]);
2041 relativeorigin[1] = BigFloat(vert->origin[1]);
2042 relativeorigin[2] = BigFloat(vert->origin[2]);
2043 relativenormal[0] = BigFloat(vert->normal[0]);
2044 relativenormal[1] = BigFloat(vert->normal[1]);
2045 relativenormal[2] = BigFloat(vert->normal[2]);
2046 // blend the vertex bone weights into the base mesh
2047 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2048 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2049 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2050 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2051 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2052 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2055 // store the first (and often only) weight
2056 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = influence;
2057 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
2061 // sort the new weight into this vertex's weight table
2062 // (which only accepts up to 4 bones per vertex)
2063 for (l = 0;l < 4;l++)
2065 if (loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] < influence)
2067 // move weaker influence weights out of the way first
2069 for (l2 = 3;l2 > l;l2--)
2071 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2-1];
2072 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2-1];
2074 // store the new weight
2075 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] = influence;
2076 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l] = boneindex;
2081 data += sizeof(dpmbonevert_t);
2084 for (l = 0;l < 4;l++)
2085 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l];
2086 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2088 float f = 1.0f / sum;
2089 for (l = 0;l < 4;l++)
2090 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] *= f;
2094 // since dpm models do not have named sections, reuse their shader name as the section name
2095 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2097 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2100 Mod_FreeSkinFiles(skinfiles);
2102 // compute all the mesh information that was not loaded from the file
2103 Mod_BuildBaseBonePoses();
2104 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);
2105 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2107 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2110 // no idea why PSK/PSA files contain weird quaternions but they do...
2111 #define PSKQUATNEGATIONS
2112 void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend)
2114 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2115 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2116 fs_offset_t filesize;
2121 pskboneinfo_t *bones;
2122 pskrawweights_t *rawweights;
2123 pskboneinfo_t *animbones;
2124 pskaniminfo_t *anims;
2125 pskanimkeys_t *animkeys;
2126 void *animfilebuffer, *animbuffer, *animbufferend;
2127 unsigned char *data;
2129 skinfile_t *skinfiles;
2130 char animname[MAX_QPATH];
2132 pchunk = (pskchunk_t *)buffer;
2133 if (strcmp(pchunk->id, "ACTRHEAD"))
2134 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2136 loadmodel->modeldatatypestring = "PSK";
2138 loadmodel->type = mod_alias;
2139 loadmodel->DrawSky = NULL;
2140 loadmodel->DrawAddWaterPlanes = NULL;
2141 loadmodel->Draw = R_Q1BSP_Draw;
2142 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2143 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2144 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2145 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2146 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2147 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2148 loadmodel->PointSuperContents = NULL;
2149 loadmodel->synctype = ST_RAND;
2151 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2152 strlcat(animname, ".psa", sizeof(animname));
2153 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2154 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2155 if (animbuffer == NULL)
2156 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2175 while (buffer < bufferend)
2177 pchunk = (pskchunk_t *)buffer;
2178 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2179 version = LittleLong(pchunk->version);
2180 recordsize = LittleLong(pchunk->recordsize);
2181 numrecords = LittleLong(pchunk->numrecords);
2182 if (developer.integer >= 100)
2183 Con_Printf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2184 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2185 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);
2186 if (!strcmp(pchunk->id, "ACTRHEAD"))
2190 else if (!strcmp(pchunk->id, "PNTS0000"))
2193 if (recordsize != sizeof(*p))
2194 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2195 // byteswap in place and keep the pointer
2196 numpnts = numrecords;
2197 pnts = (pskpnts_t *)buffer;
2198 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2200 p->origin[0] = LittleFloat(p->origin[0]);
2201 p->origin[1] = LittleFloat(p->origin[1]);
2202 p->origin[2] = LittleFloat(p->origin[2]);
2206 else if (!strcmp(pchunk->id, "VTXW0000"))
2209 if (recordsize != sizeof(*p))
2210 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2211 // byteswap in place and keep the pointer
2212 numvtxw = numrecords;
2213 vtxw = (pskvtxw_t *)buffer;
2214 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2216 p->pntsindex = LittleShort(p->pntsindex);
2217 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2218 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2219 if (p->pntsindex >= numpnts)
2221 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2227 else if (!strcmp(pchunk->id, "FACE0000"))
2230 if (recordsize != sizeof(*p))
2231 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2232 // byteswap in place and keep the pointer
2233 numfaces = numrecords;
2234 faces = (pskface_t *)buffer;
2235 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2237 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2238 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2239 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2240 p->group = LittleLong(p->group);
2241 if (p->vtxwindex[0] >= numvtxw)
2243 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2244 p->vtxwindex[0] = 0;
2246 if (p->vtxwindex[1] >= numvtxw)
2248 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2249 p->vtxwindex[1] = 0;
2251 if (p->vtxwindex[2] >= numvtxw)
2253 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2254 p->vtxwindex[2] = 0;
2259 else if (!strcmp(pchunk->id, "MATT0000"))
2262 if (recordsize != sizeof(*p))
2263 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2264 // byteswap in place and keep the pointer
2265 nummatts = numrecords;
2266 matts = (pskmatt_t *)buffer;
2267 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2273 else if (!strcmp(pchunk->id, "REFSKELT"))
2276 if (recordsize != sizeof(*p))
2277 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2278 // byteswap in place and keep the pointer
2279 numbones = numrecords;
2280 bones = (pskboneinfo_t *)buffer;
2281 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2283 p->numchildren = LittleLong(p->numchildren);
2284 p->parent = LittleLong(p->parent);
2285 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2286 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2287 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2288 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2289 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2290 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2291 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2292 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2293 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2294 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2295 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2296 #ifdef PSKQUATNEGATIONS
2299 p->basepose.quat[0] *= -1;
2300 p->basepose.quat[1] *= -1;
2301 p->basepose.quat[2] *= -1;
2305 p->basepose.quat[0] *= 1;
2306 p->basepose.quat[1] *= -1;
2307 p->basepose.quat[2] *= 1;
2310 if (p->parent < 0 || p->parent >= numbones)
2312 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2318 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2321 if (recordsize != sizeof(*p))
2322 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2323 // byteswap in place and keep the pointer
2324 numrawweights = numrecords;
2325 rawweights = (pskrawweights_t *)buffer;
2326 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2328 p->weight = LittleFloat(p->weight);
2329 p->pntsindex = LittleLong(p->pntsindex);
2330 p->boneindex = LittleLong(p->boneindex);
2331 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2333 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2336 if (p->boneindex < 0 || p->boneindex >= numbones)
2338 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2346 while (animbuffer < animbufferend)
2348 pchunk = (pskchunk_t *)animbuffer;
2349 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2350 version = LittleLong(pchunk->version);
2351 recordsize = LittleLong(pchunk->recordsize);
2352 numrecords = LittleLong(pchunk->numrecords);
2353 if (developer.integer >= 100)
2354 Con_Printf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2355 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2356 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);
2357 if (!strcmp(pchunk->id, "ANIMHEAD"))
2361 else if (!strcmp(pchunk->id, "BONENAMES"))
2364 if (recordsize != sizeof(*p))
2365 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2366 // byteswap in place and keep the pointer
2367 numanimbones = numrecords;
2368 animbones = (pskboneinfo_t *)animbuffer;
2369 // NOTE: supposedly psa does not need to match the psk model, the
2370 // bones missing from the psa would simply use their base
2371 // positions from the psk, but this is hard for me to implement
2372 // and people can easily make animations that match.
2373 if (numanimbones != numbones)
2374 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2375 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2377 p->numchildren = LittleLong(p->numchildren);
2378 p->parent = LittleLong(p->parent);
2379 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2380 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2381 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2382 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2383 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2384 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2385 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2386 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2387 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2388 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2389 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2390 #ifdef PSKQUATNEGATIONS
2393 p->basepose.quat[0] *= -1;
2394 p->basepose.quat[1] *= -1;
2395 p->basepose.quat[2] *= -1;
2399 p->basepose.quat[0] *= 1;
2400 p->basepose.quat[1] *= -1;
2401 p->basepose.quat[2] *= 1;
2404 if (p->parent < 0 || p->parent >= numanimbones)
2406 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2409 // check that bones are the same as in the base
2410 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2411 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2415 else if (!strcmp(pchunk->id, "ANIMINFO"))
2418 if (recordsize != sizeof(*p))
2419 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2420 // byteswap in place and keep the pointer
2421 numanims = numrecords;
2422 anims = (pskaniminfo_t *)animbuffer;
2423 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2425 p->numbones = LittleLong(p->numbones);
2426 p->playtime = LittleFloat(p->playtime);
2427 p->fps = LittleFloat(p->fps);
2428 p->firstframe = LittleLong(p->firstframe);
2429 p->numframes = LittleLong(p->numframes);
2430 if (p->numbones != numbones)
2431 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2435 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2438 if (recordsize != sizeof(*p))
2439 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2440 numanimkeys = numrecords;
2441 animkeys = (pskanimkeys_t *)animbuffer;
2442 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2444 p->origin[0] = LittleFloat(p->origin[0]);
2445 p->origin[1] = LittleFloat(p->origin[1]);
2446 p->origin[2] = LittleFloat(p->origin[2]);
2447 p->quat[0] = LittleFloat(p->quat[0]);
2448 p->quat[1] = LittleFloat(p->quat[1]);
2449 p->quat[2] = LittleFloat(p->quat[2]);
2450 p->quat[3] = LittleFloat(p->quat[3]);
2451 p->frametime = LittleFloat(p->frametime);
2452 #ifdef PSKQUATNEGATIONS
2453 if (index % numbones)
2468 // TODO: allocate bonepose stuff
2471 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2474 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2475 Host_Error("%s: missing required chunks", loadmodel->name);
2477 loadmodel->numframes = 0;
2478 for (index = 0;index < numanims;index++)
2479 loadmodel->numframes += anims[index].numframes;
2481 if (numanimkeys != numbones * loadmodel->numframes)
2482 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2484 meshvertices = numvtxw;
2485 meshtriangles = numfaces;
2487 // load external .skin files if present
2488 skinfiles = Mod_LoadSkinFiles();
2489 if (loadmodel->numskins < 1)
2490 loadmodel->numskins = 1;
2491 loadmodel->num_bones = numbones;
2492 loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
2493 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2494 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2495 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2496 // do most allocations as one merged chunk
2497 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));
2498 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2499 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2500 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2501 loadmodel->surfmesh.num_vertices = meshvertices;
2502 loadmodel->surfmesh.num_triangles = meshtriangles;
2503 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2504 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2505 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2506 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2507 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2508 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2509 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2510 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
2511 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
2512 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
2513 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2514 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2515 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2516 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2518 for (i = 0;i < loadmodel->numskins;i++)
2520 loadmodel->skinscenes[i].firstframe = i;
2521 loadmodel->skinscenes[i].framecount = 1;
2522 loadmodel->skinscenes[i].loop = true;
2523 loadmodel->skinscenes[i].framerate = 10;
2527 for (index = 0, i = 0;index < nummatts;index++)
2529 // since psk models do not have named sections, reuse their shader name as the section name
2530 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2531 loadmodel->surfacelist[index] = index;
2532 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2533 loadmodel->data_surfaces[index].num_firstvertex = 0;
2534 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2537 // copy over the vertex locations and texcoords
2538 for (index = 0;index < numvtxw;index++)
2540 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2541 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2542 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2543 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2544 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2547 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2548 for (index = 0;index < numfaces;index++)
2549 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2550 for (index = 0, i = 0;index < nummatts;index++)
2552 loadmodel->data_surfaces[index].num_firsttriangle = i;
2553 i += loadmodel->data_surfaces[index].num_triangles;
2554 loadmodel->data_surfaces[index].num_triangles = 0;
2556 for (index = 0;index < numfaces;index++)
2558 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2559 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2560 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2561 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2564 // copy over the bones
2565 for (index = 0;index < numbones;index++)
2567 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2568 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2569 if (loadmodel->data_bones[index].parent >= index)
2570 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2573 // sort the psk point weights into the vertex weight tables
2574 // (which only accept up to 4 bones per vertex)
2575 for (index = 0;index < numvtxw;index++)
2579 for (j = 0;j < numrawweights;j++)
2581 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2583 int boneindex = rawweights[j].boneindex;
2584 float influence = rawweights[j].weight;
2585 for (l = 0;l < 4;l++)
2587 if (loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] < influence)
2589 // move lower influence weights out of the way first
2591 for (l2 = 3;l2 > l;l2--)
2593 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2-1];
2594 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2-1];
2596 // store the new weight
2597 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] = influence;
2598 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l] = boneindex;
2605 for (l = 0;l < 4;l++)
2606 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l];
2607 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2609 float f = 1.0f / sum;
2610 for (l = 0;l < 4;l++)
2611 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] *= f;
2615 // set up the animscenes based on the anims
2616 for (index = 0, i = 0;index < numanims;index++)
2618 for (j = 0;j < anims[index].numframes;j++, i++)
2620 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2621 loadmodel->animscenes[i].firstframe = i;
2622 loadmodel->animscenes[i].framecount = 1;
2623 loadmodel->animscenes[i].loop = true;
2624 loadmodel->animscenes[i].framerate = 10;
2628 // load the poses from the animkeys
2629 for (index = 0;index < numanimkeys;index++)
2631 pskanimkeys_t *k = animkeys + index;
2633 Matrix4x4_FromOriginQuat(&matrix, k->origin[0], k->origin[1], k->origin[2], k->quat[0], k->quat[1], k->quat[2], k->quat[3]);
2634 Matrix4x4_ToArray12FloatD3D(&matrix, loadmodel->data_poses + index*12);
2636 Mod_FreeSkinFiles(skinfiles);
2637 Mem_Free(animfilebuffer);
2639 // compute all the mesh information that was not loaded from the file
2640 // TODO: honor smoothing groups somehow?
2641 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2642 Mod_BuildBaseBonePoses();
2643 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2644 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);
2645 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2646 Mod_Alias_CalculateBoundingBox();
2648 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;