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
53 float boneposerelative[MAX_BONES][12];
54 float *matrix, m[12], bonepose[MAX_BONES][12];
56 // interpolate matrices and concatenate them to their parents
57 for (i = 0;i < model->num_bones;i++)
59 for (k = 0;k < 12;k++)
61 for (blends = 0;blends < 4 && frameblend[blends].lerp > 0;blends++)
63 matrix = model->data_poses + (frameblend[blends].frame * model->num_bones + i) * 12;
64 for (k = 0;k < 12;k++)
65 m[k] += matrix[k] * frameblend[blends].lerp;
67 if (i == r_skeletal_debugbone.integer)
68 m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
69 m[3] *= r_skeletal_debugtranslatex.value;
70 m[7] *= r_skeletal_debugtranslatey.value;
71 m[11] *= r_skeletal_debugtranslatez.value;
72 if (model->data_bones[i].parent >= 0)
73 R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
75 for (k = 0;k < 12;k++)
76 bonepose[i][k] = m[k];
77 // create a relative deformation matrix to describe displacement
78 // from the base mesh, which is used by the actual weighting
79 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]);
81 // blend the vertex bone weights
82 // 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)
83 // special case for the first bone because it avoids the need to memset the arrays before filling
85 const float *v = model->surfmesh.data_vertex3f;
86 const int *wi = model->surfmesh.data_vertexweightindex4i;
87 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
88 memset(vertex3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
89 for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, wi += 4, wf += 4, vertex3f += 3)
93 const float *m = boneposerelative[wi[0]];
94 vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
95 vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
96 vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
100 const float *m = boneposerelative[wi[0]];
102 vertex3f[0] = f * (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
103 vertex3f[1] = f * (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
104 vertex3f[2] = f * (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
105 for (k = 1;k < 4 && wf[k];k++)
107 const float *m = boneposerelative[wi[k]];
109 vertex3f[0] += f * (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
110 vertex3f[1] += f * (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
111 vertex3f[2] += f * (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
118 const float *n = model->surfmesh.data_normal3f;
119 const int *wi = model->surfmesh.data_vertexweightindex4i;
120 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
121 memset(normal3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
122 for (i = 0;i < model->surfmesh.num_vertices;i++, n += 3, wi += 4, wf += 4, normal3f += 3)
126 const float *m = boneposerelative[wi[0]];
127 normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
128 normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
129 normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
133 const float *m = boneposerelative[wi[0]];
135 normal3f[0] = f * (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
136 normal3f[1] = f * (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
137 normal3f[2] = f * (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
138 for (k = 1;k < 4 && wf[k];k++)
140 const float *m = boneposerelative[wi[k]];
142 normal3f[0] += f * (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
143 normal3f[1] += f * (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
144 normal3f[2] += f * (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
151 const float *sv = model->surfmesh.data_svector3f;
152 const int *wi = model->surfmesh.data_vertexweightindex4i;
153 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
154 memset(svector3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
155 for (i = 0;i < model->surfmesh.num_vertices;i++, sv += 3, wi += 4, wf += 4, svector3f += 3)
159 const float *m = boneposerelative[wi[0]];
160 svector3f[0] = (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
161 svector3f[1] = (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
162 svector3f[2] = (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
166 const float *m = boneposerelative[wi[0]];
168 svector3f[0] = f * (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
169 svector3f[1] = f * (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
170 svector3f[2] = f * (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
171 for (k = 1;k < 4 && wf[k];k++)
173 const float *m = boneposerelative[wi[k]];
175 svector3f[0] += f * (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
176 svector3f[1] += f * (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
177 svector3f[2] += f * (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
184 const float *tv = model->surfmesh.data_tvector3f;
185 const int *wi = model->surfmesh.data_vertexweightindex4i;
186 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
187 memset(tvector3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
188 for (i = 0;i < model->surfmesh.num_vertices;i++, tv += 3, wi += 4, wf += 4, tvector3f += 3)
192 const float *m = boneposerelative[wi[0]];
193 tvector3f[0] = (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
194 tvector3f[1] = (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
195 tvector3f[2] = (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
199 const float *m = boneposerelative[wi[0]];
201 tvector3f[0] = f * (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
202 tvector3f[1] = f * (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
203 tvector3f[2] = f * (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
204 for (k = 1;k < 4 && wf[k];k++)
206 const float *m = boneposerelative[wi[k]];
208 tvector3f[0] += f * (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
209 tvector3f[1] += f * (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
210 tvector3f[2] += f * (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
217 void Mod_MD3_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
220 int i, numblends, blendnum;
221 int numverts = model->surfmesh.num_vertices;
223 for (blendnum = 0;blendnum < 4;blendnum++)
225 //VectorMA(translate, model->surfmesh.num_morphmdlframetranslate, frameblend[blendnum].lerp, translate);
226 if (frameblend[blendnum].lerp > 0)
227 numblends = blendnum + 1;
229 // special case for the first blend because it avoids some adds and the need to memset the arrays first
230 for (blendnum = 0;blendnum < numblends;blendnum++)
232 const md3vertex_t *verts = model->surfmesh.data_morphmd3vertex + numverts * frameblend[blendnum].frame;
233 float scale = frameblend[blendnum].lerp * (1.0f / 64.0f);
236 for (i = 0;i < numverts;i++)
238 vertex3f[i * 3 + 0] = verts[i].origin[0] * scale;
239 vertex3f[i * 3 + 1] = verts[i].origin[1] * scale;
240 vertex3f[i * 3 + 2] = verts[i].origin[2] * scale;
245 for (i = 0;i < numverts;i++)
247 vertex3f[i * 3 + 0] += verts[i].origin[0] * scale;
248 vertex3f[i * 3 + 1] += verts[i].origin[1] * scale;
249 vertex3f[i * 3 + 2] += verts[i].origin[2] * scale;
252 // the yaw and pitch stored in md3 models are 8bit quantized angles
253 // (0-255), and as such a lookup table is very well suited to
254 // decoding them, and since cosine is equivilant to sine with an
255 // extra 45 degree rotation, this uses one lookup table for both
256 // sine and cosine with a +64 bias to get cosine.
259 float lerp = frameblend[blendnum].lerp;
262 for (i = 0;i < numverts;i++)
264 normal3f[i * 3 + 0] = mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
265 normal3f[i * 3 + 1] = mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
266 normal3f[i * 3 + 2] = mod_md3_sin[verts[i].pitch + 64] * lerp;
271 for (i = 0;i < numverts;i++)
273 normal3f[i * 3 + 0] += mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
274 normal3f[i * 3 + 1] += mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
275 normal3f[i * 3 + 2] += mod_md3_sin[verts[i].pitch + 64] * lerp;
281 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].frame;
282 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
285 for (i = 0;i < numverts;i++, texvecvert++)
287 VectorScale(texvecvert->svec, f, svector3f + i*3);
288 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
293 for (i = 0;i < numverts;i++, texvecvert++)
295 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
296 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
303 void Mod_MDL_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
306 int i, numblends, blendnum;
307 int numverts = model->surfmesh.num_vertices;
309 VectorClear(translate);
311 // blend the frame translates to avoid redundantly doing so on each vertex
312 // (a bit of a brain twister but it works)
313 for (blendnum = 0;blendnum < 4;blendnum++)
315 if (model->surfmesh.data_morphmd2framesize6f)
316 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].frame * 6 + 3, translate);
318 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.num_morphmdlframetranslate, translate);
319 if (frameblend[blendnum].lerp > 0)
320 numblends = blendnum + 1;
322 // special case for the first blend because it avoids some adds and the need to memset the arrays first
323 for (blendnum = 0;blendnum < numblends;blendnum++)
325 const trivertx_t *verts = model->surfmesh.data_morphmdlvertex + numverts * frameblend[blendnum].frame;
327 if (model->surfmesh.data_morphmd2framesize6f)
328 VectorScale(model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].frame * 6, frameblend[blendnum].lerp, scale);
330 VectorScale(model->surfmesh.num_morphmdlframescale, frameblend[blendnum].lerp, scale);
333 for (i = 0;i < numverts;i++)
335 vertex3f[i * 3 + 0] = translate[0] + verts[i].v[0] * scale[0];
336 vertex3f[i * 3 + 1] = translate[1] + verts[i].v[1] * scale[1];
337 vertex3f[i * 3 + 2] = translate[2] + verts[i].v[2] * scale[2];
342 for (i = 0;i < numverts;i++)
344 vertex3f[i * 3 + 0] += verts[i].v[0] * scale[0];
345 vertex3f[i * 3 + 1] += verts[i].v[1] * scale[1];
346 vertex3f[i * 3 + 2] += verts[i].v[2] * scale[2];
349 // the vertex normals in mdl models are an index into a table of
350 // 162 unique values, this very crude quantization reduces the
351 // vertex normal to only one byte, which saves a lot of space but
352 // also makes lighting pretty coarse
355 float lerp = frameblend[blendnum].lerp;
358 for (i = 0;i < numverts;i++)
360 const float *vn = m_bytenormals[verts[i].lightnormalindex];
361 VectorScale(vn, lerp, normal3f + i*3);
366 for (i = 0;i < numverts;i++)
368 const float *vn = m_bytenormals[verts[i].lightnormalindex];
369 VectorMA(normal3f + i*3, lerp, vn, normal3f + i*3);
375 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].frame;
376 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
379 for (i = 0;i < numverts;i++, texvecvert++)
381 VectorScale(texvecvert->svec, f, svector3f + i*3);
382 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
387 for (i = 0;i < numverts;i++, texvecvert++)
389 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
390 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
397 int Mod_Alias_GetTagMatrix(const dp_model_t *model, int poseframe, int tagindex, matrix4x4_t *outmatrix)
399 const float *boneframe;
400 float tempbonematrix[12], bonematrix[12];
401 *outmatrix = identitymatrix;
402 if (model->num_bones)
404 if (tagindex < 0 || tagindex >= model->num_bones)
406 if (poseframe >= model->num_poses)
408 boneframe = model->data_poses + poseframe * model->num_bones * 12;
409 memcpy(bonematrix, boneframe + tagindex * 12, sizeof(float[12]));
410 while (model->data_bones[tagindex].parent >= 0)
412 memcpy(tempbonematrix, bonematrix, sizeof(float[12]));
413 R_ConcatTransforms(boneframe + model->data_bones[tagindex].parent * 12, tempbonematrix, bonematrix);
414 tagindex = model->data_bones[tagindex].parent;
416 Matrix4x4_FromArray12FloatD3D(outmatrix, bonematrix);
418 else if (model->num_tags)
420 if (tagindex < 0 || tagindex >= model->num_tags)
422 if (poseframe >= model->num_tagframes)
424 Matrix4x4_FromArray12FloatGL(outmatrix, model->data_tags[poseframe * model->num_tags + tagindex].matrixgl);
429 int Mod_Alias_GetTagIndexForName(const dp_model_t *model, unsigned int skin, const char *tagname)
432 if(skin >= (unsigned int)model->numskins)
434 if (model->num_bones)
435 for (i = 0;i < model->num_bones;i++)
436 if (!strcasecmp(tagname, model->data_bones[i].name))
439 for (i = 0;i < model->num_tags;i++)
440 if (!strcasecmp(tagname, model->data_tags[i].name))
445 static void Mod_BuildBaseBonePoses(void)
449 float *basebonepose = Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(float[12]));
450 float *in12f = loadmodel->data_poses;
451 float *out12f = basebonepose;
452 float *outinv12f = loadmodel->data_baseboneposeinverse;
453 for (i = 0;i < loadmodel->num_bones;i++, in12f += 12, out12f += 12, outinv12f += 12)
455 if (loadmodel->data_bones[i].parent >= 0)
456 R_ConcatTransforms(basebonepose + 12 * loadmodel->data_bones[i].parent, in12f, out12f);
458 for (k = 0;k < 12;k++)
459 out12f[k] = in12f[k];
463 // we only support uniform scaling, so assume the first row is enough
464 // (note the lack of sqrt here, because we're trying to undo the scaling,
465 // this means multiplying by the inverse scale twice - squaring it, which
466 // makes the sqrt a waste of time)
467 scale = 1.0 / (out12f[ 0] * out12f[ 0] + out12f[ 1] * out12f[ 1] + out12f[ 2] * out12f[ 2]);
469 // invert the rotation by transposing and multiplying by the squared
470 // recipricol of the input matrix scale as described above
471 outinv12f[ 0] = (float)(out12f[ 0] * scale);
472 outinv12f[ 1] = (float)(out12f[ 4] * scale);
473 outinv12f[ 2] = (float)(out12f[ 8] * scale);
474 outinv12f[ 4] = (float)(out12f[ 1] * scale);
475 outinv12f[ 5] = (float)(out12f[ 5] * scale);
476 outinv12f[ 6] = (float)(out12f[ 9] * scale);
477 outinv12f[ 8] = (float)(out12f[ 2] * scale);
478 outinv12f[ 9] = (float)(out12f[ 6] * scale);
479 outinv12f[10] = (float)(out12f[10] * scale);
481 // invert the translate
482 outinv12f[ 3] = -(out12f[ 3] * outinv12f[ 0] + out12f[ 7] * outinv12f[ 1] + out12f[11] * outinv12f[ 2]);
483 outinv12f[ 7] = -(out12f[ 3] * outinv12f[ 4] + out12f[ 7] * outinv12f[ 5] + out12f[11] * outinv12f[ 6]);
484 outinv12f[11] = -(out12f[ 3] * outinv12f[ 8] + out12f[ 7] * outinv12f[ 9] + out12f[11] * outinv12f[10]);
486 Mem_Free(basebonepose);
489 static void Mod_Alias_CalculateBoundingBox(void)
492 qboolean firstvertex = true;
493 float dist, yawradius, radius;
496 frameblend_t frameblend[4];
497 memset(frameblend, 0, sizeof(frameblend));
498 frameblend[0].lerp = 1;
499 vertex3f = Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
500 VectorClear(loadmodel->normalmins);
501 VectorClear(loadmodel->normalmaxs);
504 for (frameblend[0].frame = 0;frameblend[0].frame < loadmodel->num_poses;frameblend[0].frame++)
506 loadmodel->AnimateVertices(loadmodel, frameblend, vertex3f, NULL, NULL, NULL);
507 for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
512 VectorCopy(v, loadmodel->normalmins);
513 VectorCopy(v, loadmodel->normalmaxs);
517 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
518 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
519 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
520 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
521 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
522 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
524 dist = v[0] * v[0] + v[1] * v[1];
525 if (yawradius < dist)
533 radius = sqrt(radius);
534 yawradius = sqrt(yawradius);
535 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
536 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
537 loadmodel->yawmins[2] = loadmodel->normalmins[2];
538 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
539 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
540 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
541 loadmodel->radius = radius;
542 loadmodel->radius2 = radius * radius;
545 static void Mod_Alias_MorphMesh_CompileFrames(void)
548 frameblend_t frameblend[4] = {{0, 1}, {0, 0}, {0, 0}, {0, 0}};
549 unsigned char *datapointer;
550 datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
551 loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
552 loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
553 loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
554 loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
555 loadmodel->surfmesh.data_morphtexvecvertex = (texvecvertex_t *)datapointer;datapointer += loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices * sizeof(texvecvertex_t);
556 // 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)
557 for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
559 frameblend[0].frame = i;
560 loadmodel->AnimateVertices(loadmodel, frameblend, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
561 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);
562 // encode the svector and tvector in 3 byte format for permanent storage
563 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
565 VectorScale(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
566 VectorScale(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
571 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)
574 float segmentmins[3], segmentmaxs[3];
575 frameblend_t frameblend[4];
577 static int maxvertices = 0;
578 static float *vertex3f = NULL;
579 memset(trace, 0, sizeof(*trace));
581 trace->realfraction = 1;
582 trace->hitsupercontentsmask = hitsupercontentsmask;
583 memset(frameblend, 0, sizeof(frameblend));
584 frameblend[0].frame = frame;
585 frameblend[0].lerp = 1;
586 if (maxvertices < model->surfmesh.num_vertices)
590 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
591 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
593 if (VectorLength2(boxmins) + VectorLength2(boxmaxs) == 0)
596 segmentmins[0] = min(start[0], end[0]) - 1;
597 segmentmins[1] = min(start[1], end[1]) - 1;
598 segmentmins[2] = min(start[2], end[2]) - 1;
599 segmentmaxs[0] = max(start[0], end[0]) + 1;
600 segmentmaxs[1] = max(start[1], end[1]) + 1;
601 segmentmaxs[2] = max(start[2], end[2]) + 1;
602 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
604 model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL);
605 Collision_TraceLineTriangleMeshFloat(trace, start, end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, SUPERCONTENTS_SOLID, 0, surface->texture, segmentmins, segmentmaxs);
610 // box trace, performed as brush trace
611 colbrushf_t *thisbrush_start, *thisbrush_end;
612 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
613 segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
614 segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
615 segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
616 segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
617 segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
618 segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
619 VectorAdd(start, boxmins, boxstartmins);
620 VectorAdd(start, boxmaxs, boxstartmaxs);
621 VectorAdd(end, boxmins, boxendmins);
622 VectorAdd(end, boxmaxs, boxendmaxs);
623 thisbrush_start = Collision_BrushForBox(&identitymatrix, boxstartmins, boxstartmaxs, 0, 0, NULL);
624 thisbrush_end = Collision_BrushForBox(&identitymatrix, boxendmins, boxendmaxs, 0, 0, NULL);
625 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
627 if (maxvertices < model->surfmesh.num_vertices)
631 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
632 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
634 model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL);
635 Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, SUPERCONTENTS_SOLID, 0, surface->texture, segmentmins, segmentmaxs);
640 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
643 for (i = 0;i < inverts;i++)
645 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
647 j = vertremap[i]; // not onseam
650 j = vertremap[i+inverts]; // onseam
656 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
658 int i, f, pose, groupframes;
660 daliasframetype_t *pframetype;
661 daliasframe_t *pinframe;
662 daliasgroup_t *group;
663 daliasinterval_t *intervals;
666 scene = loadmodel->animscenes;
667 for (f = 0;f < loadmodel->numframes;f++)
669 pframetype = (daliasframetype_t *)datapointer;
670 datapointer += sizeof(daliasframetype_t);
671 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
673 // a single frame is still treated as a group
680 group = (daliasgroup_t *)datapointer;
681 datapointer += sizeof(daliasgroup_t);
682 groupframes = LittleLong (group->numframes);
684 // intervals (time per frame)
685 intervals = (daliasinterval_t *)datapointer;
686 datapointer += sizeof(daliasinterval_t) * groupframes;
688 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
689 if (interval < 0.01f)
691 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
696 // get scene name from first frame
697 pinframe = (daliasframe_t *)datapointer;
699 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
700 scene->firstframe = pose;
701 scene->framecount = groupframes;
702 scene->framerate = 1.0f / interval;
707 for (i = 0;i < groupframes;i++)
709 pinframe = (daliasframe_t *)datapointer;
710 datapointer += sizeof(daliasframe_t);
711 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
712 datapointer += sizeof(trivertx_t) * inverts;
718 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
720 if (cls.state == ca_dedicated)
724 skinframe = R_SkinFrame_LoadMissing();
725 memset(texture, 0, sizeof(*texture));
726 texture->currentframe = texture;
727 //texture->animated = false;
728 texture->numskinframes = 1;
729 texture->skinframerate = 1;
730 texture->skinframes[0] = skinframe;
731 texture->currentskinframe = skinframe;
732 //texture->backgroundnumskinframes = 0;
733 //texture->customblendfunc[0] = 0;
734 //texture->customblendfunc[1] = 0;
735 //texture->surfaceflags = 0;
736 //texture->supercontents = 0;
737 //texture->surfaceparms = 0;
738 //texture->textureflags = 0;
740 texture->basematerialflags = MATERIALFLAG_WALL;
741 if (texture->currentskinframe->fog)
742 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
743 texture->currentmaterialflags = texture->basematerialflags;
746 static void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, char *meshname, char *shadername)
749 skinfileitem_t *skinfileitem;
752 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
753 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
755 memset(skin, 0, sizeof(*skin));
757 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
759 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
760 if (!strcmp(skinfileitem->name, meshname))
762 Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
768 // don't render unmentioned meshes
769 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
770 skin->basematerialflags = skin->currentmaterialflags = 0;
775 Mod_LoadTextureFromQ3Shader(skin, shadername, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
778 #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);
779 #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);
780 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
782 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
783 float scales, scalet, interval;
787 stvert_t *pinstverts;
788 dtriangle_t *pintriangles;
789 daliasskintype_t *pinskintype;
790 daliasskingroup_t *pinskingroup;
791 daliasskininterval_t *pinskinintervals;
792 daliasframetype_t *pinframetype;
793 daliasgroup_t *pinframegroup;
794 unsigned char *datapointer, *startframes, *startskins;
795 char name[MAX_QPATH];
796 skinframe_t *tempskinframe;
797 animscene_t *tempskinscenes;
798 texture_t *tempaliasskins;
800 int *vertonseam, *vertremap;
801 skinfile_t *skinfiles;
803 datapointer = (unsigned char *)buffer;
804 pinmodel = (mdl_t *)datapointer;
805 datapointer += sizeof(mdl_t);
807 version = LittleLong (pinmodel->version);
808 if (version != ALIAS_VERSION)
809 Host_Error ("%s has wrong version number (%i should be %i)",
810 loadmodel->name, version, ALIAS_VERSION);
812 loadmodel->modeldatatypestring = "MDL";
814 loadmodel->type = mod_alias;
815 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
816 loadmodel->DrawSky = NULL;
817 loadmodel->DrawAddWaterPlanes = NULL;
818 loadmodel->Draw = R_Q1BSP_Draw;
819 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
820 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
821 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
822 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
823 loadmodel->DrawLight = R_Q1BSP_DrawLight;
824 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
825 loadmodel->PointSuperContents = NULL;
827 loadmodel->num_surfaces = 1;
828 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
829 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
830 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
831 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
832 loadmodel->surfacelist[0] = 0;
834 loadmodel->numskins = LittleLong(pinmodel->numskins);
835 BOUNDI(loadmodel->numskins,0,65536);
836 skinwidth = LittleLong (pinmodel->skinwidth);
837 BOUNDI(skinwidth,0,65536);
838 skinheight = LittleLong (pinmodel->skinheight);
839 BOUNDI(skinheight,0,65536);
840 numverts = LittleLong(pinmodel->numverts);
841 BOUNDI(numverts,0,65536);
842 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
843 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
844 loadmodel->numframes = LittleLong(pinmodel->numframes);
845 BOUNDI(loadmodel->numframes,0,65536);
846 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
847 BOUNDI(loadmodel->synctype,0,2);
848 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
849 i = LittleLong (pinmodel->flags);
850 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
852 for (i = 0;i < 3;i++)
854 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
855 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
858 startskins = datapointer;
860 for (i = 0;i < loadmodel->numskins;i++)
862 pinskintype = (daliasskintype_t *)datapointer;
863 datapointer += sizeof(daliasskintype_t);
864 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
868 pinskingroup = (daliasskingroup_t *)datapointer;
869 datapointer += sizeof(daliasskingroup_t);
870 groupskins = LittleLong(pinskingroup->numskins);
871 datapointer += sizeof(daliasskininterval_t) * groupskins;
874 for (j = 0;j < groupskins;j++)
876 datapointer += skinwidth * skinheight;
881 pinstverts = (stvert_t *)datapointer;
882 datapointer += sizeof(stvert_t) * numverts;
884 pintriangles = (dtriangle_t *)datapointer;
885 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
887 startframes = datapointer;
888 loadmodel->surfmesh.num_morphframes = 0;
889 for (i = 0;i < loadmodel->numframes;i++)
891 pinframetype = (daliasframetype_t *)datapointer;
892 datapointer += sizeof(daliasframetype_t);
893 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
897 pinframegroup = (daliasgroup_t *)datapointer;
898 datapointer += sizeof(daliasgroup_t);
899 groupframes = LittleLong(pinframegroup->numframes);
900 datapointer += sizeof(daliasinterval_t) * groupframes;
903 for (j = 0;j < groupframes;j++)
905 datapointer += sizeof(daliasframe_t);
906 datapointer += sizeof(trivertx_t) * numverts;
907 loadmodel->surfmesh.num_morphframes++;
910 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
912 // store texture coordinates into temporary array, they will be stored
913 // after usage is determined (triangle data)
914 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
915 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
916 vertonseam = vertremap + numverts * 2;
918 scales = 1.0 / skinwidth;
919 scalet = 1.0 / skinheight;
920 for (i = 0;i < numverts;i++)
922 vertonseam[i] = LittleLong(pinstverts[i].onseam);
923 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
924 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
925 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
926 vertst[(i+numverts)*2+1] = vertst[i*2+1];
929 // load triangle data
930 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
932 // read the triangle elements
933 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
934 for (j = 0;j < 3;j++)
935 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
936 // validate (note numverts is used because this is the original data)
937 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
938 // now butcher the elements according to vertonseam and tri->facesfront
939 // and then compact the vertex set to remove duplicates
940 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
941 if (!LittleLong(pintriangles[i].facesfront)) // backface
942 for (j = 0;j < 3;j++)
943 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
944 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
946 // (this uses vertremap to count usage to save some memory)
947 for (i = 0;i < numverts*2;i++)
949 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
950 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
951 // build remapping table and compact array
952 loadmodel->surfmesh.num_vertices = 0;
953 for (i = 0;i < numverts*2;i++)
957 vertremap[i] = loadmodel->surfmesh.num_vertices;
958 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
959 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
960 loadmodel->surfmesh.num_vertices++;
963 vertremap[i] = -1; // not used at all
965 // remap the elements to the new vertex set
966 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
967 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
968 // store the texture coordinates
969 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
970 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
972 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
973 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
976 // generate ushort elements array if possible
977 if (loadmodel->surfmesh.num_vertices <= 65536)
979 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
980 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
981 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
985 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
986 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
987 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
988 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
989 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
990 Mod_Alias_CalculateBoundingBox();
991 Mod_Alias_MorphMesh_CompileFrames();
997 skinfiles = Mod_LoadSkinFiles();
1000 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1001 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1002 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1003 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1004 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1005 Mod_FreeSkinFiles(skinfiles);
1006 for (i = 0;i < loadmodel->numskins;i++)
1008 loadmodel->skinscenes[i].firstframe = i;
1009 loadmodel->skinscenes[i].framecount = 1;
1010 loadmodel->skinscenes[i].loop = true;
1011 loadmodel->skinscenes[i].framerate = 10;
1016 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1017 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1018 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1019 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1021 datapointer = startskins;
1022 for (i = 0;i < loadmodel->numskins;i++)
1024 pinskintype = (daliasskintype_t *)datapointer;
1025 datapointer += sizeof(daliasskintype_t);
1027 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1034 pinskingroup = (daliasskingroup_t *)datapointer;
1035 datapointer += sizeof(daliasskingroup_t);
1037 groupskins = LittleLong (pinskingroup->numskins);
1039 pinskinintervals = (daliasskininterval_t *)datapointer;
1040 datapointer += sizeof(daliasskininterval_t) * groupskins;
1042 interval = LittleFloat(pinskinintervals[0].interval);
1043 if (interval < 0.01f)
1045 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1050 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1051 loadmodel->skinscenes[i].firstframe = totalskins;
1052 loadmodel->skinscenes[i].framecount = groupskins;
1053 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1054 loadmodel->skinscenes[i].loop = true;
1056 for (j = 0;j < groupskins;j++)
1059 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1061 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1062 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))
1063 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));
1064 datapointer += skinwidth * skinheight;
1068 // check for skins that don't exist in the model, but do exist as external images
1069 // (this was added because yummyluv kept pestering me about support for it)
1070 // TODO: support shaders here?
1071 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)))
1073 // expand the arrays to make room
1074 tempskinscenes = loadmodel->skinscenes;
1075 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1076 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1077 Mem_Free(tempskinscenes);
1079 tempaliasskins = loadmodel->data_textures;
1080 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1081 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1082 Mem_Free(tempaliasskins);
1084 // store the info about the new skin
1085 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1086 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1087 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1088 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1089 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1090 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1092 //increase skin counts
1093 loadmodel->numskins++;
1096 // fix up the pointers since they are pointing at the old textures array
1097 // FIXME: this is a hack!
1098 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1099 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1103 surface = loadmodel->data_surfaces;
1104 surface->texture = loadmodel->data_textures;
1105 surface->num_firsttriangle = 0;
1106 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1107 surface->num_firstvertex = 0;
1108 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1110 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1113 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1115 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1116 float iskinwidth, iskinheight;
1117 unsigned char *data;
1118 msurface_t *surface;
1120 unsigned char *base, *datapointer;
1121 md2frame_t *pinframe;
1123 md2triangle_t *intri;
1124 unsigned short *inst;
1125 struct md2verthash_s
1127 struct md2verthash_s *next;
1131 *hash, **md2verthash, *md2verthashdata;
1132 skinfile_t *skinfiles;
1134 pinmodel = (md2_t *)buffer;
1135 base = (unsigned char *)buffer;
1137 version = LittleLong (pinmodel->version);
1138 if (version != MD2ALIAS_VERSION)
1139 Host_Error ("%s has wrong version number (%i should be %i)",
1140 loadmodel->name, version, MD2ALIAS_VERSION);
1142 loadmodel->modeldatatypestring = "MD2";
1144 loadmodel->type = mod_alias;
1145 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1146 loadmodel->DrawSky = NULL;
1147 loadmodel->DrawAddWaterPlanes = NULL;
1148 loadmodel->Draw = R_Q1BSP_Draw;
1149 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1150 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1151 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1152 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1153 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1154 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1155 loadmodel->PointSuperContents = NULL;
1157 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1158 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1159 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1160 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1161 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1162 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1163 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1164 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1166 end = LittleLong(pinmodel->ofs_end);
1167 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1168 Host_Error ("%s is not a valid model", loadmodel->name);
1169 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1170 Host_Error ("%s is not a valid model", loadmodel->name);
1171 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1172 Host_Error ("%s is not a valid model", loadmodel->name);
1173 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1174 Host_Error ("%s is not a valid model", loadmodel->name);
1175 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1176 Host_Error ("%s is not a valid model", loadmodel->name);
1178 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1179 numxyz = LittleLong(pinmodel->num_xyz);
1180 numst = LittleLong(pinmodel->num_st);
1181 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1182 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1183 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1184 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1185 skinwidth = LittleLong(pinmodel->skinwidth);
1186 skinheight = LittleLong(pinmodel->skinheight);
1187 iskinwidth = 1.0f / skinwidth;
1188 iskinheight = 1.0f / skinheight;
1190 loadmodel->num_surfaces = 1;
1191 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1192 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]));
1193 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1194 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1195 loadmodel->surfacelist[0] = 0;
1196 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1197 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1198 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1199 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1201 loadmodel->synctype = ST_RAND;
1204 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1205 skinfiles = Mod_LoadSkinFiles();
1208 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1209 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1210 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1211 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1212 Mod_FreeSkinFiles(skinfiles);
1214 else if (loadmodel->numskins)
1216 // skins found (most likely not a player model)
1217 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1218 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1219 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1220 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1221 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);
1225 // no skins (most likely a player model)
1226 loadmodel->numskins = 1;
1227 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1228 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1229 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1230 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1233 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1234 for (i = 0;i < loadmodel->numskins;i++)
1236 loadmodel->skinscenes[i].firstframe = i;
1237 loadmodel->skinscenes[i].framecount = 1;
1238 loadmodel->skinscenes[i].loop = true;
1239 loadmodel->skinscenes[i].framerate = 10;
1242 // load the triangles and stvert data
1243 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1244 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1245 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1246 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1247 // swap the triangle list
1248 loadmodel->surfmesh.num_vertices = 0;
1249 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1251 for (j = 0;j < 3;j++)
1253 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1254 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1257 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1262 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1265 hashindex = (xyz * 256 + st) & 65535;
1266 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1267 if (hash->xyz == xyz && hash->st == st)
1271 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1274 hash->next = md2verthash[hashindex];
1275 md2verthash[hashindex] = hash;
1277 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1281 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1282 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));
1283 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1284 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1285 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1288 hash = md2verthashdata + i;
1289 vertremap[i] = hash->xyz;
1290 sts = LittleShort(inst[hash->st*2+0]);
1291 stt = LittleShort(inst[hash->st*2+1]);
1292 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1294 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1298 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1299 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1302 Mem_Free(md2verthash);
1303 Mem_Free(md2verthashdata);
1305 // generate ushort elements array if possible
1306 if (loadmodel->surfmesh.num_vertices <= 65536)
1308 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1309 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1310 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1314 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1315 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1320 pinframe = (md2frame_t *)datapointer;
1321 datapointer += sizeof(md2frame_t);
1322 // store the frame scale/translate into the appropriate array
1323 for (j = 0;j < 3;j++)
1325 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1326 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1328 // convert the vertices
1329 v = (trivertx_t *)datapointer;
1330 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1331 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1332 out[k] = v[vertremap[k]];
1333 datapointer += numxyz * sizeof(trivertx_t);
1335 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1336 loadmodel->animscenes[i].firstframe = i;
1337 loadmodel->animscenes[i].framecount = 1;
1338 loadmodel->animscenes[i].framerate = 10;
1339 loadmodel->animscenes[i].loop = true;
1342 Mem_Free(vertremap);
1344 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1345 Mod_Alias_CalculateBoundingBox();
1346 Mod_Alias_MorphMesh_CompileFrames();
1348 surface = loadmodel->data_surfaces;
1349 surface->texture = loadmodel->data_textures;
1350 surface->num_firsttriangle = 0;
1351 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1352 surface->num_firstvertex = 0;
1353 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1355 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1358 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1360 int i, j, k, version, meshvertices, meshtriangles;
1361 unsigned char *data;
1362 msurface_t *surface;
1363 md3modelheader_t *pinmodel;
1364 md3frameinfo_t *pinframe;
1367 skinfile_t *skinfiles;
1369 pinmodel = (md3modelheader_t *)buffer;
1371 if (memcmp(pinmodel->identifier, "IDP3", 4))
1372 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1373 version = LittleLong (pinmodel->version);
1374 if (version != MD3VERSION)
1375 Host_Error ("%s has wrong version number (%i should be %i)",
1376 loadmodel->name, version, MD3VERSION);
1378 skinfiles = Mod_LoadSkinFiles();
1379 if (loadmodel->numskins < 1)
1380 loadmodel->numskins = 1;
1382 loadmodel->modeldatatypestring = "MD3";
1384 loadmodel->type = mod_alias;
1385 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1386 loadmodel->DrawSky = NULL;
1387 loadmodel->DrawAddWaterPlanes = NULL;
1388 loadmodel->Draw = R_Q1BSP_Draw;
1389 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1390 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1391 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1392 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1393 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1394 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1395 loadmodel->PointSuperContents = NULL;
1396 loadmodel->synctype = ST_RAND;
1397 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1398 i = LittleLong (pinmodel->flags);
1399 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1401 // set up some global info about the model
1402 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1403 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1405 // make skinscenes for the skins (no groups)
1406 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1407 for (i = 0;i < loadmodel->numskins;i++)
1409 loadmodel->skinscenes[i].firstframe = i;
1410 loadmodel->skinscenes[i].framecount = 1;
1411 loadmodel->skinscenes[i].loop = true;
1412 loadmodel->skinscenes[i].framerate = 10;
1416 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1417 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1419 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1420 loadmodel->animscenes[i].firstframe = i;
1421 loadmodel->animscenes[i].framecount = 1;
1422 loadmodel->animscenes[i].framerate = 10;
1423 loadmodel->animscenes[i].loop = true;
1427 loadmodel->num_tagframes = loadmodel->numframes;
1428 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1429 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1430 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1432 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1433 for (j = 0;j < 9;j++)
1434 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1435 for (j = 0;j < 3;j++)
1436 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1437 //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);
1443 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)))
1445 if (memcmp(pinmesh->identifier, "IDP3", 4))
1446 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1447 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1448 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1449 meshvertices += LittleLong(pinmesh->num_vertices);
1450 meshtriangles += LittleLong(pinmesh->num_triangles);
1453 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1454 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1455 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1456 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));
1457 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1458 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1459 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1460 loadmodel->surfmesh.num_vertices = meshvertices;
1461 loadmodel->surfmesh.num_triangles = meshtriangles;
1462 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1463 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1464 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1465 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1466 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1467 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1468 if (meshvertices <= 65536)
1470 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1471 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1472 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1477 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)))
1479 if (memcmp(pinmesh->identifier, "IDP3", 4))
1480 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1481 loadmodel->surfacelist[i] = i;
1482 surface = loadmodel->data_surfaces + i;
1483 surface->texture = loadmodel->data_textures + i;
1484 surface->num_firsttriangle = meshtriangles;
1485 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1486 surface->num_firstvertex = meshvertices;
1487 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1488 meshvertices += surface->num_vertices;
1489 meshtriangles += surface->num_triangles;
1491 for (j = 0;j < surface->num_triangles * 3;j++)
1492 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1493 for (j = 0;j < surface->num_vertices;j++)
1495 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1496 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1498 for (j = 0;j < loadmodel->numframes;j++)
1500 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1501 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1502 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1504 out->origin[0] = LittleShort(in->origin[0]);
1505 out->origin[1] = LittleShort(in->origin[1]);
1506 out->origin[2] = LittleShort(in->origin[2]);
1507 out->pitch = in->pitch;
1512 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1514 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1516 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1517 Mod_Alias_MorphMesh_CompileFrames();
1518 Mod_Alias_CalculateBoundingBox();
1519 Mod_FreeSkinFiles(skinfiles);
1521 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1522 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1525 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1527 zymtype1header_t *pinmodel, *pheader;
1528 unsigned char *pbase;
1529 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1530 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose;
1531 zymvertex_t *verts, *vertdata;
1535 skinfile_t *skinfiles;
1536 unsigned char *data;
1537 msurface_t *surface;
1539 pinmodel = (zymtype1header_t *)buffer;
1540 pbase = (unsigned char *)buffer;
1541 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1542 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1543 if (BigLong(pinmodel->type) != 1)
1544 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1546 loadmodel->modeldatatypestring = "ZYM";
1548 loadmodel->type = mod_alias;
1549 loadmodel->synctype = ST_RAND;
1553 pheader->type = BigLong(pinmodel->type);
1554 pheader->filesize = BigLong(pinmodel->filesize);
1555 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1556 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1557 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1558 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1559 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1560 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1561 pheader->radius = BigFloat(pinmodel->radius);
1562 pheader->numverts = BigLong(pinmodel->numverts);
1563 pheader->numtris = BigLong(pinmodel->numtris);
1564 pheader->numshaders = BigLong(pinmodel->numshaders);
1565 pheader->numbones = BigLong(pinmodel->numbones);
1566 pheader->numscenes = BigLong(pinmodel->numscenes);
1567 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1568 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1569 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1570 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1571 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1572 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1573 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1574 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1575 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1576 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1577 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1578 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1579 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1580 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1581 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1582 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1583 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1584 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1586 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1588 Con_Printf("%s has no geometry\n", loadmodel->name);
1591 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1593 Con_Printf("%s has no animations\n", loadmodel->name);
1597 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1598 loadmodel->DrawSky = NULL;
1599 loadmodel->DrawAddWaterPlanes = NULL;
1600 loadmodel->Draw = R_Q1BSP_Draw;
1601 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1602 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1603 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1604 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1605 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1606 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1607 loadmodel->PointSuperContents = NULL;
1609 loadmodel->numframes = pheader->numscenes;
1610 loadmodel->num_surfaces = pheader->numshaders;
1612 skinfiles = Mod_LoadSkinFiles();
1613 if (loadmodel->numskins < 1)
1614 loadmodel->numskins = 1;
1616 // make skinscenes for the skins (no groups)
1617 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1618 for (i = 0;i < loadmodel->numskins;i++)
1620 loadmodel->skinscenes[i].firstframe = i;
1621 loadmodel->skinscenes[i].framecount = 1;
1622 loadmodel->skinscenes[i].loop = true;
1623 loadmodel->skinscenes[i].framerate = 10;
1627 modelradius = pheader->radius;
1628 for (i = 0;i < 3;i++)
1630 loadmodel->normalmins[i] = pheader->mins[i];
1631 loadmodel->normalmaxs[i] = pheader->maxs[i];
1632 loadmodel->rotatedmins[i] = -modelradius;
1633 loadmodel->rotatedmaxs[i] = modelradius;
1635 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1636 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1637 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1638 if (loadmodel->yawmaxs[0] > modelradius)
1639 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1640 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1641 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1642 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1643 loadmodel->radius = modelradius;
1644 loadmodel->radius2 = modelradius * modelradius;
1646 // go through the lumps, swapping things
1648 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1649 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1650 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1651 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1652 for (i = 0;i < pheader->numscenes;i++)
1654 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1655 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1656 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1657 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1658 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1659 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1660 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1661 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1662 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1663 if (loadmodel->animscenes[i].framerate < 0)
1664 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1668 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1669 loadmodel->num_bones = pheader->numbones;
1670 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, pheader->numbones * sizeof(aliasbone_t));
1671 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1672 for (i = 0;i < pheader->numbones;i++)
1674 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1675 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1676 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1677 if (loadmodel->data_bones[i].parent >= i)
1678 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1681 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1682 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1683 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1684 for (i = 0;i < pheader->numverts;i++)
1686 vertbonecounts[i] = BigLong(bonecount[i]);
1687 if (vertbonecounts[i] != 1)
1688 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1691 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]);
1693 meshvertices = pheader->numverts;
1694 meshtriangles = pheader->numtris;
1696 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1697 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1698 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1699 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]));
1700 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1701 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1702 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1703 loadmodel->surfmesh.num_vertices = meshvertices;
1704 loadmodel->surfmesh.num_triangles = meshtriangles;
1705 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1706 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1707 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1708 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1709 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1710 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1711 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1712 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1713 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1714 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
1715 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1716 if (loadmodel->surfmesh.num_vertices <= 65536)
1718 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1719 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1720 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1723 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1724 poses = (float *) (pheader->lump_poses.start + pbase);
1725 for (i = 0;i < pheader->lump_poses.length / 4;i++)
1726 loadmodel->data_poses[i] = BigFloat(poses[i]);
1728 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1729 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1730 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1731 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1732 // (converting from weight-blending skeletal animation to
1733 // deformation-based skeletal animation)
1734 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1735 for (i = 0;i < loadmodel->num_bones;i++)
1737 const float *m = loadmodel->data_poses + i * 12;
1738 if (loadmodel->data_bones[i].parent >= 0)
1739 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1741 for (k = 0;k < 12;k++)
1742 bonepose[12*i+k] = m[k];
1744 for (j = 0;j < pheader->numverts;j++)
1746 // this format really should have had a per vertexweight weight value...
1747 // but since it does not, the weighting is completely ignored and
1748 // only one weight is allowed per vertex
1749 int boneindex = BigLong(vertdata[j].bonenum);
1750 const float *m = bonepose + 12 * boneindex;
1751 float relativeorigin[3];
1752 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1753 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1754 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1755 // transform the vertex bone weight into the base mesh
1756 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1757 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1758 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1759 // store the weight as the primary weight on this vertex
1760 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
1761 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = 1;
1764 // normals and tangents are calculated after elements are loaded
1766 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1767 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1768 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1769 for (i = 0;i < pheader->numverts;i++)
1771 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1772 // flip T coordinate for OpenGL
1773 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1776 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1777 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1778 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1780 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1781 //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)
1782 // byteswap, validate, and swap winding order of tris
1783 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1784 if (pheader->lump_render.length != count)
1785 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1786 renderlist = (int *) (pheader->lump_render.start + pbase);
1787 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1789 for (i = 0;i < loadmodel->num_surfaces;i++)
1791 int firstvertex, lastvertex;
1792 if (renderlist >= renderlistend)
1793 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1794 count = BigLong(*renderlist);renderlist++;
1795 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1796 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1798 loadmodel->surfacelist[i] = i;
1799 surface = loadmodel->data_surfaces + i;
1800 surface->texture = loadmodel->data_textures + i;
1801 surface->num_firsttriangle = meshtriangles;
1802 surface->num_triangles = count;
1803 meshtriangles += surface->num_triangles;
1805 // load the elements
1806 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
1807 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
1809 outelements[j*3+2] = BigLong(renderlist[0]);
1810 outelements[j*3+1] = BigLong(renderlist[1]);
1811 outelements[j*3+0] = BigLong(renderlist[2]);
1813 // validate the elements and find the used vertex range
1814 firstvertex = meshvertices;
1816 for (j = 0;j < surface->num_triangles * 3;j++)
1818 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
1819 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
1820 firstvertex = min(firstvertex, outelements[j]);
1821 lastvertex = max(lastvertex, outelements[j]);
1823 surface->num_firstvertex = firstvertex;
1824 surface->num_vertices = lastvertex + 1 - firstvertex;
1826 // since zym models do not have named sections, reuse their shader
1827 // name as the section name
1828 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
1829 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
1831 Mod_FreeSkinFiles(skinfiles);
1832 Mem_Free(vertbonecounts);
1835 // compute all the mesh information that was not loaded from the file
1836 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
1837 Mod_BuildBaseBonePoses();
1838 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
1839 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);
1840 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1842 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1845 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1847 dpmheader_t *pheader;
1851 unsigned char *pbase;
1852 int i, j, k, meshvertices, meshtriangles;
1853 skinfile_t *skinfiles;
1854 unsigned char *data;
1857 pheader = (dpmheader_t *)buffer;
1858 pbase = (unsigned char *)buffer;
1859 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
1860 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
1861 if (BigLong(pheader->type) != 2)
1862 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1864 loadmodel->modeldatatypestring = "DPM";
1866 loadmodel->type = mod_alias;
1867 loadmodel->synctype = ST_RAND;
1870 pheader->type = BigLong(pheader->type);
1871 pheader->filesize = BigLong(pheader->filesize);
1872 pheader->mins[0] = BigFloat(pheader->mins[0]);
1873 pheader->mins[1] = BigFloat(pheader->mins[1]);
1874 pheader->mins[2] = BigFloat(pheader->mins[2]);
1875 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
1876 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
1877 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
1878 pheader->yawradius = BigFloat(pheader->yawradius);
1879 pheader->allradius = BigFloat(pheader->allradius);
1880 pheader->num_bones = BigLong(pheader->num_bones);
1881 pheader->num_meshs = BigLong(pheader->num_meshs);
1882 pheader->num_frames = BigLong(pheader->num_frames);
1883 pheader->ofs_bones = BigLong(pheader->ofs_bones);
1884 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
1885 pheader->ofs_frames = BigLong(pheader->ofs_frames);
1887 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
1889 Con_Printf("%s has no geometry\n", loadmodel->name);
1892 if (pheader->num_frames < 1)
1894 Con_Printf("%s has no frames\n", loadmodel->name);
1898 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1899 loadmodel->DrawSky = NULL;
1900 loadmodel->DrawAddWaterPlanes = NULL;
1901 loadmodel->Draw = R_Q1BSP_Draw;
1902 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1903 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1904 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1905 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1906 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1907 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1908 loadmodel->PointSuperContents = NULL;
1911 for (i = 0;i < 3;i++)
1913 loadmodel->normalmins[i] = pheader->mins[i];
1914 loadmodel->normalmaxs[i] = pheader->maxs[i];
1915 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
1916 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
1917 loadmodel->rotatedmins[i] = -pheader->allradius;
1918 loadmodel->rotatedmaxs[i] = pheader->allradius;
1920 loadmodel->radius = pheader->allradius;
1921 loadmodel->radius2 = pheader->allradius * pheader->allradius;
1923 // load external .skin files if present
1924 skinfiles = Mod_LoadSkinFiles();
1925 if (loadmodel->numskins < 1)
1926 loadmodel->numskins = 1;
1931 // gather combined statistics from the meshes
1932 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
1933 for (i = 0;i < (int)pheader->num_meshs;i++)
1935 int numverts = BigLong(dpmmesh->num_verts);
1936 meshvertices += numverts;
1937 meshtriangles += BigLong(dpmmesh->num_tris);
1941 loadmodel->numframes = pheader->num_frames;
1942 loadmodel->num_bones = pheader->num_bones;
1943 loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
1944 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
1945 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1946 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1947 // do most allocations as one merged chunk
1948 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));
1949 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1950 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1951 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1952 loadmodel->surfmesh.num_vertices = meshvertices;
1953 loadmodel->surfmesh.num_triangles = meshtriangles;
1954 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1955 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1956 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1957 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1958 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1959 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1960 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1961 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1962 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1963 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
1964 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1965 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
1966 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
1967 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1968 if (meshvertices <= 65536)
1970 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1971 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1972 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1975 for (i = 0;i < loadmodel->numskins;i++)
1977 loadmodel->skinscenes[i].firstframe = i;
1978 loadmodel->skinscenes[i].framecount = 1;
1979 loadmodel->skinscenes[i].loop = true;
1980 loadmodel->skinscenes[i].framerate = 10;
1983 // load the bone info
1984 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
1985 for (i = 0;i < loadmodel->num_bones;i++)
1987 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1988 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1989 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1990 if (loadmodel->data_bones[i].parent >= i)
1991 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1995 frame = (dpmframe_t *) (pbase + pheader->ofs_frames);
1996 for (i = 0;i < loadmodel->numframes;i++)
1999 memcpy(loadmodel->animscenes[i].name, frame->name, sizeof(frame->name));
2000 loadmodel->animscenes[i].firstframe = i;
2001 loadmodel->animscenes[i].framecount = 1;
2002 loadmodel->animscenes[i].loop = true;
2003 loadmodel->animscenes[i].framerate = 10;
2004 // load the bone poses for this frame
2005 poses = (float *) (pbase + BigLong(frame->ofs_bonepositions));
2006 for (j = 0;j < loadmodel->num_bones*12;j++)
2007 loadmodel->data_poses[i * loadmodel->num_bones*12 + j] = BigFloat(poses[j]);
2008 // stuff not processed here: mins, maxs, yawradius, allradius
2012 // load the meshes now
2013 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2016 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2017 // (converting from weight-blending skeletal animation to
2018 // deformation-based skeletal animation)
2019 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2020 for (i = 0;i < loadmodel->num_bones;i++)
2022 const float *m = loadmodel->data_poses + i * 12;
2023 if (loadmodel->data_bones[i].parent >= 0)
2024 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2026 for (k = 0;k < 12;k++)
2027 bonepose[12*i+k] = m[k];
2029 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2031 const int *inelements;
2033 const float *intexcoord;
2034 msurface_t *surface;
2036 loadmodel->surfacelist[i] = i;
2037 surface = loadmodel->data_surfaces + i;
2038 surface->texture = loadmodel->data_textures + i;
2039 surface->num_firsttriangle = meshtriangles;
2040 surface->num_triangles = BigLong(dpmmesh->num_tris);
2041 surface->num_firstvertex = meshvertices;
2042 surface->num_vertices = BigLong(dpmmesh->num_verts);
2043 meshvertices += surface->num_vertices;
2044 meshtriangles += surface->num_triangles;
2046 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2047 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2048 for (j = 0;j < surface->num_triangles;j++)
2050 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2051 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2052 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2053 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2058 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2059 for (j = 0;j < surface->num_vertices*2;j++)
2060 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2062 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2063 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2067 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2068 data += sizeof(dpmvertex_t);
2069 for (k = 0;k < numweights;k++)
2071 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2072 int boneindex = BigLong(vert->bonenum);
2073 const float *m = bonepose + 12 * boneindex;
2074 float influence = BigFloat(vert->influence);
2075 float relativeorigin[3], relativenormal[3];
2076 relativeorigin[0] = BigFloat(vert->origin[0]);
2077 relativeorigin[1] = BigFloat(vert->origin[1]);
2078 relativeorigin[2] = BigFloat(vert->origin[2]);
2079 relativenormal[0] = BigFloat(vert->normal[0]);
2080 relativenormal[1] = BigFloat(vert->normal[1]);
2081 relativenormal[2] = BigFloat(vert->normal[2]);
2082 // blend the vertex bone weights into the base mesh
2083 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2084 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2085 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2086 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2087 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2088 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2091 // store the first (and often only) weight
2092 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = influence;
2093 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
2097 // sort the new weight into this vertex's weight table
2098 // (which only accepts up to 4 bones per vertex)
2099 for (l = 0;l < 4;l++)
2101 if (loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] < influence)
2103 // move weaker influence weights out of the way first
2105 for (l2 = 3;l2 > l;l2--)
2107 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2-1];
2108 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2-1];
2110 // store the new weight
2111 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] = influence;
2112 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l] = boneindex;
2117 data += sizeof(dpmbonevert_t);
2120 for (l = 0;l < 4;l++)
2121 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l];
2122 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2124 float f = 1.0f / sum;
2125 for (l = 0;l < 4;l++)
2126 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] *= f;
2130 // since dpm models do not have named sections, reuse their shader name as the section name
2131 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2133 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2136 Mod_FreeSkinFiles(skinfiles);
2138 // compute all the mesh information that was not loaded from the file
2139 Mod_BuildBaseBonePoses();
2140 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);
2141 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2143 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2146 // no idea why PSK/PSA files contain weird quaternions but they do...
2147 #define PSKQUATNEGATIONS
2148 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2150 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2151 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2152 fs_offset_t filesize;
2157 pskboneinfo_t *bones;
2158 pskrawweights_t *rawweights;
2159 pskboneinfo_t *animbones;
2160 pskaniminfo_t *anims;
2161 pskanimkeys_t *animkeys;
2162 void *animfilebuffer, *animbuffer, *animbufferend;
2163 unsigned char *data;
2165 skinfile_t *skinfiles;
2166 char animname[MAX_QPATH];
2169 pchunk = (pskchunk_t *)buffer;
2170 if (strcmp(pchunk->id, "ACTRHEAD"))
2171 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2173 loadmodel->modeldatatypestring = "PSK";
2175 loadmodel->type = mod_alias;
2176 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2177 loadmodel->DrawSky = NULL;
2178 loadmodel->DrawAddWaterPlanes = NULL;
2179 loadmodel->Draw = R_Q1BSP_Draw;
2180 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2181 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2182 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2183 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2184 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2185 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2186 loadmodel->PointSuperContents = NULL;
2187 loadmodel->synctype = ST_RAND;
2189 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2190 strlcat(animname, ".psa", sizeof(animname));
2191 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2192 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2193 if (animbuffer == NULL)
2194 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2213 while (buffer < bufferend)
2215 pchunk = (pskchunk_t *)buffer;
2216 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2217 version = LittleLong(pchunk->version);
2218 recordsize = LittleLong(pchunk->recordsize);
2219 numrecords = LittleLong(pchunk->numrecords);
2220 if (developer.integer >= 100)
2221 Con_Printf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2222 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2223 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);
2224 if (!strcmp(pchunk->id, "ACTRHEAD"))
2228 else if (!strcmp(pchunk->id, "PNTS0000"))
2231 if (recordsize != sizeof(*p))
2232 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2233 // byteswap in place and keep the pointer
2234 numpnts = numrecords;
2235 pnts = (pskpnts_t *)buffer;
2236 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2238 p->origin[0] = LittleFloat(p->origin[0]);
2239 p->origin[1] = LittleFloat(p->origin[1]);
2240 p->origin[2] = LittleFloat(p->origin[2]);
2244 else if (!strcmp(pchunk->id, "VTXW0000"))
2247 if (recordsize != sizeof(*p))
2248 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2249 // byteswap in place and keep the pointer
2250 numvtxw = numrecords;
2251 vtxw = (pskvtxw_t *)buffer;
2252 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2254 p->pntsindex = LittleShort(p->pntsindex);
2255 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2256 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2257 if (p->pntsindex >= numpnts)
2259 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2265 else if (!strcmp(pchunk->id, "FACE0000"))
2268 if (recordsize != sizeof(*p))
2269 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2270 // byteswap in place and keep the pointer
2271 numfaces = numrecords;
2272 faces = (pskface_t *)buffer;
2273 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2275 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2276 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2277 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2278 p->group = LittleLong(p->group);
2279 if (p->vtxwindex[0] >= numvtxw)
2281 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2282 p->vtxwindex[0] = 0;
2284 if (p->vtxwindex[1] >= numvtxw)
2286 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2287 p->vtxwindex[1] = 0;
2289 if (p->vtxwindex[2] >= numvtxw)
2291 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2292 p->vtxwindex[2] = 0;
2297 else if (!strcmp(pchunk->id, "MATT0000"))
2300 if (recordsize != sizeof(*p))
2301 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2302 // byteswap in place and keep the pointer
2303 nummatts = numrecords;
2304 matts = (pskmatt_t *)buffer;
2305 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2311 else if (!strcmp(pchunk->id, "REFSKELT"))
2314 if (recordsize != sizeof(*p))
2315 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2316 // byteswap in place and keep the pointer
2317 numbones = numrecords;
2318 bones = (pskboneinfo_t *)buffer;
2319 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2321 p->numchildren = LittleLong(p->numchildren);
2322 p->parent = LittleLong(p->parent);
2323 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2324 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2325 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2326 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2327 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2328 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2329 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2330 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2331 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2332 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2333 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2334 #ifdef PSKQUATNEGATIONS
2337 p->basepose.quat[0] *= -1;
2338 p->basepose.quat[1] *= -1;
2339 p->basepose.quat[2] *= -1;
2343 p->basepose.quat[0] *= 1;
2344 p->basepose.quat[1] *= -1;
2345 p->basepose.quat[2] *= 1;
2348 if (p->parent < 0 || p->parent >= numbones)
2350 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2356 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2359 if (recordsize != sizeof(*p))
2360 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2361 // byteswap in place and keep the pointer
2362 numrawweights = numrecords;
2363 rawweights = (pskrawweights_t *)buffer;
2364 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2366 p->weight = LittleFloat(p->weight);
2367 p->pntsindex = LittleLong(p->pntsindex);
2368 p->boneindex = LittleLong(p->boneindex);
2369 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2371 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2374 if (p->boneindex < 0 || p->boneindex >= numbones)
2376 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2384 while (animbuffer < animbufferend)
2386 pchunk = (pskchunk_t *)animbuffer;
2387 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2388 version = LittleLong(pchunk->version);
2389 recordsize = LittleLong(pchunk->recordsize);
2390 numrecords = LittleLong(pchunk->numrecords);
2391 if (developer.integer >= 100)
2392 Con_Printf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2393 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2394 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);
2395 if (!strcmp(pchunk->id, "ANIMHEAD"))
2399 else if (!strcmp(pchunk->id, "BONENAMES"))
2402 if (recordsize != sizeof(*p))
2403 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2404 // byteswap in place and keep the pointer
2405 numanimbones = numrecords;
2406 animbones = (pskboneinfo_t *)animbuffer;
2407 // NOTE: supposedly psa does not need to match the psk model, the
2408 // bones missing from the psa would simply use their base
2409 // positions from the psk, but this is hard for me to implement
2410 // and people can easily make animations that match.
2411 if (numanimbones != numbones)
2412 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2413 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2415 p->numchildren = LittleLong(p->numchildren);
2416 p->parent = LittleLong(p->parent);
2417 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2418 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2419 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2420 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2421 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2422 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2423 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2424 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2425 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2426 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2427 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2428 #ifdef PSKQUATNEGATIONS
2431 p->basepose.quat[0] *= -1;
2432 p->basepose.quat[1] *= -1;
2433 p->basepose.quat[2] *= -1;
2437 p->basepose.quat[0] *= 1;
2438 p->basepose.quat[1] *= -1;
2439 p->basepose.quat[2] *= 1;
2442 if (p->parent < 0 || p->parent >= numanimbones)
2444 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2447 // check that bones are the same as in the base
2448 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2449 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2453 else if (!strcmp(pchunk->id, "ANIMINFO"))
2456 if (recordsize != sizeof(*p))
2457 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2458 // byteswap in place and keep the pointer
2459 numanims = numrecords;
2460 anims = (pskaniminfo_t *)animbuffer;
2461 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2463 p->numbones = LittleLong(p->numbones);
2464 p->playtime = LittleFloat(p->playtime);
2465 p->fps = LittleFloat(p->fps);
2466 p->firstframe = LittleLong(p->firstframe);
2467 p->numframes = LittleLong(p->numframes);
2468 if (p->numbones != numbones)
2469 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2473 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2476 if (recordsize != sizeof(*p))
2477 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2478 numanimkeys = numrecords;
2479 animkeys = (pskanimkeys_t *)animbuffer;
2480 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2482 p->origin[0] = LittleFloat(p->origin[0]);
2483 p->origin[1] = LittleFloat(p->origin[1]);
2484 p->origin[2] = LittleFloat(p->origin[2]);
2485 p->quat[0] = LittleFloat(p->quat[0]);
2486 p->quat[1] = LittleFloat(p->quat[1]);
2487 p->quat[2] = LittleFloat(p->quat[2]);
2488 p->quat[3] = LittleFloat(p->quat[3]);
2489 p->frametime = LittleFloat(p->frametime);
2490 #ifdef PSKQUATNEGATIONS
2491 if (index % numbones)
2506 // TODO: allocate bonepose stuff
2509 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2512 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2513 Host_Error("%s: missing required chunks", loadmodel->name);
2515 loadmodel->numframes = 0;
2516 for (index = 0;index < numanims;index++)
2517 loadmodel->numframes += anims[index].numframes;
2519 if (numanimkeys != numbones * loadmodel->numframes)
2520 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2522 meshvertices = numvtxw;
2523 meshtriangles = numfaces;
2525 // load external .skin files if present
2526 skinfiles = Mod_LoadSkinFiles();
2527 if (loadmodel->numskins < 1)
2528 loadmodel->numskins = 1;
2529 loadmodel->num_bones = numbones;
2530 loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
2531 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2532 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2533 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2534 loadmodel->surfmesh.num_vertices = meshvertices;
2535 loadmodel->surfmesh.num_triangles = meshtriangles;
2536 // do most allocations as one merged chunk
2537 size = loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + loadmodel->surfmesh.num_triangles * sizeof(int[3]) + loadmodel->surfmesh.num_triangles * sizeof(int[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[2]) + loadmodel->surfmesh.num_vertices * sizeof(int[4]) + loadmodel->surfmesh.num_vertices * 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) + ((loadmodel->surfmesh.num_vertices <= 65536) ? (loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3])) : 0);
2538 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2539 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2540 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2541 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2542 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2543 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2544 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2545 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2546 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2547 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2548 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2549 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += loadmodel->surfmesh.num_vertices * sizeof(int[4]);
2550 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[4]);
2551 //loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
2552 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2553 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2554 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2555 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2556 if (loadmodel->surfmesh.num_vertices <= 65536)
2558 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2559 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2560 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2562 loadmodel->data_poses = Mem_Alloc(loadmodel->mempool, loadmodel->num_poses * sizeof(float[12]));
2564 for (i = 0;i < loadmodel->numskins;i++)
2566 loadmodel->skinscenes[i].firstframe = i;
2567 loadmodel->skinscenes[i].framecount = 1;
2568 loadmodel->skinscenes[i].loop = true;
2569 loadmodel->skinscenes[i].framerate = 10;
2573 for (index = 0, i = 0;index < nummatts;index++)
2575 // since psk models do not have named sections, reuse their shader name as the section name
2576 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2577 loadmodel->surfacelist[index] = index;
2578 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2579 loadmodel->data_surfaces[index].num_firstvertex = 0;
2580 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2583 // copy over the vertex locations and texcoords
2584 for (index = 0;index < numvtxw;index++)
2586 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2587 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2588 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2589 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2590 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2593 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2594 for (index = 0;index < numfaces;index++)
2595 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2596 for (index = 0, i = 0;index < nummatts;index++)
2598 loadmodel->data_surfaces[index].num_firsttriangle = i;
2599 i += loadmodel->data_surfaces[index].num_triangles;
2600 loadmodel->data_surfaces[index].num_triangles = 0;
2602 for (index = 0;index < numfaces;index++)
2604 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2605 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2606 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2607 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2610 // copy over the bones
2611 for (index = 0;index < numbones;index++)
2613 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2614 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2615 if (loadmodel->data_bones[index].parent >= index)
2616 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2619 // sort the psk point weights into the vertex weight tables
2620 // (which only accept up to 4 bones per vertex)
2621 for (index = 0;index < numvtxw;index++)
2625 for (j = 0;j < numrawweights;j++)
2627 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2629 int boneindex = rawweights[j].boneindex;
2630 float influence = rawweights[j].weight;
2631 for (l = 0;l < 4;l++)
2633 if (loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] < influence)
2635 // move lower influence weights out of the way first
2637 for (l2 = 3;l2 > l;l2--)
2639 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2-1];
2640 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2-1];
2642 // store the new weight
2643 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] = influence;
2644 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l] = boneindex;
2651 for (l = 0;l < 4;l++)
2652 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l];
2653 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2655 float f = 1.0f / sum;
2656 for (l = 0;l < 4;l++)
2657 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] *= f;
2661 // set up the animscenes based on the anims
2662 for (index = 0, i = 0;index < numanims;index++)
2664 for (j = 0;j < anims[index].numframes;j++, i++)
2666 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2667 loadmodel->animscenes[i].firstframe = i;
2668 loadmodel->animscenes[i].framecount = 1;
2669 loadmodel->animscenes[i].loop = true;
2670 loadmodel->animscenes[i].framerate = 10;
2674 // load the poses from the animkeys
2675 for (index = 0;index < numanimkeys;index++)
2677 pskanimkeys_t *k = animkeys + index;
2679 Matrix4x4_FromOriginQuat(&matrix, k->origin[0], k->origin[1], k->origin[2], k->quat[0], k->quat[1], k->quat[2], k->quat[3]);
2680 Matrix4x4_ToArray12FloatD3D(&matrix, loadmodel->data_poses + index*12);
2682 Mod_FreeSkinFiles(skinfiles);
2683 Mem_Free(animfilebuffer);
2685 // compute all the mesh information that was not loaded from the file
2686 // TODO: honor smoothing groups somehow?
2687 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2688 Mod_BuildBaseBonePoses();
2689 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2690 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);
2691 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2692 Mod_Alias_CalculateBoundingBox();
2694 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;