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->num_bones)
434 for (i = 0;i < model->num_bones;i++)
435 if (!strcasecmp(tagname, model->data_bones[i].name))
438 for (i = 0;i < model->num_tags;i++)
439 if (!strcasecmp(tagname, model->data_tags[i].name))
444 static void Mod_BuildBaseBonePoses(void)
448 float *basebonepose = Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(float[12]));
449 float *in12f = loadmodel->data_poses;
450 float *out12f = basebonepose;
451 float *outinv12f = loadmodel->data_baseboneposeinverse;
452 for (i = 0;i < loadmodel->num_bones;i++, in12f += 12, out12f += 12, outinv12f += 12)
454 if (loadmodel->data_bones[i].parent >= 0)
455 R_ConcatTransforms(basebonepose + 12 * loadmodel->data_bones[i].parent, in12f, out12f);
457 for (k = 0;k < 12;k++)
458 out12f[k] = in12f[k];
462 // we only support uniform scaling, so assume the first row is enough
463 // (note the lack of sqrt here, because we're trying to undo the scaling,
464 // this means multiplying by the inverse scale twice - squaring it, which
465 // makes the sqrt a waste of time)
466 scale = 1.0 / (out12f[ 0] * out12f[ 0] + out12f[ 1] * out12f[ 1] + out12f[ 2] * out12f[ 2]);
468 // invert the rotation by transposing and multiplying by the squared
469 // recipricol of the input matrix scale as described above
470 outinv12f[ 0] = (float)(out12f[ 0] * scale);
471 outinv12f[ 1] = (float)(out12f[ 4] * scale);
472 outinv12f[ 2] = (float)(out12f[ 8] * scale);
473 outinv12f[ 4] = (float)(out12f[ 1] * scale);
474 outinv12f[ 5] = (float)(out12f[ 5] * scale);
475 outinv12f[ 6] = (float)(out12f[ 9] * scale);
476 outinv12f[ 8] = (float)(out12f[ 2] * scale);
477 outinv12f[ 9] = (float)(out12f[ 6] * scale);
478 outinv12f[10] = (float)(out12f[10] * scale);
480 // invert the translate
481 outinv12f[ 3] = -(out12f[ 3] * outinv12f[ 0] + out12f[ 7] * outinv12f[ 1] + out12f[11] * outinv12f[ 2]);
482 outinv12f[ 7] = -(out12f[ 3] * outinv12f[ 4] + out12f[ 7] * outinv12f[ 5] + out12f[11] * outinv12f[ 6]);
483 outinv12f[11] = -(out12f[ 3] * outinv12f[ 8] + out12f[ 7] * outinv12f[ 9] + out12f[11] * outinv12f[10]);
485 Mem_Free(basebonepose);
488 static void Mod_Alias_CalculateBoundingBox(void)
491 qboolean firstvertex = true;
492 float dist, yawradius, radius;
495 frameblend_t frameblend[4];
496 memset(frameblend, 0, sizeof(frameblend));
497 frameblend[0].lerp = 1;
498 vertex3f = Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
499 VectorClear(loadmodel->normalmins);
500 VectorClear(loadmodel->normalmaxs);
503 for (frameblend[0].frame = 0;frameblend[0].frame < loadmodel->num_poses;frameblend[0].frame++)
505 loadmodel->AnimateVertices(loadmodel, frameblend, vertex3f, NULL, NULL, NULL);
506 for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
511 VectorCopy(v, loadmodel->normalmins);
512 VectorCopy(v, loadmodel->normalmaxs);
516 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
517 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
518 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
519 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
520 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
521 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
523 dist = v[0] * v[0] + v[1] * v[1];
524 if (yawradius < dist)
532 radius = sqrt(radius);
533 yawradius = sqrt(yawradius);
534 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
535 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
536 loadmodel->yawmins[2] = loadmodel->normalmins[2];
537 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
538 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
539 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
540 loadmodel->radius = radius;
541 loadmodel->radius2 = radius * radius;
544 static void Mod_Alias_MorphMesh_CompileFrames(void)
547 frameblend_t frameblend[4] = {{0, 1}, {0, 0}, {0, 0}, {0, 0}};
548 unsigned char *datapointer;
549 datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
550 loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
551 loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
552 loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
553 loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
554 loadmodel->surfmesh.data_morphtexvecvertex = (texvecvertex_t *)datapointer;datapointer += loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices * sizeof(texvecvertex_t);
555 // 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)
556 for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
558 frameblend[0].frame = i;
559 loadmodel->AnimateVertices(loadmodel, frameblend, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
560 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);
561 // encode the svector and tvector in 3 byte format for permanent storage
562 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
564 VectorScale(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
565 VectorScale(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
570 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)
573 float segmentmins[3], segmentmaxs[3];
574 frameblend_t frameblend[4];
576 static int maxvertices = 0;
577 static float *vertex3f = NULL;
578 memset(trace, 0, sizeof(*trace));
580 trace->realfraction = 1;
581 trace->hitsupercontentsmask = hitsupercontentsmask;
582 memset(frameblend, 0, sizeof(frameblend));
583 frameblend[0].frame = frame;
584 frameblend[0].lerp = 1;
585 if (maxvertices < model->surfmesh.num_vertices)
589 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
590 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
592 if (VectorLength2(boxmins) + VectorLength2(boxmaxs) == 0)
595 segmentmins[0] = min(start[0], end[0]) - 1;
596 segmentmins[1] = min(start[1], end[1]) - 1;
597 segmentmins[2] = min(start[2], end[2]) - 1;
598 segmentmaxs[0] = max(start[0], end[0]) + 1;
599 segmentmaxs[1] = max(start[1], end[1]) + 1;
600 segmentmaxs[2] = max(start[2], end[2]) + 1;
601 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
603 model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL);
604 Collision_TraceLineTriangleMeshFloat(trace, start, end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, SUPERCONTENTS_SOLID, 0, surface->texture, segmentmins, segmentmaxs);
609 // box trace, performed as brush trace
610 colbrushf_t *thisbrush_start, *thisbrush_end;
611 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
612 segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
613 segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
614 segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
615 segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
616 segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
617 segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
618 VectorAdd(start, boxmins, boxstartmins);
619 VectorAdd(start, boxmaxs, boxstartmaxs);
620 VectorAdd(end, boxmins, boxendmins);
621 VectorAdd(end, boxmaxs, boxendmaxs);
622 thisbrush_start = Collision_BrushForBox(&identitymatrix, boxstartmins, boxstartmaxs, 0, 0, NULL);
623 thisbrush_end = Collision_BrushForBox(&identitymatrix, boxendmins, boxendmaxs, 0, 0, NULL);
624 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
626 if (maxvertices < model->surfmesh.num_vertices)
630 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
631 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
633 model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL);
634 Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, SUPERCONTENTS_SOLID, 0, surface->texture, segmentmins, segmentmaxs);
639 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
642 for (i = 0;i < inverts;i++)
644 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
646 j = vertremap[i]; // not onseam
649 j = vertremap[i+inverts]; // onseam
655 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
657 int i, f, pose, groupframes;
659 daliasframetype_t *pframetype;
660 daliasframe_t *pinframe;
661 daliasgroup_t *group;
662 daliasinterval_t *intervals;
665 scene = loadmodel->animscenes;
666 for (f = 0;f < loadmodel->numframes;f++)
668 pframetype = (daliasframetype_t *)datapointer;
669 datapointer += sizeof(daliasframetype_t);
670 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
672 // a single frame is still treated as a group
679 group = (daliasgroup_t *)datapointer;
680 datapointer += sizeof(daliasgroup_t);
681 groupframes = LittleLong (group->numframes);
683 // intervals (time per frame)
684 intervals = (daliasinterval_t *)datapointer;
685 datapointer += sizeof(daliasinterval_t) * groupframes;
687 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
688 if (interval < 0.01f)
690 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
695 // get scene name from first frame
696 pinframe = (daliasframe_t *)datapointer;
698 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
699 scene->firstframe = pose;
700 scene->framecount = groupframes;
701 scene->framerate = 1.0f / interval;
706 for (i = 0;i < groupframes;i++)
708 pinframe = (daliasframe_t *)datapointer;
709 datapointer += sizeof(daliasframe_t);
710 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
711 datapointer += sizeof(trivertx_t) * inverts;
717 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
719 if (cls.state == ca_dedicated)
723 skinframe = R_SkinFrame_LoadMissing();
724 memset(texture, 0, sizeof(*texture));
725 texture->currentframe = texture;
726 //texture->animated = false;
727 texture->numskinframes = 1;
728 texture->skinframerate = 1;
729 texture->skinframes[0] = skinframe;
730 texture->currentskinframe = skinframe;
731 //texture->backgroundnumskinframes = 0;
732 //texture->customblendfunc[0] = 0;
733 //texture->customblendfunc[1] = 0;
734 //texture->surfaceflags = 0;
735 //texture->supercontents = 0;
736 //texture->surfaceparms = 0;
737 //texture->textureflags = 0;
739 texture->basematerialflags = MATERIALFLAG_WALL;
740 if (texture->currentskinframe->fog)
741 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
742 texture->currentmaterialflags = texture->basematerialflags;
745 static void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, char *meshname, char *shadername)
748 skinfileitem_t *skinfileitem;
751 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
752 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
754 memset(skin, 0, sizeof(*skin));
756 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
758 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
759 if (!strcmp(skinfileitem->name, meshname))
761 Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
767 // don't render unmentioned meshes
768 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
769 skin->basematerialflags = skin->currentmaterialflags = 0;
774 Mod_LoadTextureFromQ3Shader(skin, shadername, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
777 #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);
778 #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);
779 void Mod_IDP0_Load(model_t *mod, void *buffer, void *bufferend)
781 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
782 float scales, scalet, interval;
786 stvert_t *pinstverts;
787 dtriangle_t *pintriangles;
788 daliasskintype_t *pinskintype;
789 daliasskingroup_t *pinskingroup;
790 daliasskininterval_t *pinskinintervals;
791 daliasframetype_t *pinframetype;
792 daliasgroup_t *pinframegroup;
793 unsigned char *datapointer, *startframes, *startskins;
794 char name[MAX_QPATH];
795 skinframe_t *tempskinframe;
796 animscene_t *tempskinscenes;
797 texture_t *tempaliasskins;
799 int *vertonseam, *vertremap;
800 skinfile_t *skinfiles;
802 datapointer = (unsigned char *)buffer;
803 pinmodel = (mdl_t *)datapointer;
804 datapointer += sizeof(mdl_t);
806 version = LittleLong (pinmodel->version);
807 if (version != ALIAS_VERSION)
808 Host_Error ("%s has wrong version number (%i should be %i)",
809 loadmodel->name, version, ALIAS_VERSION);
811 loadmodel->modeldatatypestring = "MDL";
813 loadmodel->type = mod_alias;
814 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
815 loadmodel->DrawSky = NULL;
816 loadmodel->DrawAddWaterPlanes = NULL;
817 loadmodel->Draw = R_Q1BSP_Draw;
818 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
819 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
820 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
821 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
822 loadmodel->DrawLight = R_Q1BSP_DrawLight;
823 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
824 loadmodel->PointSuperContents = NULL;
826 loadmodel->num_surfaces = 1;
827 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
828 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
829 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
830 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
831 loadmodel->surfacelist[0] = 0;
833 loadmodel->numskins = LittleLong(pinmodel->numskins);
834 BOUNDI(loadmodel->numskins,0,65536);
835 skinwidth = LittleLong (pinmodel->skinwidth);
836 BOUNDI(skinwidth,0,65536);
837 skinheight = LittleLong (pinmodel->skinheight);
838 BOUNDI(skinheight,0,65536);
839 numverts = LittleLong(pinmodel->numverts);
840 BOUNDI(numverts,0,65536);
841 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
842 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
843 loadmodel->numframes = LittleLong(pinmodel->numframes);
844 BOUNDI(loadmodel->numframes,0,65536);
845 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
846 BOUNDI(loadmodel->synctype,0,2);
847 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
848 i = LittleLong (pinmodel->flags);
849 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
851 for (i = 0;i < 3;i++)
853 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
854 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
857 startskins = datapointer;
859 for (i = 0;i < loadmodel->numskins;i++)
861 pinskintype = (daliasskintype_t *)datapointer;
862 datapointer += sizeof(daliasskintype_t);
863 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
867 pinskingroup = (daliasskingroup_t *)datapointer;
868 datapointer += sizeof(daliasskingroup_t);
869 groupskins = LittleLong(pinskingroup->numskins);
870 datapointer += sizeof(daliasskininterval_t) * groupskins;
873 for (j = 0;j < groupskins;j++)
875 datapointer += skinwidth * skinheight;
880 pinstverts = (stvert_t *)datapointer;
881 datapointer += sizeof(stvert_t) * numverts;
883 pintriangles = (dtriangle_t *)datapointer;
884 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
886 startframes = datapointer;
887 loadmodel->surfmesh.num_morphframes = 0;
888 for (i = 0;i < loadmodel->numframes;i++)
890 pinframetype = (daliasframetype_t *)datapointer;
891 datapointer += sizeof(daliasframetype_t);
892 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
896 pinframegroup = (daliasgroup_t *)datapointer;
897 datapointer += sizeof(daliasgroup_t);
898 groupframes = LittleLong(pinframegroup->numframes);
899 datapointer += sizeof(daliasinterval_t) * groupframes;
902 for (j = 0;j < groupframes;j++)
904 datapointer += sizeof(daliasframe_t);
905 datapointer += sizeof(trivertx_t) * numverts;
906 loadmodel->surfmesh.num_morphframes++;
909 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
911 // store texture coordinates into temporary array, they will be stored
912 // after usage is determined (triangle data)
913 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
914 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
915 vertonseam = vertremap + numverts * 2;
917 scales = 1.0 / skinwidth;
918 scalet = 1.0 / skinheight;
919 for (i = 0;i < numverts;i++)
921 vertonseam[i] = LittleLong(pinstverts[i].onseam);
922 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
923 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
924 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
925 vertst[(i+numverts)*2+1] = vertst[i*2+1];
928 // load triangle data
929 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
931 // read the triangle elements
932 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
933 for (j = 0;j < 3;j++)
934 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
935 // validate (note numverts is used because this is the original data)
936 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
937 // now butcher the elements according to vertonseam and tri->facesfront
938 // and then compact the vertex set to remove duplicates
939 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
940 if (!LittleLong(pintriangles[i].facesfront)) // backface
941 for (j = 0;j < 3;j++)
942 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
943 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
945 // (this uses vertremap to count usage to save some memory)
946 for (i = 0;i < numverts*2;i++)
948 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
949 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
950 // build remapping table and compact array
951 loadmodel->surfmesh.num_vertices = 0;
952 for (i = 0;i < numverts*2;i++)
956 vertremap[i] = loadmodel->surfmesh.num_vertices;
957 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
958 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
959 loadmodel->surfmesh.num_vertices++;
962 vertremap[i] = -1; // not used at all
964 // remap the elements to the new vertex set
965 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
966 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
967 // store the texture coordinates
968 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
969 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
971 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
972 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
976 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
977 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
978 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
979 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
980 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
981 Mod_Alias_CalculateBoundingBox();
982 Mod_Alias_MorphMesh_CompileFrames();
988 skinfiles = Mod_LoadSkinFiles();
989 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
990 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
991 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
992 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
995 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
996 Mod_FreeSkinFiles(skinfiles);
997 for (i = 0;i < loadmodel->numskins;i++)
999 loadmodel->skinscenes[i].firstframe = i;
1000 loadmodel->skinscenes[i].framecount = 1;
1001 loadmodel->skinscenes[i].loop = true;
1002 loadmodel->skinscenes[i].framerate = 10;
1008 datapointer = startskins;
1009 for (i = 0;i < loadmodel->numskins;i++)
1011 pinskintype = (daliasskintype_t *)datapointer;
1012 datapointer += sizeof(daliasskintype_t);
1014 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1021 pinskingroup = (daliasskingroup_t *)datapointer;
1022 datapointer += sizeof(daliasskingroup_t);
1024 groupskins = LittleLong (pinskingroup->numskins);
1026 pinskinintervals = (daliasskininterval_t *)datapointer;
1027 datapointer += sizeof(daliasskininterval_t) * groupskins;
1029 interval = LittleFloat(pinskinintervals[0].interval);
1030 if (interval < 0.01f)
1032 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1037 sprintf(loadmodel->skinscenes[i].name, "skin %i", i);
1038 loadmodel->skinscenes[i].firstframe = totalskins;
1039 loadmodel->skinscenes[i].framecount = groupskins;
1040 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1041 loadmodel->skinscenes[i].loop = true;
1043 for (j = 0;j < groupskins;j++)
1046 sprintf (name, "%s_%i_%i", loadmodel->name, i, j);
1048 sprintf (name, "%s_%i", loadmodel->name, i);
1049 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))
1050 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));
1051 datapointer += skinwidth * skinheight;
1055 // check for skins that don't exist in the model, but do exist as external images
1056 // (this was added because yummyluv kept pestering me about support for it)
1057 // TODO: support shaders here?
1058 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)))
1060 // expand the arrays to make room
1061 tempskinscenes = loadmodel->skinscenes;
1062 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1063 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1064 Mem_Free(tempskinscenes);
1066 tempaliasskins = loadmodel->data_textures;
1067 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1068 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1069 Mem_Free(tempaliasskins);
1071 // store the info about the new skin
1072 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1073 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1074 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1075 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1076 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1077 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1079 //increase skin counts
1080 loadmodel->numskins++;
1083 // fix up the pointers since they are pointing at the old textures array
1084 // FIXME: this is a hack!
1085 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1086 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1090 surface = loadmodel->data_surfaces;
1091 surface->texture = loadmodel->data_textures;
1092 surface->num_firsttriangle = 0;
1093 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1094 surface->num_firstvertex = 0;
1095 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1097 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1100 void Mod_IDP2_Load(model_t *mod, void *buffer, void *bufferend)
1102 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1103 float iskinwidth, iskinheight;
1104 unsigned char *data;
1105 msurface_t *surface;
1107 unsigned char *base, *datapointer;
1108 md2frame_t *pinframe;
1110 md2triangle_t *intri;
1111 unsigned short *inst;
1112 struct md2verthash_s
1114 struct md2verthash_s *next;
1118 *hash, **md2verthash, *md2verthashdata;
1119 skinfile_t *skinfiles;
1121 pinmodel = (md2_t *)buffer;
1122 base = (unsigned char *)buffer;
1124 version = LittleLong (pinmodel->version);
1125 if (version != MD2ALIAS_VERSION)
1126 Host_Error ("%s has wrong version number (%i should be %i)",
1127 loadmodel->name, version, MD2ALIAS_VERSION);
1129 loadmodel->modeldatatypestring = "MD2";
1131 loadmodel->type = mod_alias;
1132 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1133 loadmodel->DrawSky = NULL;
1134 loadmodel->DrawAddWaterPlanes = NULL;
1135 loadmodel->Draw = R_Q1BSP_Draw;
1136 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1137 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1138 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1139 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1140 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1141 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1142 loadmodel->PointSuperContents = NULL;
1144 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1145 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1146 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1147 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1148 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1149 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1150 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1151 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1153 end = LittleLong(pinmodel->ofs_end);
1154 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1155 Host_Error ("%s is not a valid model", loadmodel->name);
1156 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1157 Host_Error ("%s is not a valid model", loadmodel->name);
1158 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1159 Host_Error ("%s is not a valid model", loadmodel->name);
1160 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1161 Host_Error ("%s is not a valid model", loadmodel->name);
1162 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1163 Host_Error ("%s is not a valid model", loadmodel->name);
1165 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1166 numxyz = LittleLong(pinmodel->num_xyz);
1167 numst = LittleLong(pinmodel->num_st);
1168 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1169 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1170 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1171 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1172 skinwidth = LittleLong(pinmodel->skinwidth);
1173 skinheight = LittleLong(pinmodel->skinheight);
1174 iskinwidth = 1.0f / skinwidth;
1175 iskinheight = 1.0f / skinheight;
1177 loadmodel->num_surfaces = 1;
1178 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1179 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]));
1180 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1181 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1182 loadmodel->surfacelist[0] = 0;
1183 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1184 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1185 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1186 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1188 loadmodel->synctype = ST_RAND;
1191 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1192 skinfiles = Mod_LoadSkinFiles();
1195 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1196 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1197 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1198 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1199 Mod_FreeSkinFiles(skinfiles);
1201 else if (loadmodel->numskins)
1203 // skins found (most likely not a player model)
1204 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1205 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1206 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1207 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1208 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);
1212 // no skins (most likely a player model)
1213 loadmodel->numskins = 1;
1214 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1215 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1216 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1217 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1220 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1221 for (i = 0;i < loadmodel->numskins;i++)
1223 loadmodel->skinscenes[i].firstframe = i;
1224 loadmodel->skinscenes[i].framecount = 1;
1225 loadmodel->skinscenes[i].loop = true;
1226 loadmodel->skinscenes[i].framerate = 10;
1229 // load the triangles and stvert data
1230 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1231 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1232 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1233 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1234 // swap the triangle list
1235 loadmodel->surfmesh.num_vertices = 0;
1236 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1238 for (j = 0;j < 3;j++)
1240 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1241 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1244 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1249 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1252 hashindex = (xyz * 256 + st) & 65535;
1253 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1254 if (hash->xyz == xyz && hash->st == st)
1258 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1261 hash->next = md2verthash[hashindex];
1262 md2verthash[hashindex] = hash;
1264 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1268 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1269 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));
1270 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1271 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1272 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1275 hash = md2verthashdata + i;
1276 vertremap[i] = hash->xyz;
1277 sts = LittleShort(inst[hash->st*2+0]);
1278 stt = LittleShort(inst[hash->st*2+1]);
1279 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1281 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1285 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1286 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1289 Mem_Free(md2verthash);
1290 Mem_Free(md2verthashdata);
1293 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1294 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1299 pinframe = (md2frame_t *)datapointer;
1300 datapointer += sizeof(md2frame_t);
1301 // store the frame scale/translate into the appropriate array
1302 for (j = 0;j < 3;j++)
1304 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1305 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1307 // convert the vertices
1308 v = (trivertx_t *)datapointer;
1309 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1310 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1311 out[k] = v[vertremap[k]];
1312 datapointer += numxyz * sizeof(trivertx_t);
1314 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1315 loadmodel->animscenes[i].firstframe = i;
1316 loadmodel->animscenes[i].framecount = 1;
1317 loadmodel->animscenes[i].framerate = 10;
1318 loadmodel->animscenes[i].loop = true;
1321 Mem_Free(vertremap);
1323 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1324 Mod_Alias_CalculateBoundingBox();
1325 Mod_Alias_MorphMesh_CompileFrames();
1327 surface = loadmodel->data_surfaces;
1328 surface->texture = loadmodel->data_textures;
1329 surface->num_firsttriangle = 0;
1330 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1331 surface->num_firstvertex = 0;
1332 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1334 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1337 void Mod_IDP3_Load(model_t *mod, void *buffer, void *bufferend)
1339 int i, j, k, version, meshvertices, meshtriangles;
1340 unsigned char *data;
1341 msurface_t *surface;
1342 md3modelheader_t *pinmodel;
1343 md3frameinfo_t *pinframe;
1346 skinfile_t *skinfiles;
1348 pinmodel = (md3modelheader_t *)buffer;
1350 if (memcmp(pinmodel->identifier, "IDP3", 4))
1351 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1352 version = LittleLong (pinmodel->version);
1353 if (version != MD3VERSION)
1354 Host_Error ("%s has wrong version number (%i should be %i)",
1355 loadmodel->name, version, MD3VERSION);
1357 skinfiles = Mod_LoadSkinFiles();
1358 if (loadmodel->numskins < 1)
1359 loadmodel->numskins = 1;
1361 loadmodel->modeldatatypestring = "MD3";
1363 loadmodel->type = mod_alias;
1364 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1365 loadmodel->DrawSky = NULL;
1366 loadmodel->DrawAddWaterPlanes = NULL;
1367 loadmodel->Draw = R_Q1BSP_Draw;
1368 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1369 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1370 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1371 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1372 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1373 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1374 loadmodel->PointSuperContents = NULL;
1375 loadmodel->synctype = ST_RAND;
1376 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1377 i = LittleLong (pinmodel->flags);
1378 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1380 // set up some global info about the model
1381 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1382 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1384 // make skinscenes for the skins (no groups)
1385 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1386 for (i = 0;i < loadmodel->numskins;i++)
1388 loadmodel->skinscenes[i].firstframe = i;
1389 loadmodel->skinscenes[i].framecount = 1;
1390 loadmodel->skinscenes[i].loop = true;
1391 loadmodel->skinscenes[i].framerate = 10;
1395 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1396 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1398 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1399 loadmodel->animscenes[i].firstframe = i;
1400 loadmodel->animscenes[i].framecount = 1;
1401 loadmodel->animscenes[i].framerate = 10;
1402 loadmodel->animscenes[i].loop = true;
1406 loadmodel->num_tagframes = loadmodel->numframes;
1407 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1408 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1409 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1411 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1412 for (j = 0;j < 9;j++)
1413 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1414 for (j = 0;j < 3;j++)
1415 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1416 //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);
1422 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)))
1424 if (memcmp(pinmesh->identifier, "IDP3", 4))
1425 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1426 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1427 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1428 meshvertices += LittleLong(pinmesh->num_vertices);
1429 meshtriangles += LittleLong(pinmesh->num_triangles);
1432 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1433 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1434 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1435 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));
1436 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1437 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1438 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1439 loadmodel->surfmesh.num_vertices = meshvertices;
1440 loadmodel->surfmesh.num_triangles = meshtriangles;
1441 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1442 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1443 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1444 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1445 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1446 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1450 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)))
1452 if (memcmp(pinmesh->identifier, "IDP3", 4))
1453 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1454 loadmodel->surfacelist[i] = i;
1455 surface = loadmodel->data_surfaces + i;
1456 surface->texture = loadmodel->data_textures + i;
1457 surface->num_firsttriangle = meshtriangles;
1458 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1459 surface->num_firstvertex = meshvertices;
1460 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1461 meshvertices += surface->num_vertices;
1462 meshtriangles += surface->num_triangles;
1464 for (j = 0;j < surface->num_triangles * 3;j++)
1465 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1466 for (j = 0;j < surface->num_vertices;j++)
1468 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1469 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1471 for (j = 0;j < loadmodel->numframes;j++)
1473 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1474 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1475 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1477 out->origin[0] = LittleShort(in->origin[0]);
1478 out->origin[1] = LittleShort(in->origin[1]);
1479 out->origin[2] = LittleShort(in->origin[2]);
1480 out->pitch = in->pitch;
1485 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1487 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1489 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1490 Mod_Alias_MorphMesh_CompileFrames();
1491 Mod_Alias_CalculateBoundingBox();
1492 Mod_FreeSkinFiles(skinfiles);
1494 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1495 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1498 void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer, void *bufferend)
1500 zymtype1header_t *pinmodel, *pheader;
1501 unsigned char *pbase;
1502 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1503 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose;
1504 zymvertex_t *verts, *vertdata;
1508 skinfile_t *skinfiles;
1509 unsigned char *data;
1510 msurface_t *surface;
1512 pinmodel = (zymtype1header_t *)buffer;
1513 pbase = (unsigned char *)buffer;
1514 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1515 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1516 if (BigLong(pinmodel->type) != 1)
1517 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1519 loadmodel->modeldatatypestring = "ZYM";
1521 loadmodel->type = mod_alias;
1522 loadmodel->synctype = ST_RAND;
1526 pheader->type = BigLong(pinmodel->type);
1527 pheader->filesize = BigLong(pinmodel->filesize);
1528 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1529 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1530 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1531 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1532 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1533 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1534 pheader->radius = BigFloat(pinmodel->radius);
1535 pheader->numverts = BigLong(pinmodel->numverts);
1536 pheader->numtris = BigLong(pinmodel->numtris);
1537 pheader->numshaders = BigLong(pinmodel->numshaders);
1538 pheader->numbones = BigLong(pinmodel->numbones);
1539 pheader->numscenes = BigLong(pinmodel->numscenes);
1540 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1541 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1542 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1543 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1544 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1545 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1546 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1547 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1548 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1549 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1550 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1551 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1552 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1553 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1554 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1555 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1556 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1557 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1559 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1561 Con_Printf("%s has no geometry\n", loadmodel->name);
1564 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1566 Con_Printf("%s has no animations\n", loadmodel->name);
1570 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1571 loadmodel->DrawSky = NULL;
1572 loadmodel->DrawAddWaterPlanes = NULL;
1573 loadmodel->Draw = R_Q1BSP_Draw;
1574 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1575 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1576 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1577 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1578 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1579 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1580 loadmodel->PointSuperContents = NULL;
1582 loadmodel->numframes = pheader->numscenes;
1583 loadmodel->num_surfaces = pheader->numshaders;
1585 skinfiles = Mod_LoadSkinFiles();
1586 if (loadmodel->numskins < 1)
1587 loadmodel->numskins = 1;
1589 // make skinscenes for the skins (no groups)
1590 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1591 for (i = 0;i < loadmodel->numskins;i++)
1593 loadmodel->skinscenes[i].firstframe = i;
1594 loadmodel->skinscenes[i].framecount = 1;
1595 loadmodel->skinscenes[i].loop = true;
1596 loadmodel->skinscenes[i].framerate = 10;
1600 modelradius = pheader->radius;
1601 for (i = 0;i < 3;i++)
1603 loadmodel->normalmins[i] = pheader->mins[i];
1604 loadmodel->normalmaxs[i] = pheader->maxs[i];
1605 loadmodel->rotatedmins[i] = -modelradius;
1606 loadmodel->rotatedmaxs[i] = modelradius;
1608 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1609 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1610 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1611 if (loadmodel->yawmaxs[0] > modelradius)
1612 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1613 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1614 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1615 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1616 loadmodel->radius = modelradius;
1617 loadmodel->radius2 = modelradius * modelradius;
1619 // go through the lumps, swapping things
1621 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1622 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1623 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1624 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1625 for (i = 0;i < pheader->numscenes;i++)
1627 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1628 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1629 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1630 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1631 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1632 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1633 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1634 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1635 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1636 if (loadmodel->animscenes[i].framerate < 0)
1637 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1641 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1642 loadmodel->num_bones = pheader->numbones;
1643 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, pheader->numbones * sizeof(aliasbone_t));
1644 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1645 for (i = 0;i < pheader->numbones;i++)
1647 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1648 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1649 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1650 if (loadmodel->data_bones[i].parent >= i)
1651 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1654 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1655 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1656 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1657 for (i = 0;i < pheader->numverts;i++)
1659 vertbonecounts[i] = BigLong(bonecount[i]);
1660 if (vertbonecounts[i] != 1)
1661 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1664 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]);
1666 meshvertices = pheader->numverts;
1667 meshtriangles = pheader->numtris;
1669 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1670 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1671 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1672 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]));
1673 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1674 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1675 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1676 loadmodel->surfmesh.num_vertices = meshvertices;
1677 loadmodel->surfmesh.num_triangles = meshtriangles;
1678 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1679 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1680 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1681 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1682 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1683 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1684 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1685 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1686 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1687 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
1688 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1690 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1691 poses = (float *) (pheader->lump_poses.start + pbase);
1692 for (i = 0;i < pheader->lump_poses.length / 4;i++)
1693 loadmodel->data_poses[i] = BigFloat(poses[i]);
1695 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1696 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1697 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1698 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1699 // (converting from weight-blending skeletal animation to
1700 // deformation-based skeletal animation)
1701 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1702 for (i = 0;i < loadmodel->num_bones;i++)
1704 const float *m = loadmodel->data_poses + i * 12;
1705 if (loadmodel->data_bones[i].parent >= 0)
1706 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1708 for (k = 0;k < 12;k++)
1709 bonepose[12*i+k] = m[k];
1711 for (j = 0;j < pheader->numverts;j++)
1713 // this format really should have had a per vertexweight weight value...
1714 // but since it does not, the weighting is completely ignored and
1715 // only one weight is allowed per vertex
1716 int boneindex = BigLong(vertdata[j].bonenum);
1717 const float *m = bonepose + 12 * boneindex;
1718 float relativeorigin[3];
1719 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1720 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1721 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1722 // transform the vertex bone weight into the base mesh
1723 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1724 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1725 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1726 // store the weight as the primary weight on this vertex
1727 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
1728 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = 1;
1731 // normals and tangents are calculated after elements are loaded
1733 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1734 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1735 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1736 for (i = 0;i < pheader->numverts;i++)
1738 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1739 // flip T coordinate for OpenGL
1740 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1743 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1744 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1745 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1747 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1748 //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)
1749 // byteswap, validate, and swap winding order of tris
1750 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1751 if (pheader->lump_render.length != count)
1752 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1753 renderlist = (int *) (pheader->lump_render.start + pbase);
1754 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1756 for (i = 0;i < loadmodel->num_surfaces;i++)
1758 int firstvertex, lastvertex;
1759 if (renderlist >= renderlistend)
1760 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1761 count = BigLong(*renderlist);renderlist++;
1762 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1763 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1765 loadmodel->surfacelist[i] = i;
1766 surface = loadmodel->data_surfaces + i;
1767 surface->texture = loadmodel->data_textures + i;
1768 surface->num_firsttriangle = meshtriangles;
1769 surface->num_triangles = count;
1770 meshtriangles += surface->num_triangles;
1772 // load the elements
1773 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
1774 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
1776 outelements[j*3+2] = BigLong(renderlist[0]);
1777 outelements[j*3+1] = BigLong(renderlist[1]);
1778 outelements[j*3+0] = BigLong(renderlist[2]);
1780 // validate the elements and find the used vertex range
1781 firstvertex = meshvertices;
1783 for (j = 0;j < surface->num_triangles * 3;j++)
1785 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
1786 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
1787 firstvertex = min(firstvertex, outelements[j]);
1788 lastvertex = max(lastvertex, outelements[j]);
1790 surface->num_firstvertex = firstvertex;
1791 surface->num_vertices = lastvertex + 1 - firstvertex;
1793 // since zym models do not have named sections, reuse their shader
1794 // name as the section name
1795 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
1796 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
1798 Mod_FreeSkinFiles(skinfiles);
1799 Mem_Free(vertbonecounts);
1802 // compute all the mesh information that was not loaded from the file
1803 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
1804 Mod_BuildBaseBonePoses();
1805 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
1806 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);
1807 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1809 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1812 void Mod_DARKPLACESMODEL_Load(model_t *mod, void *buffer, void *bufferend)
1814 dpmheader_t *pheader;
1818 unsigned char *pbase;
1819 int i, j, k, meshvertices, meshtriangles;
1820 skinfile_t *skinfiles;
1821 unsigned char *data;
1824 pheader = (dpmheader_t *)buffer;
1825 pbase = (unsigned char *)buffer;
1826 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
1827 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
1828 if (BigLong(pheader->type) != 2)
1829 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1831 loadmodel->modeldatatypestring = "DPM";
1833 loadmodel->type = mod_alias;
1834 loadmodel->synctype = ST_RAND;
1837 pheader->type = BigLong(pheader->type);
1838 pheader->filesize = BigLong(pheader->filesize);
1839 pheader->mins[0] = BigFloat(pheader->mins[0]);
1840 pheader->mins[1] = BigFloat(pheader->mins[1]);
1841 pheader->mins[2] = BigFloat(pheader->mins[2]);
1842 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
1843 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
1844 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
1845 pheader->yawradius = BigFloat(pheader->yawradius);
1846 pheader->allradius = BigFloat(pheader->allradius);
1847 pheader->num_bones = BigLong(pheader->num_bones);
1848 pheader->num_meshs = BigLong(pheader->num_meshs);
1849 pheader->num_frames = BigLong(pheader->num_frames);
1850 pheader->ofs_bones = BigLong(pheader->ofs_bones);
1851 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
1852 pheader->ofs_frames = BigLong(pheader->ofs_frames);
1854 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
1856 Con_Printf("%s has no geometry\n", loadmodel->name);
1859 if (pheader->num_frames < 1)
1861 Con_Printf("%s has no frames\n", loadmodel->name);
1865 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1866 loadmodel->DrawSky = NULL;
1867 loadmodel->DrawAddWaterPlanes = NULL;
1868 loadmodel->Draw = R_Q1BSP_Draw;
1869 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1870 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1871 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1872 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1873 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1874 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1875 loadmodel->PointSuperContents = NULL;
1878 for (i = 0;i < 3;i++)
1880 loadmodel->normalmins[i] = pheader->mins[i];
1881 loadmodel->normalmaxs[i] = pheader->maxs[i];
1882 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
1883 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
1884 loadmodel->rotatedmins[i] = -pheader->allradius;
1885 loadmodel->rotatedmaxs[i] = pheader->allradius;
1887 loadmodel->radius = pheader->allradius;
1888 loadmodel->radius2 = pheader->allradius * pheader->allradius;
1890 // load external .skin files if present
1891 skinfiles = Mod_LoadSkinFiles();
1892 if (loadmodel->numskins < 1)
1893 loadmodel->numskins = 1;
1898 // gather combined statistics from the meshes
1899 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
1900 for (i = 0;i < (int)pheader->num_meshs;i++)
1902 int numverts = BigLong(dpmmesh->num_verts);
1903 meshvertices += numverts;;
1904 meshtriangles += BigLong(dpmmesh->num_tris);
1908 loadmodel->numframes = pheader->num_frames;
1909 loadmodel->num_bones = pheader->num_bones;
1910 loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
1911 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
1912 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1913 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1914 // do most allocations as one merged chunk
1915 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));
1916 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1917 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1918 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1919 loadmodel->surfmesh.num_vertices = meshvertices;
1920 loadmodel->surfmesh.num_triangles = meshtriangles;
1921 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1922 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1923 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1924 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1925 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1926 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1927 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1928 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1929 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1930 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
1931 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1932 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
1933 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
1934 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1936 for (i = 0;i < loadmodel->numskins;i++)
1938 loadmodel->skinscenes[i].firstframe = i;
1939 loadmodel->skinscenes[i].framecount = 1;
1940 loadmodel->skinscenes[i].loop = true;
1941 loadmodel->skinscenes[i].framerate = 10;
1944 // load the bone info
1945 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
1946 for (i = 0;i < loadmodel->num_bones;i++)
1948 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1949 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1950 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1951 if (loadmodel->data_bones[i].parent >= i)
1952 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1956 frame = (dpmframe_t *) (pbase + pheader->ofs_frames);
1957 for (i = 0;i < loadmodel->numframes;i++)
1960 memcpy(loadmodel->animscenes[i].name, frame->name, sizeof(frame->name));
1961 loadmodel->animscenes[i].firstframe = i;
1962 loadmodel->animscenes[i].framecount = 1;
1963 loadmodel->animscenes[i].loop = true;
1964 loadmodel->animscenes[i].framerate = 10;
1965 // load the bone poses for this frame
1966 poses = (float *) (pbase + BigLong(frame->ofs_bonepositions));
1967 for (j = 0;j < loadmodel->num_bones*12;j++)
1968 loadmodel->data_poses[i * loadmodel->num_bones*12 + j] = BigFloat(poses[j]);
1969 // stuff not processed here: mins, maxs, yawradius, allradius
1973 // load the meshes now
1974 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
1977 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1978 // (converting from weight-blending skeletal animation to
1979 // deformation-based skeletal animation)
1980 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1981 for (i = 0;i < loadmodel->num_bones;i++)
1983 const float *m = loadmodel->data_poses + i * 12;
1984 if (loadmodel->data_bones[i].parent >= 0)
1985 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1987 for (k = 0;k < 12;k++)
1988 bonepose[12*i+k] = m[k];
1990 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
1992 const int *inelements;
1994 const float *intexcoord;
1995 msurface_t *surface;
1997 loadmodel->surfacelist[i] = i;
1998 surface = loadmodel->data_surfaces + i;
1999 surface->texture = loadmodel->data_textures + i;
2000 surface->num_firsttriangle = meshtriangles;
2001 surface->num_triangles = BigLong(dpmmesh->num_tris);
2002 surface->num_firstvertex = meshvertices;
2003 surface->num_vertices = BigLong(dpmmesh->num_verts);
2004 meshvertices += surface->num_vertices;
2005 meshtriangles += surface->num_triangles;
2007 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2008 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2009 for (j = 0;j < surface->num_triangles;j++)
2011 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2012 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2013 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2014 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2019 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2020 for (j = 0;j < surface->num_vertices*2;j++)
2021 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2023 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2024 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2028 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2029 data += sizeof(dpmvertex_t);
2030 for (k = 0;k < numweights;k++)
2032 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2033 int boneindex = BigLong(vert->bonenum);
2034 const float *m = bonepose + 12 * boneindex;
2035 float influence = BigFloat(vert->influence);
2036 float relativeorigin[3], relativenormal[3];
2037 relativeorigin[0] = BigFloat(vert->origin[0]);
2038 relativeorigin[1] = BigFloat(vert->origin[1]);
2039 relativeorigin[2] = BigFloat(vert->origin[2]);
2040 relativenormal[0] = BigFloat(vert->normal[0]);
2041 relativenormal[1] = BigFloat(vert->normal[1]);
2042 relativenormal[2] = BigFloat(vert->normal[2]);
2043 // blend the vertex bone weights into the base mesh
2044 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2045 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2046 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2047 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2048 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2049 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2052 // store the first (and often only) weight
2053 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = influence;
2054 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
2058 // sort the new weight into this vertex's weight table
2059 // (which only accepts up to 4 bones per vertex)
2060 for (l = 0;l < 4;l++)
2062 if (loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] < influence)
2064 // move weaker influence weights out of the way first
2066 for (l2 = 3;l2 > l;l2--)
2068 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2-1];
2069 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2-1];
2071 // store the new weight
2072 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] = influence;
2073 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l] = boneindex;
2078 data += sizeof(dpmbonevert_t);
2081 for (l = 0;l < 4;l++)
2082 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l];
2083 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2085 float f = 1.0f / sum;
2086 for (l = 0;l < 4;l++)
2087 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] *= f;
2091 // since dpm models do not have named sections, reuse their shader name as the section name
2092 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2094 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2097 Mod_FreeSkinFiles(skinfiles);
2099 // compute all the mesh information that was not loaded from the file
2100 Mod_BuildBaseBonePoses();
2101 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);
2102 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2104 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2107 // no idea why PSK/PSA files contain weird quaternions but they do...
2108 #define PSKQUATNEGATIONS
2109 void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend)
2111 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2112 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2113 fs_offset_t filesize;
2118 pskboneinfo_t *bones;
2119 pskrawweights_t *rawweights;
2120 pskboneinfo_t *animbones;
2121 pskaniminfo_t *anims;
2122 pskanimkeys_t *animkeys;
2123 void *animfilebuffer, *animbuffer, *animbufferend;
2124 unsigned char *data;
2126 skinfile_t *skinfiles;
2127 char animname[MAX_QPATH];
2129 pchunk = (pskchunk_t *)buffer;
2130 if (strcmp(pchunk->id, "ACTRHEAD"))
2131 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2133 loadmodel->modeldatatypestring = "PSK";
2135 loadmodel->type = mod_alias;
2136 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2137 loadmodel->DrawSky = NULL;
2138 loadmodel->DrawAddWaterPlanes = NULL;
2139 loadmodel->Draw = R_Q1BSP_Draw;
2140 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2141 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2142 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2143 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2144 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2145 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2146 loadmodel->PointSuperContents = NULL;
2147 loadmodel->synctype = ST_RAND;
2149 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2150 strlcat(animname, ".psa", sizeof(animname));
2151 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2152 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2153 if (animbuffer == NULL)
2154 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2173 while (buffer < bufferend)
2175 pchunk = (pskchunk_t *)buffer;
2176 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2177 version = LittleLong(pchunk->version);
2178 recordsize = LittleLong(pchunk->recordsize);
2179 numrecords = LittleLong(pchunk->numrecords);
2180 if (developer.integer >= 100)
2181 Con_Printf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2182 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2183 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);
2184 if (!strcmp(pchunk->id, "ACTRHEAD"))
2188 else if (!strcmp(pchunk->id, "PNTS0000"))
2191 if (recordsize != sizeof(*p))
2192 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2193 // byteswap in place and keep the pointer
2194 numpnts = numrecords;
2195 pnts = (pskpnts_t *)buffer;
2196 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2198 p->origin[0] = LittleFloat(p->origin[0]);
2199 p->origin[1] = LittleFloat(p->origin[1]);
2200 p->origin[2] = LittleFloat(p->origin[2]);
2204 else if (!strcmp(pchunk->id, "VTXW0000"))
2207 if (recordsize != sizeof(*p))
2208 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2209 // byteswap in place and keep the pointer
2210 numvtxw = numrecords;
2211 vtxw = (pskvtxw_t *)buffer;
2212 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2214 p->pntsindex = LittleShort(p->pntsindex);
2215 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2216 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2217 if (p->pntsindex >= numpnts)
2219 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2225 else if (!strcmp(pchunk->id, "FACE0000"))
2228 if (recordsize != sizeof(*p))
2229 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2230 // byteswap in place and keep the pointer
2231 numfaces = numrecords;
2232 faces = (pskface_t *)buffer;
2233 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2235 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2236 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2237 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2238 p->group = LittleLong(p->group);
2239 if (p->vtxwindex[0] >= numvtxw)
2241 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2242 p->vtxwindex[0] = 0;
2244 if (p->vtxwindex[1] >= numvtxw)
2246 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2247 p->vtxwindex[1] = 0;
2249 if (p->vtxwindex[2] >= numvtxw)
2251 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2252 p->vtxwindex[2] = 0;
2257 else if (!strcmp(pchunk->id, "MATT0000"))
2260 if (recordsize != sizeof(*p))
2261 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2262 // byteswap in place and keep the pointer
2263 nummatts = numrecords;
2264 matts = (pskmatt_t *)buffer;
2265 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2271 else if (!strcmp(pchunk->id, "REFSKELT"))
2274 if (recordsize != sizeof(*p))
2275 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2276 // byteswap in place and keep the pointer
2277 numbones = numrecords;
2278 bones = (pskboneinfo_t *)buffer;
2279 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2281 p->numchildren = LittleLong(p->numchildren);
2282 p->parent = LittleLong(p->parent);
2283 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2284 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2285 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2286 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2287 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2288 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2289 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2290 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2291 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2292 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2293 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2294 #ifdef PSKQUATNEGATIONS
2297 p->basepose.quat[0] *= -1;
2298 p->basepose.quat[1] *= -1;
2299 p->basepose.quat[2] *= -1;
2303 p->basepose.quat[0] *= 1;
2304 p->basepose.quat[1] *= -1;
2305 p->basepose.quat[2] *= 1;
2308 if (p->parent < 0 || p->parent >= numbones)
2310 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2316 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2319 if (recordsize != sizeof(*p))
2320 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2321 // byteswap in place and keep the pointer
2322 numrawweights = numrecords;
2323 rawweights = (pskrawweights_t *)buffer;
2324 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2326 p->weight = LittleFloat(p->weight);
2327 p->pntsindex = LittleLong(p->pntsindex);
2328 p->boneindex = LittleLong(p->boneindex);
2329 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2331 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2334 if (p->boneindex < 0 || p->boneindex >= numbones)
2336 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2344 while (animbuffer < animbufferend)
2346 pchunk = (pskchunk_t *)animbuffer;
2347 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2348 version = LittleLong(pchunk->version);
2349 recordsize = LittleLong(pchunk->recordsize);
2350 numrecords = LittleLong(pchunk->numrecords);
2351 if (developer.integer >= 100)
2352 Con_Printf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2353 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2354 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);
2355 if (!strcmp(pchunk->id, "ANIMHEAD"))
2359 else if (!strcmp(pchunk->id, "BONENAMES"))
2362 if (recordsize != sizeof(*p))
2363 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2364 // byteswap in place and keep the pointer
2365 numanimbones = numrecords;
2366 animbones = (pskboneinfo_t *)animbuffer;
2367 // NOTE: supposedly psa does not need to match the psk model, the
2368 // bones missing from the psa would simply use their base
2369 // positions from the psk, but this is hard for me to implement
2370 // and people can easily make animations that match.
2371 if (numanimbones != numbones)
2372 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2373 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2375 p->numchildren = LittleLong(p->numchildren);
2376 p->parent = LittleLong(p->parent);
2377 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2378 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2379 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2380 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2381 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2382 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2383 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2384 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2385 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2386 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2387 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2388 #ifdef PSKQUATNEGATIONS
2391 p->basepose.quat[0] *= -1;
2392 p->basepose.quat[1] *= -1;
2393 p->basepose.quat[2] *= -1;
2397 p->basepose.quat[0] *= 1;
2398 p->basepose.quat[1] *= -1;
2399 p->basepose.quat[2] *= 1;
2402 if (p->parent < 0 || p->parent >= numanimbones)
2404 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2407 // check that bones are the same as in the base
2408 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2409 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2413 else if (!strcmp(pchunk->id, "ANIMINFO"))
2416 if (recordsize != sizeof(*p))
2417 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2418 // byteswap in place and keep the pointer
2419 numanims = numrecords;
2420 anims = (pskaniminfo_t *)animbuffer;
2421 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2423 p->numbones = LittleLong(p->numbones);
2424 p->playtime = LittleFloat(p->playtime);
2425 p->fps = LittleFloat(p->fps);
2426 p->firstframe = LittleLong(p->firstframe);
2427 p->numframes = LittleLong(p->numframes);
2428 if (p->numbones != numbones)
2429 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2433 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2436 if (recordsize != sizeof(*p))
2437 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2438 numanimkeys = numrecords;
2439 animkeys = (pskanimkeys_t *)animbuffer;
2440 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2442 p->origin[0] = LittleFloat(p->origin[0]);
2443 p->origin[1] = LittleFloat(p->origin[1]);
2444 p->origin[2] = LittleFloat(p->origin[2]);
2445 p->quat[0] = LittleFloat(p->quat[0]);
2446 p->quat[1] = LittleFloat(p->quat[1]);
2447 p->quat[2] = LittleFloat(p->quat[2]);
2448 p->quat[3] = LittleFloat(p->quat[3]);
2449 p->frametime = LittleFloat(p->frametime);
2450 #ifdef PSKQUATNEGATIONS
2451 if (index % numbones)
2466 // TODO: allocate bonepose stuff
2469 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2472 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2473 Host_Error("%s: missing required chunks", loadmodel->name);
2475 loadmodel->numframes = 0;
2476 for (index = 0;index < numanims;index++)
2477 loadmodel->numframes += anims[index].numframes;
2479 if (numanimkeys != numbones * loadmodel->numframes)
2480 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2482 meshvertices = numvtxw;
2483 meshtriangles = numfaces;
2485 // load external .skin files if present
2486 skinfiles = Mod_LoadSkinFiles();
2487 if (loadmodel->numskins < 1)
2488 loadmodel->numskins = 1;
2489 loadmodel->num_bones = numbones;
2490 loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
2491 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2492 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2493 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2494 // do most allocations as one merged chunk
2495 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));
2496 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2497 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2498 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2499 loadmodel->surfmesh.num_vertices = meshvertices;
2500 loadmodel->surfmesh.num_triangles = meshtriangles;
2501 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2502 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2503 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2504 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2505 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2506 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2507 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2508 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
2509 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
2510 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
2511 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2512 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2513 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2514 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2516 for (i = 0;i < loadmodel->numskins;i++)
2518 loadmodel->skinscenes[i].firstframe = i;
2519 loadmodel->skinscenes[i].framecount = 1;
2520 loadmodel->skinscenes[i].loop = true;
2521 loadmodel->skinscenes[i].framerate = 10;
2525 for (index = 0, i = 0;index < nummatts;index++)
2527 // since psk models do not have named sections, reuse their shader name as the section name
2528 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2529 loadmodel->surfacelist[index] = index;
2530 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2531 loadmodel->data_surfaces[index].num_firstvertex = 0;
2532 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2535 // copy over the vertex locations and texcoords
2536 for (index = 0;index < numvtxw;index++)
2538 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2539 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2540 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2541 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2542 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2545 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2546 for (index = 0;index < numfaces;index++)
2547 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2548 for (index = 0, i = 0;index < nummatts;index++)
2550 loadmodel->data_surfaces[index].num_firsttriangle = i;
2551 i += loadmodel->data_surfaces[index].num_triangles;
2552 loadmodel->data_surfaces[index].num_triangles = 0;
2554 for (index = 0;index < numfaces;index++)
2556 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2557 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2558 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2559 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2562 // copy over the bones
2563 for (index = 0;index < numbones;index++)
2565 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2566 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2567 if (loadmodel->data_bones[index].parent >= index)
2568 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2571 // sort the psk point weights into the vertex weight tables
2572 // (which only accept up to 4 bones per vertex)
2573 for (index = 0;index < numvtxw;index++)
2577 for (j = 0;j < numrawweights;j++)
2579 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2581 int boneindex = rawweights[j].boneindex;
2582 float influence = rawweights[j].weight;
2583 for (l = 0;l < 4;l++)
2585 if (loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] < influence)
2587 // move lower influence weights out of the way first
2589 for (l2 = 3;l2 > l;l2--)
2591 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2-1];
2592 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2-1];
2594 // store the new weight
2595 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] = influence;
2596 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l] = boneindex;
2603 for (l = 0;l < 4;l++)
2604 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l];
2605 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2607 float f = 1.0f / sum;
2608 for (l = 0;l < 4;l++)
2609 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] *= f;
2613 // set up the animscenes based on the anims
2614 for (index = 0, i = 0;index < numanims;index++)
2616 for (j = 0;j < anims[index].numframes;j++, i++)
2618 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2619 loadmodel->animscenes[i].firstframe = i;
2620 loadmodel->animscenes[i].framecount = 1;
2621 loadmodel->animscenes[i].loop = true;
2622 loadmodel->animscenes[i].framerate = 10;
2626 // load the poses from the animkeys
2627 for (index = 0;index < numanimkeys;index++)
2629 pskanimkeys_t *k = animkeys + index;
2631 Matrix4x4_FromOriginQuat(&matrix, k->origin[0], k->origin[1], k->origin[2], k->quat[0], k->quat[1], k->quat[2], k->quat[3]);
2632 Matrix4x4_ToArray12FloatD3D(&matrix, loadmodel->data_poses + index*12);
2634 Mod_FreeSkinFiles(skinfiles);
2635 Mem_Free(animfilebuffer);
2637 // compute all the mesh information that was not loaded from the file
2638 // TODO: honor smoothing groups somehow?
2639 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2640 Mod_BuildBaseBonePoses();
2641 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2642 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);
2643 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2644 Mod_Alias_CalculateBoundingBox();
2646 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;