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_Skeletal_AnimateVertices(const model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
50 // vertex weighted skeletal
52 float boneposerelative[MAX_BONES][12];
53 // interpolate matrices and concatenate them to their parents
54 for (i = 0;i < model->num_bones;i++)
57 float *matrix, m[12], bonepose[MAX_BONES][12];
58 for (k = 0;k < 12;k++)
60 for (blends = 0;blends < 4 && frameblend[blends].lerp > 0;blends++)
62 matrix = model->data_poses + (frameblend[blends].frame * model->num_bones + i) * 12;
63 for (k = 0;k < 12;k++)
64 m[k] += matrix[k] * frameblend[blends].lerp;
66 if (i == r_skeletal_debugbone.integer)
67 m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
68 m[3] *= r_skeletal_debugtranslatex.value;
69 m[7] *= r_skeletal_debugtranslatey.value;
70 m[11] *= r_skeletal_debugtranslatez.value;
71 if (model->data_bones[i].parent >= 0)
72 R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
74 for (k = 0;k < 12;k++)
75 bonepose[i][k] = m[k];
76 // create a relative deformation matrix to describe displacement
77 // from the base mesh, which is used by the actual weighting
78 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]);
80 // blend the vertex bone weights
81 // 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)
82 // special case for the first bone because it avoids the need to memset the arrays before filling
84 const float *v = model->surfmesh.data_vertex3f;
85 const int *wi = model->surfmesh.data_vertexweightindex4i;
86 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
87 memset(vertex3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
88 for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, wi += 4, wf += 4, vertex3f += 3)
92 const float *m = boneposerelative[wi[0]];
93 vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
94 vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
95 vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
99 const float *m = boneposerelative[wi[0]];
101 vertex3f[0] = f * (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
102 vertex3f[1] = f * (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
103 vertex3f[2] = f * (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
104 for (k = 1;k < 4 && wf[k];k++)
106 const float *m = boneposerelative[wi[k]];
108 vertex3f[0] += f * (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
109 vertex3f[1] += f * (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
110 vertex3f[2] += f * (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
117 const float *n = model->surfmesh.data_normal3f;
118 const int *wi = model->surfmesh.data_vertexweightindex4i;
119 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
120 memset(normal3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
121 for (i = 0;i < model->surfmesh.num_vertices;i++, n += 3, wi += 4, wf += 4, normal3f += 3)
125 const float *m = boneposerelative[wi[0]];
126 normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
127 normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
128 normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
132 const float *m = boneposerelative[wi[0]];
134 normal3f[0] = f * (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
135 normal3f[1] = f * (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
136 normal3f[2] = f * (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
137 for (k = 1;k < 4 && wf[k];k++)
139 const float *m = boneposerelative[wi[k]];
141 normal3f[0] += f * (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
142 normal3f[1] += f * (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
143 normal3f[2] += f * (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
150 const float *sv = model->surfmesh.data_svector3f;
151 const int *wi = model->surfmesh.data_vertexweightindex4i;
152 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
153 memset(svector3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
154 for (i = 0;i < model->surfmesh.num_vertices;i++, sv += 3, wi += 4, wf += 4, svector3f += 3)
158 const float *m = boneposerelative[wi[0]];
159 svector3f[0] = (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
160 svector3f[1] = (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
161 svector3f[2] = (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
165 const float *m = boneposerelative[wi[0]];
167 svector3f[0] = f * (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
168 svector3f[1] = f * (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
169 svector3f[2] = f * (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
170 for (k = 1;k < 4 && wf[k];k++)
172 const float *m = boneposerelative[wi[k]];
174 svector3f[0] += f * (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
175 svector3f[1] += f * (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
176 svector3f[2] += f * (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
183 const float *tv = model->surfmesh.data_tvector3f;
184 const int *wi = model->surfmesh.data_vertexweightindex4i;
185 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
186 memset(tvector3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
187 for (i = 0;i < model->surfmesh.num_vertices;i++, tv += 3, wi += 4, wf += 4, tvector3f += 3)
191 const float *m = boneposerelative[wi[0]];
192 tvector3f[0] = (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
193 tvector3f[1] = (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
194 tvector3f[2] = (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
198 const float *m = boneposerelative[wi[0]];
200 tvector3f[0] = f * (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
201 tvector3f[1] = f * (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
202 tvector3f[2] = f * (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
203 for (k = 1;k < 4 && wf[k];k++)
205 const float *m = boneposerelative[wi[k]];
207 tvector3f[0] += f * (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
208 tvector3f[1] += f * (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
209 tvector3f[2] += f * (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
216 void Mod_MD3_AnimateVertices(const model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
219 int i, numblends, blendnum;
220 int numverts = model->surfmesh.num_vertices;
222 for (blendnum = 0;blendnum < 4;blendnum++)
224 //VectorMA(translate, model->surfmesh.num_morphmdlframetranslate, frameblend[blendnum].lerp, translate);
225 if (frameblend[blendnum].lerp > 0)
226 numblends = blendnum + 1;
228 // special case for the first blend because it avoids some adds and the need to memset the arrays first
229 for (blendnum = 0;blendnum < numblends;blendnum++)
231 const md3vertex_t *verts = model->surfmesh.data_morphmd3vertex + numverts * frameblend[blendnum].frame;
232 float scale = frameblend[blendnum].lerp * (1.0f / 64.0f);
235 for (i = 0;i < numverts;i++)
237 vertex3f[i * 3 + 0] = verts[i].origin[0] * scale;
238 vertex3f[i * 3 + 1] = verts[i].origin[1] * scale;
239 vertex3f[i * 3 + 2] = verts[i].origin[2] * scale;
244 for (i = 0;i < numverts;i++)
246 vertex3f[i * 3 + 0] += verts[i].origin[0] * scale;
247 vertex3f[i * 3 + 1] += verts[i].origin[1] * scale;
248 vertex3f[i * 3 + 2] += verts[i].origin[2] * scale;
251 // the yaw and pitch stored in md3 models are 8bit quantized angles
252 // (0-255), and as such a lookup table is very well suited to
253 // decoding them, and since cosine is equivilant to sine with an
254 // extra 45 degree rotation, this uses one lookup table for both
255 // sine and cosine with a +64 bias to get cosine.
258 float lerp = frameblend[blendnum].lerp;
261 for (i = 0;i < numverts;i++)
263 normal3f[i * 3 + 0] = mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
264 normal3f[i * 3 + 1] = mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
265 normal3f[i * 3 + 2] = mod_md3_sin[verts[i].pitch + 64] * lerp;
270 for (i = 0;i < numverts;i++)
272 normal3f[i * 3 + 0] += mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
273 normal3f[i * 3 + 1] += mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
274 normal3f[i * 3 + 2] += mod_md3_sin[verts[i].pitch + 64] * lerp;
280 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].frame;
281 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
284 for (i = 0;i < numverts;i++, texvecvert++)
286 VectorScale(texvecvert->svec, f, svector3f + i*3);
287 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
292 for (i = 0;i < numverts;i++, texvecvert++)
294 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
295 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
302 void Mod_MDL_AnimateVertices(const model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
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 int Mod_Alias_GetTagMatrix(const model_t *model, int poseframe, int tagindex, matrix4x4_t *outmatrix)
398 const float *boneframe;
399 float tempbonematrix[12], bonematrix[12];
400 *outmatrix = identitymatrix;
401 if (model->num_bones)
403 if (tagindex < 0 || tagindex >= model->num_bones)
405 if (poseframe >= model->num_poses)
407 boneframe = model->data_poses + poseframe * model->num_bones * 12;
408 memcpy(bonematrix, boneframe + tagindex * 12, sizeof(float[12]));
409 while (model->data_bones[tagindex].parent >= 0)
411 memcpy(tempbonematrix, bonematrix, sizeof(float[12]));
412 R_ConcatTransforms(boneframe + model->data_bones[tagindex].parent * 12, tempbonematrix, bonematrix);
413 tagindex = model->data_bones[tagindex].parent;
415 Matrix4x4_FromArray12FloatD3D(outmatrix, bonematrix);
417 else if (model->num_tags)
419 if (tagindex < 0 || tagindex >= model->num_tags)
421 if (poseframe >= model->num_tagframes)
423 Matrix4x4_FromArray12FloatGL(outmatrix, model->data_tags[poseframe * model->num_tags + tagindex].matrixgl);
428 int Mod_Alias_GetTagIndexForName(const model_t *model, unsigned int skin, const char *tagname)
431 if(skin >= (unsigned int)model->numskins)
433 if (model->data_overridetagnamesforskin && skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)skin].num_overridetagnames)
434 for (i = 0;i < model->data_overridetagnamesforskin[skin].num_overridetagnames;i++)
435 if (!strcasecmp(tagname, model->data_overridetagnamesforskin[skin].data_overridetagnames[i].name))
437 if (model->num_bones)
438 for (i = 0;i < model->num_bones;i++)
439 if (!strcasecmp(tagname, model->data_bones[i].name))
442 for (i = 0;i < model->num_tags;i++)
443 if (!strcasecmp(tagname, model->data_tags[i].name))
448 static void Mod_BuildBaseBonePoses(void)
452 float *basebonepose = Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(float[12]));
453 float *in12f = loadmodel->data_poses;
454 float *out12f = basebonepose;
455 float *outinv12f = loadmodel->data_baseboneposeinverse;
456 for (i = 0;i < loadmodel->num_bones;i++, in12f += 12, out12f += 12, outinv12f += 12)
458 if (loadmodel->data_bones[i].parent >= 0)
459 R_ConcatTransforms(basebonepose + 12 * loadmodel->data_bones[i].parent, in12f, out12f);
461 for (k = 0;k < 12;k++)
462 out12f[k] = in12f[k];
466 // we only support uniform scaling, so assume the first row is enough
467 // (note the lack of sqrt here, because we're trying to undo the scaling,
468 // this means multiplying by the inverse scale twice - squaring it, which
469 // makes the sqrt a waste of time)
470 scale = 1.0 / (out12f[ 0] * out12f[ 0] + out12f[ 1] * out12f[ 1] + out12f[ 2] * out12f[ 2]);
472 // invert the rotation by transposing and multiplying by the squared
473 // recipricol of the input matrix scale as described above
474 outinv12f[ 0] = (float)(out12f[ 0] * scale);
475 outinv12f[ 1] = (float)(out12f[ 4] * scale);
476 outinv12f[ 2] = (float)(out12f[ 8] * scale);
477 outinv12f[ 4] = (float)(out12f[ 1] * scale);
478 outinv12f[ 5] = (float)(out12f[ 5] * scale);
479 outinv12f[ 6] = (float)(out12f[ 9] * scale);
480 outinv12f[ 8] = (float)(out12f[ 2] * scale);
481 outinv12f[ 9] = (float)(out12f[ 6] * scale);
482 outinv12f[10] = (float)(out12f[10] * scale);
484 // invert the translate
485 outinv12f[ 3] = -(out12f[ 3] * outinv12f[ 0] + out12f[ 7] * outinv12f[ 1] + out12f[11] * outinv12f[ 2]);
486 outinv12f[ 7] = -(out12f[ 3] * outinv12f[ 4] + out12f[ 7] * outinv12f[ 5] + out12f[11] * outinv12f[ 6]);
487 outinv12f[11] = -(out12f[ 3] * outinv12f[ 8] + out12f[ 7] * outinv12f[ 9] + out12f[11] * outinv12f[10]);
489 Mem_Free(basebonepose);
492 static void Mod_Alias_CalculateBoundingBox(void)
495 qboolean firstvertex = true;
496 float dist, yawradius, radius;
499 frameblend_t frameblend[4];
500 memset(frameblend, 0, sizeof(frameblend));
501 frameblend[0].lerp = 1;
502 vertex3f = Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
503 VectorClear(loadmodel->normalmins);
504 VectorClear(loadmodel->normalmaxs);
507 for (frameblend[0].frame = 0;frameblend[0].frame < loadmodel->num_poses;frameblend[0].frame++)
509 loadmodel->AnimateVertices(loadmodel, frameblend, vertex3f, NULL, NULL, NULL);
510 for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
515 VectorCopy(v, loadmodel->normalmins);
516 VectorCopy(v, loadmodel->normalmaxs);
520 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
521 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
522 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
523 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
524 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
525 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
527 dist = v[0] * v[0] + v[1] * v[1];
528 if (yawradius < dist)
536 radius = sqrt(radius);
537 yawradius = sqrt(yawradius);
538 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
539 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
540 loadmodel->yawmins[2] = loadmodel->normalmins[2];
541 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
542 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
543 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
544 loadmodel->radius = radius;
545 loadmodel->radius2 = radius * radius;
548 static void Mod_Alias_MorphMesh_CompileFrames(void)
551 frameblend_t frameblend[4] = {{0, 1}, {0, 0}, {0, 0}, {0, 0}};
552 unsigned char *datapointer;
553 datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
554 loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
555 loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
556 loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
557 loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
558 loadmodel->surfmesh.data_morphtexvecvertex = (texvecvertex_t *)datapointer;datapointer += loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices * sizeof(texvecvertex_t);
559 // 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)
560 for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
562 frameblend[0].frame = i;
563 loadmodel->AnimateVertices(loadmodel, frameblend, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
564 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);
565 // encode the svector and tvector in 3 byte format for permanent storage
566 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
568 VectorScale(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
569 VectorScale(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
574 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)
577 float segmentmins[3], segmentmaxs[3];
578 frameblend_t frameblend[4];
580 static int maxvertices = 0;
581 static float *vertex3f = NULL;
582 memset(trace, 0, sizeof(*trace));
584 trace->realfraction = 1;
585 trace->hitsupercontentsmask = hitsupercontentsmask;
586 memset(frameblend, 0, sizeof(frameblend));
587 frameblend[0].frame = frame;
588 frameblend[0].lerp = 1;
589 if (maxvertices < model->surfmesh.num_vertices)
593 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
594 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
596 if (VectorLength2(boxmins) + VectorLength2(boxmaxs) == 0)
599 segmentmins[0] = min(start[0], end[0]) - 1;
600 segmentmins[1] = min(start[1], end[1]) - 1;
601 segmentmins[2] = min(start[2], end[2]) - 1;
602 segmentmaxs[0] = max(start[0], end[0]) + 1;
603 segmentmaxs[1] = max(start[1], end[1]) + 1;
604 segmentmaxs[2] = max(start[2], end[2]) + 1;
605 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
607 model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL);
608 Collision_TraceLineTriangleMeshFloat(trace, start, end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, SUPERCONTENTS_SOLID, 0, surface->texture, segmentmins, segmentmaxs);
613 // box trace, performed as brush trace
614 colbrushf_t *thisbrush_start, *thisbrush_end;
615 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
616 segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
617 segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
618 segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
619 segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
620 segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
621 segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
622 VectorAdd(start, boxmins, boxstartmins);
623 VectorAdd(start, boxmaxs, boxstartmaxs);
624 VectorAdd(end, boxmins, boxendmins);
625 VectorAdd(end, boxmaxs, boxendmaxs);
626 thisbrush_start = Collision_BrushForBox(&identitymatrix, boxstartmins, boxstartmaxs, 0, 0, NULL);
627 thisbrush_end = Collision_BrushForBox(&identitymatrix, boxendmins, boxendmaxs, 0, 0, NULL);
628 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
630 if (maxvertices < model->surfmesh.num_vertices)
634 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
635 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
637 model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL);
638 Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, SUPERCONTENTS_SOLID, 0, surface->texture, segmentmins, segmentmaxs);
643 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
646 for (i = 0;i < inverts;i++)
648 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
650 j = vertremap[i]; // not onseam
653 j = vertremap[i+inverts]; // onseam
659 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
661 int i, f, pose, groupframes;
663 daliasframetype_t *pframetype;
664 daliasframe_t *pinframe;
665 daliasgroup_t *group;
666 daliasinterval_t *intervals;
669 scene = loadmodel->animscenes;
670 for (f = 0;f < loadmodel->numframes;f++)
672 pframetype = (daliasframetype_t *)datapointer;
673 datapointer += sizeof(daliasframetype_t);
674 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
676 // a single frame is still treated as a group
683 group = (daliasgroup_t *)datapointer;
684 datapointer += sizeof(daliasgroup_t);
685 groupframes = LittleLong (group->numframes);
687 // intervals (time per frame)
688 intervals = (daliasinterval_t *)datapointer;
689 datapointer += sizeof(daliasinterval_t) * groupframes;
691 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
692 if (interval < 0.01f)
694 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
699 // get scene name from first frame
700 pinframe = (daliasframe_t *)datapointer;
702 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
703 scene->firstframe = pose;
704 scene->framecount = groupframes;
705 scene->framerate = 1.0f / interval;
710 for (i = 0;i < groupframes;i++)
712 pinframe = (daliasframe_t *)datapointer;
713 datapointer += sizeof(daliasframe_t);
714 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
715 datapointer += sizeof(trivertx_t) * inverts;
721 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
723 if (cls.state == ca_dedicated)
727 skinframe = R_SkinFrame_LoadMissing();
728 memset(texture, 0, sizeof(*texture));
729 texture->currentframe = texture;
730 //texture->animated = false;
731 texture->numskinframes = 1;
732 texture->skinframerate = 1;
733 texture->skinframes[0] = skinframe;
734 texture->currentskinframe = skinframe;
735 //texture->backgroundnumskinframes = 0;
736 //texture->customblendfunc[0] = 0;
737 //texture->customblendfunc[1] = 0;
738 //texture->surfaceflags = 0;
739 //texture->supercontents = 0;
740 //texture->surfaceparms = 0;
741 //texture->textureflags = 0;
743 texture->basematerialflags = MATERIALFLAG_WALL;
744 if (texture->currentskinframe->fog)
745 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
746 texture->currentmaterialflags = texture->basematerialflags;
749 static void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, char *meshname, char *shadername)
752 skinfileitem_t *skinfileitem;
755 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
756 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
758 memset(skin, 0, sizeof(*skin));
760 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
762 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
763 if (!strcmp(skinfileitem->name, meshname))
765 Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
771 // don't render unmentioned meshes
772 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
773 skin->basematerialflags = skin->currentmaterialflags = 0;
778 Mod_LoadTextureFromQ3Shader(skin, shadername, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
781 #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);
782 #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);
783 void Mod_IDP0_Load(model_t *mod, void *buffer, void *bufferend)
785 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
786 float scales, scalet, interval;
790 stvert_t *pinstverts;
791 dtriangle_t *pintriangles;
792 daliasskintype_t *pinskintype;
793 daliasskingroup_t *pinskingroup;
794 daliasskininterval_t *pinskinintervals;
795 daliasframetype_t *pinframetype;
796 daliasgroup_t *pinframegroup;
797 unsigned char *datapointer, *startframes, *startskins;
798 char name[MAX_QPATH];
799 skinframe_t *tempskinframe;
800 animscene_t *tempskinscenes;
801 texture_t *tempaliasskins;
803 int *vertonseam, *vertremap;
804 skinfile_t *skinfiles;
806 datapointer = (unsigned char *)buffer;
807 pinmodel = (mdl_t *)datapointer;
808 datapointer += sizeof(mdl_t);
810 version = LittleLong (pinmodel->version);
811 if (version != ALIAS_VERSION)
812 Host_Error ("%s has wrong version number (%i should be %i)",
813 loadmodel->name, version, ALIAS_VERSION);
815 loadmodel->modeldatatypestring = "MDL";
817 loadmodel->type = mod_alias;
818 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
819 loadmodel->DrawSky = NULL;
820 loadmodel->DrawAddWaterPlanes = NULL;
821 loadmodel->Draw = R_Q1BSP_Draw;
822 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
823 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
824 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
825 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
826 loadmodel->DrawLight = R_Q1BSP_DrawLight;
827 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
828 loadmodel->PointSuperContents = NULL;
830 loadmodel->num_surfaces = 1;
831 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
832 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
833 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
834 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
835 loadmodel->surfacelist[0] = 0;
837 loadmodel->numskins = LittleLong(pinmodel->numskins);
838 BOUNDI(loadmodel->numskins,0,65536);
839 skinwidth = LittleLong (pinmodel->skinwidth);
840 BOUNDI(skinwidth,0,65536);
841 skinheight = LittleLong (pinmodel->skinheight);
842 BOUNDI(skinheight,0,65536);
843 numverts = LittleLong(pinmodel->numverts);
844 BOUNDI(numverts,0,65536);
845 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
846 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
847 loadmodel->numframes = LittleLong(pinmodel->numframes);
848 BOUNDI(loadmodel->numframes,0,65536);
849 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
850 BOUNDI(loadmodel->synctype,0,2);
851 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
852 i = LittleLong (pinmodel->flags);
853 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
855 for (i = 0;i < 3;i++)
857 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
858 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
861 startskins = datapointer;
863 for (i = 0;i < loadmodel->numskins;i++)
865 pinskintype = (daliasskintype_t *)datapointer;
866 datapointer += sizeof(daliasskintype_t);
867 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
871 pinskingroup = (daliasskingroup_t *)datapointer;
872 datapointer += sizeof(daliasskingroup_t);
873 groupskins = LittleLong(pinskingroup->numskins);
874 datapointer += sizeof(daliasskininterval_t) * groupskins;
877 for (j = 0;j < groupskins;j++)
879 datapointer += skinwidth * skinheight;
884 pinstverts = (stvert_t *)datapointer;
885 datapointer += sizeof(stvert_t) * numverts;
887 pintriangles = (dtriangle_t *)datapointer;
888 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
890 startframes = datapointer;
891 loadmodel->surfmesh.num_morphframes = 0;
892 for (i = 0;i < loadmodel->numframes;i++)
894 pinframetype = (daliasframetype_t *)datapointer;
895 datapointer += sizeof(daliasframetype_t);
896 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
900 pinframegroup = (daliasgroup_t *)datapointer;
901 datapointer += sizeof(daliasgroup_t);
902 groupframes = LittleLong(pinframegroup->numframes);
903 datapointer += sizeof(daliasinterval_t) * groupframes;
906 for (j = 0;j < groupframes;j++)
908 datapointer += sizeof(daliasframe_t);
909 datapointer += sizeof(trivertx_t) * numverts;
910 loadmodel->surfmesh.num_morphframes++;
913 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
915 // store texture coordinates into temporary array, they will be stored
916 // after usage is determined (triangle data)
917 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
918 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
919 vertonseam = vertremap + numverts * 2;
921 scales = 1.0 / skinwidth;
922 scalet = 1.0 / skinheight;
923 for (i = 0;i < numverts;i++)
925 vertonseam[i] = LittleLong(pinstverts[i].onseam);
926 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
927 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
928 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
929 vertst[(i+numverts)*2+1] = vertst[i*2+1];
932 // load triangle data
933 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
935 // read the triangle elements
936 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
937 for (j = 0;j < 3;j++)
938 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
939 // validate (note numverts is used because this is the original data)
940 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
941 // now butcher the elements according to vertonseam and tri->facesfront
942 // and then compact the vertex set to remove duplicates
943 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
944 if (!LittleLong(pintriangles[i].facesfront)) // backface
945 for (j = 0;j < 3;j++)
946 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
947 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
949 // (this uses vertremap to count usage to save some memory)
950 for (i = 0;i < numverts*2;i++)
952 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
953 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
954 // build remapping table and compact array
955 loadmodel->surfmesh.num_vertices = 0;
956 for (i = 0;i < numverts*2;i++)
960 vertremap[i] = loadmodel->surfmesh.num_vertices;
961 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
962 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
963 loadmodel->surfmesh.num_vertices++;
966 vertremap[i] = -1; // not used at all
968 // remap the elements to the new vertex set
969 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
970 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
971 // store the texture coordinates
972 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
973 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
975 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
976 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
980 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
981 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
982 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
983 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
984 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
985 Mod_Alias_CalculateBoundingBox();
986 Mod_Alias_MorphMesh_CompileFrames();
992 skinfiles = Mod_LoadSkinFiles();
993 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
994 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
995 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
996 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
999 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1000 Mod_FreeSkinFiles(skinfiles);
1001 for (i = 0;i < loadmodel->numskins;i++)
1003 loadmodel->skinscenes[i].firstframe = i;
1004 loadmodel->skinscenes[i].framecount = 1;
1005 loadmodel->skinscenes[i].loop = true;
1006 loadmodel->skinscenes[i].framerate = 10;
1012 datapointer = startskins;
1013 for (i = 0;i < loadmodel->numskins;i++)
1015 pinskintype = (daliasskintype_t *)datapointer;
1016 datapointer += sizeof(daliasskintype_t);
1018 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1025 pinskingroup = (daliasskingroup_t *)datapointer;
1026 datapointer += sizeof(daliasskingroup_t);
1028 groupskins = LittleLong (pinskingroup->numskins);
1030 pinskinintervals = (daliasskininterval_t *)datapointer;
1031 datapointer += sizeof(daliasskininterval_t) * groupskins;
1033 interval = LittleFloat(pinskinintervals[0].interval);
1034 if (interval < 0.01f)
1036 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1041 sprintf(loadmodel->skinscenes[i].name, "skin %i", i);
1042 loadmodel->skinscenes[i].firstframe = totalskins;
1043 loadmodel->skinscenes[i].framecount = groupskins;
1044 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1045 loadmodel->skinscenes[i].loop = true;
1047 for (j = 0;j < groupskins;j++)
1050 sprintf (name, "%s_%i_%i", loadmodel->name, i, j);
1052 sprintf (name, "%s_%i", loadmodel->name, i);
1053 if (!Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, name, false, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS))
1054 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, R_SkinFrame_LoadInternalQuake(name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP, true, r_fullbrights.integer, (unsigned char *)datapointer, skinwidth, skinheight));
1055 datapointer += skinwidth * skinheight;
1059 // check for skins that don't exist in the model, but do exist as external images
1060 // (this was added because yummyluv kept pestering me about support for it)
1061 // TODO: support shaders here?
1062 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)))
1064 // expand the arrays to make room
1065 tempskinscenes = loadmodel->skinscenes;
1066 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1067 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1068 Mem_Free(tempskinscenes);
1070 tempaliasskins = loadmodel->data_textures;
1071 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1072 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1073 Mem_Free(tempaliasskins);
1075 // store the info about the new skin
1076 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1077 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1078 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1079 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1080 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1081 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1083 //increase skin counts
1084 loadmodel->numskins++;
1087 // fix up the pointers since they are pointing at the old textures array
1088 // FIXME: this is a hack!
1089 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1090 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1094 surface = loadmodel->data_surfaces;
1095 surface->texture = loadmodel->data_textures;
1096 surface->num_firsttriangle = 0;
1097 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1098 surface->num_firstvertex = 0;
1099 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1101 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1104 void Mod_IDP2_Load(model_t *mod, void *buffer, void *bufferend)
1106 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1107 float iskinwidth, iskinheight;
1108 unsigned char *data;
1109 msurface_t *surface;
1111 unsigned char *base, *datapointer;
1112 md2frame_t *pinframe;
1114 md2triangle_t *intri;
1115 unsigned short *inst;
1116 struct md2verthash_s
1118 struct md2verthash_s *next;
1122 *hash, **md2verthash, *md2verthashdata;
1123 skinfile_t *skinfiles;
1125 pinmodel = (md2_t *)buffer;
1126 base = (unsigned char *)buffer;
1128 version = LittleLong (pinmodel->version);
1129 if (version != MD2ALIAS_VERSION)
1130 Host_Error ("%s has wrong version number (%i should be %i)",
1131 loadmodel->name, version, MD2ALIAS_VERSION);
1133 loadmodel->modeldatatypestring = "MD2";
1135 loadmodel->type = mod_alias;
1136 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1137 loadmodel->DrawSky = NULL;
1138 loadmodel->DrawAddWaterPlanes = NULL;
1139 loadmodel->Draw = R_Q1BSP_Draw;
1140 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1141 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1142 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1143 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1144 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1145 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1146 loadmodel->PointSuperContents = NULL;
1148 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1149 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1150 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1151 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1152 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1153 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1154 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1155 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1157 end = LittleLong(pinmodel->ofs_end);
1158 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1159 Host_Error ("%s is not a valid model", loadmodel->name);
1160 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1161 Host_Error ("%s is not a valid model", loadmodel->name);
1162 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1163 Host_Error ("%s is not a valid model", loadmodel->name);
1164 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1165 Host_Error ("%s is not a valid model", loadmodel->name);
1166 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1167 Host_Error ("%s is not a valid model", loadmodel->name);
1169 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1170 numxyz = LittleLong(pinmodel->num_xyz);
1171 numst = LittleLong(pinmodel->num_st);
1172 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1173 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1174 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1175 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1176 skinwidth = LittleLong(pinmodel->skinwidth);
1177 skinheight = LittleLong(pinmodel->skinheight);
1178 iskinwidth = 1.0f / skinwidth;
1179 iskinheight = 1.0f / skinheight;
1181 loadmodel->num_surfaces = 1;
1182 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1183 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]));
1184 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1185 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1186 loadmodel->surfacelist[0] = 0;
1187 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1188 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1189 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1190 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1192 loadmodel->synctype = ST_RAND;
1195 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1196 skinfiles = Mod_LoadSkinFiles();
1199 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1200 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1201 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1202 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1203 Mod_FreeSkinFiles(skinfiles);
1205 else if (loadmodel->numskins)
1207 // skins found (most likely not a player model)
1208 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1209 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1210 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1211 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1212 Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
1216 // no skins (most likely a player model)
1217 loadmodel->numskins = 1;
1218 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1219 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1220 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1221 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1224 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1225 for (i = 0;i < loadmodel->numskins;i++)
1227 loadmodel->skinscenes[i].firstframe = i;
1228 loadmodel->skinscenes[i].framecount = 1;
1229 loadmodel->skinscenes[i].loop = true;
1230 loadmodel->skinscenes[i].framerate = 10;
1233 // load the triangles and stvert data
1234 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1235 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1236 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1237 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1238 // swap the triangle list
1239 loadmodel->surfmesh.num_vertices = 0;
1240 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1242 for (j = 0;j < 3;j++)
1244 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1245 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1248 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1253 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1256 hashindex = (xyz * 256 + st) & 65535;
1257 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1258 if (hash->xyz == xyz && hash->st == st)
1262 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1265 hash->next = md2verthash[hashindex];
1266 md2verthash[hashindex] = hash;
1268 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1272 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1273 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));
1274 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1275 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1276 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1279 hash = md2verthashdata + i;
1280 vertremap[i] = hash->xyz;
1281 sts = LittleShort(inst[hash->st*2+0]);
1282 stt = LittleShort(inst[hash->st*2+1]);
1283 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1285 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1289 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1290 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1293 Mem_Free(md2verthash);
1294 Mem_Free(md2verthashdata);
1297 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1298 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1303 pinframe = (md2frame_t *)datapointer;
1304 datapointer += sizeof(md2frame_t);
1305 // store the frame scale/translate into the appropriate array
1306 for (j = 0;j < 3;j++)
1308 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1309 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1311 // convert the vertices
1312 v = (trivertx_t *)datapointer;
1313 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1314 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1315 out[k] = v[vertremap[k]];
1316 datapointer += numxyz * sizeof(trivertx_t);
1318 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1319 loadmodel->animscenes[i].firstframe = i;
1320 loadmodel->animscenes[i].framecount = 1;
1321 loadmodel->animscenes[i].framerate = 10;
1322 loadmodel->animscenes[i].loop = true;
1325 Mem_Free(vertremap);
1327 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1328 Mod_Alias_CalculateBoundingBox();
1329 Mod_Alias_MorphMesh_CompileFrames();
1331 surface = loadmodel->data_surfaces;
1332 surface->texture = loadmodel->data_textures;
1333 surface->num_firsttriangle = 0;
1334 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1335 surface->num_firstvertex = 0;
1336 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1338 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1341 void Mod_IDP3_Load(model_t *mod, void *buffer, void *bufferend)
1343 int i, j, k, version, meshvertices, meshtriangles;
1344 unsigned char *data;
1345 msurface_t *surface;
1346 md3modelheader_t *pinmodel;
1347 md3frameinfo_t *pinframe;
1350 skinfile_t *skinfiles;
1352 pinmodel = (md3modelheader_t *)buffer;
1354 if (memcmp(pinmodel->identifier, "IDP3", 4))
1355 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1356 version = LittleLong (pinmodel->version);
1357 if (version != MD3VERSION)
1358 Host_Error ("%s has wrong version number (%i should be %i)",
1359 loadmodel->name, version, MD3VERSION);
1361 skinfiles = Mod_LoadSkinFiles();
1362 if (loadmodel->numskins < 1)
1363 loadmodel->numskins = 1;
1365 loadmodel->modeldatatypestring = "MD3";
1367 loadmodel->type = mod_alias;
1368 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1369 loadmodel->DrawSky = NULL;
1370 loadmodel->DrawAddWaterPlanes = NULL;
1371 loadmodel->Draw = R_Q1BSP_Draw;
1372 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1373 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1374 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1375 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1376 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1377 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1378 loadmodel->PointSuperContents = NULL;
1379 loadmodel->synctype = ST_RAND;
1380 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1381 i = LittleLong (pinmodel->flags);
1382 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1384 // set up some global info about the model
1385 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1386 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1388 // make skinscenes for the skins (no groups)
1389 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1390 for (i = 0;i < loadmodel->numskins;i++)
1392 loadmodel->skinscenes[i].firstframe = i;
1393 loadmodel->skinscenes[i].framecount = 1;
1394 loadmodel->skinscenes[i].loop = true;
1395 loadmodel->skinscenes[i].framerate = 10;
1399 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1400 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1402 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1403 loadmodel->animscenes[i].firstframe = i;
1404 loadmodel->animscenes[i].framecount = 1;
1405 loadmodel->animscenes[i].framerate = 10;
1406 loadmodel->animscenes[i].loop = true;
1410 loadmodel->num_tagframes = loadmodel->numframes;
1411 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1412 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1413 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1415 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1416 for (j = 0;j < 9;j++)
1417 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1418 for (j = 0;j < 3;j++)
1419 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1420 //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);
1426 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)))
1428 if (memcmp(pinmesh->identifier, "IDP3", 4))
1429 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1430 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1431 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1432 meshvertices += LittleLong(pinmesh->num_vertices);
1433 meshtriangles += LittleLong(pinmesh->num_triangles);
1436 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1437 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1438 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1439 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));
1440 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1441 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1442 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1443 loadmodel->surfmesh.num_vertices = meshvertices;
1444 loadmodel->surfmesh.num_triangles = meshtriangles;
1445 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1446 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1447 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1448 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1449 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1450 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1454 for (i = 0, pinmesh = (md3mesh_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_meshes));i < loadmodel->num_surfaces;i++, pinmesh = (md3mesh_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_end)))
1456 if (memcmp(pinmesh->identifier, "IDP3", 4))
1457 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1458 loadmodel->surfacelist[i] = i;
1459 surface = loadmodel->data_surfaces + i;
1460 surface->texture = loadmodel->data_textures + i;
1461 surface->num_firsttriangle = meshtriangles;
1462 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1463 surface->num_firstvertex = meshvertices;
1464 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1465 meshvertices += surface->num_vertices;
1466 meshtriangles += surface->num_triangles;
1468 for (j = 0;j < surface->num_triangles * 3;j++)
1469 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1470 for (j = 0;j < surface->num_vertices;j++)
1472 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1473 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1475 for (j = 0;j < loadmodel->numframes;j++)
1477 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1478 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1479 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1481 out->origin[0] = LittleShort(in->origin[0]);
1482 out->origin[1] = LittleShort(in->origin[1]);
1483 out->origin[2] = LittleShort(in->origin[2]);
1484 out->pitch = in->pitch;
1489 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1491 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1493 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1494 Mod_Alias_MorphMesh_CompileFrames();
1495 Mod_Alias_CalculateBoundingBox();
1496 Mod_FreeSkinFiles(skinfiles);
1498 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1499 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1502 void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer, void *bufferend)
1504 zymtype1header_t *pinmodel, *pheader;
1505 unsigned char *pbase;
1506 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1507 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose;
1508 zymvertex_t *verts, *vertdata;
1512 skinfile_t *skinfiles;
1513 unsigned char *data;
1514 msurface_t *surface;
1516 pinmodel = (zymtype1header_t *)buffer;
1517 pbase = (unsigned char *)buffer;
1518 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1519 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1520 if (BigLong(pinmodel->type) != 1)
1521 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1523 loadmodel->modeldatatypestring = "ZYM";
1525 loadmodel->type = mod_alias;
1526 loadmodel->synctype = ST_RAND;
1530 pheader->type = BigLong(pinmodel->type);
1531 pheader->filesize = BigLong(pinmodel->filesize);
1532 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1533 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1534 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1535 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1536 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1537 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1538 pheader->radius = BigFloat(pinmodel->radius);
1539 pheader->numverts = BigLong(pinmodel->numverts);
1540 pheader->numtris = BigLong(pinmodel->numtris);
1541 pheader->numshaders = BigLong(pinmodel->numshaders);
1542 pheader->numbones = BigLong(pinmodel->numbones);
1543 pheader->numscenes = BigLong(pinmodel->numscenes);
1544 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1545 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1546 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1547 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1548 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1549 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1550 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1551 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1552 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1553 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1554 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1555 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1556 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1557 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1558 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1559 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1560 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1561 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1563 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1565 Con_Printf("%s has no geometry\n", loadmodel->name);
1568 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1570 Con_Printf("%s has no animations\n", loadmodel->name);
1574 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1575 loadmodel->DrawSky = NULL;
1576 loadmodel->DrawAddWaterPlanes = NULL;
1577 loadmodel->Draw = R_Q1BSP_Draw;
1578 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1579 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1580 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1581 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1582 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1583 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1584 loadmodel->PointSuperContents = NULL;
1586 loadmodel->numframes = pheader->numscenes;
1587 loadmodel->num_surfaces = pheader->numshaders;
1589 skinfiles = Mod_LoadSkinFiles();
1590 if (loadmodel->numskins < 1)
1591 loadmodel->numskins = 1;
1593 // make skinscenes for the skins (no groups)
1594 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1595 for (i = 0;i < loadmodel->numskins;i++)
1597 loadmodel->skinscenes[i].firstframe = i;
1598 loadmodel->skinscenes[i].framecount = 1;
1599 loadmodel->skinscenes[i].loop = true;
1600 loadmodel->skinscenes[i].framerate = 10;
1604 modelradius = pheader->radius;
1605 for (i = 0;i < 3;i++)
1607 loadmodel->normalmins[i] = pheader->mins[i];
1608 loadmodel->normalmaxs[i] = pheader->maxs[i];
1609 loadmodel->rotatedmins[i] = -modelradius;
1610 loadmodel->rotatedmaxs[i] = modelradius;
1612 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1613 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1614 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1615 if (loadmodel->yawmaxs[0] > modelradius)
1616 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1617 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1618 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1619 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1620 loadmodel->radius = modelradius;
1621 loadmodel->radius2 = modelradius * modelradius;
1623 // go through the lumps, swapping things
1625 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1626 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1627 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1628 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1629 for (i = 0;i < pheader->numscenes;i++)
1631 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1632 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1633 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1634 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1635 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1636 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1637 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1638 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1639 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1640 if (loadmodel->animscenes[i].framerate < 0)
1641 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1645 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1646 loadmodel->num_bones = pheader->numbones;
1647 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, pheader->numbones * sizeof(aliasbone_t));
1648 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1649 for (i = 0;i < pheader->numbones;i++)
1651 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1652 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1653 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1654 if (loadmodel->data_bones[i].parent >= i)
1655 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1658 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1659 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1660 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1661 for (i = 0;i < pheader->numverts;i++)
1663 vertbonecounts[i] = BigLong(bonecount[i]);
1664 if (vertbonecounts[i] != 1)
1665 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1668 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]);
1670 meshvertices = pheader->numverts;
1671 meshtriangles = pheader->numtris;
1673 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1674 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1675 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1676 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + meshtriangles * sizeof(int[3]) + meshvertices * sizeof(float[14]) + meshvertices * sizeof(int[4]) + meshvertices * sizeof(float[4]) + loadmodel->num_poses * sizeof(float[12]) + loadmodel->num_bones * sizeof(float[12]));
1677 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1678 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1679 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1680 loadmodel->surfmesh.num_vertices = meshvertices;
1681 loadmodel->surfmesh.num_triangles = meshtriangles;
1682 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1683 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1684 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1685 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1686 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1687 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1688 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1689 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1690 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1691 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
1692 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1694 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1695 poses = (float *) (pheader->lump_poses.start + pbase);
1696 for (i = 0;i < pheader->lump_poses.length / 4;i++)
1697 loadmodel->data_poses[i] = BigFloat(poses[i]);
1699 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1700 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1701 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1702 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1703 // (converting from weight-blending skeletal animation to
1704 // deformation-based skeletal animation)
1705 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1706 for (i = 0;i < loadmodel->num_bones;i++)
1708 const float *m = loadmodel->data_poses + i * 12;
1709 if (loadmodel->data_bones[i].parent >= 0)
1710 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1712 for (k = 0;k < 12;k++)
1713 bonepose[12*i+k] = m[k];
1715 for (j = 0;j < pheader->numverts;j++)
1717 // this format really should have had a per vertexweight weight value...
1718 // but since it does not, the weighting is completely ignored and
1719 // only one weight is allowed per vertex
1720 int boneindex = BigLong(vertdata[j].bonenum);
1721 const float *m = bonepose + 12 * boneindex;
1722 float relativeorigin[3];
1723 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1724 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1725 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1726 // transform the vertex bone weight into the base mesh
1727 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1728 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1729 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1730 // store the weight as the primary weight on this vertex
1731 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
1732 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = 1;
1735 // normals and tangents are calculated after elements are loaded
1737 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1738 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1739 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1740 for (i = 0;i < pheader->numverts;i++)
1742 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1743 // flip T coordinate for OpenGL
1744 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1747 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1748 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1749 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1751 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1752 //zymlump_t lump_render; // int renderlist[rendersize]; // sorted by shader with run lengths (int count), shaders are sequentially used, each run can be used with glDrawElements (each triangle is 3 int indices)
1753 // byteswap, validate, and swap winding order of tris
1754 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1755 if (pheader->lump_render.length != count)
1756 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1757 renderlist = (int *) (pheader->lump_render.start + pbase);
1758 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1760 for (i = 0;i < loadmodel->num_surfaces;i++)
1762 int firstvertex, lastvertex;
1763 if (renderlist >= renderlistend)
1764 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1765 count = BigLong(*renderlist);renderlist++;
1766 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1767 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1769 loadmodel->surfacelist[i] = i;
1770 surface = loadmodel->data_surfaces + i;
1771 surface->texture = loadmodel->data_textures + i;
1772 surface->num_firsttriangle = meshtriangles;
1773 surface->num_triangles = count;
1774 meshtriangles += surface->num_triangles;
1776 // load the elements
1777 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
1778 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
1780 outelements[j*3+2] = BigLong(renderlist[0]);
1781 outelements[j*3+1] = BigLong(renderlist[1]);
1782 outelements[j*3+0] = BigLong(renderlist[2]);
1784 // validate the elements and find the used vertex range
1785 firstvertex = meshvertices;
1787 for (j = 0;j < surface->num_triangles * 3;j++)
1789 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
1790 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
1791 firstvertex = min(firstvertex, outelements[j]);
1792 lastvertex = max(lastvertex, outelements[j]);
1794 surface->num_firstvertex = firstvertex;
1795 surface->num_vertices = lastvertex + 1 - firstvertex;
1797 // since zym models do not have named sections, reuse their shader
1798 // name as the section name
1799 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
1800 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
1802 Mod_FreeSkinFiles(skinfiles);
1803 Mem_Free(vertbonecounts);
1806 // compute all the mesh information that was not loaded from the file
1807 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
1808 Mod_BuildBaseBonePoses();
1809 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
1810 Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, true);
1811 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1813 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1816 void Mod_DARKPLACESMODEL_Load(model_t *mod, void *buffer, void *bufferend)
1818 dpmheader_t *pheader;
1822 unsigned char *pbase;
1823 int i, j, k, meshvertices, meshtriangles;
1824 skinfile_t *skinfiles;
1825 unsigned char *data;
1828 pheader = (dpmheader_t *)buffer;
1829 pbase = (unsigned char *)buffer;
1830 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
1831 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
1832 if (BigLong(pheader->type) != 2)
1833 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1835 loadmodel->modeldatatypestring = "DPM";
1837 loadmodel->type = mod_alias;
1838 loadmodel->synctype = ST_RAND;
1841 pheader->type = BigLong(pheader->type);
1842 pheader->filesize = BigLong(pheader->filesize);
1843 pheader->mins[0] = BigFloat(pheader->mins[0]);
1844 pheader->mins[1] = BigFloat(pheader->mins[1]);
1845 pheader->mins[2] = BigFloat(pheader->mins[2]);
1846 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
1847 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
1848 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
1849 pheader->yawradius = BigFloat(pheader->yawradius);
1850 pheader->allradius = BigFloat(pheader->allradius);
1851 pheader->num_bones = BigLong(pheader->num_bones);
1852 pheader->num_meshs = BigLong(pheader->num_meshs);
1853 pheader->num_frames = BigLong(pheader->num_frames);
1854 pheader->ofs_bones = BigLong(pheader->ofs_bones);
1855 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
1856 pheader->ofs_frames = BigLong(pheader->ofs_frames);
1858 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
1860 Con_Printf("%s has no geometry\n", loadmodel->name);
1863 if (pheader->num_frames < 1)
1865 Con_Printf("%s has no frames\n", loadmodel->name);
1869 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1870 loadmodel->DrawSky = NULL;
1871 loadmodel->DrawAddWaterPlanes = NULL;
1872 loadmodel->Draw = R_Q1BSP_Draw;
1873 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1874 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1875 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1876 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1877 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1878 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1879 loadmodel->PointSuperContents = NULL;
1882 for (i = 0;i < 3;i++)
1884 loadmodel->normalmins[i] = pheader->mins[i];
1885 loadmodel->normalmaxs[i] = pheader->maxs[i];
1886 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
1887 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
1888 loadmodel->rotatedmins[i] = -pheader->allradius;
1889 loadmodel->rotatedmaxs[i] = pheader->allradius;
1891 loadmodel->radius = pheader->allradius;
1892 loadmodel->radius2 = pheader->allradius * pheader->allradius;
1894 // load external .skin files if present
1895 skinfiles = Mod_LoadSkinFiles();
1896 if (loadmodel->numskins < 1)
1897 loadmodel->numskins = 1;
1902 // gather combined statistics from the meshes
1903 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
1904 for (i = 0;i < (int)pheader->num_meshs;i++)
1906 int numverts = BigLong(dpmmesh->num_verts);
1907 meshvertices += numverts;;
1908 meshtriangles += BigLong(dpmmesh->num_tris);
1912 loadmodel->numframes = pheader->num_frames;
1913 loadmodel->num_bones = pheader->num_bones;
1914 loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
1915 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
1916 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1917 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1918 // do most allocations as one merged chunk
1919 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));
1920 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1921 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1922 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1923 loadmodel->surfmesh.num_vertices = meshvertices;
1924 loadmodel->surfmesh.num_triangles = meshtriangles;
1925 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1926 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1927 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1928 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1929 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1930 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1931 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1932 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1933 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1934 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
1935 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1936 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
1937 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
1938 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1940 for (i = 0;i < loadmodel->numskins;i++)
1942 loadmodel->skinscenes[i].firstframe = i;
1943 loadmodel->skinscenes[i].framecount = 1;
1944 loadmodel->skinscenes[i].loop = true;
1945 loadmodel->skinscenes[i].framerate = 10;
1948 // load the bone info
1949 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
1950 for (i = 0;i < loadmodel->num_bones;i++)
1952 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1953 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1954 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1955 if (loadmodel->data_bones[i].parent >= i)
1956 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1960 frame = (dpmframe_t *) (pbase + pheader->ofs_frames);
1961 for (i = 0;i < loadmodel->numframes;i++)
1964 memcpy(loadmodel->animscenes[i].name, frame->name, sizeof(frame->name));
1965 loadmodel->animscenes[i].firstframe = i;
1966 loadmodel->animscenes[i].framecount = 1;
1967 loadmodel->animscenes[i].loop = true;
1968 loadmodel->animscenes[i].framerate = 10;
1969 // load the bone poses for this frame
1970 poses = (float *) (pbase + BigLong(frame->ofs_bonepositions));
1971 for (j = 0;j < loadmodel->num_bones*12;j++)
1972 loadmodel->data_poses[i * loadmodel->num_bones*12 + j] = BigFloat(poses[j]);
1973 // stuff not processed here: mins, maxs, yawradius, allradius
1977 // load the meshes now
1978 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
1981 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1982 // (converting from weight-blending skeletal animation to
1983 // deformation-based skeletal animation)
1984 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1985 for (i = 0;i < loadmodel->num_bones;i++)
1987 const float *m = loadmodel->data_poses + i * 12;
1988 if (loadmodel->data_bones[i].parent >= 0)
1989 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1991 for (k = 0;k < 12;k++)
1992 bonepose[12*i+k] = m[k];
1994 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
1996 const int *inelements;
1998 const float *intexcoord;
1999 msurface_t *surface;
2001 loadmodel->surfacelist[i] = i;
2002 surface = loadmodel->data_surfaces + i;
2003 surface->texture = loadmodel->data_textures + i;
2004 surface->num_firsttriangle = meshtriangles;
2005 surface->num_triangles = BigLong(dpmmesh->num_tris);
2006 surface->num_firstvertex = meshvertices;
2007 surface->num_vertices = BigLong(dpmmesh->num_verts);
2008 meshvertices += surface->num_vertices;
2009 meshtriangles += surface->num_triangles;
2011 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2012 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2013 for (j = 0;j < surface->num_triangles;j++)
2015 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2016 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2017 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2018 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2023 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2024 for (j = 0;j < surface->num_vertices*2;j++)
2025 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2027 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2028 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2032 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2033 data += sizeof(dpmvertex_t);
2034 for (k = 0;k < numweights;k++)
2036 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2037 int boneindex = BigLong(vert->bonenum);
2038 const float *m = bonepose + 12 * boneindex;
2039 float influence = BigFloat(vert->influence);
2040 float relativeorigin[3], relativenormal[3];
2041 relativeorigin[0] = BigFloat(vert->origin[0]);
2042 relativeorigin[1] = BigFloat(vert->origin[1]);
2043 relativeorigin[2] = BigFloat(vert->origin[2]);
2044 relativenormal[0] = BigFloat(vert->normal[0]);
2045 relativenormal[1] = BigFloat(vert->normal[1]);
2046 relativenormal[2] = BigFloat(vert->normal[2]);
2047 // blend the vertex bone weights into the base mesh
2048 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2049 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2050 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2051 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2052 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2053 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2056 // store the first (and often only) weight
2057 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = influence;
2058 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
2062 // sort the new weight into this vertex's weight table
2063 // (which only accepts up to 4 bones per vertex)
2064 for (l = 0;l < 4;l++)
2066 if (loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] < influence)
2068 // move weaker influence weights out of the way first
2070 for (l2 = 3;l2 > l;l2--)
2072 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2-1];
2073 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2-1];
2075 // store the new weight
2076 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] = influence;
2077 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l] = boneindex;
2082 data += sizeof(dpmbonevert_t);
2085 for (l = 0;l < 4;l++)
2086 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l];
2087 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2089 float f = 1.0f / sum;
2090 for (l = 0;l < 4;l++)
2091 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] *= f;
2095 // since dpm models do not have named sections, reuse their shader name as the section name
2096 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2098 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2101 Mod_FreeSkinFiles(skinfiles);
2103 // compute all the mesh information that was not loaded from the file
2104 Mod_BuildBaseBonePoses();
2105 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);
2106 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2108 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2111 // no idea why PSK/PSA files contain weird quaternions but they do...
2112 #define PSKQUATNEGATIONS
2113 void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend)
2115 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2116 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2117 fs_offset_t filesize;
2122 pskboneinfo_t *bones;
2123 pskrawweights_t *rawweights;
2124 pskboneinfo_t *animbones;
2125 pskaniminfo_t *anims;
2126 pskanimkeys_t *animkeys;
2127 void *animfilebuffer, *animbuffer, *animbufferend;
2128 unsigned char *data;
2130 skinfile_t *skinfiles;
2131 char animname[MAX_QPATH];
2133 pchunk = (pskchunk_t *)buffer;
2134 if (strcmp(pchunk->id, "ACTRHEAD"))
2135 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2137 loadmodel->modeldatatypestring = "PSK";
2139 loadmodel->type = mod_alias;
2140 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2141 loadmodel->DrawSky = NULL;
2142 loadmodel->DrawAddWaterPlanes = NULL;
2143 loadmodel->Draw = R_Q1BSP_Draw;
2144 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2145 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2146 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2147 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2148 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2149 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2150 loadmodel->PointSuperContents = NULL;
2151 loadmodel->synctype = ST_RAND;
2153 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2154 strlcat(animname, ".psa", sizeof(animname));
2155 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2156 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2157 if (animbuffer == NULL)
2158 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2177 while (buffer < bufferend)
2179 pchunk = (pskchunk_t *)buffer;
2180 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2181 version = LittleLong(pchunk->version);
2182 recordsize = LittleLong(pchunk->recordsize);
2183 numrecords = LittleLong(pchunk->numrecords);
2184 if (developer.integer >= 100)
2185 Con_Printf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2186 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2187 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);
2188 if (!strcmp(pchunk->id, "ACTRHEAD"))
2192 else if (!strcmp(pchunk->id, "PNTS0000"))
2195 if (recordsize != sizeof(*p))
2196 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2197 // byteswap in place and keep the pointer
2198 numpnts = numrecords;
2199 pnts = (pskpnts_t *)buffer;
2200 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2202 p->origin[0] = LittleFloat(p->origin[0]);
2203 p->origin[1] = LittleFloat(p->origin[1]);
2204 p->origin[2] = LittleFloat(p->origin[2]);
2208 else if (!strcmp(pchunk->id, "VTXW0000"))
2211 if (recordsize != sizeof(*p))
2212 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2213 // byteswap in place and keep the pointer
2214 numvtxw = numrecords;
2215 vtxw = (pskvtxw_t *)buffer;
2216 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2218 p->pntsindex = LittleShort(p->pntsindex);
2219 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2220 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2221 if (p->pntsindex >= numpnts)
2223 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2229 else if (!strcmp(pchunk->id, "FACE0000"))
2232 if (recordsize != sizeof(*p))
2233 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2234 // byteswap in place and keep the pointer
2235 numfaces = numrecords;
2236 faces = (pskface_t *)buffer;
2237 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2239 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2240 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2241 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2242 p->group = LittleLong(p->group);
2243 if (p->vtxwindex[0] >= numvtxw)
2245 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2246 p->vtxwindex[0] = 0;
2248 if (p->vtxwindex[1] >= numvtxw)
2250 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2251 p->vtxwindex[1] = 0;
2253 if (p->vtxwindex[2] >= numvtxw)
2255 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2256 p->vtxwindex[2] = 0;
2261 else if (!strcmp(pchunk->id, "MATT0000"))
2264 if (recordsize != sizeof(*p))
2265 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2266 // byteswap in place and keep the pointer
2267 nummatts = numrecords;
2268 matts = (pskmatt_t *)buffer;
2269 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2275 else if (!strcmp(pchunk->id, "REFSKELT"))
2278 if (recordsize != sizeof(*p))
2279 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2280 // byteswap in place and keep the pointer
2281 numbones = numrecords;
2282 bones = (pskboneinfo_t *)buffer;
2283 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2285 p->numchildren = LittleLong(p->numchildren);
2286 p->parent = LittleLong(p->parent);
2287 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2288 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2289 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2290 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2291 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2292 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2293 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2294 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2295 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2296 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2297 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2298 #ifdef PSKQUATNEGATIONS
2301 p->basepose.quat[0] *= -1;
2302 p->basepose.quat[1] *= -1;
2303 p->basepose.quat[2] *= -1;
2307 p->basepose.quat[0] *= 1;
2308 p->basepose.quat[1] *= -1;
2309 p->basepose.quat[2] *= 1;
2312 if (p->parent < 0 || p->parent >= numbones)
2314 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2320 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2323 if (recordsize != sizeof(*p))
2324 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2325 // byteswap in place and keep the pointer
2326 numrawweights = numrecords;
2327 rawweights = (pskrawweights_t *)buffer;
2328 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2330 p->weight = LittleFloat(p->weight);
2331 p->pntsindex = LittleLong(p->pntsindex);
2332 p->boneindex = LittleLong(p->boneindex);
2333 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2335 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2338 if (p->boneindex < 0 || p->boneindex >= numbones)
2340 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2348 while (animbuffer < animbufferend)
2350 pchunk = (pskchunk_t *)animbuffer;
2351 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2352 version = LittleLong(pchunk->version);
2353 recordsize = LittleLong(pchunk->recordsize);
2354 numrecords = LittleLong(pchunk->numrecords);
2355 if (developer.integer >= 100)
2356 Con_Printf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2357 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2358 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);
2359 if (!strcmp(pchunk->id, "ANIMHEAD"))
2363 else if (!strcmp(pchunk->id, "BONENAMES"))
2366 if (recordsize != sizeof(*p))
2367 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2368 // byteswap in place and keep the pointer
2369 numanimbones = numrecords;
2370 animbones = (pskboneinfo_t *)animbuffer;
2371 // NOTE: supposedly psa does not need to match the psk model, the
2372 // bones missing from the psa would simply use their base
2373 // positions from the psk, but this is hard for me to implement
2374 // and people can easily make animations that match.
2375 if (numanimbones != numbones)
2376 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2377 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2379 p->numchildren = LittleLong(p->numchildren);
2380 p->parent = LittleLong(p->parent);
2381 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2382 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2383 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2384 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2385 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2386 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2387 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2388 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2389 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2390 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2391 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2392 #ifdef PSKQUATNEGATIONS
2395 p->basepose.quat[0] *= -1;
2396 p->basepose.quat[1] *= -1;
2397 p->basepose.quat[2] *= -1;
2401 p->basepose.quat[0] *= 1;
2402 p->basepose.quat[1] *= -1;
2403 p->basepose.quat[2] *= 1;
2406 if (p->parent < 0 || p->parent >= numanimbones)
2408 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2411 // check that bones are the same as in the base
2412 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2413 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2417 else if (!strcmp(pchunk->id, "ANIMINFO"))
2420 if (recordsize != sizeof(*p))
2421 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2422 // byteswap in place and keep the pointer
2423 numanims = numrecords;
2424 anims = (pskaniminfo_t *)animbuffer;
2425 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2427 p->numbones = LittleLong(p->numbones);
2428 p->playtime = LittleFloat(p->playtime);
2429 p->fps = LittleFloat(p->fps);
2430 p->firstframe = LittleLong(p->firstframe);
2431 p->numframes = LittleLong(p->numframes);
2432 if (p->numbones != numbones)
2433 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2437 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2440 if (recordsize != sizeof(*p))
2441 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2442 numanimkeys = numrecords;
2443 animkeys = (pskanimkeys_t *)animbuffer;
2444 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2446 p->origin[0] = LittleFloat(p->origin[0]);
2447 p->origin[1] = LittleFloat(p->origin[1]);
2448 p->origin[2] = LittleFloat(p->origin[2]);
2449 p->quat[0] = LittleFloat(p->quat[0]);
2450 p->quat[1] = LittleFloat(p->quat[1]);
2451 p->quat[2] = LittleFloat(p->quat[2]);
2452 p->quat[3] = LittleFloat(p->quat[3]);
2453 p->frametime = LittleFloat(p->frametime);
2454 #ifdef PSKQUATNEGATIONS
2455 if (index % numbones)
2470 // TODO: allocate bonepose stuff
2473 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2476 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2477 Host_Error("%s: missing required chunks", loadmodel->name);
2479 loadmodel->numframes = 0;
2480 for (index = 0;index < numanims;index++)
2481 loadmodel->numframes += anims[index].numframes;
2483 if (numanimkeys != numbones * loadmodel->numframes)
2484 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2486 meshvertices = numvtxw;
2487 meshtriangles = numfaces;
2489 // load external .skin files if present
2490 skinfiles = Mod_LoadSkinFiles();
2491 if (loadmodel->numskins < 1)
2492 loadmodel->numskins = 1;
2493 loadmodel->num_bones = numbones;
2494 loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
2495 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2496 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2497 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2498 // do most allocations as one merged chunk
2499 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));
2500 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2501 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2502 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2503 loadmodel->surfmesh.num_vertices = meshvertices;
2504 loadmodel->surfmesh.num_triangles = meshtriangles;
2505 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2506 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2507 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2508 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2509 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2510 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2511 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2512 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
2513 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
2514 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
2515 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2516 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2517 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2518 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2520 for (i = 0;i < loadmodel->numskins;i++)
2522 loadmodel->skinscenes[i].firstframe = i;
2523 loadmodel->skinscenes[i].framecount = 1;
2524 loadmodel->skinscenes[i].loop = true;
2525 loadmodel->skinscenes[i].framerate = 10;
2529 for (index = 0, i = 0;index < nummatts;index++)
2531 // since psk models do not have named sections, reuse their shader name as the section name
2532 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2533 loadmodel->surfacelist[index] = index;
2534 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2535 loadmodel->data_surfaces[index].num_firstvertex = 0;
2536 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2539 // copy over the vertex locations and texcoords
2540 for (index = 0;index < numvtxw;index++)
2542 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2543 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2544 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2545 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2546 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2549 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2550 for (index = 0;index < numfaces;index++)
2551 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2552 for (index = 0, i = 0;index < nummatts;index++)
2554 loadmodel->data_surfaces[index].num_firsttriangle = i;
2555 i += loadmodel->data_surfaces[index].num_triangles;
2556 loadmodel->data_surfaces[index].num_triangles = 0;
2558 for (index = 0;index < numfaces;index++)
2560 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2561 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2562 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2563 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2566 // copy over the bones
2567 for (index = 0;index < numbones;index++)
2569 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2570 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2571 if (loadmodel->data_bones[index].parent >= index)
2572 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2575 // sort the psk point weights into the vertex weight tables
2576 // (which only accept up to 4 bones per vertex)
2577 for (index = 0;index < numvtxw;index++)
2581 for (j = 0;j < numrawweights;j++)
2583 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2585 int boneindex = rawweights[j].boneindex;
2586 float influence = rawweights[j].weight;
2587 for (l = 0;l < 4;l++)
2589 if (loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] < influence)
2591 // move lower influence weights out of the way first
2593 for (l2 = 3;l2 > l;l2--)
2595 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2-1];
2596 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2-1];
2598 // store the new weight
2599 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] = influence;
2600 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l] = boneindex;
2607 for (l = 0;l < 4;l++)
2608 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l];
2609 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2611 float f = 1.0f / sum;
2612 for (l = 0;l < 4;l++)
2613 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] *= f;
2617 // set up the animscenes based on the anims
2618 for (index = 0, i = 0;index < numanims;index++)
2620 for (j = 0;j < anims[index].numframes;j++, i++)
2622 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2623 loadmodel->animscenes[i].firstframe = i;
2624 loadmodel->animscenes[i].framecount = 1;
2625 loadmodel->animscenes[i].loop = true;
2626 loadmodel->animscenes[i].framerate = 10;
2630 // load the poses from the animkeys
2631 for (index = 0;index < numanimkeys;index++)
2633 pskanimkeys_t *k = animkeys + index;
2635 Matrix4x4_FromOriginQuat(&matrix, k->origin[0], k->origin[1], k->origin[2], k->quat[0], k->quat[1], k->quat[2], k->quat[3]);
2636 Matrix4x4_ToArray12FloatD3D(&matrix, loadmodel->data_poses + index*12);
2638 Mod_FreeSkinFiles(skinfiles);
2639 Mem_Free(animfilebuffer);
2641 // compute all the mesh information that was not loaded from the file
2642 // TODO: honor smoothing groups somehow?
2643 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2644 Mod_BuildBaseBonePoses();
2645 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2646 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);
2647 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2648 Mod_Alias_CalculateBoundingBox();
2650 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;