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;
849 loadmodel->PointSuperContents = NULL;
851 loadmodel->num_surfaces = 1;
852 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
853 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
854 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
855 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
856 loadmodel->surfacelist[0] = 0;
858 loadmodel->numskins = LittleLong(pinmodel->numskins);
859 BOUNDI(loadmodel->numskins,0,65536);
860 skinwidth = LittleLong (pinmodel->skinwidth);
861 BOUNDI(skinwidth,0,65536);
862 skinheight = LittleLong (pinmodel->skinheight);
863 BOUNDI(skinheight,0,65536);
864 numverts = LittleLong(pinmodel->numverts);
865 BOUNDI(numverts,0,65536);
866 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
867 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
868 loadmodel->numframes = LittleLong(pinmodel->numframes);
869 BOUNDI(loadmodel->numframes,0,65536);
870 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
871 BOUNDI(loadmodel->synctype,0,2);
872 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
873 i = LittleLong (pinmodel->flags);
874 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
876 for (i = 0;i < 3;i++)
878 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
879 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
882 startskins = datapointer;
884 for (i = 0;i < loadmodel->numskins;i++)
886 pinskintype = (daliasskintype_t *)datapointer;
887 datapointer += sizeof(daliasskintype_t);
888 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
892 pinskingroup = (daliasskingroup_t *)datapointer;
893 datapointer += sizeof(daliasskingroup_t);
894 groupskins = LittleLong(pinskingroup->numskins);
895 datapointer += sizeof(daliasskininterval_t) * groupskins;
898 for (j = 0;j < groupskins;j++)
900 datapointer += skinwidth * skinheight;
905 pinstverts = (stvert_t *)datapointer;
906 datapointer += sizeof(stvert_t) * numverts;
908 pintriangles = (dtriangle_t *)datapointer;
909 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
911 startframes = datapointer;
912 loadmodel->surfmesh.num_morphframes = 0;
913 for (i = 0;i < loadmodel->numframes;i++)
915 pinframetype = (daliasframetype_t *)datapointer;
916 datapointer += sizeof(daliasframetype_t);
917 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
921 pinframegroup = (daliasgroup_t *)datapointer;
922 datapointer += sizeof(daliasgroup_t);
923 groupframes = LittleLong(pinframegroup->numframes);
924 datapointer += sizeof(daliasinterval_t) * groupframes;
927 for (j = 0;j < groupframes;j++)
929 datapointer += sizeof(daliasframe_t);
930 datapointer += sizeof(trivertx_t) * numverts;
931 loadmodel->surfmesh.num_morphframes++;
935 // store texture coordinates into temporary array, they will be stored
936 // after usage is determined (triangle data)
937 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
938 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
939 vertonseam = vertremap + numverts * 2;
941 scales = 1.0 / skinwidth;
942 scalet = 1.0 / skinheight;
943 for (i = 0;i < numverts;i++)
945 vertonseam[i] = LittleLong(pinstverts[i].onseam);
946 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
947 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
948 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
949 vertst[(i+numverts)*2+1] = vertst[i*2+1];
952 // load triangle data
953 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
955 // read the triangle elements
956 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
957 for (j = 0;j < 3;j++)
958 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
959 // validate (note numverts is used because this is the original data)
960 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
961 // now butcher the elements according to vertonseam and tri->facesfront
962 // and then compact the vertex set to remove duplicates
963 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
964 if (!LittleLong(pintriangles[i].facesfront)) // backface
965 for (j = 0;j < 3;j++)
966 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
967 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
969 // (this uses vertremap to count usage to save some memory)
970 for (i = 0;i < numverts*2;i++)
972 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
973 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
974 // build remapping table and compact array
975 loadmodel->surfmesh.num_vertices = 0;
976 for (i = 0;i < numverts*2;i++)
980 vertremap[i] = loadmodel->surfmesh.num_vertices;
981 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
982 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
983 loadmodel->surfmesh.num_vertices++;
986 vertremap[i] = -1; // not used at all
988 // remap the elements to the new vertex set
989 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
990 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
991 // store the texture coordinates
992 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
993 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
995 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
996 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1000 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1001 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1002 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1003 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1004 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1005 Mod_Alias_CalculateBoundingBox();
1006 Mod_Alias_MorphMesh_CompileFrames();
1009 Mem_Free(vertremap);
1012 skinfiles = Mod_LoadSkinFiles();
1013 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1014 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1015 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1016 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1019 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1020 Mod_FreeSkinFiles(skinfiles);
1021 for (i = 0;i < loadmodel->numskins;i++)
1023 loadmodel->skinscenes[i].firstframe = i;
1024 loadmodel->skinscenes[i].framecount = 1;
1025 loadmodel->skinscenes[i].loop = true;
1026 loadmodel->skinscenes[i].framerate = 10;
1032 datapointer = startskins;
1033 for (i = 0;i < loadmodel->numskins;i++)
1035 pinskintype = (daliasskintype_t *)datapointer;
1036 datapointer += sizeof(daliasskintype_t);
1038 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1045 pinskingroup = (daliasskingroup_t *)datapointer;
1046 datapointer += sizeof(daliasskingroup_t);
1048 groupskins = LittleLong (pinskingroup->numskins);
1050 pinskinintervals = (daliasskininterval_t *)datapointer;
1051 datapointer += sizeof(daliasskininterval_t) * groupskins;
1053 interval = LittleFloat(pinskinintervals[0].interval);
1054 if (interval < 0.01f)
1056 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1061 sprintf(loadmodel->skinscenes[i].name, "skin %i", i);
1062 loadmodel->skinscenes[i].firstframe = totalskins;
1063 loadmodel->skinscenes[i].framecount = groupskins;
1064 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1065 loadmodel->skinscenes[i].loop = true;
1067 for (j = 0;j < groupskins;j++)
1070 sprintf (name, "%s_%i_%i", loadmodel->name, i, j);
1072 sprintf (name, "%s_%i", loadmodel->name, i);
1073 if (!Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, name, false, false, true))
1075 tempskinframe = R_SkinFrame_LoadExternal(name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS, false);
1077 tempskinframe = R_SkinFrame_LoadInternalQuake(name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP, true, r_fullbrights.integer, (unsigned char *)datapointer, skinwidth, skinheight);
1078 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1080 datapointer += skinwidth * skinheight;
1084 // check for skins that don't exist in the model, but do exist as external images
1085 // (this was added because yummyluv kept pestering me about support for it)
1086 // TODO: support shaders here?
1087 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)))
1089 // expand the arrays to make room
1090 tempskinscenes = loadmodel->skinscenes;
1091 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1092 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1093 Mem_Free(tempskinscenes);
1095 tempaliasskins = loadmodel->data_textures;
1096 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1097 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1098 Mem_Free(tempaliasskins);
1100 // store the info about the new skin
1101 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1102 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1103 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1104 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1105 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1106 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1108 //increase skin counts
1109 loadmodel->numskins++;
1112 // fix up the pointers since they are pointing at the old textures array
1113 // FIXME: this is a hack!
1114 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1115 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1119 surface = loadmodel->data_surfaces;
1120 surface->texture = loadmodel->data_textures;
1121 surface->num_firsttriangle = 0;
1122 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1123 surface->num_firstvertex = 0;
1124 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1126 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1129 void Mod_IDP2_Load(model_t *mod, void *buffer, void *bufferend)
1131 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1132 float iskinwidth, iskinheight;
1133 unsigned char *data;
1134 msurface_t *surface;
1136 unsigned char *base, *datapointer;
1137 md2frame_t *pinframe;
1139 md2triangle_t *intri;
1140 unsigned short *inst;
1141 struct md2verthash_s
1143 struct md2verthash_s *next;
1147 *hash, **md2verthash, *md2verthashdata;
1148 skinframe_t *tempskinframe;
1149 skinfile_t *skinfiles;
1151 pinmodel = (md2_t *)buffer;
1152 base = (unsigned char *)buffer;
1154 version = LittleLong (pinmodel->version);
1155 if (version != MD2ALIAS_VERSION)
1156 Host_Error ("%s has wrong version number (%i should be %i)",
1157 loadmodel->name, version, MD2ALIAS_VERSION);
1159 loadmodel->modeldatatypestring = "MD2";
1161 loadmodel->type = mod_alias;
1162 loadmodel->DrawSky = NULL;
1163 loadmodel->DrawAddWaterPlanes = NULL;
1164 loadmodel->Draw = R_Q1BSP_Draw;
1165 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1166 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1167 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1168 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1169 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1170 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1171 loadmodel->PointSuperContents = NULL;
1173 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1174 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1175 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1176 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1177 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1178 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1179 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1180 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1182 end = LittleLong(pinmodel->ofs_end);
1183 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1184 Host_Error ("%s is not a valid model", loadmodel->name);
1185 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1186 Host_Error ("%s is not a valid model", loadmodel->name);
1187 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1188 Host_Error ("%s is not a valid model", loadmodel->name);
1189 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1190 Host_Error ("%s is not a valid model", loadmodel->name);
1191 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1192 Host_Error ("%s is not a valid model", loadmodel->name);
1194 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1195 numxyz = LittleLong(pinmodel->num_xyz);
1196 numst = LittleLong(pinmodel->num_st);
1197 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1198 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1199 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1200 skinwidth = LittleLong(pinmodel->skinwidth);
1201 skinheight = LittleLong(pinmodel->skinheight);
1202 iskinwidth = 1.0f / skinwidth;
1203 iskinheight = 1.0f / skinheight;
1205 loadmodel->num_surfaces = 1;
1206 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1207 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]));
1208 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1209 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1210 loadmodel->surfacelist[0] = 0;
1211 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1212 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1213 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1214 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1216 loadmodel->synctype = ST_RAND;
1219 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1220 skinfiles = Mod_LoadSkinFiles();
1223 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1224 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1225 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1226 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1227 Mod_FreeSkinFiles(skinfiles);
1229 else if (loadmodel->numskins)
1231 // skins found (most likely not a player model)
1232 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1233 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1234 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1235 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1237 if (!Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, false, false, true))
1239 tempskinframe = R_SkinFrame_LoadExternal(inskin, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS, false);
1241 Con_Printf("%s is missing skin \"%s\"\n", loadmodel->name, inskin);
1242 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i * loadmodel->num_surfaces, tempskinframe);
1248 // no skins (most likely a player model)
1249 loadmodel->numskins = 1;
1250 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1251 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1252 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1253 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1256 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1257 for (i = 0;i < loadmodel->numskins;i++)
1259 loadmodel->skinscenes[i].firstframe = i;
1260 loadmodel->skinscenes[i].framecount = 1;
1261 loadmodel->skinscenes[i].loop = true;
1262 loadmodel->skinscenes[i].framerate = 10;
1265 // load the triangles and stvert data
1266 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1267 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1268 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1269 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1270 // swap the triangle list
1271 loadmodel->surfmesh.num_vertices = 0;
1272 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1274 for (j = 0;j < 3;j++)
1276 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1277 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1280 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1285 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1288 hashindex = (xyz * 256 + st) & 65535;
1289 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1290 if (hash->xyz == xyz && hash->st == st)
1294 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1297 hash->next = md2verthash[hashindex];
1298 md2verthash[hashindex] = hash;
1300 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1304 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1305 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));
1306 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1307 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1308 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1311 hash = md2verthashdata + i;
1312 vertremap[i] = hash->xyz;
1313 sts = LittleShort(inst[hash->st*2+0]);
1314 stt = LittleShort(inst[hash->st*2+1]);
1315 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1317 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1321 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1322 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1325 Mem_Free(md2verthash);
1326 Mem_Free(md2verthashdata);
1329 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1330 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1335 pinframe = (md2frame_t *)datapointer;
1336 datapointer += sizeof(md2frame_t);
1337 // store the frame scale/translate into the appropriate array
1338 for (j = 0;j < 3;j++)
1340 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1341 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1343 // convert the vertices
1344 v = (trivertx_t *)datapointer;
1345 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1346 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1347 out[k] = v[vertremap[k]];
1348 datapointer += numxyz * sizeof(trivertx_t);
1350 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1351 loadmodel->animscenes[i].firstframe = i;
1352 loadmodel->animscenes[i].framecount = 1;
1353 loadmodel->animscenes[i].framerate = 10;
1354 loadmodel->animscenes[i].loop = true;
1357 Mem_Free(vertremap);
1359 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1360 Mod_Alias_CalculateBoundingBox();
1361 Mod_Alias_MorphMesh_CompileFrames();
1363 surface = loadmodel->data_surfaces;
1364 surface->texture = loadmodel->data_textures;
1365 surface->num_firsttriangle = 0;
1366 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1367 surface->num_firstvertex = 0;
1368 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1370 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1373 void Mod_IDP3_Load(model_t *mod, void *buffer, void *bufferend)
1375 int i, j, k, version, meshvertices, meshtriangles;
1376 unsigned char *data;
1377 msurface_t *surface;
1378 md3modelheader_t *pinmodel;
1379 md3frameinfo_t *pinframe;
1382 skinfile_t *skinfiles;
1384 pinmodel = (md3modelheader_t *)buffer;
1386 if (memcmp(pinmodel->identifier, "IDP3", 4))
1387 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1388 version = LittleLong (pinmodel->version);
1389 if (version != MD3VERSION)
1390 Host_Error ("%s has wrong version number (%i should be %i)",
1391 loadmodel->name, version, MD3VERSION);
1393 skinfiles = Mod_LoadSkinFiles();
1394 if (loadmodel->numskins < 1)
1395 loadmodel->numskins = 1;
1397 loadmodel->modeldatatypestring = "MD3";
1399 loadmodel->type = mod_alias;
1400 loadmodel->DrawSky = NULL;
1401 loadmodel->DrawAddWaterPlanes = NULL;
1402 loadmodel->Draw = R_Q1BSP_Draw;
1403 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1404 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1405 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1406 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1407 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1408 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1409 loadmodel->PointSuperContents = NULL;
1410 loadmodel->synctype = ST_RAND;
1411 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1412 i = LittleLong (pinmodel->flags);
1413 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1415 // set up some global info about the model
1416 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1417 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1419 // make skinscenes for the skins (no groups)
1420 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1421 for (i = 0;i < loadmodel->numskins;i++)
1423 loadmodel->skinscenes[i].firstframe = i;
1424 loadmodel->skinscenes[i].framecount = 1;
1425 loadmodel->skinscenes[i].loop = true;
1426 loadmodel->skinscenes[i].framerate = 10;
1430 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1431 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1433 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1434 loadmodel->animscenes[i].firstframe = i;
1435 loadmodel->animscenes[i].framecount = 1;
1436 loadmodel->animscenes[i].framerate = 10;
1437 loadmodel->animscenes[i].loop = true;
1441 loadmodel->num_tagframes = loadmodel->numframes;
1442 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1443 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1444 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1446 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1447 for (j = 0;j < 9;j++)
1448 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1449 for (j = 0;j < 3;j++)
1450 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1451 //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);
1457 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)))
1459 if (memcmp(pinmesh->identifier, "IDP3", 4))
1460 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1461 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1462 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1463 meshvertices += LittleLong(pinmesh->num_vertices);
1464 meshtriangles += LittleLong(pinmesh->num_triangles);
1467 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1468 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1469 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1470 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));
1471 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1472 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1473 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1474 loadmodel->surfmesh.num_vertices = meshvertices;
1475 loadmodel->surfmesh.num_triangles = meshtriangles;
1476 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1477 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1478 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1479 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1480 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1484 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)))
1486 if (memcmp(pinmesh->identifier, "IDP3", 4))
1487 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1488 loadmodel->surfacelist[i] = i;
1489 surface = loadmodel->data_surfaces + i;
1490 surface->texture = loadmodel->data_textures + i;
1491 surface->num_firsttriangle = meshtriangles;
1492 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1493 surface->num_firstvertex = meshvertices;
1494 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1495 meshvertices += surface->num_vertices;
1496 meshtriangles += surface->num_triangles;
1498 for (j = 0;j < surface->num_triangles * 3;j++)
1499 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1500 for (j = 0;j < surface->num_vertices;j++)
1502 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1503 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1505 for (j = 0;j < loadmodel->numframes;j++)
1507 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1508 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1509 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1511 out->origin[0] = LittleShort(in->origin[0]);
1512 out->origin[1] = LittleShort(in->origin[1]);
1513 out->origin[2] = LittleShort(in->origin[2]);
1514 out->pitch = in->pitch;
1519 if (LittleLong(pinmesh->num_shaders) >= 1)
1520 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name);
1522 for (j = 0;j < loadmodel->numskins;j++)
1523 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i + j * loadmodel->num_surfaces, NULL);
1525 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1527 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1528 Mod_Alias_MorphMesh_CompileFrames();
1529 Mod_Alias_CalculateBoundingBox();
1530 Mod_FreeSkinFiles(skinfiles);
1532 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1535 void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer, void *bufferend)
1537 zymtype1header_t *pinmodel, *pheader;
1538 unsigned char *pbase;
1539 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1540 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose;
1541 zymvertex_t *verts, *vertdata;
1545 skinfile_t *skinfiles;
1546 unsigned char *data;
1547 msurface_t *surface;
1549 pinmodel = (zymtype1header_t *)buffer;
1550 pbase = (unsigned char *)buffer;
1551 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1552 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1553 if (BigLong(pinmodel->type) != 1)
1554 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1556 loadmodel->modeldatatypestring = "ZYM";
1558 loadmodel->type = mod_alias;
1559 loadmodel->synctype = ST_RAND;
1563 pheader->type = BigLong(pinmodel->type);
1564 pheader->filesize = BigLong(pinmodel->filesize);
1565 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1566 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1567 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1568 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1569 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1570 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1571 pheader->radius = BigFloat(pinmodel->radius);
1572 pheader->numverts = BigLong(pinmodel->numverts);
1573 pheader->numtris = BigLong(pinmodel->numtris);
1574 pheader->numshaders = BigLong(pinmodel->numshaders);
1575 pheader->numbones = BigLong(pinmodel->numbones);
1576 pheader->numscenes = BigLong(pinmodel->numscenes);
1577 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1578 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1579 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1580 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1581 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1582 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1583 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1584 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1585 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1586 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1587 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1588 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1589 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1590 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1591 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1592 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1593 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1594 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1596 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1598 Con_Printf("%s has no geometry\n", loadmodel->name);
1601 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1603 Con_Printf("%s has no animations\n", loadmodel->name);
1607 loadmodel->DrawSky = NULL;
1608 loadmodel->DrawAddWaterPlanes = NULL;
1609 loadmodel->Draw = R_Q1BSP_Draw;
1610 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1611 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1612 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1613 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1614 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1615 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1616 loadmodel->PointSuperContents = NULL;
1618 loadmodel->numframes = pheader->numscenes;
1619 loadmodel->num_surfaces = pheader->numshaders;
1621 skinfiles = Mod_LoadSkinFiles();
1622 if (loadmodel->numskins < 1)
1623 loadmodel->numskins = 1;
1625 // make skinscenes for the skins (no groups)
1626 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1627 for (i = 0;i < loadmodel->numskins;i++)
1629 loadmodel->skinscenes[i].firstframe = i;
1630 loadmodel->skinscenes[i].framecount = 1;
1631 loadmodel->skinscenes[i].loop = true;
1632 loadmodel->skinscenes[i].framerate = 10;
1636 modelradius = pheader->radius;
1637 for (i = 0;i < 3;i++)
1639 loadmodel->normalmins[i] = pheader->mins[i];
1640 loadmodel->normalmaxs[i] = pheader->maxs[i];
1641 loadmodel->rotatedmins[i] = -modelradius;
1642 loadmodel->rotatedmaxs[i] = modelradius;
1644 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1645 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1646 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1647 if (loadmodel->yawmaxs[0] > modelradius)
1648 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1649 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1650 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1651 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1652 loadmodel->radius = modelradius;
1653 loadmodel->radius2 = modelradius * modelradius;
1655 // go through the lumps, swapping things
1657 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1658 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1659 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1660 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1661 for (i = 0;i < pheader->numscenes;i++)
1663 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1664 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1665 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1666 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1667 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1668 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1669 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1670 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1671 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1672 if (loadmodel->animscenes[i].framerate < 0)
1673 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1677 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1678 loadmodel->num_bones = pheader->numbones;
1679 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, pheader->numbones * sizeof(aliasbone_t));
1680 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1681 for (i = 0;i < pheader->numbones;i++)
1683 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1684 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1685 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1686 if (loadmodel->data_bones[i].parent >= i)
1687 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1690 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1691 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1692 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1693 for (i = 0;i < pheader->numverts;i++)
1695 vertbonecounts[i] = BigLong(bonecount[i]);
1696 if (vertbonecounts[i] != 1)
1697 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1700 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]);
1702 meshvertices = pheader->numverts;
1703 meshtriangles = pheader->numtris;
1705 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1706 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1707 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1708 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]));
1709 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1710 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1711 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1712 loadmodel->surfmesh.num_vertices = meshvertices;
1713 loadmodel->surfmesh.num_triangles = meshtriangles;
1714 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1715 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1716 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1717 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1718 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1719 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1720 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1721 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1722 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1723 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
1724 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1726 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1727 poses = (float *) (pheader->lump_poses.start + pbase);
1728 for (i = 0;i < pheader->lump_poses.length / 4;i++)
1729 loadmodel->data_poses[i] = BigFloat(poses[i]);
1731 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1732 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1733 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1734 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1735 // (converting from weight-blending skeletal animation to
1736 // deformation-based skeletal animation)
1737 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1738 for (i = 0;i < loadmodel->num_bones;i++)
1740 const float *m = loadmodel->data_poses + i * 12;
1741 if (loadmodel->data_bones[i].parent >= 0)
1742 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1744 for (k = 0;k < 12;k++)
1745 bonepose[12*i+k] = m[k];
1747 for (j = 0;j < pheader->numverts;j++)
1749 // this format really should have had a per vertexweight weight value...
1750 // but since it does not, the weighting is completely ignored and
1751 // only one weight is allowed per vertex
1752 int boneindex = BigLong(vertdata[j].bonenum);
1753 const float *m = bonepose + 12 * boneindex;
1754 float relativeorigin[3];
1755 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1756 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1757 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1758 // transform the vertex bone weight into the base mesh
1759 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1760 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1761 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1762 // store the weight as the primary weight on this vertex
1763 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
1764 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = 1;
1767 // normals and tangents are calculated after elements are loaded
1769 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1770 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1771 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1772 for (i = 0;i < pheader->numverts;i++)
1774 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1775 // flip T coordinate for OpenGL
1776 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1779 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1780 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1781 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1783 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1784 //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)
1785 // byteswap, validate, and swap winding order of tris
1786 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1787 if (pheader->lump_render.length != count)
1788 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1789 renderlist = (int *) (pheader->lump_render.start + pbase);
1790 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1792 for (i = 0;i < loadmodel->num_surfaces;i++)
1794 int firstvertex, lastvertex;
1795 if (renderlist >= renderlistend)
1796 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1797 count = BigLong(*renderlist);renderlist++;
1798 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1799 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1801 loadmodel->surfacelist[i] = i;
1802 surface = loadmodel->data_surfaces + i;
1803 surface->texture = loadmodel->data_textures + i;
1804 surface->num_firsttriangle = meshtriangles;
1805 surface->num_triangles = count;
1806 meshtriangles += surface->num_triangles;
1808 // load the elements
1809 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
1810 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
1812 outelements[j*3+2] = BigLong(renderlist[0]);
1813 outelements[j*3+1] = BigLong(renderlist[1]);
1814 outelements[j*3+0] = BigLong(renderlist[2]);
1816 // validate the elements and find the used vertex range
1817 firstvertex = meshvertices;
1819 for (j = 0;j < surface->num_triangles * 3;j++)
1821 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
1822 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
1823 firstvertex = min(firstvertex, outelements[j]);
1824 lastvertex = max(lastvertex, outelements[j]);
1826 surface->num_firstvertex = firstvertex;
1827 surface->num_vertices = lastvertex + 1 - firstvertex;
1829 // since zym models do not have named sections, reuse their shader
1830 // name as the section name
1831 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
1833 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
1835 for (j = 0;j < loadmodel->numskins;j++)
1836 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i + j * loadmodel->num_surfaces, NULL);
1838 Mod_FreeSkinFiles(skinfiles);
1839 Mem_Free(vertbonecounts);
1842 // compute all the mesh information that was not loaded from the file
1843 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
1844 Mod_BuildBaseBonePoses();
1845 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
1846 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);
1847 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1849 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1852 void Mod_DARKPLACESMODEL_Load(model_t *mod, void *buffer, void *bufferend)
1854 dpmheader_t *pheader;
1858 unsigned char *pbase;
1859 int i, j, k, meshvertices, meshtriangles;
1860 skinfile_t *skinfiles;
1861 unsigned char *data;
1864 pheader = (dpmheader_t *)buffer;
1865 pbase = (unsigned char *)buffer;
1866 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
1867 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
1868 if (BigLong(pheader->type) != 2)
1869 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1871 loadmodel->modeldatatypestring = "DPM";
1873 loadmodel->type = mod_alias;
1874 loadmodel->synctype = ST_RAND;
1877 pheader->type = BigLong(pheader->type);
1878 pheader->filesize = BigLong(pheader->filesize);
1879 pheader->mins[0] = BigFloat(pheader->mins[0]);
1880 pheader->mins[1] = BigFloat(pheader->mins[1]);
1881 pheader->mins[2] = BigFloat(pheader->mins[2]);
1882 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
1883 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
1884 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
1885 pheader->yawradius = BigFloat(pheader->yawradius);
1886 pheader->allradius = BigFloat(pheader->allradius);
1887 pheader->num_bones = BigLong(pheader->num_bones);
1888 pheader->num_meshs = BigLong(pheader->num_meshs);
1889 pheader->num_frames = BigLong(pheader->num_frames);
1890 pheader->ofs_bones = BigLong(pheader->ofs_bones);
1891 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
1892 pheader->ofs_frames = BigLong(pheader->ofs_frames);
1894 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
1896 Con_Printf("%s has no geometry\n", loadmodel->name);
1899 if (pheader->num_frames < 1)
1901 Con_Printf("%s has no frames\n", loadmodel->name);
1905 loadmodel->DrawSky = NULL;
1906 loadmodel->DrawAddWaterPlanes = NULL;
1907 loadmodel->Draw = R_Q1BSP_Draw;
1908 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1909 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1910 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1911 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1912 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1913 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1914 loadmodel->PointSuperContents = NULL;
1917 for (i = 0;i < 3;i++)
1919 loadmodel->normalmins[i] = pheader->mins[i];
1920 loadmodel->normalmaxs[i] = pheader->maxs[i];
1921 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
1922 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
1923 loadmodel->rotatedmins[i] = -pheader->allradius;
1924 loadmodel->rotatedmaxs[i] = pheader->allradius;
1926 loadmodel->radius = pheader->allradius;
1927 loadmodel->radius2 = pheader->allradius * pheader->allradius;
1929 // load external .skin files if present
1930 skinfiles = Mod_LoadSkinFiles();
1931 if (loadmodel->numskins < 1)
1932 loadmodel->numskins = 1;
1937 // gather combined statistics from the meshes
1938 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
1939 for (i = 0;i < (int)pheader->num_meshs;i++)
1941 int numverts = BigLong(dpmmesh->num_verts);
1942 meshvertices += numverts;;
1943 meshtriangles += BigLong(dpmmesh->num_tris);
1947 loadmodel->numframes = pheader->num_frames;
1948 loadmodel->num_bones = pheader->num_bones;
1949 loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
1950 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
1951 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1952 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1953 // do most allocations as one merged chunk
1954 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));
1955 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1956 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1957 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1958 loadmodel->surfmesh.num_vertices = meshvertices;
1959 loadmodel->surfmesh.num_triangles = meshtriangles;
1960 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1961 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1962 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1963 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1964 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1965 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1966 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1967 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1968 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1969 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
1970 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1971 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
1972 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
1973 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1975 for (i = 0;i < loadmodel->numskins;i++)
1977 loadmodel->skinscenes[i].firstframe = i;
1978 loadmodel->skinscenes[i].framecount = 1;
1979 loadmodel->skinscenes[i].loop = true;
1980 loadmodel->skinscenes[i].framerate = 10;
1983 // load the bone info
1984 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
1985 for (i = 0;i < loadmodel->num_bones;i++)
1987 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1988 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1989 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1990 if (loadmodel->data_bones[i].parent >= i)
1991 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1995 frame = (dpmframe_t *) (pbase + pheader->ofs_frames);
1996 for (i = 0;i < loadmodel->numframes;i++)
1999 memcpy(loadmodel->animscenes[i].name, frame->name, sizeof(frame->name));
2000 loadmodel->animscenes[i].firstframe = i;
2001 loadmodel->animscenes[i].framecount = 1;
2002 loadmodel->animscenes[i].loop = true;
2003 loadmodel->animscenes[i].framerate = 10;
2004 // load the bone poses for this frame
2005 poses = (float *) (pbase + BigLong(frame->ofs_bonepositions));
2006 for (j = 0;j < loadmodel->num_bones*12;j++)
2007 loadmodel->data_poses[i * loadmodel->num_bones*12 + j] = BigFloat(poses[j]);
2008 // stuff not processed here: mins, maxs, yawradius, allradius
2012 // load the meshes now
2013 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2016 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2017 // (converting from weight-blending skeletal animation to
2018 // deformation-based skeletal animation)
2019 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2020 for (i = 0;i < loadmodel->num_bones;i++)
2022 const float *m = loadmodel->data_poses + i * 12;
2023 if (loadmodel->data_bones[i].parent >= 0)
2024 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2026 for (k = 0;k < 12;k++)
2027 bonepose[12*i+k] = m[k];
2029 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2031 const int *inelements;
2033 const float *intexcoord;
2034 msurface_t *surface;
2036 loadmodel->surfacelist[i] = i;
2037 surface = loadmodel->data_surfaces + i;
2038 surface->texture = loadmodel->data_textures + i;
2039 surface->num_firsttriangle = meshtriangles;
2040 surface->num_triangles = BigLong(dpmmesh->num_tris);
2041 surface->num_firstvertex = meshvertices;
2042 surface->num_vertices = BigLong(dpmmesh->num_verts);
2043 meshvertices += surface->num_vertices;
2044 meshtriangles += surface->num_triangles;
2046 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2047 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2048 for (j = 0;j < surface->num_triangles;j++)
2050 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2051 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2052 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2053 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2058 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2059 for (j = 0;j < surface->num_vertices*2;j++)
2060 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2062 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2063 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2067 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2068 data += sizeof(dpmvertex_t);
2069 for (k = 0;k < numweights;k++)
2071 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2072 int boneindex = BigLong(vert->bonenum);
2073 const float *m = bonepose + 12 * boneindex;
2074 float influence = BigFloat(vert->influence);
2075 float relativeorigin[3], relativenormal[3];
2076 relativeorigin[0] = BigFloat(vert->origin[0]);
2077 relativeorigin[1] = BigFloat(vert->origin[1]);
2078 relativeorigin[2] = BigFloat(vert->origin[2]);
2079 relativenormal[0] = BigFloat(vert->normal[0]);
2080 relativenormal[1] = BigFloat(vert->normal[1]);
2081 relativenormal[2] = BigFloat(vert->normal[2]);
2082 // blend the vertex bone weights into the base mesh
2083 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2084 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2085 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2086 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2087 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2088 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2091 // store the first (and often only) weight
2092 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = influence;
2093 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
2097 // sort the new weight into this vertex's weight table
2098 // (which only accepts up to 4 bones per vertex)
2099 for (l = 0;l < 4;l++)
2101 if (loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] < influence)
2103 // move weaker influence weights out of the way first
2105 for (l2 = 3;l2 > l;l2--)
2107 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2-1];
2108 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2-1];
2110 // store the new weight
2111 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] = influence;
2112 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l] = boneindex;
2117 data += sizeof(dpmbonevert_t);
2120 for (l = 0;l < 4;l++)
2121 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l];
2122 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2124 float f = 1.0f / sum;
2125 for (l = 0;l < 4;l++)
2126 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] *= f;
2130 // since dpm models do not have named sections, reuse their shader name as the section name
2131 if (dpmmesh->shadername[0])
2132 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2134 for (j = 0;j < loadmodel->numskins;j++)
2135 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i + j * loadmodel->num_surfaces, NULL);
2137 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2140 Mod_FreeSkinFiles(skinfiles);
2142 // compute all the mesh information that was not loaded from the file
2143 Mod_BuildBaseBonePoses();
2144 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);
2145 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2147 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2150 // no idea why PSK/PSA files contain weird quaternions but they do...
2151 #define PSKQUATNEGATIONS
2152 void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend)
2154 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2155 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2156 fs_offset_t filesize;
2161 pskboneinfo_t *bones;
2162 pskrawweights_t *rawweights;
2163 pskboneinfo_t *animbones;
2164 pskaniminfo_t *anims;
2165 pskanimkeys_t *animkeys;
2166 void *animfilebuffer, *animbuffer, *animbufferend;
2167 unsigned char *data;
2169 skinfile_t *skinfiles;
2170 char animname[MAX_QPATH];
2172 pchunk = (pskchunk_t *)buffer;
2173 if (strcmp(pchunk->id, "ACTRHEAD"))
2174 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2176 loadmodel->modeldatatypestring = "PSK";
2178 loadmodel->type = mod_alias;
2179 loadmodel->DrawSky = NULL;
2180 loadmodel->DrawAddWaterPlanes = NULL;
2181 loadmodel->Draw = R_Q1BSP_Draw;
2182 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2183 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2184 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2185 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2186 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2187 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2188 loadmodel->PointSuperContents = NULL;
2189 loadmodel->synctype = ST_RAND;
2191 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2192 strlcat(animname, ".psa", sizeof(animname));
2193 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2194 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2195 if (animbuffer == NULL)
2196 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2215 while (buffer < bufferend)
2217 pchunk = (pskchunk_t *)buffer;
2218 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2219 version = LittleLong(pchunk->version);
2220 recordsize = LittleLong(pchunk->recordsize);
2221 numrecords = LittleLong(pchunk->numrecords);
2222 if (developer.integer >= 100)
2223 Con_Printf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2224 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2225 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);
2226 if (!strcmp(pchunk->id, "ACTRHEAD"))
2230 else if (!strcmp(pchunk->id, "PNTS0000"))
2233 if (recordsize != sizeof(*p))
2234 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2235 // byteswap in place and keep the pointer
2236 numpnts = numrecords;
2237 pnts = (pskpnts_t *)buffer;
2238 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2240 p->origin[0] = LittleFloat(p->origin[0]);
2241 p->origin[1] = LittleFloat(p->origin[1]);
2242 p->origin[2] = LittleFloat(p->origin[2]);
2246 else if (!strcmp(pchunk->id, "VTXW0000"))
2249 if (recordsize != sizeof(*p))
2250 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2251 // byteswap in place and keep the pointer
2252 numvtxw = numrecords;
2253 vtxw = (pskvtxw_t *)buffer;
2254 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2256 p->pntsindex = LittleShort(p->pntsindex);
2257 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2258 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2259 if (p->pntsindex >= numpnts)
2261 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2267 else if (!strcmp(pchunk->id, "FACE0000"))
2270 if (recordsize != sizeof(*p))
2271 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2272 // byteswap in place and keep the pointer
2273 numfaces = numrecords;
2274 faces = (pskface_t *)buffer;
2275 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2277 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2278 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2279 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2280 p->group = LittleLong(p->group);
2281 if (p->vtxwindex[0] >= numvtxw)
2283 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2284 p->vtxwindex[0] = 0;
2286 if (p->vtxwindex[1] >= numvtxw)
2288 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2289 p->vtxwindex[1] = 0;
2291 if (p->vtxwindex[2] >= numvtxw)
2293 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2294 p->vtxwindex[2] = 0;
2299 else if (!strcmp(pchunk->id, "MATT0000"))
2302 if (recordsize != sizeof(*p))
2303 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2304 // byteswap in place and keep the pointer
2305 nummatts = numrecords;
2306 matts = (pskmatt_t *)buffer;
2307 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2313 else if (!strcmp(pchunk->id, "REFSKELT"))
2316 if (recordsize != sizeof(*p))
2317 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2318 // byteswap in place and keep the pointer
2319 numbones = numrecords;
2320 bones = (pskboneinfo_t *)buffer;
2321 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2323 p->numchildren = LittleLong(p->numchildren);
2324 p->parent = LittleLong(p->parent);
2325 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2326 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2327 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2328 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2329 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2330 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2331 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2332 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2333 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2334 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2335 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2336 #ifdef PSKQUATNEGATIONS
2339 p->basepose.quat[0] *= -1;
2340 p->basepose.quat[1] *= -1;
2341 p->basepose.quat[2] *= -1;
2345 p->basepose.quat[0] *= 1;
2346 p->basepose.quat[1] *= -1;
2347 p->basepose.quat[2] *= 1;
2350 if (p->parent < 0 || p->parent >= numbones)
2352 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2358 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2361 if (recordsize != sizeof(*p))
2362 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2363 // byteswap in place and keep the pointer
2364 numrawweights = numrecords;
2365 rawweights = (pskrawweights_t *)buffer;
2366 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2368 p->weight = LittleFloat(p->weight);
2369 p->pntsindex = LittleLong(p->pntsindex);
2370 p->boneindex = LittleLong(p->boneindex);
2371 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2373 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2376 if (p->boneindex < 0 || p->boneindex >= numbones)
2378 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2386 while (animbuffer < animbufferend)
2388 pchunk = (pskchunk_t *)animbuffer;
2389 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2390 version = LittleLong(pchunk->version);
2391 recordsize = LittleLong(pchunk->recordsize);
2392 numrecords = LittleLong(pchunk->numrecords);
2393 if (developer.integer >= 100)
2394 Con_Printf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2395 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2396 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);
2397 if (!strcmp(pchunk->id, "ANIMHEAD"))
2401 else if (!strcmp(pchunk->id, "BONENAMES"))
2404 if (recordsize != sizeof(*p))
2405 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2406 // byteswap in place and keep the pointer
2407 numanimbones = numrecords;
2408 animbones = (pskboneinfo_t *)animbuffer;
2409 // NOTE: supposedly psa does not need to match the psk model, the
2410 // bones missing from the psa would simply use their base
2411 // positions from the psk, but this is hard for me to implement
2412 // and people can easily make animations that match.
2413 if (numanimbones != numbones)
2414 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2415 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2417 p->numchildren = LittleLong(p->numchildren);
2418 p->parent = LittleLong(p->parent);
2419 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2420 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2421 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2422 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2423 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2424 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2425 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2426 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2427 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2428 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2429 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2430 #ifdef PSKQUATNEGATIONS
2433 p->basepose.quat[0] *= -1;
2434 p->basepose.quat[1] *= -1;
2435 p->basepose.quat[2] *= -1;
2439 p->basepose.quat[0] *= 1;
2440 p->basepose.quat[1] *= -1;
2441 p->basepose.quat[2] *= 1;
2444 if (p->parent < 0 || p->parent >= numanimbones)
2446 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2449 // check that bones are the same as in the base
2450 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2451 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2455 else if (!strcmp(pchunk->id, "ANIMINFO"))
2458 if (recordsize != sizeof(*p))
2459 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2460 // byteswap in place and keep the pointer
2461 numanims = numrecords;
2462 anims = (pskaniminfo_t *)animbuffer;
2463 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2465 p->numbones = LittleLong(p->numbones);
2466 p->playtime = LittleFloat(p->playtime);
2467 p->fps = LittleFloat(p->fps);
2468 p->firstframe = LittleLong(p->firstframe);
2469 p->numframes = LittleLong(p->numframes);
2470 if (p->numbones != numbones)
2471 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2475 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2478 if (recordsize != sizeof(*p))
2479 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2480 numanimkeys = numrecords;
2481 animkeys = (pskanimkeys_t *)animbuffer;
2482 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2484 p->origin[0] = LittleFloat(p->origin[0]);
2485 p->origin[1] = LittleFloat(p->origin[1]);
2486 p->origin[2] = LittleFloat(p->origin[2]);
2487 p->quat[0] = LittleFloat(p->quat[0]);
2488 p->quat[1] = LittleFloat(p->quat[1]);
2489 p->quat[2] = LittleFloat(p->quat[2]);
2490 p->quat[3] = LittleFloat(p->quat[3]);
2491 p->frametime = LittleFloat(p->frametime);
2492 #ifdef PSKQUATNEGATIONS
2493 if (index % numbones)
2508 // TODO: allocate bonepose stuff
2511 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2514 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2515 Host_Error("%s: missing required chunks", loadmodel->name);
2517 loadmodel->numframes = 0;
2518 for (index = 0;index < numanims;index++)
2519 loadmodel->numframes += anims[index].numframes;
2521 if (numanimkeys != numbones * loadmodel->numframes)
2522 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2524 meshvertices = numvtxw;
2525 meshtriangles = numfaces;
2527 // load external .skin files if present
2528 skinfiles = Mod_LoadSkinFiles();
2529 if (loadmodel->numskins < 1)
2530 loadmodel->numskins = 1;
2531 loadmodel->num_bones = numbones;
2532 loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
2533 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2534 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2535 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2536 // do most allocations as one merged chunk
2537 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));
2538 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2539 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2540 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2541 loadmodel->surfmesh.num_vertices = meshvertices;
2542 loadmodel->surfmesh.num_triangles = meshtriangles;
2543 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2544 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2545 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2546 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2547 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2548 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2549 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2550 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
2551 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
2552 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
2553 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2554 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2555 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2556 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2558 for (i = 0;i < loadmodel->numskins;i++)
2560 loadmodel->skinscenes[i].firstframe = i;
2561 loadmodel->skinscenes[i].framecount = 1;
2562 loadmodel->skinscenes[i].loop = true;
2563 loadmodel->skinscenes[i].framerate = 10;
2567 for (index = 0, i = 0;index < nummatts;index++)
2569 // since psk models do not have named sections, reuse their shader name as the section name
2570 if (matts[index].name[0])
2571 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2573 for (j = 0;j < loadmodel->numskins;j++)
2574 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + index + j * loadmodel->num_surfaces, NULL);
2575 loadmodel->surfacelist[index] = index;
2576 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2577 loadmodel->data_surfaces[index].num_firstvertex = 0;
2578 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2581 // copy over the vertex locations and texcoords
2582 for (index = 0;index < numvtxw;index++)
2584 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2585 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2586 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2587 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2588 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2591 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2592 for (index = 0;index < numfaces;index++)
2593 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2594 for (index = 0, i = 0;index < nummatts;index++)
2596 loadmodel->data_surfaces[index].num_firsttriangle = i;
2597 i += loadmodel->data_surfaces[index].num_triangles;
2598 loadmodel->data_surfaces[index].num_triangles = 0;
2600 for (index = 0;index < numfaces;index++)
2602 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2603 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2604 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2605 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2608 // copy over the bones
2609 for (index = 0;index < numbones;index++)
2611 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2612 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2613 if (loadmodel->data_bones[index].parent >= index)
2614 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2617 // sort the psk point weights into the vertex weight tables
2618 // (which only accept up to 4 bones per vertex)
2619 for (index = 0;index < numvtxw;index++)
2623 for (j = 0;j < numrawweights;j++)
2625 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2627 int boneindex = rawweights[j].boneindex;
2628 float influence = rawweights[j].weight;
2629 for (l = 0;l < 4;l++)
2631 if (loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] < influence)
2633 // move lower influence weights out of the way first
2635 for (l2 = 3;l2 > l;l2--)
2637 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2-1];
2638 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2-1];
2640 // store the new weight
2641 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] = influence;
2642 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l] = boneindex;
2649 for (l = 0;l < 4;l++)
2650 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l];
2651 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2653 float f = 1.0f / sum;
2654 for (l = 0;l < 4;l++)
2655 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] *= f;
2659 // set up the animscenes based on the anims
2660 for (index = 0, i = 0;index < numanims;index++)
2662 for (j = 0;j < anims[index].numframes;j++, i++)
2664 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2665 loadmodel->animscenes[i].firstframe = i;
2666 loadmodel->animscenes[i].framecount = 1;
2667 loadmodel->animscenes[i].loop = true;
2668 loadmodel->animscenes[i].framerate = 10;
2672 // load the poses from the animkeys
2673 for (index = 0;index < numanimkeys;index++)
2675 pskanimkeys_t *k = animkeys + index;
2677 Matrix4x4_FromOriginQuat(&matrix, k->origin[0], k->origin[1], k->origin[2], k->quat[0], k->quat[1], k->quat[2], k->quat[3]);
2678 Matrix4x4_ToArray12FloatD3D(&matrix, loadmodel->data_poses + index*12);
2680 Mod_FreeSkinFiles(skinfiles);
2681 Mem_Free(animfilebuffer);
2683 // compute all the mesh information that was not loaded from the file
2684 // TODO: honor smoothing groups somehow?
2685 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2686 Mod_BuildBaseBonePoses();
2687 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2688 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);
2689 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2690 Mod_Alias_CalculateBoundingBox();
2692 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;