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();
998 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
999 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1000 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1001 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * 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;
1017 datapointer = startskins;
1018 for (i = 0;i < loadmodel->numskins;i++)
1020 pinskintype = (daliasskintype_t *)datapointer;
1021 datapointer += sizeof(daliasskintype_t);
1023 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1030 pinskingroup = (daliasskingroup_t *)datapointer;
1031 datapointer += sizeof(daliasskingroup_t);
1033 groupskins = LittleLong (pinskingroup->numskins);
1035 pinskinintervals = (daliasskininterval_t *)datapointer;
1036 datapointer += sizeof(daliasskininterval_t) * groupskins;
1038 interval = LittleFloat(pinskinintervals[0].interval);
1039 if (interval < 0.01f)
1041 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1046 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1047 loadmodel->skinscenes[i].firstframe = totalskins;
1048 loadmodel->skinscenes[i].framecount = groupskins;
1049 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1050 loadmodel->skinscenes[i].loop = true;
1052 for (j = 0;j < groupskins;j++)
1055 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1057 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1058 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))
1059 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));
1060 datapointer += skinwidth * skinheight;
1064 // check for skins that don't exist in the model, but do exist as external images
1065 // (this was added because yummyluv kept pestering me about support for it)
1066 // TODO: support shaders here?
1067 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)))
1069 // expand the arrays to make room
1070 tempskinscenes = loadmodel->skinscenes;
1071 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1072 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1073 Mem_Free(tempskinscenes);
1075 tempaliasskins = loadmodel->data_textures;
1076 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1077 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1078 Mem_Free(tempaliasskins);
1080 // store the info about the new skin
1081 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1082 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1083 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1084 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1085 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1086 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1088 //increase skin counts
1089 loadmodel->numskins++;
1092 // fix up the pointers since they are pointing at the old textures array
1093 // FIXME: this is a hack!
1094 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1095 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1099 surface = loadmodel->data_surfaces;
1100 surface->texture = loadmodel->data_textures;
1101 surface->num_firsttriangle = 0;
1102 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1103 surface->num_firstvertex = 0;
1104 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1106 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1109 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1111 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1112 float iskinwidth, iskinheight;
1113 unsigned char *data;
1114 msurface_t *surface;
1116 unsigned char *base, *datapointer;
1117 md2frame_t *pinframe;
1119 md2triangle_t *intri;
1120 unsigned short *inst;
1121 struct md2verthash_s
1123 struct md2verthash_s *next;
1127 *hash, **md2verthash, *md2verthashdata;
1128 skinfile_t *skinfiles;
1130 pinmodel = (md2_t *)buffer;
1131 base = (unsigned char *)buffer;
1133 version = LittleLong (pinmodel->version);
1134 if (version != MD2ALIAS_VERSION)
1135 Host_Error ("%s has wrong version number (%i should be %i)",
1136 loadmodel->name, version, MD2ALIAS_VERSION);
1138 loadmodel->modeldatatypestring = "MD2";
1140 loadmodel->type = mod_alias;
1141 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1142 loadmodel->DrawSky = NULL;
1143 loadmodel->DrawAddWaterPlanes = NULL;
1144 loadmodel->Draw = R_Q1BSP_Draw;
1145 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1146 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1147 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1148 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1149 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1150 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1151 loadmodel->PointSuperContents = NULL;
1153 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1154 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1155 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1156 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1157 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1158 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1159 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1160 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1162 end = LittleLong(pinmodel->ofs_end);
1163 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1164 Host_Error ("%s is not a valid model", loadmodel->name);
1165 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1166 Host_Error ("%s is not a valid model", loadmodel->name);
1167 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1168 Host_Error ("%s is not a valid model", loadmodel->name);
1169 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1170 Host_Error ("%s is not a valid model", loadmodel->name);
1171 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1172 Host_Error ("%s is not a valid model", loadmodel->name);
1174 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1175 numxyz = LittleLong(pinmodel->num_xyz);
1176 numst = LittleLong(pinmodel->num_st);
1177 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1178 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1179 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1180 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1181 skinwidth = LittleLong(pinmodel->skinwidth);
1182 skinheight = LittleLong(pinmodel->skinheight);
1183 iskinwidth = 1.0f / skinwidth;
1184 iskinheight = 1.0f / skinheight;
1186 loadmodel->num_surfaces = 1;
1187 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1188 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]));
1189 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1190 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1191 loadmodel->surfacelist[0] = 0;
1192 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1193 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1194 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1195 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1197 loadmodel->synctype = ST_RAND;
1200 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1201 skinfiles = Mod_LoadSkinFiles();
1204 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1205 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1206 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1207 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1208 Mod_FreeSkinFiles(skinfiles);
1210 else if (loadmodel->numskins)
1212 // skins found (most likely not a player model)
1213 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1214 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1215 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1216 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1217 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);
1221 // no skins (most likely a player model)
1222 loadmodel->numskins = 1;
1223 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1224 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1225 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1226 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1229 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1230 for (i = 0;i < loadmodel->numskins;i++)
1232 loadmodel->skinscenes[i].firstframe = i;
1233 loadmodel->skinscenes[i].framecount = 1;
1234 loadmodel->skinscenes[i].loop = true;
1235 loadmodel->skinscenes[i].framerate = 10;
1238 // load the triangles and stvert data
1239 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1240 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1241 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1242 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1243 // swap the triangle list
1244 loadmodel->surfmesh.num_vertices = 0;
1245 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1247 for (j = 0;j < 3;j++)
1249 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1250 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1253 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1258 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1261 hashindex = (xyz * 256 + st) & 65535;
1262 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1263 if (hash->xyz == xyz && hash->st == st)
1267 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1270 hash->next = md2verthash[hashindex];
1271 md2verthash[hashindex] = hash;
1273 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1277 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1278 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));
1279 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1280 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1281 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1284 hash = md2verthashdata + i;
1285 vertremap[i] = hash->xyz;
1286 sts = LittleShort(inst[hash->st*2+0]);
1287 stt = LittleShort(inst[hash->st*2+1]);
1288 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1290 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1294 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1295 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1298 Mem_Free(md2verthash);
1299 Mem_Free(md2verthashdata);
1301 // generate ushort elements array if possible
1302 if (loadmodel->surfmesh.num_vertices <= 65536)
1304 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1305 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1306 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1310 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1311 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1316 pinframe = (md2frame_t *)datapointer;
1317 datapointer += sizeof(md2frame_t);
1318 // store the frame scale/translate into the appropriate array
1319 for (j = 0;j < 3;j++)
1321 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1322 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1324 // convert the vertices
1325 v = (trivertx_t *)datapointer;
1326 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1327 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1328 out[k] = v[vertremap[k]];
1329 datapointer += numxyz * sizeof(trivertx_t);
1331 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1332 loadmodel->animscenes[i].firstframe = i;
1333 loadmodel->animscenes[i].framecount = 1;
1334 loadmodel->animscenes[i].framerate = 10;
1335 loadmodel->animscenes[i].loop = true;
1338 Mem_Free(vertremap);
1340 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1341 Mod_Alias_CalculateBoundingBox();
1342 Mod_Alias_MorphMesh_CompileFrames();
1344 surface = loadmodel->data_surfaces;
1345 surface->texture = loadmodel->data_textures;
1346 surface->num_firsttriangle = 0;
1347 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1348 surface->num_firstvertex = 0;
1349 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1351 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1354 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1356 int i, j, k, version, meshvertices, meshtriangles;
1357 unsigned char *data;
1358 msurface_t *surface;
1359 md3modelheader_t *pinmodel;
1360 md3frameinfo_t *pinframe;
1363 skinfile_t *skinfiles;
1365 pinmodel = (md3modelheader_t *)buffer;
1367 if (memcmp(pinmodel->identifier, "IDP3", 4))
1368 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1369 version = LittleLong (pinmodel->version);
1370 if (version != MD3VERSION)
1371 Host_Error ("%s has wrong version number (%i should be %i)",
1372 loadmodel->name, version, MD3VERSION);
1374 skinfiles = Mod_LoadSkinFiles();
1375 if (loadmodel->numskins < 1)
1376 loadmodel->numskins = 1;
1378 loadmodel->modeldatatypestring = "MD3";
1380 loadmodel->type = mod_alias;
1381 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1382 loadmodel->DrawSky = NULL;
1383 loadmodel->DrawAddWaterPlanes = NULL;
1384 loadmodel->Draw = R_Q1BSP_Draw;
1385 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1386 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1387 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1388 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1389 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1390 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1391 loadmodel->PointSuperContents = NULL;
1392 loadmodel->synctype = ST_RAND;
1393 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1394 i = LittleLong (pinmodel->flags);
1395 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1397 // set up some global info about the model
1398 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1399 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1401 // make skinscenes for the skins (no groups)
1402 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1403 for (i = 0;i < loadmodel->numskins;i++)
1405 loadmodel->skinscenes[i].firstframe = i;
1406 loadmodel->skinscenes[i].framecount = 1;
1407 loadmodel->skinscenes[i].loop = true;
1408 loadmodel->skinscenes[i].framerate = 10;
1412 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1413 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1415 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1416 loadmodel->animscenes[i].firstframe = i;
1417 loadmodel->animscenes[i].framecount = 1;
1418 loadmodel->animscenes[i].framerate = 10;
1419 loadmodel->animscenes[i].loop = true;
1423 loadmodel->num_tagframes = loadmodel->numframes;
1424 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1425 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1426 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1428 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1429 for (j = 0;j < 9;j++)
1430 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1431 for (j = 0;j < 3;j++)
1432 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1433 //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);
1439 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)))
1441 if (memcmp(pinmesh->identifier, "IDP3", 4))
1442 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1443 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1444 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1445 meshvertices += LittleLong(pinmesh->num_vertices);
1446 meshtriangles += LittleLong(pinmesh->num_triangles);
1449 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1450 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1451 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1452 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));
1453 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1454 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1455 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1456 loadmodel->surfmesh.num_vertices = meshvertices;
1457 loadmodel->surfmesh.num_triangles = meshtriangles;
1458 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1459 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1460 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1461 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1462 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1463 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1464 if (meshvertices <= 65536)
1466 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1467 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1468 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1473 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)))
1475 if (memcmp(pinmesh->identifier, "IDP3", 4))
1476 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1477 loadmodel->surfacelist[i] = i;
1478 surface = loadmodel->data_surfaces + i;
1479 surface->texture = loadmodel->data_textures + i;
1480 surface->num_firsttriangle = meshtriangles;
1481 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1482 surface->num_firstvertex = meshvertices;
1483 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1484 meshvertices += surface->num_vertices;
1485 meshtriangles += surface->num_triangles;
1487 for (j = 0;j < surface->num_triangles * 3;j++)
1488 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1489 for (j = 0;j < surface->num_vertices;j++)
1491 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1492 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1494 for (j = 0;j < loadmodel->numframes;j++)
1496 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1497 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1498 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1500 out->origin[0] = LittleShort(in->origin[0]);
1501 out->origin[1] = LittleShort(in->origin[1]);
1502 out->origin[2] = LittleShort(in->origin[2]);
1503 out->pitch = in->pitch;
1508 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1510 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1512 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1513 Mod_Alias_MorphMesh_CompileFrames();
1514 Mod_Alias_CalculateBoundingBox();
1515 Mod_FreeSkinFiles(skinfiles);
1517 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1518 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1521 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1523 zymtype1header_t *pinmodel, *pheader;
1524 unsigned char *pbase;
1525 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1526 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose;
1527 zymvertex_t *verts, *vertdata;
1531 skinfile_t *skinfiles;
1532 unsigned char *data;
1533 msurface_t *surface;
1535 pinmodel = (zymtype1header_t *)buffer;
1536 pbase = (unsigned char *)buffer;
1537 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1538 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1539 if (BigLong(pinmodel->type) != 1)
1540 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1542 loadmodel->modeldatatypestring = "ZYM";
1544 loadmodel->type = mod_alias;
1545 loadmodel->synctype = ST_RAND;
1549 pheader->type = BigLong(pinmodel->type);
1550 pheader->filesize = BigLong(pinmodel->filesize);
1551 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1552 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1553 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1554 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1555 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1556 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1557 pheader->radius = BigFloat(pinmodel->radius);
1558 pheader->numverts = BigLong(pinmodel->numverts);
1559 pheader->numtris = BigLong(pinmodel->numtris);
1560 pheader->numshaders = BigLong(pinmodel->numshaders);
1561 pheader->numbones = BigLong(pinmodel->numbones);
1562 pheader->numscenes = BigLong(pinmodel->numscenes);
1563 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1564 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1565 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1566 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1567 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1568 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1569 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1570 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1571 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1572 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1573 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1574 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1575 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1576 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1577 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1578 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1579 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1580 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1582 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1584 Con_Printf("%s has no geometry\n", loadmodel->name);
1587 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1589 Con_Printf("%s has no animations\n", loadmodel->name);
1593 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1594 loadmodel->DrawSky = NULL;
1595 loadmodel->DrawAddWaterPlanes = NULL;
1596 loadmodel->Draw = R_Q1BSP_Draw;
1597 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1598 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1599 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1600 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1601 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1602 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1603 loadmodel->PointSuperContents = NULL;
1605 loadmodel->numframes = pheader->numscenes;
1606 loadmodel->num_surfaces = pheader->numshaders;
1608 skinfiles = Mod_LoadSkinFiles();
1609 if (loadmodel->numskins < 1)
1610 loadmodel->numskins = 1;
1612 // make skinscenes for the skins (no groups)
1613 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1614 for (i = 0;i < loadmodel->numskins;i++)
1616 loadmodel->skinscenes[i].firstframe = i;
1617 loadmodel->skinscenes[i].framecount = 1;
1618 loadmodel->skinscenes[i].loop = true;
1619 loadmodel->skinscenes[i].framerate = 10;
1623 modelradius = pheader->radius;
1624 for (i = 0;i < 3;i++)
1626 loadmodel->normalmins[i] = pheader->mins[i];
1627 loadmodel->normalmaxs[i] = pheader->maxs[i];
1628 loadmodel->rotatedmins[i] = -modelradius;
1629 loadmodel->rotatedmaxs[i] = modelradius;
1631 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1632 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1633 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1634 if (loadmodel->yawmaxs[0] > modelradius)
1635 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1636 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1637 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1638 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1639 loadmodel->radius = modelradius;
1640 loadmodel->radius2 = modelradius * modelradius;
1642 // go through the lumps, swapping things
1644 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1645 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1646 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1647 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1648 for (i = 0;i < pheader->numscenes;i++)
1650 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1651 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1652 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1653 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1654 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1655 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1656 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1657 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1658 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1659 if (loadmodel->animscenes[i].framerate < 0)
1660 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1664 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1665 loadmodel->num_bones = pheader->numbones;
1666 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, pheader->numbones * sizeof(aliasbone_t));
1667 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1668 for (i = 0;i < pheader->numbones;i++)
1670 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1671 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1672 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1673 if (loadmodel->data_bones[i].parent >= i)
1674 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1677 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1678 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1679 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1680 for (i = 0;i < pheader->numverts;i++)
1682 vertbonecounts[i] = BigLong(bonecount[i]);
1683 if (vertbonecounts[i] != 1)
1684 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1687 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]);
1689 meshvertices = pheader->numverts;
1690 meshtriangles = pheader->numtris;
1692 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1693 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1694 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1695 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]));
1696 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1697 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1698 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1699 loadmodel->surfmesh.num_vertices = meshvertices;
1700 loadmodel->surfmesh.num_triangles = meshtriangles;
1701 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1702 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1703 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1704 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1705 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1706 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1707 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1708 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1709 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1710 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
1711 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1712 if (loadmodel->surfmesh.num_vertices <= 65536)
1714 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1715 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1716 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1719 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1720 poses = (float *) (pheader->lump_poses.start + pbase);
1721 for (i = 0;i < pheader->lump_poses.length / 4;i++)
1722 loadmodel->data_poses[i] = BigFloat(poses[i]);
1724 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1725 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1726 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1727 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1728 // (converting from weight-blending skeletal animation to
1729 // deformation-based skeletal animation)
1730 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1731 for (i = 0;i < loadmodel->num_bones;i++)
1733 const float *m = loadmodel->data_poses + i * 12;
1734 if (loadmodel->data_bones[i].parent >= 0)
1735 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1737 for (k = 0;k < 12;k++)
1738 bonepose[12*i+k] = m[k];
1740 for (j = 0;j < pheader->numverts;j++)
1742 // this format really should have had a per vertexweight weight value...
1743 // but since it does not, the weighting is completely ignored and
1744 // only one weight is allowed per vertex
1745 int boneindex = BigLong(vertdata[j].bonenum);
1746 const float *m = bonepose + 12 * boneindex;
1747 float relativeorigin[3];
1748 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1749 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1750 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1751 // transform the vertex bone weight into the base mesh
1752 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1753 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1754 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1755 // store the weight as the primary weight on this vertex
1756 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
1757 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = 1;
1760 // normals and tangents are calculated after elements are loaded
1762 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1763 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1764 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1765 for (i = 0;i < pheader->numverts;i++)
1767 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1768 // flip T coordinate for OpenGL
1769 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1772 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1773 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1774 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1776 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1777 //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)
1778 // byteswap, validate, and swap winding order of tris
1779 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1780 if (pheader->lump_render.length != count)
1781 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1782 renderlist = (int *) (pheader->lump_render.start + pbase);
1783 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1785 for (i = 0;i < loadmodel->num_surfaces;i++)
1787 int firstvertex, lastvertex;
1788 if (renderlist >= renderlistend)
1789 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1790 count = BigLong(*renderlist);renderlist++;
1791 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1792 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1794 loadmodel->surfacelist[i] = i;
1795 surface = loadmodel->data_surfaces + i;
1796 surface->texture = loadmodel->data_textures + i;
1797 surface->num_firsttriangle = meshtriangles;
1798 surface->num_triangles = count;
1799 meshtriangles += surface->num_triangles;
1801 // load the elements
1802 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
1803 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
1805 outelements[j*3+2] = BigLong(renderlist[0]);
1806 outelements[j*3+1] = BigLong(renderlist[1]);
1807 outelements[j*3+0] = BigLong(renderlist[2]);
1809 // validate the elements and find the used vertex range
1810 firstvertex = meshvertices;
1812 for (j = 0;j < surface->num_triangles * 3;j++)
1814 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
1815 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
1816 firstvertex = min(firstvertex, outelements[j]);
1817 lastvertex = max(lastvertex, outelements[j]);
1819 surface->num_firstvertex = firstvertex;
1820 surface->num_vertices = lastvertex + 1 - firstvertex;
1822 // since zym models do not have named sections, reuse their shader
1823 // name as the section name
1824 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
1825 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
1827 Mod_FreeSkinFiles(skinfiles);
1828 Mem_Free(vertbonecounts);
1831 // compute all the mesh information that was not loaded from the file
1832 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
1833 Mod_BuildBaseBonePoses();
1834 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
1835 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);
1836 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1838 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1841 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1843 dpmheader_t *pheader;
1847 unsigned char *pbase;
1848 int i, j, k, meshvertices, meshtriangles;
1849 skinfile_t *skinfiles;
1850 unsigned char *data;
1853 pheader = (dpmheader_t *)buffer;
1854 pbase = (unsigned char *)buffer;
1855 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
1856 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
1857 if (BigLong(pheader->type) != 2)
1858 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1860 loadmodel->modeldatatypestring = "DPM";
1862 loadmodel->type = mod_alias;
1863 loadmodel->synctype = ST_RAND;
1866 pheader->type = BigLong(pheader->type);
1867 pheader->filesize = BigLong(pheader->filesize);
1868 pheader->mins[0] = BigFloat(pheader->mins[0]);
1869 pheader->mins[1] = BigFloat(pheader->mins[1]);
1870 pheader->mins[2] = BigFloat(pheader->mins[2]);
1871 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
1872 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
1873 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
1874 pheader->yawradius = BigFloat(pheader->yawradius);
1875 pheader->allradius = BigFloat(pheader->allradius);
1876 pheader->num_bones = BigLong(pheader->num_bones);
1877 pheader->num_meshs = BigLong(pheader->num_meshs);
1878 pheader->num_frames = BigLong(pheader->num_frames);
1879 pheader->ofs_bones = BigLong(pheader->ofs_bones);
1880 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
1881 pheader->ofs_frames = BigLong(pheader->ofs_frames);
1883 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
1885 Con_Printf("%s has no geometry\n", loadmodel->name);
1888 if (pheader->num_frames < 1)
1890 Con_Printf("%s has no frames\n", loadmodel->name);
1894 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1895 loadmodel->DrawSky = NULL;
1896 loadmodel->DrawAddWaterPlanes = NULL;
1897 loadmodel->Draw = R_Q1BSP_Draw;
1898 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1899 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1900 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1901 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1902 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1903 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1904 loadmodel->PointSuperContents = NULL;
1907 for (i = 0;i < 3;i++)
1909 loadmodel->normalmins[i] = pheader->mins[i];
1910 loadmodel->normalmaxs[i] = pheader->maxs[i];
1911 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
1912 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
1913 loadmodel->rotatedmins[i] = -pheader->allradius;
1914 loadmodel->rotatedmaxs[i] = pheader->allradius;
1916 loadmodel->radius = pheader->allradius;
1917 loadmodel->radius2 = pheader->allradius * pheader->allradius;
1919 // load external .skin files if present
1920 skinfiles = Mod_LoadSkinFiles();
1921 if (loadmodel->numskins < 1)
1922 loadmodel->numskins = 1;
1927 // gather combined statistics from the meshes
1928 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
1929 for (i = 0;i < (int)pheader->num_meshs;i++)
1931 int numverts = BigLong(dpmmesh->num_verts);
1932 meshvertices += numverts;
1933 meshtriangles += BigLong(dpmmesh->num_tris);
1937 loadmodel->numframes = pheader->num_frames;
1938 loadmodel->num_bones = pheader->num_bones;
1939 loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
1940 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
1941 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1942 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1943 // do most allocations as one merged chunk
1944 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));
1945 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1946 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1947 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1948 loadmodel->surfmesh.num_vertices = meshvertices;
1949 loadmodel->surfmesh.num_triangles = meshtriangles;
1950 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1951 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1952 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1953 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1954 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1955 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1956 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1957 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1958 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1959 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
1960 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1961 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
1962 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
1963 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1964 if (meshvertices <= 65536)
1966 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1967 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1968 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1971 for (i = 0;i < loadmodel->numskins;i++)
1973 loadmodel->skinscenes[i].firstframe = i;
1974 loadmodel->skinscenes[i].framecount = 1;
1975 loadmodel->skinscenes[i].loop = true;
1976 loadmodel->skinscenes[i].framerate = 10;
1979 // load the bone info
1980 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
1981 for (i = 0;i < loadmodel->num_bones;i++)
1983 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1984 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1985 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1986 if (loadmodel->data_bones[i].parent >= i)
1987 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1991 frame = (dpmframe_t *) (pbase + pheader->ofs_frames);
1992 for (i = 0;i < loadmodel->numframes;i++)
1995 memcpy(loadmodel->animscenes[i].name, frame->name, sizeof(frame->name));
1996 loadmodel->animscenes[i].firstframe = i;
1997 loadmodel->animscenes[i].framecount = 1;
1998 loadmodel->animscenes[i].loop = true;
1999 loadmodel->animscenes[i].framerate = 10;
2000 // load the bone poses for this frame
2001 poses = (float *) (pbase + BigLong(frame->ofs_bonepositions));
2002 for (j = 0;j < loadmodel->num_bones*12;j++)
2003 loadmodel->data_poses[i * loadmodel->num_bones*12 + j] = BigFloat(poses[j]);
2004 // stuff not processed here: mins, maxs, yawradius, allradius
2008 // load the meshes now
2009 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2012 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2013 // (converting from weight-blending skeletal animation to
2014 // deformation-based skeletal animation)
2015 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2016 for (i = 0;i < loadmodel->num_bones;i++)
2018 const float *m = loadmodel->data_poses + i * 12;
2019 if (loadmodel->data_bones[i].parent >= 0)
2020 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2022 for (k = 0;k < 12;k++)
2023 bonepose[12*i+k] = m[k];
2025 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2027 const int *inelements;
2029 const float *intexcoord;
2030 msurface_t *surface;
2032 loadmodel->surfacelist[i] = i;
2033 surface = loadmodel->data_surfaces + i;
2034 surface->texture = loadmodel->data_textures + i;
2035 surface->num_firsttriangle = meshtriangles;
2036 surface->num_triangles = BigLong(dpmmesh->num_tris);
2037 surface->num_firstvertex = meshvertices;
2038 surface->num_vertices = BigLong(dpmmesh->num_verts);
2039 meshvertices += surface->num_vertices;
2040 meshtriangles += surface->num_triangles;
2042 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2043 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2044 for (j = 0;j < surface->num_triangles;j++)
2046 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2047 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2048 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2049 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2054 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2055 for (j = 0;j < surface->num_vertices*2;j++)
2056 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2058 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2059 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2063 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2064 data += sizeof(dpmvertex_t);
2065 for (k = 0;k < numweights;k++)
2067 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2068 int boneindex = BigLong(vert->bonenum);
2069 const float *m = bonepose + 12 * boneindex;
2070 float influence = BigFloat(vert->influence);
2071 float relativeorigin[3], relativenormal[3];
2072 relativeorigin[0] = BigFloat(vert->origin[0]);
2073 relativeorigin[1] = BigFloat(vert->origin[1]);
2074 relativeorigin[2] = BigFloat(vert->origin[2]);
2075 relativenormal[0] = BigFloat(vert->normal[0]);
2076 relativenormal[1] = BigFloat(vert->normal[1]);
2077 relativenormal[2] = BigFloat(vert->normal[2]);
2078 // blend the vertex bone weights into the base mesh
2079 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2080 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2081 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2082 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2083 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2084 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2087 // store the first (and often only) weight
2088 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = influence;
2089 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
2093 // sort the new weight into this vertex's weight table
2094 // (which only accepts up to 4 bones per vertex)
2095 for (l = 0;l < 4;l++)
2097 if (loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] < influence)
2099 // move weaker influence weights out of the way first
2101 for (l2 = 3;l2 > l;l2--)
2103 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2-1];
2104 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2-1];
2106 // store the new weight
2107 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] = influence;
2108 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l] = boneindex;
2113 data += sizeof(dpmbonevert_t);
2116 for (l = 0;l < 4;l++)
2117 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l];
2118 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2120 float f = 1.0f / sum;
2121 for (l = 0;l < 4;l++)
2122 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] *= f;
2126 // since dpm models do not have named sections, reuse their shader name as the section name
2127 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2129 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2132 Mod_FreeSkinFiles(skinfiles);
2134 // compute all the mesh information that was not loaded from the file
2135 Mod_BuildBaseBonePoses();
2136 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);
2137 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2139 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2142 // no idea why PSK/PSA files contain weird quaternions but they do...
2143 #define PSKQUATNEGATIONS
2144 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2146 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2147 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2148 fs_offset_t filesize;
2153 pskboneinfo_t *bones;
2154 pskrawweights_t *rawweights;
2155 pskboneinfo_t *animbones;
2156 pskaniminfo_t *anims;
2157 pskanimkeys_t *animkeys;
2158 void *animfilebuffer, *animbuffer, *animbufferend;
2159 unsigned char *data;
2161 skinfile_t *skinfiles;
2162 char animname[MAX_QPATH];
2165 pchunk = (pskchunk_t *)buffer;
2166 if (strcmp(pchunk->id, "ACTRHEAD"))
2167 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2169 loadmodel->modeldatatypestring = "PSK";
2171 loadmodel->type = mod_alias;
2172 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2173 loadmodel->DrawSky = NULL;
2174 loadmodel->DrawAddWaterPlanes = NULL;
2175 loadmodel->Draw = R_Q1BSP_Draw;
2176 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2177 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2178 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2179 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2180 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2181 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2182 loadmodel->PointSuperContents = NULL;
2183 loadmodel->synctype = ST_RAND;
2185 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2186 strlcat(animname, ".psa", sizeof(animname));
2187 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2188 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2189 if (animbuffer == NULL)
2190 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2209 while (buffer < bufferend)
2211 pchunk = (pskchunk_t *)buffer;
2212 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2213 version = LittleLong(pchunk->version);
2214 recordsize = LittleLong(pchunk->recordsize);
2215 numrecords = LittleLong(pchunk->numrecords);
2216 if (developer.integer >= 100)
2217 Con_Printf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2218 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2219 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);
2220 if (!strcmp(pchunk->id, "ACTRHEAD"))
2224 else if (!strcmp(pchunk->id, "PNTS0000"))
2227 if (recordsize != sizeof(*p))
2228 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2229 // byteswap in place and keep the pointer
2230 numpnts = numrecords;
2231 pnts = (pskpnts_t *)buffer;
2232 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2234 p->origin[0] = LittleFloat(p->origin[0]);
2235 p->origin[1] = LittleFloat(p->origin[1]);
2236 p->origin[2] = LittleFloat(p->origin[2]);
2240 else if (!strcmp(pchunk->id, "VTXW0000"))
2243 if (recordsize != sizeof(*p))
2244 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2245 // byteswap in place and keep the pointer
2246 numvtxw = numrecords;
2247 vtxw = (pskvtxw_t *)buffer;
2248 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2250 p->pntsindex = LittleShort(p->pntsindex);
2251 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2252 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2253 if (p->pntsindex >= numpnts)
2255 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2261 else if (!strcmp(pchunk->id, "FACE0000"))
2264 if (recordsize != sizeof(*p))
2265 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2266 // byteswap in place and keep the pointer
2267 numfaces = numrecords;
2268 faces = (pskface_t *)buffer;
2269 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2271 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2272 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2273 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2274 p->group = LittleLong(p->group);
2275 if (p->vtxwindex[0] >= numvtxw)
2277 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2278 p->vtxwindex[0] = 0;
2280 if (p->vtxwindex[1] >= numvtxw)
2282 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2283 p->vtxwindex[1] = 0;
2285 if (p->vtxwindex[2] >= numvtxw)
2287 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2288 p->vtxwindex[2] = 0;
2293 else if (!strcmp(pchunk->id, "MATT0000"))
2296 if (recordsize != sizeof(*p))
2297 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2298 // byteswap in place and keep the pointer
2299 nummatts = numrecords;
2300 matts = (pskmatt_t *)buffer;
2301 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2307 else if (!strcmp(pchunk->id, "REFSKELT"))
2310 if (recordsize != sizeof(*p))
2311 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2312 // byteswap in place and keep the pointer
2313 numbones = numrecords;
2314 bones = (pskboneinfo_t *)buffer;
2315 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2317 p->numchildren = LittleLong(p->numchildren);
2318 p->parent = LittleLong(p->parent);
2319 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2320 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2321 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2322 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2323 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2324 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2325 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2326 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2327 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2328 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2329 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2330 #ifdef PSKQUATNEGATIONS
2333 p->basepose.quat[0] *= -1;
2334 p->basepose.quat[1] *= -1;
2335 p->basepose.quat[2] *= -1;
2339 p->basepose.quat[0] *= 1;
2340 p->basepose.quat[1] *= -1;
2341 p->basepose.quat[2] *= 1;
2344 if (p->parent < 0 || p->parent >= numbones)
2346 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2352 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2355 if (recordsize != sizeof(*p))
2356 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2357 // byteswap in place and keep the pointer
2358 numrawweights = numrecords;
2359 rawweights = (pskrawweights_t *)buffer;
2360 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2362 p->weight = LittleFloat(p->weight);
2363 p->pntsindex = LittleLong(p->pntsindex);
2364 p->boneindex = LittleLong(p->boneindex);
2365 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2367 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2370 if (p->boneindex < 0 || p->boneindex >= numbones)
2372 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2380 while (animbuffer < animbufferend)
2382 pchunk = (pskchunk_t *)animbuffer;
2383 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2384 version = LittleLong(pchunk->version);
2385 recordsize = LittleLong(pchunk->recordsize);
2386 numrecords = LittleLong(pchunk->numrecords);
2387 if (developer.integer >= 100)
2388 Con_Printf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2389 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2390 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);
2391 if (!strcmp(pchunk->id, "ANIMHEAD"))
2395 else if (!strcmp(pchunk->id, "BONENAMES"))
2398 if (recordsize != sizeof(*p))
2399 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2400 // byteswap in place and keep the pointer
2401 numanimbones = numrecords;
2402 animbones = (pskboneinfo_t *)animbuffer;
2403 // NOTE: supposedly psa does not need to match the psk model, the
2404 // bones missing from the psa would simply use their base
2405 // positions from the psk, but this is hard for me to implement
2406 // and people can easily make animations that match.
2407 if (numanimbones != numbones)
2408 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2409 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2411 p->numchildren = LittleLong(p->numchildren);
2412 p->parent = LittleLong(p->parent);
2413 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2414 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2415 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2416 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2417 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2418 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2419 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2420 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2421 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2422 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2423 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2424 #ifdef PSKQUATNEGATIONS
2427 p->basepose.quat[0] *= -1;
2428 p->basepose.quat[1] *= -1;
2429 p->basepose.quat[2] *= -1;
2433 p->basepose.quat[0] *= 1;
2434 p->basepose.quat[1] *= -1;
2435 p->basepose.quat[2] *= 1;
2438 if (p->parent < 0 || p->parent >= numanimbones)
2440 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2443 // check that bones are the same as in the base
2444 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2445 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2449 else if (!strcmp(pchunk->id, "ANIMINFO"))
2452 if (recordsize != sizeof(*p))
2453 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2454 // byteswap in place and keep the pointer
2455 numanims = numrecords;
2456 anims = (pskaniminfo_t *)animbuffer;
2457 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2459 p->numbones = LittleLong(p->numbones);
2460 p->playtime = LittleFloat(p->playtime);
2461 p->fps = LittleFloat(p->fps);
2462 p->firstframe = LittleLong(p->firstframe);
2463 p->numframes = LittleLong(p->numframes);
2464 if (p->numbones != numbones)
2465 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2469 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2472 if (recordsize != sizeof(*p))
2473 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2474 numanimkeys = numrecords;
2475 animkeys = (pskanimkeys_t *)animbuffer;
2476 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2478 p->origin[0] = LittleFloat(p->origin[0]);
2479 p->origin[1] = LittleFloat(p->origin[1]);
2480 p->origin[2] = LittleFloat(p->origin[2]);
2481 p->quat[0] = LittleFloat(p->quat[0]);
2482 p->quat[1] = LittleFloat(p->quat[1]);
2483 p->quat[2] = LittleFloat(p->quat[2]);
2484 p->quat[3] = LittleFloat(p->quat[3]);
2485 p->frametime = LittleFloat(p->frametime);
2486 #ifdef PSKQUATNEGATIONS
2487 if (index % numbones)
2502 // TODO: allocate bonepose stuff
2505 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2508 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2509 Host_Error("%s: missing required chunks", loadmodel->name);
2511 loadmodel->numframes = 0;
2512 for (index = 0;index < numanims;index++)
2513 loadmodel->numframes += anims[index].numframes;
2515 if (numanimkeys != numbones * loadmodel->numframes)
2516 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2518 meshvertices = numvtxw;
2519 meshtriangles = numfaces;
2521 // load external .skin files if present
2522 skinfiles = Mod_LoadSkinFiles();
2523 if (loadmodel->numskins < 1)
2524 loadmodel->numskins = 1;
2525 loadmodel->num_bones = numbones;
2526 loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
2527 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2528 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2529 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2530 loadmodel->surfmesh.num_vertices = meshvertices;
2531 loadmodel->surfmesh.num_triangles = meshtriangles;
2532 // do most allocations as one merged chunk
2533 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);
2534 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2535 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2536 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2537 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2538 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2539 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2540 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2541 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2542 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2543 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2544 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2545 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += loadmodel->surfmesh.num_vertices * sizeof(int[4]);
2546 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[4]);
2547 //loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
2548 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2549 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2550 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2551 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2552 if (loadmodel->surfmesh.num_vertices <= 65536)
2554 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2555 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2556 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2558 loadmodel->data_poses = Mem_Alloc(loadmodel->mempool, loadmodel->num_poses * sizeof(float[12]));
2560 for (i = 0;i < loadmodel->numskins;i++)
2562 loadmodel->skinscenes[i].firstframe = i;
2563 loadmodel->skinscenes[i].framecount = 1;
2564 loadmodel->skinscenes[i].loop = true;
2565 loadmodel->skinscenes[i].framerate = 10;
2569 for (index = 0, i = 0;index < nummatts;index++)
2571 // since psk models do not have named sections, reuse their shader name as the section name
2572 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2573 loadmodel->surfacelist[index] = index;
2574 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2575 loadmodel->data_surfaces[index].num_firstvertex = 0;
2576 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2579 // copy over the vertex locations and texcoords
2580 for (index = 0;index < numvtxw;index++)
2582 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2583 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2584 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2585 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2586 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2589 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2590 for (index = 0;index < numfaces;index++)
2591 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2592 for (index = 0, i = 0;index < nummatts;index++)
2594 loadmodel->data_surfaces[index].num_firsttriangle = i;
2595 i += loadmodel->data_surfaces[index].num_triangles;
2596 loadmodel->data_surfaces[index].num_triangles = 0;
2598 for (index = 0;index < numfaces;index++)
2600 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2601 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2602 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2603 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2606 // copy over the bones
2607 for (index = 0;index < numbones;index++)
2609 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2610 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2611 if (loadmodel->data_bones[index].parent >= index)
2612 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2615 // sort the psk point weights into the vertex weight tables
2616 // (which only accept up to 4 bones per vertex)
2617 for (index = 0;index < numvtxw;index++)
2621 for (j = 0;j < numrawweights;j++)
2623 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2625 int boneindex = rawweights[j].boneindex;
2626 float influence = rawweights[j].weight;
2627 for (l = 0;l < 4;l++)
2629 if (loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] < influence)
2631 // move lower influence weights out of the way first
2633 for (l2 = 3;l2 > l;l2--)
2635 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2-1];
2636 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2-1];
2638 // store the new weight
2639 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] = influence;
2640 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l] = boneindex;
2647 for (l = 0;l < 4;l++)
2648 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l];
2649 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2651 float f = 1.0f / sum;
2652 for (l = 0;l < 4;l++)
2653 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] *= f;
2657 // set up the animscenes based on the anims
2658 for (index = 0, i = 0;index < numanims;index++)
2660 for (j = 0;j < anims[index].numframes;j++, i++)
2662 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2663 loadmodel->animscenes[i].firstframe = i;
2664 loadmodel->animscenes[i].framecount = 1;
2665 loadmodel->animscenes[i].loop = true;
2666 loadmodel->animscenes[i].framerate = 10;
2670 // load the poses from the animkeys
2671 for (index = 0;index < numanimkeys;index++)
2673 pskanimkeys_t *k = animkeys + index;
2675 Matrix4x4_FromOriginQuat(&matrix, k->origin[0], k->origin[1], k->origin[2], k->quat[0], k->quat[1], k->quat[2], k->quat[3]);
2676 Matrix4x4_ToArray12FloatD3D(&matrix, loadmodel->data_poses + index*12);
2678 Mod_FreeSkinFiles(skinfiles);
2679 Mem_Free(animfilebuffer);
2681 // compute all the mesh information that was not loaded from the file
2682 // TODO: honor smoothing groups somehow?
2683 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2684 Mod_BuildBaseBonePoses();
2685 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2686 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);
2687 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2688 Mod_Alias_CalculateBoundingBox();
2690 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;