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 dp_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 dp_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 dp_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 dp_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 dp_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(dp_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(dp_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];
975 // generate ushort elements array if possible
976 if (loadmodel->surfmesh.num_vertices <= 65536)
978 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
979 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
980 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
984 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
985 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
986 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
987 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
988 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
989 Mod_Alias_CalculateBoundingBox();
990 Mod_Alias_MorphMesh_CompileFrames();
996 skinfiles = Mod_LoadSkinFiles();
997 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
998 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
999 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1000 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1003 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1004 Mod_FreeSkinFiles(skinfiles);
1005 for (i = 0;i < loadmodel->numskins;i++)
1007 loadmodel->skinscenes[i].firstframe = i;
1008 loadmodel->skinscenes[i].framecount = 1;
1009 loadmodel->skinscenes[i].loop = true;
1010 loadmodel->skinscenes[i].framerate = 10;
1016 datapointer = startskins;
1017 for (i = 0;i < loadmodel->numskins;i++)
1019 pinskintype = (daliasskintype_t *)datapointer;
1020 datapointer += sizeof(daliasskintype_t);
1022 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1029 pinskingroup = (daliasskingroup_t *)datapointer;
1030 datapointer += sizeof(daliasskingroup_t);
1032 groupskins = LittleLong (pinskingroup->numskins);
1034 pinskinintervals = (daliasskininterval_t *)datapointer;
1035 datapointer += sizeof(daliasskininterval_t) * groupskins;
1037 interval = LittleFloat(pinskinintervals[0].interval);
1038 if (interval < 0.01f)
1040 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1045 sprintf(loadmodel->skinscenes[i].name, "skin %i", i);
1046 loadmodel->skinscenes[i].firstframe = totalskins;
1047 loadmodel->skinscenes[i].framecount = groupskins;
1048 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1049 loadmodel->skinscenes[i].loop = true;
1051 for (j = 0;j < groupskins;j++)
1054 sprintf (name, "%s_%i_%i", loadmodel->name, i, j);
1056 sprintf (name, "%s_%i", loadmodel->name, i);
1057 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))
1058 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));
1059 datapointer += skinwidth * skinheight;
1063 // check for skins that don't exist in the model, but do exist as external images
1064 // (this was added because yummyluv kept pestering me about support for it)
1065 // TODO: support shaders here?
1066 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)))
1068 // expand the arrays to make room
1069 tempskinscenes = loadmodel->skinscenes;
1070 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1071 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1072 Mem_Free(tempskinscenes);
1074 tempaliasskins = loadmodel->data_textures;
1075 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1076 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1077 Mem_Free(tempaliasskins);
1079 // store the info about the new skin
1080 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1081 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1082 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1083 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1084 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1085 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1087 //increase skin counts
1088 loadmodel->numskins++;
1091 // fix up the pointers since they are pointing at the old textures array
1092 // FIXME: this is a hack!
1093 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1094 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1098 surface = loadmodel->data_surfaces;
1099 surface->texture = loadmodel->data_textures;
1100 surface->num_firsttriangle = 0;
1101 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1102 surface->num_firstvertex = 0;
1103 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1105 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1108 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1110 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1111 float iskinwidth, iskinheight;
1112 unsigned char *data;
1113 msurface_t *surface;
1115 unsigned char *base, *datapointer;
1116 md2frame_t *pinframe;
1118 md2triangle_t *intri;
1119 unsigned short *inst;
1120 struct md2verthash_s
1122 struct md2verthash_s *next;
1126 *hash, **md2verthash, *md2verthashdata;
1127 skinfile_t *skinfiles;
1129 pinmodel = (md2_t *)buffer;
1130 base = (unsigned char *)buffer;
1132 version = LittleLong (pinmodel->version);
1133 if (version != MD2ALIAS_VERSION)
1134 Host_Error ("%s has wrong version number (%i should be %i)",
1135 loadmodel->name, version, MD2ALIAS_VERSION);
1137 loadmodel->modeldatatypestring = "MD2";
1139 loadmodel->type = mod_alias;
1140 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1141 loadmodel->DrawSky = NULL;
1142 loadmodel->DrawAddWaterPlanes = NULL;
1143 loadmodel->Draw = R_Q1BSP_Draw;
1144 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1145 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1146 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1147 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1148 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1149 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1150 loadmodel->PointSuperContents = NULL;
1152 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1153 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1154 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1155 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1156 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1157 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1158 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1159 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1161 end = LittleLong(pinmodel->ofs_end);
1162 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1163 Host_Error ("%s is not a valid model", loadmodel->name);
1164 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1165 Host_Error ("%s is not a valid model", loadmodel->name);
1166 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1167 Host_Error ("%s is not a valid model", loadmodel->name);
1168 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1169 Host_Error ("%s is not a valid model", loadmodel->name);
1170 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1171 Host_Error ("%s is not a valid model", loadmodel->name);
1173 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1174 numxyz = LittleLong(pinmodel->num_xyz);
1175 numst = LittleLong(pinmodel->num_st);
1176 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1177 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1178 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1179 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1180 skinwidth = LittleLong(pinmodel->skinwidth);
1181 skinheight = LittleLong(pinmodel->skinheight);
1182 iskinwidth = 1.0f / skinwidth;
1183 iskinheight = 1.0f / skinheight;
1185 loadmodel->num_surfaces = 1;
1186 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1187 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]));
1188 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1189 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1190 loadmodel->surfacelist[0] = 0;
1191 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1192 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1193 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1194 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1196 loadmodel->synctype = ST_RAND;
1199 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1200 skinfiles = Mod_LoadSkinFiles();
1203 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1204 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1205 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1206 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1207 Mod_FreeSkinFiles(skinfiles);
1209 else if (loadmodel->numskins)
1211 // skins found (most likely not a player model)
1212 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1213 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1214 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1215 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1216 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);
1220 // no skins (most likely a player model)
1221 loadmodel->numskins = 1;
1222 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1223 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1224 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1225 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1228 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1229 for (i = 0;i < loadmodel->numskins;i++)
1231 loadmodel->skinscenes[i].firstframe = i;
1232 loadmodel->skinscenes[i].framecount = 1;
1233 loadmodel->skinscenes[i].loop = true;
1234 loadmodel->skinscenes[i].framerate = 10;
1237 // load the triangles and stvert data
1238 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1239 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1240 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1241 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1242 // swap the triangle list
1243 loadmodel->surfmesh.num_vertices = 0;
1244 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1246 for (j = 0;j < 3;j++)
1248 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1249 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1252 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1257 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1260 hashindex = (xyz * 256 + st) & 65535;
1261 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1262 if (hash->xyz == xyz && hash->st == st)
1266 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1269 hash->next = md2verthash[hashindex];
1270 md2verthash[hashindex] = hash;
1272 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1276 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1277 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));
1278 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1279 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1280 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1283 hash = md2verthashdata + i;
1284 vertremap[i] = hash->xyz;
1285 sts = LittleShort(inst[hash->st*2+0]);
1286 stt = LittleShort(inst[hash->st*2+1]);
1287 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1289 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1293 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1294 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1297 Mem_Free(md2verthash);
1298 Mem_Free(md2verthashdata);
1300 // generate ushort elements array if possible
1301 if (loadmodel->surfmesh.num_vertices <= 65536)
1303 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1304 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1305 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1309 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1310 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1315 pinframe = (md2frame_t *)datapointer;
1316 datapointer += sizeof(md2frame_t);
1317 // store the frame scale/translate into the appropriate array
1318 for (j = 0;j < 3;j++)
1320 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1321 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1323 // convert the vertices
1324 v = (trivertx_t *)datapointer;
1325 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1326 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1327 out[k] = v[vertremap[k]];
1328 datapointer += numxyz * sizeof(trivertx_t);
1330 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1331 loadmodel->animscenes[i].firstframe = i;
1332 loadmodel->animscenes[i].framecount = 1;
1333 loadmodel->animscenes[i].framerate = 10;
1334 loadmodel->animscenes[i].loop = true;
1337 Mem_Free(vertremap);
1339 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1340 Mod_Alias_CalculateBoundingBox();
1341 Mod_Alias_MorphMesh_CompileFrames();
1343 surface = loadmodel->data_surfaces;
1344 surface->texture = loadmodel->data_textures;
1345 surface->num_firsttriangle = 0;
1346 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1347 surface->num_firstvertex = 0;
1348 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1350 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1353 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1355 int i, j, k, version, meshvertices, meshtriangles;
1356 unsigned char *data;
1357 msurface_t *surface;
1358 md3modelheader_t *pinmodel;
1359 md3frameinfo_t *pinframe;
1362 skinfile_t *skinfiles;
1364 pinmodel = (md3modelheader_t *)buffer;
1366 if (memcmp(pinmodel->identifier, "IDP3", 4))
1367 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1368 version = LittleLong (pinmodel->version);
1369 if (version != MD3VERSION)
1370 Host_Error ("%s has wrong version number (%i should be %i)",
1371 loadmodel->name, version, MD3VERSION);
1373 skinfiles = Mod_LoadSkinFiles();
1374 if (loadmodel->numskins < 1)
1375 loadmodel->numskins = 1;
1377 loadmodel->modeldatatypestring = "MD3";
1379 loadmodel->type = mod_alias;
1380 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1381 loadmodel->DrawSky = NULL;
1382 loadmodel->DrawAddWaterPlanes = NULL;
1383 loadmodel->Draw = R_Q1BSP_Draw;
1384 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1385 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1386 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1387 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1388 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1389 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1390 loadmodel->PointSuperContents = NULL;
1391 loadmodel->synctype = ST_RAND;
1392 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1393 i = LittleLong (pinmodel->flags);
1394 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1396 // set up some global info about the model
1397 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1398 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1400 // make skinscenes for the skins (no groups)
1401 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1402 for (i = 0;i < loadmodel->numskins;i++)
1404 loadmodel->skinscenes[i].firstframe = i;
1405 loadmodel->skinscenes[i].framecount = 1;
1406 loadmodel->skinscenes[i].loop = true;
1407 loadmodel->skinscenes[i].framerate = 10;
1411 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1412 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1414 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1415 loadmodel->animscenes[i].firstframe = i;
1416 loadmodel->animscenes[i].framecount = 1;
1417 loadmodel->animscenes[i].framerate = 10;
1418 loadmodel->animscenes[i].loop = true;
1422 loadmodel->num_tagframes = loadmodel->numframes;
1423 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1424 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1425 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1427 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1428 for (j = 0;j < 9;j++)
1429 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1430 for (j = 0;j < 3;j++)
1431 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1432 //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);
1438 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)))
1440 if (memcmp(pinmesh->identifier, "IDP3", 4))
1441 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1442 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1443 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1444 meshvertices += LittleLong(pinmesh->num_vertices);
1445 meshtriangles += LittleLong(pinmesh->num_triangles);
1448 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1449 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1450 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1451 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 <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshvertices * sizeof(float[2]) + meshvertices * loadmodel->numframes * sizeof(md3vertex_t));
1452 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1453 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1454 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1455 loadmodel->surfmesh.num_vertices = meshvertices;
1456 loadmodel->surfmesh.num_triangles = meshtriangles;
1457 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1458 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1459 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1460 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1461 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1462 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1463 if (meshvertices <= 65536)
1465 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1466 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1467 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1472 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)))
1474 if (memcmp(pinmesh->identifier, "IDP3", 4))
1475 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1476 loadmodel->surfacelist[i] = i;
1477 surface = loadmodel->data_surfaces + i;
1478 surface->texture = loadmodel->data_textures + i;
1479 surface->num_firsttriangle = meshtriangles;
1480 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1481 surface->num_firstvertex = meshvertices;
1482 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1483 meshvertices += surface->num_vertices;
1484 meshtriangles += surface->num_triangles;
1486 for (j = 0;j < surface->num_triangles * 3;j++)
1487 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1488 for (j = 0;j < surface->num_vertices;j++)
1490 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1491 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1493 for (j = 0;j < loadmodel->numframes;j++)
1495 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1496 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1497 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1499 out->origin[0] = LittleShort(in->origin[0]);
1500 out->origin[1] = LittleShort(in->origin[1]);
1501 out->origin[2] = LittleShort(in->origin[2]);
1502 out->pitch = in->pitch;
1507 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1509 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1511 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1512 Mod_Alias_MorphMesh_CompileFrames();
1513 Mod_Alias_CalculateBoundingBox();
1514 Mod_FreeSkinFiles(skinfiles);
1516 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1517 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1520 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1522 zymtype1header_t *pinmodel, *pheader;
1523 unsigned char *pbase;
1524 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1525 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose;
1526 zymvertex_t *verts, *vertdata;
1530 skinfile_t *skinfiles;
1531 unsigned char *data;
1532 msurface_t *surface;
1534 pinmodel = (zymtype1header_t *)buffer;
1535 pbase = (unsigned char *)buffer;
1536 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1537 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1538 if (BigLong(pinmodel->type) != 1)
1539 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1541 loadmodel->modeldatatypestring = "ZYM";
1543 loadmodel->type = mod_alias;
1544 loadmodel->synctype = ST_RAND;
1548 pheader->type = BigLong(pinmodel->type);
1549 pheader->filesize = BigLong(pinmodel->filesize);
1550 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1551 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1552 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1553 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1554 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1555 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1556 pheader->radius = BigFloat(pinmodel->radius);
1557 pheader->numverts = BigLong(pinmodel->numverts);
1558 pheader->numtris = BigLong(pinmodel->numtris);
1559 pheader->numshaders = BigLong(pinmodel->numshaders);
1560 pheader->numbones = BigLong(pinmodel->numbones);
1561 pheader->numscenes = BigLong(pinmodel->numscenes);
1562 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1563 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1564 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1565 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1566 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1567 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1568 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1569 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1570 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1571 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1572 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1573 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1574 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1575 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1576 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1577 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1578 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1579 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1581 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1583 Con_Printf("%s has no geometry\n", loadmodel->name);
1586 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1588 Con_Printf("%s has no animations\n", loadmodel->name);
1592 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1593 loadmodel->DrawSky = NULL;
1594 loadmodel->DrawAddWaterPlanes = NULL;
1595 loadmodel->Draw = R_Q1BSP_Draw;
1596 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1597 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1598 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1599 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1600 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1601 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1602 loadmodel->PointSuperContents = NULL;
1604 loadmodel->numframes = pheader->numscenes;
1605 loadmodel->num_surfaces = pheader->numshaders;
1607 skinfiles = Mod_LoadSkinFiles();
1608 if (loadmodel->numskins < 1)
1609 loadmodel->numskins = 1;
1611 // make skinscenes for the skins (no groups)
1612 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1613 for (i = 0;i < loadmodel->numskins;i++)
1615 loadmodel->skinscenes[i].firstframe = i;
1616 loadmodel->skinscenes[i].framecount = 1;
1617 loadmodel->skinscenes[i].loop = true;
1618 loadmodel->skinscenes[i].framerate = 10;
1622 modelradius = pheader->radius;
1623 for (i = 0;i < 3;i++)
1625 loadmodel->normalmins[i] = pheader->mins[i];
1626 loadmodel->normalmaxs[i] = pheader->maxs[i];
1627 loadmodel->rotatedmins[i] = -modelradius;
1628 loadmodel->rotatedmaxs[i] = modelradius;
1630 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1631 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1632 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1633 if (loadmodel->yawmaxs[0] > modelradius)
1634 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1635 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1636 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1637 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1638 loadmodel->radius = modelradius;
1639 loadmodel->radius2 = modelradius * modelradius;
1641 // go through the lumps, swapping things
1643 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1644 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1645 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1646 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1647 for (i = 0;i < pheader->numscenes;i++)
1649 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1650 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1651 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1652 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1653 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1654 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1655 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1656 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1657 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1658 if (loadmodel->animscenes[i].framerate < 0)
1659 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1663 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1664 loadmodel->num_bones = pheader->numbones;
1665 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, pheader->numbones * sizeof(aliasbone_t));
1666 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1667 for (i = 0;i < pheader->numbones;i++)
1669 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1670 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1671 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1672 if (loadmodel->data_bones[i].parent >= i)
1673 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1676 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1677 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1678 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1679 for (i = 0;i < pheader->numverts;i++)
1681 vertbonecounts[i] = BigLong(bonecount[i]);
1682 if (vertbonecounts[i] != 1)
1683 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1686 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]);
1688 meshvertices = pheader->numverts;
1689 meshtriangles = pheader->numtris;
1691 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1692 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1693 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1694 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 <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshvertices * sizeof(float[14]) + meshvertices * sizeof(int[4]) + meshvertices * sizeof(float[4]) + loadmodel->num_poses * sizeof(float[12]) + loadmodel->num_bones * sizeof(float[12]));
1695 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1696 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1697 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1698 loadmodel->surfmesh.num_vertices = meshvertices;
1699 loadmodel->surfmesh.num_triangles = meshtriangles;
1700 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1701 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1702 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1703 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1704 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1705 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1706 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1707 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1708 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1709 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
1710 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1711 if (loadmodel->surfmesh.num_vertices <= 65536)
1713 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1714 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1715 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1718 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1719 poses = (float *) (pheader->lump_poses.start + pbase);
1720 for (i = 0;i < pheader->lump_poses.length / 4;i++)
1721 loadmodel->data_poses[i] = BigFloat(poses[i]);
1723 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1724 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1725 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1726 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1727 // (converting from weight-blending skeletal animation to
1728 // deformation-based skeletal animation)
1729 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1730 for (i = 0;i < loadmodel->num_bones;i++)
1732 const float *m = loadmodel->data_poses + i * 12;
1733 if (loadmodel->data_bones[i].parent >= 0)
1734 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1736 for (k = 0;k < 12;k++)
1737 bonepose[12*i+k] = m[k];
1739 for (j = 0;j < pheader->numverts;j++)
1741 // this format really should have had a per vertexweight weight value...
1742 // but since it does not, the weighting is completely ignored and
1743 // only one weight is allowed per vertex
1744 int boneindex = BigLong(vertdata[j].bonenum);
1745 const float *m = bonepose + 12 * boneindex;
1746 float relativeorigin[3];
1747 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1748 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1749 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1750 // transform the vertex bone weight into the base mesh
1751 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1752 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1753 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1754 // store the weight as the primary weight on this vertex
1755 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
1756 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = 1;
1759 // normals and tangents are calculated after elements are loaded
1761 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1762 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1763 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1764 for (i = 0;i < pheader->numverts;i++)
1766 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1767 // flip T coordinate for OpenGL
1768 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1771 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1772 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1773 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1775 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1776 //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)
1777 // byteswap, validate, and swap winding order of tris
1778 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1779 if (pheader->lump_render.length != count)
1780 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1781 renderlist = (int *) (pheader->lump_render.start + pbase);
1782 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1784 for (i = 0;i < loadmodel->num_surfaces;i++)
1786 int firstvertex, lastvertex;
1787 if (renderlist >= renderlistend)
1788 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1789 count = BigLong(*renderlist);renderlist++;
1790 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1791 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1793 loadmodel->surfacelist[i] = i;
1794 surface = loadmodel->data_surfaces + i;
1795 surface->texture = loadmodel->data_textures + i;
1796 surface->num_firsttriangle = meshtriangles;
1797 surface->num_triangles = count;
1798 meshtriangles += surface->num_triangles;
1800 // load the elements
1801 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
1802 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
1804 outelements[j*3+2] = BigLong(renderlist[0]);
1805 outelements[j*3+1] = BigLong(renderlist[1]);
1806 outelements[j*3+0] = BigLong(renderlist[2]);
1808 // validate the elements and find the used vertex range
1809 firstvertex = meshvertices;
1811 for (j = 0;j < surface->num_triangles * 3;j++)
1813 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
1814 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
1815 firstvertex = min(firstvertex, outelements[j]);
1816 lastvertex = max(lastvertex, outelements[j]);
1818 surface->num_firstvertex = firstvertex;
1819 surface->num_vertices = lastvertex + 1 - firstvertex;
1821 // since zym models do not have named sections, reuse their shader
1822 // name as the section name
1823 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
1824 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
1826 Mod_FreeSkinFiles(skinfiles);
1827 Mem_Free(vertbonecounts);
1830 // compute all the mesh information that was not loaded from the file
1831 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
1832 Mod_BuildBaseBonePoses();
1833 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
1834 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);
1835 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1837 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1840 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1842 dpmheader_t *pheader;
1846 unsigned char *pbase;
1847 int i, j, k, meshvertices, meshtriangles;
1848 skinfile_t *skinfiles;
1849 unsigned char *data;
1852 pheader = (dpmheader_t *)buffer;
1853 pbase = (unsigned char *)buffer;
1854 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
1855 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
1856 if (BigLong(pheader->type) != 2)
1857 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1859 loadmodel->modeldatatypestring = "DPM";
1861 loadmodel->type = mod_alias;
1862 loadmodel->synctype = ST_RAND;
1865 pheader->type = BigLong(pheader->type);
1866 pheader->filesize = BigLong(pheader->filesize);
1867 pheader->mins[0] = BigFloat(pheader->mins[0]);
1868 pheader->mins[1] = BigFloat(pheader->mins[1]);
1869 pheader->mins[2] = BigFloat(pheader->mins[2]);
1870 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
1871 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
1872 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
1873 pheader->yawradius = BigFloat(pheader->yawradius);
1874 pheader->allradius = BigFloat(pheader->allradius);
1875 pheader->num_bones = BigLong(pheader->num_bones);
1876 pheader->num_meshs = BigLong(pheader->num_meshs);
1877 pheader->num_frames = BigLong(pheader->num_frames);
1878 pheader->ofs_bones = BigLong(pheader->ofs_bones);
1879 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
1880 pheader->ofs_frames = BigLong(pheader->ofs_frames);
1882 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
1884 Con_Printf("%s has no geometry\n", loadmodel->name);
1887 if (pheader->num_frames < 1)
1889 Con_Printf("%s has no frames\n", loadmodel->name);
1893 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1894 loadmodel->DrawSky = NULL;
1895 loadmodel->DrawAddWaterPlanes = NULL;
1896 loadmodel->Draw = R_Q1BSP_Draw;
1897 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1898 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1899 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1900 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1901 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1902 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1903 loadmodel->PointSuperContents = NULL;
1906 for (i = 0;i < 3;i++)
1908 loadmodel->normalmins[i] = pheader->mins[i];
1909 loadmodel->normalmaxs[i] = pheader->maxs[i];
1910 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
1911 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
1912 loadmodel->rotatedmins[i] = -pheader->allradius;
1913 loadmodel->rotatedmaxs[i] = pheader->allradius;
1915 loadmodel->radius = pheader->allradius;
1916 loadmodel->radius2 = pheader->allradius * pheader->allradius;
1918 // load external .skin files if present
1919 skinfiles = Mod_LoadSkinFiles();
1920 if (loadmodel->numskins < 1)
1921 loadmodel->numskins = 1;
1926 // gather combined statistics from the meshes
1927 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
1928 for (i = 0;i < (int)pheader->num_meshs;i++)
1930 int numverts = BigLong(dpmmesh->num_verts);
1931 meshvertices += numverts;;
1932 meshtriangles += BigLong(dpmmesh->num_tris);
1936 loadmodel->numframes = pheader->num_frames;
1937 loadmodel->num_bones = pheader->num_bones;
1938 loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
1939 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
1940 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1941 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1942 // do most allocations as one merged chunk
1943 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]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + 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));
1944 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1945 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1946 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1947 loadmodel->surfmesh.num_vertices = meshvertices;
1948 loadmodel->surfmesh.num_triangles = meshtriangles;
1949 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1950 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1951 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1952 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1953 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1954 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1955 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1956 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1957 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1958 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
1959 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1960 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
1961 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
1962 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1963 if (meshvertices <= 65536)
1965 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1966 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1967 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1970 for (i = 0;i < loadmodel->numskins;i++)
1972 loadmodel->skinscenes[i].firstframe = i;
1973 loadmodel->skinscenes[i].framecount = 1;
1974 loadmodel->skinscenes[i].loop = true;
1975 loadmodel->skinscenes[i].framerate = 10;
1978 // load the bone info
1979 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
1980 for (i = 0;i < loadmodel->num_bones;i++)
1982 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1983 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1984 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1985 if (loadmodel->data_bones[i].parent >= i)
1986 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1990 frame = (dpmframe_t *) (pbase + pheader->ofs_frames);
1991 for (i = 0;i < loadmodel->numframes;i++)
1994 memcpy(loadmodel->animscenes[i].name, frame->name, sizeof(frame->name));
1995 loadmodel->animscenes[i].firstframe = i;
1996 loadmodel->animscenes[i].framecount = 1;
1997 loadmodel->animscenes[i].loop = true;
1998 loadmodel->animscenes[i].framerate = 10;
1999 // load the bone poses for this frame
2000 poses = (float *) (pbase + BigLong(frame->ofs_bonepositions));
2001 for (j = 0;j < loadmodel->num_bones*12;j++)
2002 loadmodel->data_poses[i * loadmodel->num_bones*12 + j] = BigFloat(poses[j]);
2003 // stuff not processed here: mins, maxs, yawradius, allradius
2007 // load the meshes now
2008 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2011 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2012 // (converting from weight-blending skeletal animation to
2013 // deformation-based skeletal animation)
2014 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2015 for (i = 0;i < loadmodel->num_bones;i++)
2017 const float *m = loadmodel->data_poses + i * 12;
2018 if (loadmodel->data_bones[i].parent >= 0)
2019 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2021 for (k = 0;k < 12;k++)
2022 bonepose[12*i+k] = m[k];
2024 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2026 const int *inelements;
2028 const float *intexcoord;
2029 msurface_t *surface;
2031 loadmodel->surfacelist[i] = i;
2032 surface = loadmodel->data_surfaces + i;
2033 surface->texture = loadmodel->data_textures + i;
2034 surface->num_firsttriangle = meshtriangles;
2035 surface->num_triangles = BigLong(dpmmesh->num_tris);
2036 surface->num_firstvertex = meshvertices;
2037 surface->num_vertices = BigLong(dpmmesh->num_verts);
2038 meshvertices += surface->num_vertices;
2039 meshtriangles += surface->num_triangles;
2041 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2042 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2043 for (j = 0;j < surface->num_triangles;j++)
2045 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2046 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2047 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2048 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2053 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2054 for (j = 0;j < surface->num_vertices*2;j++)
2055 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2057 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2058 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2062 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2063 data += sizeof(dpmvertex_t);
2064 for (k = 0;k < numweights;k++)
2066 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2067 int boneindex = BigLong(vert->bonenum);
2068 const float *m = bonepose + 12 * boneindex;
2069 float influence = BigFloat(vert->influence);
2070 float relativeorigin[3], relativenormal[3];
2071 relativeorigin[0] = BigFloat(vert->origin[0]);
2072 relativeorigin[1] = BigFloat(vert->origin[1]);
2073 relativeorigin[2] = BigFloat(vert->origin[2]);
2074 relativenormal[0] = BigFloat(vert->normal[0]);
2075 relativenormal[1] = BigFloat(vert->normal[1]);
2076 relativenormal[2] = BigFloat(vert->normal[2]);
2077 // blend the vertex bone weights into the base mesh
2078 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2079 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2080 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2081 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2082 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2083 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2086 // store the first (and often only) weight
2087 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = influence;
2088 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
2092 // sort the new weight into this vertex's weight table
2093 // (which only accepts up to 4 bones per vertex)
2094 for (l = 0;l < 4;l++)
2096 if (loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] < influence)
2098 // move weaker influence weights out of the way first
2100 for (l2 = 3;l2 > l;l2--)
2102 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2-1];
2103 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2-1];
2105 // store the new weight
2106 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] = influence;
2107 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l] = boneindex;
2112 data += sizeof(dpmbonevert_t);
2115 for (l = 0;l < 4;l++)
2116 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l];
2117 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2119 float f = 1.0f / sum;
2120 for (l = 0;l < 4;l++)
2121 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] *= f;
2125 // since dpm models do not have named sections, reuse their shader name as the section name
2126 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2128 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2131 Mod_FreeSkinFiles(skinfiles);
2133 // compute all the mesh information that was not loaded from the file
2134 Mod_BuildBaseBonePoses();
2135 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);
2136 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2138 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2141 // no idea why PSK/PSA files contain weird quaternions but they do...
2142 #define PSKQUATNEGATIONS
2143 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2145 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2146 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2147 fs_offset_t filesize;
2152 pskboneinfo_t *bones;
2153 pskrawweights_t *rawweights;
2154 pskboneinfo_t *animbones;
2155 pskaniminfo_t *anims;
2156 pskanimkeys_t *animkeys;
2157 void *animfilebuffer, *animbuffer, *animbufferend;
2158 unsigned char *data;
2160 skinfile_t *skinfiles;
2161 char animname[MAX_QPATH];
2163 pchunk = (pskchunk_t *)buffer;
2164 if (strcmp(pchunk->id, "ACTRHEAD"))
2165 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2167 loadmodel->modeldatatypestring = "PSK";
2169 loadmodel->type = mod_alias;
2170 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2171 loadmodel->DrawSky = NULL;
2172 loadmodel->DrawAddWaterPlanes = NULL;
2173 loadmodel->Draw = R_Q1BSP_Draw;
2174 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2175 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2176 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2177 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2178 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2179 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2180 loadmodel->PointSuperContents = NULL;
2181 loadmodel->synctype = ST_RAND;
2183 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2184 strlcat(animname, ".psa", sizeof(animname));
2185 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2186 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2187 if (animbuffer == NULL)
2188 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2207 while (buffer < bufferend)
2209 pchunk = (pskchunk_t *)buffer;
2210 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2211 version = LittleLong(pchunk->version);
2212 recordsize = LittleLong(pchunk->recordsize);
2213 numrecords = LittleLong(pchunk->numrecords);
2214 if (developer.integer >= 100)
2215 Con_Printf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2216 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2217 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);
2218 if (!strcmp(pchunk->id, "ACTRHEAD"))
2222 else if (!strcmp(pchunk->id, "PNTS0000"))
2225 if (recordsize != sizeof(*p))
2226 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2227 // byteswap in place and keep the pointer
2228 numpnts = numrecords;
2229 pnts = (pskpnts_t *)buffer;
2230 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2232 p->origin[0] = LittleFloat(p->origin[0]);
2233 p->origin[1] = LittleFloat(p->origin[1]);
2234 p->origin[2] = LittleFloat(p->origin[2]);
2238 else if (!strcmp(pchunk->id, "VTXW0000"))
2241 if (recordsize != sizeof(*p))
2242 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2243 // byteswap in place and keep the pointer
2244 numvtxw = numrecords;
2245 vtxw = (pskvtxw_t *)buffer;
2246 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2248 p->pntsindex = LittleShort(p->pntsindex);
2249 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2250 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2251 if (p->pntsindex >= numpnts)
2253 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2259 else if (!strcmp(pchunk->id, "FACE0000"))
2262 if (recordsize != sizeof(*p))
2263 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2264 // byteswap in place and keep the pointer
2265 numfaces = numrecords;
2266 faces = (pskface_t *)buffer;
2267 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2269 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2270 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2271 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2272 p->group = LittleLong(p->group);
2273 if (p->vtxwindex[0] >= numvtxw)
2275 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2276 p->vtxwindex[0] = 0;
2278 if (p->vtxwindex[1] >= numvtxw)
2280 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2281 p->vtxwindex[1] = 0;
2283 if (p->vtxwindex[2] >= numvtxw)
2285 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2286 p->vtxwindex[2] = 0;
2291 else if (!strcmp(pchunk->id, "MATT0000"))
2294 if (recordsize != sizeof(*p))
2295 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2296 // byteswap in place and keep the pointer
2297 nummatts = numrecords;
2298 matts = (pskmatt_t *)buffer;
2299 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2305 else if (!strcmp(pchunk->id, "REFSKELT"))
2308 if (recordsize != sizeof(*p))
2309 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2310 // byteswap in place and keep the pointer
2311 numbones = numrecords;
2312 bones = (pskboneinfo_t *)buffer;
2313 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2315 p->numchildren = LittleLong(p->numchildren);
2316 p->parent = LittleLong(p->parent);
2317 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2318 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2319 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2320 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2321 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2322 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2323 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2324 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2325 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2326 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2327 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2328 #ifdef PSKQUATNEGATIONS
2331 p->basepose.quat[0] *= -1;
2332 p->basepose.quat[1] *= -1;
2333 p->basepose.quat[2] *= -1;
2337 p->basepose.quat[0] *= 1;
2338 p->basepose.quat[1] *= -1;
2339 p->basepose.quat[2] *= 1;
2342 if (p->parent < 0 || p->parent >= numbones)
2344 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2350 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2353 if (recordsize != sizeof(*p))
2354 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2355 // byteswap in place and keep the pointer
2356 numrawweights = numrecords;
2357 rawweights = (pskrawweights_t *)buffer;
2358 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2360 p->weight = LittleFloat(p->weight);
2361 p->pntsindex = LittleLong(p->pntsindex);
2362 p->boneindex = LittleLong(p->boneindex);
2363 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2365 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2368 if (p->boneindex < 0 || p->boneindex >= numbones)
2370 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2378 while (animbuffer < animbufferend)
2380 pchunk = (pskchunk_t *)animbuffer;
2381 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2382 version = LittleLong(pchunk->version);
2383 recordsize = LittleLong(pchunk->recordsize);
2384 numrecords = LittleLong(pchunk->numrecords);
2385 if (developer.integer >= 100)
2386 Con_Printf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2387 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2388 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);
2389 if (!strcmp(pchunk->id, "ANIMHEAD"))
2393 else if (!strcmp(pchunk->id, "BONENAMES"))
2396 if (recordsize != sizeof(*p))
2397 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2398 // byteswap in place and keep the pointer
2399 numanimbones = numrecords;
2400 animbones = (pskboneinfo_t *)animbuffer;
2401 // NOTE: supposedly psa does not need to match the psk model, the
2402 // bones missing from the psa would simply use their base
2403 // positions from the psk, but this is hard for me to implement
2404 // and people can easily make animations that match.
2405 if (numanimbones != numbones)
2406 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2407 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2409 p->numchildren = LittleLong(p->numchildren);
2410 p->parent = LittleLong(p->parent);
2411 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2412 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2413 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2414 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2415 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2416 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2417 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2418 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2419 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2420 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2421 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2422 #ifdef PSKQUATNEGATIONS
2425 p->basepose.quat[0] *= -1;
2426 p->basepose.quat[1] *= -1;
2427 p->basepose.quat[2] *= -1;
2431 p->basepose.quat[0] *= 1;
2432 p->basepose.quat[1] *= -1;
2433 p->basepose.quat[2] *= 1;
2436 if (p->parent < 0 || p->parent >= numanimbones)
2438 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2441 // check that bones are the same as in the base
2442 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2443 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2447 else if (!strcmp(pchunk->id, "ANIMINFO"))
2450 if (recordsize != sizeof(*p))
2451 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2452 // byteswap in place and keep the pointer
2453 numanims = numrecords;
2454 anims = (pskaniminfo_t *)animbuffer;
2455 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2457 p->numbones = LittleLong(p->numbones);
2458 p->playtime = LittleFloat(p->playtime);
2459 p->fps = LittleFloat(p->fps);
2460 p->firstframe = LittleLong(p->firstframe);
2461 p->numframes = LittleLong(p->numframes);
2462 if (p->numbones != numbones)
2463 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2467 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2470 if (recordsize != sizeof(*p))
2471 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2472 numanimkeys = numrecords;
2473 animkeys = (pskanimkeys_t *)animbuffer;
2474 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2476 p->origin[0] = LittleFloat(p->origin[0]);
2477 p->origin[1] = LittleFloat(p->origin[1]);
2478 p->origin[2] = LittleFloat(p->origin[2]);
2479 p->quat[0] = LittleFloat(p->quat[0]);
2480 p->quat[1] = LittleFloat(p->quat[1]);
2481 p->quat[2] = LittleFloat(p->quat[2]);
2482 p->quat[3] = LittleFloat(p->quat[3]);
2483 p->frametime = LittleFloat(p->frametime);
2484 #ifdef PSKQUATNEGATIONS
2485 if (index % numbones)
2500 // TODO: allocate bonepose stuff
2503 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2506 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2507 Host_Error("%s: missing required chunks", loadmodel->name);
2509 loadmodel->numframes = 0;
2510 for (index = 0;index < numanims;index++)
2511 loadmodel->numframes += anims[index].numframes;
2513 if (numanimkeys != numbones * loadmodel->numframes)
2514 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2516 meshvertices = numvtxw;
2517 meshtriangles = numfaces;
2519 // load external .skin files if present
2520 skinfiles = Mod_LoadSkinFiles();
2521 if (loadmodel->numskins < 1)
2522 loadmodel->numskins = 1;
2523 loadmodel->num_bones = numbones;
2524 loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
2525 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2526 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2527 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2528 // do most allocations as one merged chunk
2529 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]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + 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));
2530 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2531 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2532 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2533 loadmodel->surfmesh.num_vertices = meshvertices;
2534 loadmodel->surfmesh.num_triangles = meshtriangles;
2535 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2536 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2537 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2538 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2539 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2540 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2541 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2542 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
2543 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
2544 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
2545 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2546 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2547 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2548 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2549 if (meshvertices <= 65536)
2551 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2552 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2553 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2556 for (i = 0;i < loadmodel->numskins;i++)
2558 loadmodel->skinscenes[i].firstframe = i;
2559 loadmodel->skinscenes[i].framecount = 1;
2560 loadmodel->skinscenes[i].loop = true;
2561 loadmodel->skinscenes[i].framerate = 10;
2565 for (index = 0, i = 0;index < nummatts;index++)
2567 // since psk models do not have named sections, reuse their shader name as the section name
2568 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2569 loadmodel->surfacelist[index] = index;
2570 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2571 loadmodel->data_surfaces[index].num_firstvertex = 0;
2572 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2575 // copy over the vertex locations and texcoords
2576 for (index = 0;index < numvtxw;index++)
2578 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2579 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2580 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2581 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2582 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2585 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2586 for (index = 0;index < numfaces;index++)
2587 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2588 for (index = 0, i = 0;index < nummatts;index++)
2590 loadmodel->data_surfaces[index].num_firsttriangle = i;
2591 i += loadmodel->data_surfaces[index].num_triangles;
2592 loadmodel->data_surfaces[index].num_triangles = 0;
2594 for (index = 0;index < numfaces;index++)
2596 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2597 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2598 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2599 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2602 // copy over the bones
2603 for (index = 0;index < numbones;index++)
2605 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2606 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2607 if (loadmodel->data_bones[index].parent >= index)
2608 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2611 // sort the psk point weights into the vertex weight tables
2612 // (which only accept up to 4 bones per vertex)
2613 for (index = 0;index < numvtxw;index++)
2617 for (j = 0;j < numrawweights;j++)
2619 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2621 int boneindex = rawweights[j].boneindex;
2622 float influence = rawweights[j].weight;
2623 for (l = 0;l < 4;l++)
2625 if (loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] < influence)
2627 // move lower influence weights out of the way first
2629 for (l2 = 3;l2 > l;l2--)
2631 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2-1];
2632 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2-1];
2634 // store the new weight
2635 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] = influence;
2636 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l] = boneindex;
2643 for (l = 0;l < 4;l++)
2644 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l];
2645 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2647 float f = 1.0f / sum;
2648 for (l = 0;l < 4;l++)
2649 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] *= f;
2653 // set up the animscenes based on the anims
2654 for (index = 0, i = 0;index < numanims;index++)
2656 for (j = 0;j < anims[index].numframes;j++, i++)
2658 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2659 loadmodel->animscenes[i].firstframe = i;
2660 loadmodel->animscenes[i].framecount = 1;
2661 loadmodel->animscenes[i].loop = true;
2662 loadmodel->animscenes[i].framerate = 10;
2666 // load the poses from the animkeys
2667 for (index = 0;index < numanimkeys;index++)
2669 pskanimkeys_t *k = animkeys + index;
2671 Matrix4x4_FromOriginQuat(&matrix, k->origin[0], k->origin[1], k->origin[2], k->quat[0], k->quat[1], k->quat[2], k->quat[3]);
2672 Matrix4x4_ToArray12FloatD3D(&matrix, loadmodel->data_poses + index*12);
2674 Mod_FreeSkinFiles(skinfiles);
2675 Mem_Free(animfilebuffer);
2677 // compute all the mesh information that was not loaded from the file
2678 // TODO: honor smoothing groups somehow?
2679 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2680 Mod_BuildBaseBonePoses();
2681 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2682 Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, true);
2683 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2684 Mod_Alias_CalculateBoundingBox();
2686 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;