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 (model->data_overridetagnamesforskin && skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)skin].num_overridetagnames)
435 for (i = 0;i < model->data_overridetagnamesforskin[skin].num_overridetagnames;i++)
436 if (!strcasecmp(tagname, model->data_overridetagnamesforskin[skin].data_overridetagnames[i].name))
438 if (model->num_bones)
439 for (i = 0;i < model->num_bones;i++)
440 if (!strcasecmp(tagname, model->data_bones[i].name))
443 for (i = 0;i < model->num_tags;i++)
444 if (!strcasecmp(tagname, model->data_tags[i].name))
449 static void Mod_BuildBaseBonePoses(void)
453 float *basebonepose = Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(float[12]));
454 float *in12f = loadmodel->data_poses;
455 float *out12f = basebonepose;
456 float *outinv12f = loadmodel->data_baseboneposeinverse;
457 for (i = 0;i < loadmodel->num_bones;i++, in12f += 12, out12f += 12, outinv12f += 12)
459 if (loadmodel->data_bones[i].parent >= 0)
460 R_ConcatTransforms(basebonepose + 12 * loadmodel->data_bones[i].parent, in12f, out12f);
462 for (k = 0;k < 12;k++)
463 out12f[k] = in12f[k];
467 // we only support uniform scaling, so assume the first row is enough
468 // (note the lack of sqrt here, because we're trying to undo the scaling,
469 // this means multiplying by the inverse scale twice - squaring it, which
470 // makes the sqrt a waste of time)
471 scale = 1.0 / (out12f[ 0] * out12f[ 0] + out12f[ 1] * out12f[ 1] + out12f[ 2] * out12f[ 2]);
473 // invert the rotation by transposing and multiplying by the squared
474 // recipricol of the input matrix scale as described above
475 outinv12f[ 0] = (float)(out12f[ 0] * scale);
476 outinv12f[ 1] = (float)(out12f[ 4] * scale);
477 outinv12f[ 2] = (float)(out12f[ 8] * scale);
478 outinv12f[ 4] = (float)(out12f[ 1] * scale);
479 outinv12f[ 5] = (float)(out12f[ 5] * scale);
480 outinv12f[ 6] = (float)(out12f[ 9] * scale);
481 outinv12f[ 8] = (float)(out12f[ 2] * scale);
482 outinv12f[ 9] = (float)(out12f[ 6] * scale);
483 outinv12f[10] = (float)(out12f[10] * scale);
485 // invert the translate
486 outinv12f[ 3] = -(out12f[ 3] * outinv12f[ 0] + out12f[ 7] * outinv12f[ 1] + out12f[11] * outinv12f[ 2]);
487 outinv12f[ 7] = -(out12f[ 3] * outinv12f[ 4] + out12f[ 7] * outinv12f[ 5] + out12f[11] * outinv12f[ 6]);
488 outinv12f[11] = -(out12f[ 3] * outinv12f[ 8] + out12f[ 7] * outinv12f[ 9] + out12f[11] * outinv12f[10]);
490 Mem_Free(basebonepose);
493 static void Mod_Alias_CalculateBoundingBox(void)
497 qboolean firstvertex = true;
498 float dist, yawradius, radius;
501 frameblend_t frameblend[4];
502 memset(frameblend, 0, sizeof(frameblend));
503 frameblend[0].lerp = 1;
504 vertex3f = Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
505 VectorClear(loadmodel->normalmins);
506 VectorClear(loadmodel->normalmaxs);
509 for (i = 0;i < loadmodel->numframes;i++)
511 for (j = 0, frameblend[0].frame = loadmodel->animscenes[i].firstframe;j < loadmodel->animscenes[i].framecount;j++, frameblend[0].frame++)
513 Mod_Alias_GetMesh_Vertices(loadmodel, frameblend, vertex3f, NULL, NULL, NULL);
514 for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
519 VectorCopy(v, loadmodel->normalmins);
520 VectorCopy(v, loadmodel->normalmaxs);
524 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
525 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
526 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
527 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
528 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
529 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
531 dist = v[0] * v[0] + v[1] * v[1];
532 if (yawradius < dist)
541 radius = sqrt(radius);
542 yawradius = sqrt(yawradius);
543 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
544 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
545 loadmodel->yawmins[2] = loadmodel->normalmins[2];
546 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
547 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
548 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
549 loadmodel->radius = radius;
550 loadmodel->radius2 = radius * radius;
553 static void Mod_Alias_MorphMesh_CompileFrames(void)
556 frameblend_t frameblend[4] = {{0, 1}, {0, 0}, {0, 0}, {0, 0}};
557 unsigned char *datapointer;
558 datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
559 loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
560 loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
561 loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
562 loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
563 loadmodel->surfmesh.data_morphtexvecvertex = (texvecvertex_t *)datapointer;datapointer += loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices * sizeof(texvecvertex_t);
564 // 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)
565 for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
567 frameblend[0].frame = i;
568 Mod_Alias_GetMesh_Vertices(loadmodel, frameblend, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
569 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);
570 // encode the svector and tvector in 3 byte format for permanent storage
571 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
573 VectorScale(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
574 VectorScale(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
579 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)
582 float segmentmins[3], segmentmaxs[3];
583 frameblend_t frameblend[4];
585 static int maxvertices = 0;
586 static float *vertex3f = NULL;
587 memset(trace, 0, sizeof(*trace));
589 trace->realfraction = 1;
590 trace->hitsupercontentsmask = hitsupercontentsmask;
591 memset(frameblend, 0, sizeof(frameblend));
592 frameblend[0].frame = frame;
593 frameblend[0].lerp = 1;
594 if (maxvertices < model->surfmesh.num_vertices)
598 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
599 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
601 if (VectorLength2(boxmins) + VectorLength2(boxmaxs) == 0)
604 segmentmins[0] = min(start[0], end[0]) - 1;
605 segmentmins[1] = min(start[1], end[1]) - 1;
606 segmentmins[2] = min(start[2], end[2]) - 1;
607 segmentmaxs[0] = max(start[0], end[0]) + 1;
608 segmentmaxs[1] = max(start[1], end[1]) + 1;
609 segmentmaxs[2] = max(start[2], end[2]) + 1;
610 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
612 Mod_Alias_GetMesh_Vertices(model, frameblend, vertex3f, NULL, NULL, NULL);
613 Collision_TraceLineTriangleMeshFloat(trace, start, end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, SUPERCONTENTS_SOLID, 0, surface->texture, segmentmins, segmentmaxs);
618 // box trace, performed as brush trace
619 colbrushf_t *thisbrush_start, *thisbrush_end;
620 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
621 segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
622 segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
623 segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
624 segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
625 segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
626 segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
627 VectorAdd(start, boxmins, boxstartmins);
628 VectorAdd(start, boxmaxs, boxstartmaxs);
629 VectorAdd(end, boxmins, boxendmins);
630 VectorAdd(end, boxmaxs, boxendmaxs);
631 thisbrush_start = Collision_BrushForBox(&identitymatrix, boxstartmins, boxstartmaxs, 0, 0, NULL);
632 thisbrush_end = Collision_BrushForBox(&identitymatrix, boxendmins, boxendmaxs, 0, 0, NULL);
633 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
635 if (maxvertices < model->surfmesh.num_vertices)
639 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
640 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
642 Mod_Alias_GetMesh_Vertices(model, frameblend, vertex3f, NULL, NULL, NULL);
643 Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, SUPERCONTENTS_SOLID, 0, surface->texture, segmentmins, segmentmaxs);
648 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
651 for (i = 0;i < inverts;i++)
653 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
655 j = vertremap[i]; // not onseam
658 j = vertremap[i+inverts]; // onseam
664 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
666 int i, f, pose, groupframes;
668 daliasframetype_t *pframetype;
669 daliasframe_t *pinframe;
670 daliasgroup_t *group;
671 daliasinterval_t *intervals;
674 scene = loadmodel->animscenes;
675 for (f = 0;f < loadmodel->numframes;f++)
677 pframetype = (daliasframetype_t *)datapointer;
678 datapointer += sizeof(daliasframetype_t);
679 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
681 // a single frame is still treated as a group
688 group = (daliasgroup_t *)datapointer;
689 datapointer += sizeof(daliasgroup_t);
690 groupframes = LittleLong (group->numframes);
692 // intervals (time per frame)
693 intervals = (daliasinterval_t *)datapointer;
694 datapointer += sizeof(daliasinterval_t) * groupframes;
696 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
697 if (interval < 0.01f)
699 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
704 // get scene name from first frame
705 pinframe = (daliasframe_t *)datapointer;
707 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
708 scene->firstframe = pose;
709 scene->framecount = groupframes;
710 scene->framerate = 1.0f / interval;
715 for (i = 0;i < groupframes;i++)
717 pinframe = (daliasframe_t *)datapointer;
718 datapointer += sizeof(daliasframe_t);
719 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
720 datapointer += sizeof(trivertx_t) * inverts;
726 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
728 if (cls.state == ca_dedicated)
732 skinframe = R_SkinFrame_LoadMissing();
733 memset(texture, 0, sizeof(*texture));
734 texture->currentframe = texture;
735 //texture->animated = false;
736 texture->numskinframes = 1;
737 texture->skinframerate = 1;
738 texture->skinframes[0] = skinframe;
739 texture->currentskinframe = skinframe;
740 //texture->backgroundnumskinframes = 0;
741 //texture->customblendfunc[0] = 0;
742 //texture->customblendfunc[1] = 0;
743 //texture->surfaceflags = 0;
744 //texture->supercontents = 0;
745 //texture->surfaceparms = 0;
746 //texture->textureflags = 0;
748 texture->basematerialflags = MATERIALFLAG_WALL;
749 if (texture->currentskinframe->fog)
750 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
751 texture->currentmaterialflags = texture->basematerialflags;
754 static void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, char *meshname, char *shadername)
757 skinfileitem_t *skinfileitem;
758 skinframe_t *tempskinframe;
761 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
762 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
764 memset(skin, 0, sizeof(*skin));
766 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
768 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
769 if (!strcmp(skinfileitem->name, meshname) && strcmp(skinfileitem->replacement, "common/nodraw") && strcmp(skinfileitem->replacement, "textures/common/nodraw"))
771 if (!Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, false, false, true))
773 tempskinframe = R_SkinFrame_LoadExternal(skinfileitem->replacement, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS, false);
775 if (cls.state != ca_dedicated)
776 Con_Printf("mesh \"%s\": failed to load skin #%i \"%s\"\n", meshname, i, skinfileitem->replacement);
777 Mod_BuildAliasSkinFromSkinFrame(skin, tempskinframe);
784 // don't render unmentioned meshes
785 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
786 skin->basematerialflags = skin->currentmaterialflags = 0;
792 if (!Mod_LoadTextureFromQ3Shader(skin, shadername, false, false, true))
794 tempskinframe = R_SkinFrame_LoadExternal(shadername, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS, false);
796 if (cls.state != ca_dedicated)
797 Con_Printf("Can't find texture \"%s\" for mesh \"%s\", using grey checkerboard\n", shadername, meshname);
798 Mod_BuildAliasSkinFromSkinFrame(skin, tempskinframe);
803 #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);
804 #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);
805 void Mod_IDP0_Load(model_t *mod, void *buffer, void *bufferend)
807 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
808 float scales, scalet, interval;
812 stvert_t *pinstverts;
813 dtriangle_t *pintriangles;
814 daliasskintype_t *pinskintype;
815 daliasskingroup_t *pinskingroup;
816 daliasskininterval_t *pinskinintervals;
817 daliasframetype_t *pinframetype;
818 daliasgroup_t *pinframegroup;
819 unsigned char *datapointer, *startframes, *startskins;
820 char name[MAX_QPATH];
821 skinframe_t *tempskinframe;
822 animscene_t *tempskinscenes;
823 texture_t *tempaliasskins;
825 int *vertonseam, *vertremap;
826 skinfile_t *skinfiles;
828 datapointer = (unsigned char *)buffer;
829 pinmodel = (mdl_t *)datapointer;
830 datapointer += sizeof(mdl_t);
832 version = LittleLong (pinmodel->version);
833 if (version != ALIAS_VERSION)
834 Host_Error ("%s has wrong version number (%i should be %i)",
835 loadmodel->name, version, ALIAS_VERSION);
837 loadmodel->modeldatatypestring = "MDL";
839 loadmodel->type = mod_alias;
840 loadmodel->DrawSky = NULL;
841 loadmodel->DrawAddWaterPlanes = NULL;
842 loadmodel->Draw = R_Q1BSP_Draw;
843 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
844 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
845 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
846 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
847 loadmodel->DrawLight = R_Q1BSP_DrawLight;
848 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
850 loadmodel->num_surfaces = 1;
851 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
852 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
853 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
854 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
855 loadmodel->surfacelist[0] = 0;
857 loadmodel->numskins = LittleLong(pinmodel->numskins);
858 BOUNDI(loadmodel->numskins,0,65536);
859 skinwidth = LittleLong (pinmodel->skinwidth);
860 BOUNDI(skinwidth,0,65536);
861 skinheight = LittleLong (pinmodel->skinheight);
862 BOUNDI(skinheight,0,65536);
863 numverts = LittleLong(pinmodel->numverts);
864 BOUNDI(numverts,0,65536);
865 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
866 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
867 loadmodel->numframes = LittleLong(pinmodel->numframes);
868 BOUNDI(loadmodel->numframes,0,65536);
869 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
870 BOUNDI(loadmodel->synctype,0,2);
871 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
872 i = LittleLong (pinmodel->flags);
873 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
875 for (i = 0;i < 3;i++)
877 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
878 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
881 startskins = datapointer;
883 for (i = 0;i < loadmodel->numskins;i++)
885 pinskintype = (daliasskintype_t *)datapointer;
886 datapointer += sizeof(daliasskintype_t);
887 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
891 pinskingroup = (daliasskingroup_t *)datapointer;
892 datapointer += sizeof(daliasskingroup_t);
893 groupskins = LittleLong(pinskingroup->numskins);
894 datapointer += sizeof(daliasskininterval_t) * groupskins;
897 for (j = 0;j < groupskins;j++)
899 datapointer += skinwidth * skinheight;
904 pinstverts = (stvert_t *)datapointer;
905 datapointer += sizeof(stvert_t) * numverts;
907 pintriangles = (dtriangle_t *)datapointer;
908 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
910 startframes = datapointer;
911 loadmodel->surfmesh.num_morphframes = 0;
912 for (i = 0;i < loadmodel->numframes;i++)
914 pinframetype = (daliasframetype_t *)datapointer;
915 datapointer += sizeof(daliasframetype_t);
916 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
920 pinframegroup = (daliasgroup_t *)datapointer;
921 datapointer += sizeof(daliasgroup_t);
922 groupframes = LittleLong(pinframegroup->numframes);
923 datapointer += sizeof(daliasinterval_t) * groupframes;
926 for (j = 0;j < groupframes;j++)
928 datapointer += sizeof(daliasframe_t);
929 datapointer += sizeof(trivertx_t) * numverts;
930 loadmodel->surfmesh.num_morphframes++;
934 // store texture coordinates into temporary array, they will be stored
935 // after usage is determined (triangle data)
936 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
937 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
938 vertonseam = vertremap + numverts * 2;
940 scales = 1.0 / skinwidth;
941 scalet = 1.0 / skinheight;
942 for (i = 0;i < numverts;i++)
944 vertonseam[i] = LittleLong(pinstverts[i].onseam);
945 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
946 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
947 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
948 vertst[(i+numverts)*2+1] = vertst[i*2+1];
951 // load triangle data
952 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
954 // read the triangle elements
955 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
956 for (j = 0;j < 3;j++)
957 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
958 // validate (note numverts is used because this is the original data)
959 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
960 // now butcher the elements according to vertonseam and tri->facesfront
961 // and then compact the vertex set to remove duplicates
962 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
963 if (!LittleLong(pintriangles[i].facesfront)) // backface
964 for (j = 0;j < 3;j++)
965 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
966 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
968 // (this uses vertremap to count usage to save some memory)
969 for (i = 0;i < numverts*2;i++)
971 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
972 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
973 // build remapping table and compact array
974 loadmodel->surfmesh.num_vertices = 0;
975 for (i = 0;i < numverts*2;i++)
979 vertremap[i] = loadmodel->surfmesh.num_vertices;
980 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
981 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
982 loadmodel->surfmesh.num_vertices++;
985 vertremap[i] = -1; // not used at all
987 // remap the elements to the new vertex set
988 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
989 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
990 // store the texture coordinates
991 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
992 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
994 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
995 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
999 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1000 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1001 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1002 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1003 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1004 Mod_Alias_CalculateBoundingBox();
1005 Mod_Alias_MorphMesh_CompileFrames();
1008 Mem_Free(vertremap);
1011 skinfiles = Mod_LoadSkinFiles();
1012 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1013 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1014 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1015 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1018 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1019 Mod_FreeSkinFiles(skinfiles);
1020 for (i = 0;i < loadmodel->numskins;i++)
1022 loadmodel->skinscenes[i].firstframe = i;
1023 loadmodel->skinscenes[i].framecount = 1;
1024 loadmodel->skinscenes[i].loop = true;
1025 loadmodel->skinscenes[i].framerate = 10;
1031 datapointer = startskins;
1032 for (i = 0;i < loadmodel->numskins;i++)
1034 pinskintype = (daliasskintype_t *)datapointer;
1035 datapointer += sizeof(daliasskintype_t);
1037 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1044 pinskingroup = (daliasskingroup_t *)datapointer;
1045 datapointer += sizeof(daliasskingroup_t);
1047 groupskins = LittleLong (pinskingroup->numskins);
1049 pinskinintervals = (daliasskininterval_t *)datapointer;
1050 datapointer += sizeof(daliasskininterval_t) * groupskins;
1052 interval = LittleFloat(pinskinintervals[0].interval);
1053 if (interval < 0.01f)
1055 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1060 sprintf(loadmodel->skinscenes[i].name, "skin %i", i);
1061 loadmodel->skinscenes[i].firstframe = totalskins;
1062 loadmodel->skinscenes[i].framecount = groupskins;
1063 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1064 loadmodel->skinscenes[i].loop = true;
1066 for (j = 0;j < groupskins;j++)
1069 sprintf (name, "%s_%i_%i", loadmodel->name, i, j);
1071 sprintf (name, "%s_%i", loadmodel->name, i);
1072 if (!Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, name, false, false, true))
1074 tempskinframe = R_SkinFrame_LoadExternal(name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS, false);
1076 tempskinframe = R_SkinFrame_LoadInternalQuake(name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP, true, r_fullbrights.integer, (unsigned char *)datapointer, skinwidth, skinheight);
1077 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1079 datapointer += skinwidth * skinheight;
1083 // check for skins that don't exist in the model, but do exist as external images
1084 // (this was added because yummyluv kept pestering me about support for it)
1085 // TODO: support shaders here?
1086 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)))
1088 // expand the arrays to make room
1089 tempskinscenes = loadmodel->skinscenes;
1090 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1091 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1092 Mem_Free(tempskinscenes);
1094 tempaliasskins = loadmodel->data_textures;
1095 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1096 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1097 Mem_Free(tempaliasskins);
1099 // store the info about the new skin
1100 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1101 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1102 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1103 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1104 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1105 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1107 //increase skin counts
1108 loadmodel->numskins++;
1111 // fix up the pointers since they are pointing at the old textures array
1112 // FIXME: this is a hack!
1113 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1114 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1118 surface = loadmodel->data_surfaces;
1119 surface->texture = loadmodel->data_textures;
1120 surface->num_firsttriangle = 0;
1121 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1122 surface->num_firstvertex = 0;
1123 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1125 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1128 void Mod_IDP2_Load(model_t *mod, void *buffer, void *bufferend)
1130 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1131 float iskinwidth, iskinheight;
1132 unsigned char *data;
1133 msurface_t *surface;
1135 unsigned char *base, *datapointer;
1136 md2frame_t *pinframe;
1138 md2triangle_t *intri;
1139 unsigned short *inst;
1140 struct md2verthash_s
1142 struct md2verthash_s *next;
1146 *hash, **md2verthash, *md2verthashdata;
1147 skinframe_t *tempskinframe;
1148 skinfile_t *skinfiles;
1150 pinmodel = (md2_t *)buffer;
1151 base = (unsigned char *)buffer;
1153 version = LittleLong (pinmodel->version);
1154 if (version != MD2ALIAS_VERSION)
1155 Host_Error ("%s has wrong version number (%i should be %i)",
1156 loadmodel->name, version, MD2ALIAS_VERSION);
1158 loadmodel->modeldatatypestring = "MD2";
1160 loadmodel->type = mod_alias;
1161 loadmodel->DrawSky = NULL;
1162 loadmodel->DrawAddWaterPlanes = NULL;
1163 loadmodel->Draw = R_Q1BSP_Draw;
1164 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1165 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1166 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1167 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1168 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1169 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1171 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1172 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1173 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1174 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1175 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1176 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1177 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1178 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1180 end = LittleLong(pinmodel->ofs_end);
1181 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1182 Host_Error ("%s is not a valid model", loadmodel->name);
1183 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1184 Host_Error ("%s is not a valid model", loadmodel->name);
1185 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1186 Host_Error ("%s is not a valid model", loadmodel->name);
1187 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1188 Host_Error ("%s is not a valid model", loadmodel->name);
1189 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1190 Host_Error ("%s is not a valid model", loadmodel->name);
1192 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1193 numxyz = LittleLong(pinmodel->num_xyz);
1194 numst = LittleLong(pinmodel->num_st);
1195 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1196 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1197 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1198 skinwidth = LittleLong(pinmodel->skinwidth);
1199 skinheight = LittleLong(pinmodel->skinheight);
1200 iskinwidth = 1.0f / skinwidth;
1201 iskinheight = 1.0f / skinheight;
1203 loadmodel->num_surfaces = 1;
1204 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1205 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]));
1206 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1207 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1208 loadmodel->surfacelist[0] = 0;
1209 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1210 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1211 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1212 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1214 loadmodel->synctype = ST_RAND;
1217 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1218 skinfiles = Mod_LoadSkinFiles();
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_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1225 Mod_FreeSkinFiles(skinfiles);
1227 else if (loadmodel->numskins)
1229 // skins found (most likely not a player model)
1230 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1231 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1232 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1233 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1235 if (!Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, false, false, true))
1237 tempskinframe = R_SkinFrame_LoadExternal(inskin, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS, false);
1239 Con_Printf("%s is missing skin \"%s\"\n", loadmodel->name, inskin);
1240 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i * loadmodel->num_surfaces, tempskinframe);
1246 // no skins (most likely a player model)
1247 loadmodel->numskins = 1;
1248 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1249 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1250 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1251 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1254 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1255 for (i = 0;i < loadmodel->numskins;i++)
1257 loadmodel->skinscenes[i].firstframe = i;
1258 loadmodel->skinscenes[i].framecount = 1;
1259 loadmodel->skinscenes[i].loop = true;
1260 loadmodel->skinscenes[i].framerate = 10;
1263 // load the triangles and stvert data
1264 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1265 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1266 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1267 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1268 // swap the triangle list
1269 loadmodel->surfmesh.num_vertices = 0;
1270 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1272 for (j = 0;j < 3;j++)
1274 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1275 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1278 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1283 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1286 hashindex = (xyz * 256 + st) & 65535;
1287 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1288 if (hash->xyz == xyz && hash->st == st)
1292 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1295 hash->next = md2verthash[hashindex];
1296 md2verthash[hashindex] = hash;
1298 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1302 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1303 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));
1304 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1305 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1306 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1309 hash = md2verthashdata + i;
1310 vertremap[i] = hash->xyz;
1311 sts = LittleShort(inst[hash->st*2+0]);
1312 stt = LittleShort(inst[hash->st*2+1]);
1313 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1315 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1319 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1320 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1323 Mem_Free(md2verthash);
1324 Mem_Free(md2verthashdata);
1327 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1328 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1333 pinframe = (md2frame_t *)datapointer;
1334 datapointer += sizeof(md2frame_t);
1335 // store the frame scale/translate into the appropriate array
1336 for (j = 0;j < 3;j++)
1338 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1339 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1341 // convert the vertices
1342 v = (trivertx_t *)datapointer;
1343 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1344 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1345 out[k] = v[vertremap[k]];
1346 datapointer += numxyz * sizeof(trivertx_t);
1348 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1349 loadmodel->animscenes[i].firstframe = i;
1350 loadmodel->animscenes[i].framecount = 1;
1351 loadmodel->animscenes[i].framerate = 10;
1352 loadmodel->animscenes[i].loop = true;
1355 Mem_Free(vertremap);
1357 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1358 Mod_Alias_CalculateBoundingBox();
1359 Mod_Alias_MorphMesh_CompileFrames();
1361 surface = loadmodel->data_surfaces;
1362 surface->texture = loadmodel->data_textures;
1363 surface->num_firsttriangle = 0;
1364 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1365 surface->num_firstvertex = 0;
1366 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1368 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1371 void Mod_IDP3_Load(model_t *mod, void *buffer, void *bufferend)
1373 int i, j, k, version, meshvertices, meshtriangles;
1374 unsigned char *data;
1375 msurface_t *surface;
1376 md3modelheader_t *pinmodel;
1377 md3frameinfo_t *pinframe;
1380 skinfile_t *skinfiles;
1382 pinmodel = (md3modelheader_t *)buffer;
1384 if (memcmp(pinmodel->identifier, "IDP3", 4))
1385 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1386 version = LittleLong (pinmodel->version);
1387 if (version != MD3VERSION)
1388 Host_Error ("%s has wrong version number (%i should be %i)",
1389 loadmodel->name, version, MD3VERSION);
1391 skinfiles = Mod_LoadSkinFiles();
1392 if (loadmodel->numskins < 1)
1393 loadmodel->numskins = 1;
1395 loadmodel->modeldatatypestring = "MD3";
1397 loadmodel->type = mod_alias;
1398 loadmodel->DrawSky = NULL;
1399 loadmodel->DrawAddWaterPlanes = NULL;
1400 loadmodel->Draw = R_Q1BSP_Draw;
1401 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1402 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1403 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1404 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1405 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1406 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1407 loadmodel->synctype = ST_RAND;
1408 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1409 i = LittleLong (pinmodel->flags);
1410 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1412 // set up some global info about the model
1413 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1414 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1416 // make skinscenes for the skins (no groups)
1417 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1418 for (i = 0;i < loadmodel->numskins;i++)
1420 loadmodel->skinscenes[i].firstframe = i;
1421 loadmodel->skinscenes[i].framecount = 1;
1422 loadmodel->skinscenes[i].loop = true;
1423 loadmodel->skinscenes[i].framerate = 10;
1427 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1428 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1430 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1431 loadmodel->animscenes[i].firstframe = i;
1432 loadmodel->animscenes[i].framecount = 1;
1433 loadmodel->animscenes[i].framerate = 10;
1434 loadmodel->animscenes[i].loop = true;
1438 loadmodel->num_tagframes = loadmodel->numframes;
1439 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1440 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1441 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1443 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1444 for (j = 0;j < 9;j++)
1445 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1446 for (j = 0;j < 3;j++)
1447 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1448 //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);
1454 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)))
1456 if (memcmp(pinmesh->identifier, "IDP3", 4))
1457 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1458 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1459 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1460 meshvertices += LittleLong(pinmesh->num_vertices);
1461 meshtriangles += LittleLong(pinmesh->num_triangles);
1464 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1465 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1466 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1467 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));
1468 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1469 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1470 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1471 loadmodel->surfmesh.num_vertices = meshvertices;
1472 loadmodel->surfmesh.num_triangles = meshtriangles;
1473 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1474 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1475 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1476 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1477 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1481 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)))
1483 if (memcmp(pinmesh->identifier, "IDP3", 4))
1484 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1485 loadmodel->surfacelist[i] = i;
1486 surface = loadmodel->data_surfaces + i;
1487 surface->texture = loadmodel->data_textures + i;
1488 surface->num_firsttriangle = meshtriangles;
1489 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1490 surface->num_firstvertex = meshvertices;
1491 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1492 meshvertices += surface->num_vertices;
1493 meshtriangles += surface->num_triangles;
1495 for (j = 0;j < surface->num_triangles * 3;j++)
1496 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1497 for (j = 0;j < surface->num_vertices;j++)
1499 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1500 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1502 for (j = 0;j < loadmodel->numframes;j++)
1504 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1505 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1506 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1508 out->origin[0] = LittleShort(in->origin[0]);
1509 out->origin[1] = LittleShort(in->origin[1]);
1510 out->origin[2] = LittleShort(in->origin[2]);
1511 out->pitch = in->pitch;
1516 if (LittleLong(pinmesh->num_shaders) >= 1)
1517 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name);
1519 for (j = 0;j < loadmodel->numskins;j++)
1520 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i + j * loadmodel->num_surfaces, NULL);
1522 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1524 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1525 Mod_Alias_MorphMesh_CompileFrames();
1526 Mod_Alias_CalculateBoundingBox();
1527 Mod_FreeSkinFiles(skinfiles);
1529 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1532 void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer, void *bufferend)
1534 zymtype1header_t *pinmodel, *pheader;
1535 unsigned char *pbase;
1536 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1537 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose;
1538 zymvertex_t *verts, *vertdata;
1542 skinfile_t *skinfiles;
1543 unsigned char *data;
1544 msurface_t *surface;
1546 pinmodel = (zymtype1header_t *)buffer;
1547 pbase = (unsigned char *)buffer;
1548 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1549 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1550 if (BigLong(pinmodel->type) != 1)
1551 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1553 loadmodel->modeldatatypestring = "ZYM";
1555 loadmodel->type = mod_alias;
1556 loadmodel->synctype = ST_RAND;
1560 pheader->type = BigLong(pinmodel->type);
1561 pheader->filesize = BigLong(pinmodel->filesize);
1562 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1563 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1564 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1565 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1566 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1567 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1568 pheader->radius = BigFloat(pinmodel->radius);
1569 pheader->numverts = BigLong(pinmodel->numverts);
1570 pheader->numtris = BigLong(pinmodel->numtris);
1571 pheader->numshaders = BigLong(pinmodel->numshaders);
1572 pheader->numbones = BigLong(pinmodel->numbones);
1573 pheader->numscenes = BigLong(pinmodel->numscenes);
1574 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1575 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1576 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1577 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1578 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1579 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1580 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1581 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1582 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1583 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1584 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1585 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1586 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1587 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1588 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1589 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1590 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1591 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1593 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1595 Con_Printf("%s has no geometry\n", loadmodel->name);
1598 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1600 Con_Printf("%s has no animations\n", loadmodel->name);
1604 loadmodel->DrawSky = NULL;
1605 loadmodel->DrawAddWaterPlanes = NULL;
1606 loadmodel->Draw = R_Q1BSP_Draw;
1607 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1608 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1609 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1610 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1611 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1612 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1614 loadmodel->numframes = pheader->numscenes;
1615 loadmodel->num_surfaces = pheader->numshaders;
1617 skinfiles = Mod_LoadSkinFiles();
1618 if (loadmodel->numskins < 1)
1619 loadmodel->numskins = 1;
1621 // make skinscenes for the skins (no groups)
1622 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1623 for (i = 0;i < loadmodel->numskins;i++)
1625 loadmodel->skinscenes[i].firstframe = i;
1626 loadmodel->skinscenes[i].framecount = 1;
1627 loadmodel->skinscenes[i].loop = true;
1628 loadmodel->skinscenes[i].framerate = 10;
1632 modelradius = pheader->radius;
1633 for (i = 0;i < 3;i++)
1635 loadmodel->normalmins[i] = pheader->mins[i];
1636 loadmodel->normalmaxs[i] = pheader->maxs[i];
1637 loadmodel->rotatedmins[i] = -modelradius;
1638 loadmodel->rotatedmaxs[i] = modelradius;
1640 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1641 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1642 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1643 if (loadmodel->yawmaxs[0] > modelradius)
1644 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1645 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1646 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1647 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1648 loadmodel->radius = modelradius;
1649 loadmodel->radius2 = modelradius * modelradius;
1651 // go through the lumps, swapping things
1653 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1654 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1655 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1656 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1657 for (i = 0;i < pheader->numscenes;i++)
1659 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1660 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1661 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1662 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1663 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1664 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1665 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1666 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1667 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1668 if (loadmodel->animscenes[i].framerate < 0)
1669 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1673 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1674 loadmodel->num_bones = pheader->numbones;
1675 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, pheader->numbones * sizeof(aliasbone_t));
1676 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1677 for (i = 0;i < pheader->numbones;i++)
1679 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1680 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1681 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1682 if (loadmodel->data_bones[i].parent >= i)
1683 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1686 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1687 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1688 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1689 for (i = 0;i < pheader->numverts;i++)
1691 vertbonecounts[i] = BigLong(bonecount[i]);
1692 if (vertbonecounts[i] != 1)
1693 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1696 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]);
1698 meshvertices = pheader->numverts;
1699 meshtriangles = pheader->numtris;
1701 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1702 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1703 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1704 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]));
1705 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1706 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1707 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1708 loadmodel->surfmesh.num_vertices = meshvertices;
1709 loadmodel->surfmesh.num_triangles = meshtriangles;
1710 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1711 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1712 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1713 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1714 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1715 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1716 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1717 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1718 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1719 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
1720 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1722 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1723 poses = (float *) (pheader->lump_poses.start + pbase);
1724 for (i = 0;i < pheader->lump_poses.length / 4;i++)
1725 loadmodel->data_poses[i] = BigFloat(poses[i]);
1727 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1728 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1729 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1730 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1731 // (converting from weight-blending skeletal animation to
1732 // deformation-based skeletal animation)
1733 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1734 for (i = 0;i < loadmodel->num_bones;i++)
1736 const float *m = loadmodel->data_poses + i * 12;
1737 if (loadmodel->data_bones[i].parent >= 0)
1738 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1740 for (k = 0;k < 12;k++)
1741 bonepose[12*i+k] = m[k];
1743 for (j = 0;j < pheader->numverts;j++)
1745 // this format really should have had a per vertexweight weight value...
1746 // but since it does not, the weighting is completely ignored and
1747 // only one weight is allowed per vertex
1748 int boneindex = BigLong(vertdata[j].bonenum);
1749 const float *m = bonepose + 12 * boneindex;
1750 float relativeorigin[3];
1751 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1752 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1753 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1754 // transform the vertex bone weight into the base mesh
1755 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1756 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1757 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1758 // store the weight as the primary weight on this vertex
1759 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
1760 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = 1;
1763 // normals and tangents are calculated after elements are loaded
1765 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1766 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1767 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1768 for (i = 0;i < pheader->numverts;i++)
1770 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1771 // flip T coordinate for OpenGL
1772 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1775 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1776 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1777 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1779 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1780 //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)
1781 // byteswap, validate, and swap winding order of tris
1782 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1783 if (pheader->lump_render.length != count)
1784 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1785 renderlist = (int *) (pheader->lump_render.start + pbase);
1786 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1788 for (i = 0;i < loadmodel->num_surfaces;i++)
1790 int firstvertex, lastvertex;
1791 if (renderlist >= renderlistend)
1792 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1793 count = BigLong(*renderlist);renderlist++;
1794 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1795 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1797 loadmodel->surfacelist[i] = i;
1798 surface = loadmodel->data_surfaces + i;
1799 surface->texture = loadmodel->data_textures + i;
1800 surface->num_firsttriangle = meshtriangles;
1801 surface->num_triangles = count;
1802 meshtriangles += surface->num_triangles;
1804 // load the elements
1805 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
1806 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
1808 outelements[j*3+2] = BigLong(renderlist[0]);
1809 outelements[j*3+1] = BigLong(renderlist[1]);
1810 outelements[j*3+0] = BigLong(renderlist[2]);
1812 // validate the elements and find the used vertex range
1813 firstvertex = meshvertices;
1815 for (j = 0;j < surface->num_triangles * 3;j++)
1817 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
1818 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
1819 firstvertex = min(firstvertex, outelements[j]);
1820 lastvertex = max(lastvertex, outelements[j]);
1822 surface->num_firstvertex = firstvertex;
1823 surface->num_vertices = lastvertex + 1 - firstvertex;
1825 // since zym models do not have named sections, reuse their shader
1826 // name as the section name
1827 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
1829 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
1831 for (j = 0;j < loadmodel->numskins;j++)
1832 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i + j * loadmodel->num_surfaces, NULL);
1834 Mod_FreeSkinFiles(skinfiles);
1835 Mem_Free(vertbonecounts);
1838 // compute all the mesh information that was not loaded from the file
1839 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
1840 Mod_BuildBaseBonePoses();
1841 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
1842 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);
1843 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1845 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1848 void Mod_DARKPLACESMODEL_Load(model_t *mod, void *buffer, void *bufferend)
1850 dpmheader_t *pheader;
1854 unsigned char *pbase;
1855 int i, j, k, meshvertices, meshtriangles;
1856 skinfile_t *skinfiles;
1857 unsigned char *data;
1860 pheader = (dpmheader_t *)buffer;
1861 pbase = (unsigned char *)buffer;
1862 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
1863 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
1864 if (BigLong(pheader->type) != 2)
1865 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1867 loadmodel->modeldatatypestring = "DPM";
1869 loadmodel->type = mod_alias;
1870 loadmodel->synctype = ST_RAND;
1873 pheader->type = BigLong(pheader->type);
1874 pheader->filesize = BigLong(pheader->filesize);
1875 pheader->mins[0] = BigFloat(pheader->mins[0]);
1876 pheader->mins[1] = BigFloat(pheader->mins[1]);
1877 pheader->mins[2] = BigFloat(pheader->mins[2]);
1878 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
1879 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
1880 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
1881 pheader->yawradius = BigFloat(pheader->yawradius);
1882 pheader->allradius = BigFloat(pheader->allradius);
1883 pheader->num_bones = BigLong(pheader->num_bones);
1884 pheader->num_meshs = BigLong(pheader->num_meshs);
1885 pheader->num_frames = BigLong(pheader->num_frames);
1886 pheader->ofs_bones = BigLong(pheader->ofs_bones);
1887 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
1888 pheader->ofs_frames = BigLong(pheader->ofs_frames);
1890 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
1892 Con_Printf("%s has no geometry\n", loadmodel->name);
1895 if (pheader->num_frames < 1)
1897 Con_Printf("%s has no frames\n", loadmodel->name);
1901 loadmodel->DrawSky = NULL;
1902 loadmodel->DrawAddWaterPlanes = NULL;
1903 loadmodel->Draw = R_Q1BSP_Draw;
1904 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1905 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1906 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1907 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1908 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1909 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1912 for (i = 0;i < 3;i++)
1914 loadmodel->normalmins[i] = pheader->mins[i];
1915 loadmodel->normalmaxs[i] = pheader->maxs[i];
1916 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
1917 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
1918 loadmodel->rotatedmins[i] = -pheader->allradius;
1919 loadmodel->rotatedmaxs[i] = pheader->allradius;
1921 loadmodel->radius = pheader->allradius;
1922 loadmodel->radius2 = pheader->allradius * pheader->allradius;
1924 // load external .skin files if present
1925 skinfiles = Mod_LoadSkinFiles();
1926 if (loadmodel->numskins < 1)
1927 loadmodel->numskins = 1;
1932 // gather combined statistics from the meshes
1933 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
1934 for (i = 0;i < (int)pheader->num_meshs;i++)
1936 int numverts = BigLong(dpmmesh->num_verts);
1937 meshvertices += numverts;;
1938 meshtriangles += BigLong(dpmmesh->num_tris);
1942 loadmodel->numframes = pheader->num_frames;
1943 loadmodel->num_bones = pheader->num_bones;
1944 loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
1945 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
1946 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1947 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1948 // do most allocations as one merged chunk
1949 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));
1950 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1951 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1952 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1953 loadmodel->surfmesh.num_vertices = meshvertices;
1954 loadmodel->surfmesh.num_triangles = meshtriangles;
1955 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1956 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1957 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1958 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1959 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1960 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1961 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1962 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1963 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1964 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
1965 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1966 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
1967 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
1968 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1970 for (i = 0;i < loadmodel->numskins;i++)
1972 loadmodel->skinscenes[i].firstframe = i;
1973 loadmodel->skinscenes[i].framecount = 1;
1974 loadmodel->skinscenes[i].loop = true;
1975 loadmodel->skinscenes[i].framerate = 10;
1978 // load the bone info
1979 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
1980 for (i = 0;i < loadmodel->num_bones;i++)
1982 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1983 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1984 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1985 if (loadmodel->data_bones[i].parent >= i)
1986 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1990 frame = (dpmframe_t *) (pbase + pheader->ofs_frames);
1991 for (i = 0;i < loadmodel->numframes;i++)
1994 memcpy(loadmodel->animscenes[i].name, frame->name, sizeof(frame->name));
1995 loadmodel->animscenes[i].firstframe = i;
1996 loadmodel->animscenes[i].framecount = 1;
1997 loadmodel->animscenes[i].loop = true;
1998 loadmodel->animscenes[i].framerate = 10;
1999 // load the bone poses for this frame
2000 poses = (float *) (pbase + BigLong(frame->ofs_bonepositions));
2001 for (j = 0;j < loadmodel->num_bones*12;j++)
2002 loadmodel->data_poses[i * loadmodel->num_bones*12 + j] = BigFloat(poses[j]);
2003 // stuff not processed here: mins, maxs, yawradius, allradius
2007 // load the meshes now
2008 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2011 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2012 // (converting from weight-blending skeletal animation to
2013 // deformation-based skeletal animation)
2014 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2015 for (i = 0;i < loadmodel->num_bones;i++)
2017 const float *m = loadmodel->data_poses + i * 12;
2018 if (loadmodel->data_bones[i].parent >= 0)
2019 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2021 for (k = 0;k < 12;k++)
2022 bonepose[12*i+k] = m[k];
2024 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2026 const int *inelements;
2028 const float *intexcoord;
2029 msurface_t *surface;
2031 loadmodel->surfacelist[i] = i;
2032 surface = loadmodel->data_surfaces + i;
2033 surface->texture = loadmodel->data_textures + i;
2034 surface->num_firsttriangle = meshtriangles;
2035 surface->num_triangles = BigLong(dpmmesh->num_tris);
2036 surface->num_firstvertex = meshvertices;
2037 surface->num_vertices = BigLong(dpmmesh->num_verts);
2038 meshvertices += surface->num_vertices;
2039 meshtriangles += surface->num_triangles;
2041 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2042 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2043 for (j = 0;j < surface->num_triangles;j++)
2045 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2046 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2047 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2048 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2053 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2054 for (j = 0;j < surface->num_vertices*2;j++)
2055 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2057 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2058 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2062 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2063 data += sizeof(dpmvertex_t);
2064 for (k = 0;k < numweights;k++)
2066 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2067 int boneindex = BigLong(vert->bonenum);
2068 const float *m = bonepose + 12 * boneindex;
2069 float influence = BigFloat(vert->influence);
2070 float relativeorigin[3], relativenormal[3];
2071 relativeorigin[0] = BigFloat(vert->origin[0]);
2072 relativeorigin[1] = BigFloat(vert->origin[1]);
2073 relativeorigin[2] = BigFloat(vert->origin[2]);
2074 relativenormal[0] = BigFloat(vert->normal[0]);
2075 relativenormal[1] = BigFloat(vert->normal[1]);
2076 relativenormal[2] = BigFloat(vert->normal[2]);
2077 // blend the vertex bone weights into the base mesh
2078 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2079 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2080 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2081 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2082 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2083 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2086 // store the first (and often only) weight
2087 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = influence;
2088 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
2092 // sort the new weight into this vertex's weight table
2093 // (which only accepts up to 4 bones per vertex)
2094 for (l = 0;l < 4;l++)
2096 if (loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] < influence)
2098 // move weaker influence weights out of the way first
2100 for (l2 = 3;l2 > l;l2--)
2102 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2-1];
2103 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2-1];
2105 // store the new weight
2106 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] = influence;
2107 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l] = boneindex;
2112 data += sizeof(dpmbonevert_t);
2115 for (l = 0;l < 4;l++)
2116 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l];
2117 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2119 float f = 1.0f / sum;
2120 for (l = 0;l < 4;l++)
2121 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] *= f;
2125 // since dpm models do not have named sections, reuse their shader name as the section name
2126 if (dpmmesh->shadername[0])
2127 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2129 for (j = 0;j < loadmodel->numskins;j++)
2130 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i + j * loadmodel->num_surfaces, NULL);
2132 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2135 Mod_FreeSkinFiles(skinfiles);
2137 // compute all the mesh information that was not loaded from the file
2138 Mod_BuildBaseBonePoses();
2139 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);
2140 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2142 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2145 // no idea why PSK/PSA files contain weird quaternions but they do...
2146 #define PSKQUATNEGATIONS
2147 void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend)
2149 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2150 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2151 fs_offset_t filesize;
2156 pskboneinfo_t *bones;
2157 pskrawweights_t *rawweights;
2158 pskboneinfo_t *animbones;
2159 pskaniminfo_t *anims;
2160 pskanimkeys_t *animkeys;
2161 void *animfilebuffer, *animbuffer, *animbufferend;
2162 unsigned char *data;
2164 skinfile_t *skinfiles;
2165 char animname[MAX_QPATH];
2167 pchunk = (pskchunk_t *)buffer;
2168 if (strcmp(pchunk->id, "ACTRHEAD"))
2169 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2171 loadmodel->modeldatatypestring = "PSK";
2173 loadmodel->type = mod_alias;
2174 loadmodel->DrawSky = NULL;
2175 loadmodel->DrawAddWaterPlanes = NULL;
2176 loadmodel->Draw = R_Q1BSP_Draw;
2177 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2178 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2179 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2180 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2181 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2182 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2183 loadmodel->synctype = ST_RAND;
2185 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2186 strlcat(animname, ".psa", sizeof(animname));
2187 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2188 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2189 if (animbuffer == NULL)
2190 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2209 while (buffer < bufferend)
2211 pchunk = (pskchunk_t *)buffer;
2212 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2213 version = LittleLong(pchunk->version);
2214 recordsize = LittleLong(pchunk->recordsize);
2215 numrecords = LittleLong(pchunk->numrecords);
2216 if (developer.integer >= 100)
2217 Con_Printf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2218 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2219 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);
2220 if (!strcmp(pchunk->id, "ACTRHEAD"))
2224 else if (!strcmp(pchunk->id, "PNTS0000"))
2227 if (recordsize != sizeof(*p))
2228 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2229 // byteswap in place and keep the pointer
2230 numpnts = numrecords;
2231 pnts = (pskpnts_t *)buffer;
2232 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2234 p->origin[0] = LittleFloat(p->origin[0]);
2235 p->origin[1] = LittleFloat(p->origin[1]);
2236 p->origin[2] = LittleFloat(p->origin[2]);
2240 else if (!strcmp(pchunk->id, "VTXW0000"))
2243 if (recordsize != sizeof(*p))
2244 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2245 // byteswap in place and keep the pointer
2246 numvtxw = numrecords;
2247 vtxw = (pskvtxw_t *)buffer;
2248 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2250 p->pntsindex = LittleShort(p->pntsindex);
2251 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2252 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2253 if (p->pntsindex >= numpnts)
2255 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2261 else if (!strcmp(pchunk->id, "FACE0000"))
2264 if (recordsize != sizeof(*p))
2265 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2266 // byteswap in place and keep the pointer
2267 numfaces = numrecords;
2268 faces = (pskface_t *)buffer;
2269 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2271 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2272 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2273 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2274 p->group = LittleLong(p->group);
2275 if (p->vtxwindex[0] >= numvtxw)
2277 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2278 p->vtxwindex[0] = 0;
2280 if (p->vtxwindex[1] >= numvtxw)
2282 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2283 p->vtxwindex[1] = 0;
2285 if (p->vtxwindex[2] >= numvtxw)
2287 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2288 p->vtxwindex[2] = 0;
2293 else if (!strcmp(pchunk->id, "MATT0000"))
2296 if (recordsize != sizeof(*p))
2297 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2298 // byteswap in place and keep the pointer
2299 nummatts = numrecords;
2300 matts = (pskmatt_t *)buffer;
2301 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2307 else if (!strcmp(pchunk->id, "REFSKELT"))
2310 if (recordsize != sizeof(*p))
2311 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2312 // byteswap in place and keep the pointer
2313 numbones = numrecords;
2314 bones = (pskboneinfo_t *)buffer;
2315 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2317 p->numchildren = LittleLong(p->numchildren);
2318 p->parent = LittleLong(p->parent);
2319 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2320 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2321 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2322 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2323 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2324 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2325 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2326 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2327 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2328 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2329 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2330 #ifdef PSKQUATNEGATIONS
2333 p->basepose.quat[0] *= -1;
2334 p->basepose.quat[1] *= -1;
2335 p->basepose.quat[2] *= -1;
2339 p->basepose.quat[0] *= 1;
2340 p->basepose.quat[1] *= -1;
2341 p->basepose.quat[2] *= 1;
2344 if (p->parent < 0 || p->parent >= numbones)
2346 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2352 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2355 if (recordsize != sizeof(*p))
2356 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2357 // byteswap in place and keep the pointer
2358 numrawweights = numrecords;
2359 rawweights = (pskrawweights_t *)buffer;
2360 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2362 p->weight = LittleFloat(p->weight);
2363 p->pntsindex = LittleLong(p->pntsindex);
2364 p->boneindex = LittleLong(p->boneindex);
2365 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2367 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2370 if (p->boneindex < 0 || p->boneindex >= numbones)
2372 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2380 while (animbuffer < animbufferend)
2382 pchunk = (pskchunk_t *)animbuffer;
2383 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2384 version = LittleLong(pchunk->version);
2385 recordsize = LittleLong(pchunk->recordsize);
2386 numrecords = LittleLong(pchunk->numrecords);
2387 if (developer.integer >= 100)
2388 Con_Printf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2389 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2390 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);
2391 if (!strcmp(pchunk->id, "ANIMHEAD"))
2395 else if (!strcmp(pchunk->id, "BONENAMES"))
2398 if (recordsize != sizeof(*p))
2399 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2400 // byteswap in place and keep the pointer
2401 numanimbones = numrecords;
2402 animbones = (pskboneinfo_t *)animbuffer;
2403 // NOTE: supposedly psa does not need to match the psk model, the
2404 // bones missing from the psa would simply use their base
2405 // positions from the psk, but this is hard for me to implement
2406 // and people can easily make animations that match.
2407 if (numanimbones != numbones)
2408 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2409 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2411 p->numchildren = LittleLong(p->numchildren);
2412 p->parent = LittleLong(p->parent);
2413 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2414 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2415 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2416 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2417 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2418 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2419 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2420 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2421 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2422 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2423 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2424 #ifdef PSKQUATNEGATIONS
2427 p->basepose.quat[0] *= -1;
2428 p->basepose.quat[1] *= -1;
2429 p->basepose.quat[2] *= -1;
2433 p->basepose.quat[0] *= 1;
2434 p->basepose.quat[1] *= -1;
2435 p->basepose.quat[2] *= 1;
2438 if (p->parent < 0 || p->parent >= numanimbones)
2440 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2443 // check that bones are the same as in the base
2444 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2445 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2449 else if (!strcmp(pchunk->id, "ANIMINFO"))
2452 if (recordsize != sizeof(*p))
2453 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2454 // byteswap in place and keep the pointer
2455 numanims = numrecords;
2456 anims = (pskaniminfo_t *)animbuffer;
2457 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2459 p->numbones = LittleLong(p->numbones);
2460 p->playtime = LittleFloat(p->playtime);
2461 p->fps = LittleFloat(p->fps);
2462 p->firstframe = LittleLong(p->firstframe);
2463 p->numframes = LittleLong(p->numframes);
2464 if (p->numbones != numbones)
2465 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2469 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2472 if (recordsize != sizeof(*p))
2473 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2474 numanimkeys = numrecords;
2475 animkeys = (pskanimkeys_t *)animbuffer;
2476 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2478 p->origin[0] = LittleFloat(p->origin[0]);
2479 p->origin[1] = LittleFloat(p->origin[1]);
2480 p->origin[2] = LittleFloat(p->origin[2]);
2481 p->quat[0] = LittleFloat(p->quat[0]);
2482 p->quat[1] = LittleFloat(p->quat[1]);
2483 p->quat[2] = LittleFloat(p->quat[2]);
2484 p->quat[3] = LittleFloat(p->quat[3]);
2485 p->frametime = LittleFloat(p->frametime);
2486 #ifdef PSKQUATNEGATIONS
2487 if (index % numbones)
2502 // TODO: allocate bonepose stuff
2505 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2508 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2509 Host_Error("%s: missing required chunks", loadmodel->name);
2511 loadmodel->numframes = 0;
2512 for (index = 0;index < numanims;index++)
2513 loadmodel->numframes += anims[index].numframes;
2515 if (numanimkeys != numbones * loadmodel->numframes)
2516 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2518 meshvertices = numvtxw;
2519 meshtriangles = numfaces;
2521 // load external .skin files if present
2522 skinfiles = Mod_LoadSkinFiles();
2523 if (loadmodel->numskins < 1)
2524 loadmodel->numskins = 1;
2525 loadmodel->num_bones = numbones;
2526 loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
2527 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2528 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2529 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2530 // do most allocations as one merged chunk
2531 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));
2532 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2533 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2534 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2535 loadmodel->surfmesh.num_vertices = meshvertices;
2536 loadmodel->surfmesh.num_triangles = meshtriangles;
2537 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2538 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2539 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2540 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2541 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2542 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2543 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2544 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
2545 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
2546 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
2547 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2548 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2549 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2550 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2552 for (i = 0;i < loadmodel->numskins;i++)
2554 loadmodel->skinscenes[i].firstframe = i;
2555 loadmodel->skinscenes[i].framecount = 1;
2556 loadmodel->skinscenes[i].loop = true;
2557 loadmodel->skinscenes[i].framerate = 10;
2561 for (index = 0, i = 0;index < nummatts;index++)
2563 // since psk models do not have named sections, reuse their shader name as the section name
2564 if (matts[index].name[0])
2565 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2567 for (j = 0;j < loadmodel->numskins;j++)
2568 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + index + j * loadmodel->num_surfaces, NULL);
2569 loadmodel->surfacelist[index] = index;
2570 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2571 loadmodel->data_surfaces[index].num_firstvertex = 0;
2572 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2575 // copy over the vertex locations and texcoords
2576 for (index = 0;index < numvtxw;index++)
2578 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2579 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2580 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2581 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2582 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2585 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2586 for (index = 0;index < numfaces;index++)
2587 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2588 for (index = 0, i = 0;index < nummatts;index++)
2590 loadmodel->data_surfaces[index].num_firsttriangle = i;
2591 i += loadmodel->data_surfaces[index].num_triangles;
2592 loadmodel->data_surfaces[index].num_triangles = 0;
2594 for (index = 0;index < numfaces;index++)
2596 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2597 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2598 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2599 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2602 // copy over the bones
2603 for (index = 0;index < numbones;index++)
2605 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2606 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2607 if (loadmodel->data_bones[index].parent >= index)
2608 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2611 // sort the psk point weights into the vertex weight tables
2612 // (which only accept up to 4 bones per vertex)
2613 for (index = 0;index < numvtxw;index++)
2617 for (j = 0;j < numrawweights;j++)
2619 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2621 int boneindex = rawweights[j].boneindex;
2622 float influence = rawweights[j].weight;
2623 for (l = 0;l < 4;l++)
2625 if (loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] < influence)
2627 // move lower influence weights out of the way first
2629 for (l2 = 3;l2 > l;l2--)
2631 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2-1];
2632 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2-1];
2634 // store the new weight
2635 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] = influence;
2636 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l] = boneindex;
2643 for (l = 0;l < 4;l++)
2644 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l];
2645 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2647 float f = 1.0f / sum;
2648 for (l = 0;l < 4;l++)
2649 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] *= f;
2653 // set up the animscenes based on the anims
2654 for (index = 0, i = 0;index < numanims;index++)
2656 for (j = 0;j < anims[index].numframes;j++, i++)
2658 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2659 loadmodel->animscenes[i].firstframe = i;
2660 loadmodel->animscenes[i].framecount = 1;
2661 loadmodel->animscenes[i].loop = true;
2662 loadmodel->animscenes[i].framerate = 10;
2666 // load the poses from the animkeys
2667 for (index = 0;index < numanimkeys;index++)
2669 pskanimkeys_t *k = animkeys + index;
2671 Matrix4x4_FromOriginQuat(&matrix, k->origin[0], k->origin[1], k->origin[2], k->quat[0], k->quat[1], k->quat[2], k->quat[3]);
2672 Matrix4x4_ToArray12FloatD3D(&matrix, loadmodel->data_poses + index*12);
2674 Mod_FreeSkinFiles(skinfiles);
2675 Mem_Free(animfilebuffer);
2677 // compute all the mesh information that was not loaded from the file
2678 // TODO: honor smoothing groups somehow?
2679 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2680 Mod_BuildBaseBonePoses();
2681 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2682 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);
2683 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2684 Mod_Alias_CalculateBoundingBox();
2686 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;