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"};
31 cvar_t mod_alias_supporttagscale = {0, "mod_alias_supporttagscale", "1", "support scaling factors in bone/tag attachment matrices as supported by MD3"};
33 float mod_md3_sin[320];
35 void Mod_AliasInit (void)
38 Cvar_RegisterVariable(&r_skeletal_debugbone);
39 Cvar_RegisterVariable(&r_skeletal_debugbonecomponent);
40 Cvar_RegisterVariable(&r_skeletal_debugbonevalue);
41 Cvar_RegisterVariable(&r_skeletal_debugtranslatex);
42 Cvar_RegisterVariable(&r_skeletal_debugtranslatey);
43 Cvar_RegisterVariable(&r_skeletal_debugtranslatez);
44 Cvar_RegisterVariable(&mod_alias_supporttagscale);
45 for (i = 0;i < 320;i++)
46 mod_md3_sin[i] = sin(i * M_PI * 2.0f / 256.0);
49 void Mod_Skeletal_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
52 // vertex weighted skeletal
55 float boneposerelative[MAX_BONES][12];
56 float *matrix, m[12], bonepose[MAX_BONES][12];
58 // interpolate matrices and concatenate them to their parents
59 for (i = 0;i < model->num_bones;i++)
61 for (k = 0;k < 12;k++)
63 for (blends = 0;blends < 4 && frameblend[blends].lerp > 0;blends++)
65 matrix = model->data_poses + (frameblend[blends].frame * model->num_bones + i) * 12;
66 for (k = 0;k < 12;k++)
67 m[k] += matrix[k] * frameblend[blends].lerp;
69 if (i == r_skeletal_debugbone.integer)
70 m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
71 m[3] *= r_skeletal_debugtranslatex.value;
72 m[7] *= r_skeletal_debugtranslatey.value;
73 m[11] *= r_skeletal_debugtranslatez.value;
74 if (model->data_bones[i].parent >= 0)
75 R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
77 for (k = 0;k < 12;k++)
78 bonepose[i][k] = m[k];
79 // create a relative deformation matrix to describe displacement
80 // from the base mesh, which is used by the actual weighting
81 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]);
83 // blend the vertex bone weights
84 // 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)
85 // special case for the first bone because it avoids the need to memset the arrays before filling
87 const float *v = model->surfmesh.data_vertex3f;
88 const int *wi = model->surfmesh.data_vertexweightindex4i;
89 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
90 memset(vertex3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
91 for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, wi += 4, wf += 4, vertex3f += 3)
95 const float *m = boneposerelative[wi[0]];
96 vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
97 vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
98 vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
102 const float *m = boneposerelative[wi[0]];
104 vertex3f[0] = f * (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
105 vertex3f[1] = f * (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
106 vertex3f[2] = f * (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
107 for (k = 1;k < 4 && wf[k];k++)
109 const float *m = boneposerelative[wi[k]];
111 vertex3f[0] += f * (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
112 vertex3f[1] += f * (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
113 vertex3f[2] += f * (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
120 const float *n = model->surfmesh.data_normal3f;
121 const int *wi = model->surfmesh.data_vertexweightindex4i;
122 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
123 memset(normal3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
124 for (i = 0;i < model->surfmesh.num_vertices;i++, n += 3, wi += 4, wf += 4, normal3f += 3)
128 const float *m = boneposerelative[wi[0]];
129 normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
130 normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
131 normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
135 const float *m = boneposerelative[wi[0]];
137 normal3f[0] = f * (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
138 normal3f[1] = f * (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
139 normal3f[2] = f * (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
140 for (k = 1;k < 4 && wf[k];k++)
142 const float *m = boneposerelative[wi[k]];
144 normal3f[0] += f * (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
145 normal3f[1] += f * (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
146 normal3f[2] += f * (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
153 const float *sv = model->surfmesh.data_svector3f;
154 const int *wi = model->surfmesh.data_vertexweightindex4i;
155 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
156 memset(svector3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
157 for (i = 0;i < model->surfmesh.num_vertices;i++, sv += 3, wi += 4, wf += 4, svector3f += 3)
161 const float *m = boneposerelative[wi[0]];
162 svector3f[0] = (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
163 svector3f[1] = (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
164 svector3f[2] = (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
168 const float *m = boneposerelative[wi[0]];
170 svector3f[0] = f * (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
171 svector3f[1] = f * (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
172 svector3f[2] = f * (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
173 for (k = 1;k < 4 && wf[k];k++)
175 const float *m = boneposerelative[wi[k]];
177 svector3f[0] += f * (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
178 svector3f[1] += f * (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
179 svector3f[2] += f * (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
186 const float *tv = model->surfmesh.data_tvector3f;
187 const int *wi = model->surfmesh.data_vertexweightindex4i;
188 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
189 memset(tvector3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
190 for (i = 0;i < model->surfmesh.num_vertices;i++, tv += 3, wi += 4, wf += 4, tvector3f += 3)
194 const float *m = boneposerelative[wi[0]];
195 tvector3f[0] = (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
196 tvector3f[1] = (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
197 tvector3f[2] = (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
201 const float *m = boneposerelative[wi[0]];
203 tvector3f[0] = f * (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
204 tvector3f[1] = f * (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
205 tvector3f[2] = f * (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
206 for (k = 1;k < 4 && wf[k];k++)
208 const float *m = boneposerelative[wi[k]];
210 tvector3f[0] += f * (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
211 tvector3f[1] += f * (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
212 tvector3f[2] += f * (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
219 void Mod_MD3_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
222 int i, numblends, blendnum;
223 int numverts = model->surfmesh.num_vertices;
225 for (blendnum = 0;blendnum < 4;blendnum++)
227 //VectorMA(translate, model->surfmesh.num_morphmdlframetranslate, frameblend[blendnum].lerp, translate);
228 if (frameblend[blendnum].lerp > 0)
229 numblends = blendnum + 1;
231 // special case for the first blend because it avoids some adds and the need to memset the arrays first
232 for (blendnum = 0;blendnum < numblends;blendnum++)
234 const md3vertex_t *verts = model->surfmesh.data_morphmd3vertex + numverts * frameblend[blendnum].frame;
235 float scale = frameblend[blendnum].lerp * (1.0f / 64.0f);
238 for (i = 0;i < numverts;i++)
240 vertex3f[i * 3 + 0] = verts[i].origin[0] * scale;
241 vertex3f[i * 3 + 1] = verts[i].origin[1] * scale;
242 vertex3f[i * 3 + 2] = verts[i].origin[2] * scale;
247 for (i = 0;i < numverts;i++)
249 vertex3f[i * 3 + 0] += verts[i].origin[0] * scale;
250 vertex3f[i * 3 + 1] += verts[i].origin[1] * scale;
251 vertex3f[i * 3 + 2] += verts[i].origin[2] * scale;
254 // the yaw and pitch stored in md3 models are 8bit quantized angles
255 // (0-255), and as such a lookup table is very well suited to
256 // decoding them, and since cosine is equivilant to sine with an
257 // extra 45 degree rotation, this uses one lookup table for both
258 // sine and cosine with a +64 bias to get cosine.
261 float lerp = frameblend[blendnum].lerp;
264 for (i = 0;i < numverts;i++)
266 normal3f[i * 3 + 0] = mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
267 normal3f[i * 3 + 1] = mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
268 normal3f[i * 3 + 2] = mod_md3_sin[verts[i].pitch + 64] * lerp;
273 for (i = 0;i < numverts;i++)
275 normal3f[i * 3 + 0] += mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
276 normal3f[i * 3 + 1] += mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
277 normal3f[i * 3 + 2] += mod_md3_sin[verts[i].pitch + 64] * lerp;
283 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].frame;
284 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
287 for (i = 0;i < numverts;i++, texvecvert++)
289 VectorScale(texvecvert->svec, f, svector3f + i*3);
290 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
295 for (i = 0;i < numverts;i++, texvecvert++)
297 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
298 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
305 void Mod_MDL_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
308 int i, numblends, blendnum;
309 int numverts = model->surfmesh.num_vertices;
311 VectorClear(translate);
313 // blend the frame translates to avoid redundantly doing so on each vertex
314 // (a bit of a brain twister but it works)
315 for (blendnum = 0;blendnum < 4;blendnum++)
317 if (model->surfmesh.data_morphmd2framesize6f)
318 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].frame * 6 + 3, translate);
320 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.num_morphmdlframetranslate, translate);
321 if (frameblend[blendnum].lerp > 0)
322 numblends = blendnum + 1;
324 // special case for the first blend because it avoids some adds and the need to memset the arrays first
325 for (blendnum = 0;blendnum < numblends;blendnum++)
327 const trivertx_t *verts = model->surfmesh.data_morphmdlvertex + numverts * frameblend[blendnum].frame;
329 if (model->surfmesh.data_morphmd2framesize6f)
330 VectorScale(model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].frame * 6, frameblend[blendnum].lerp, scale);
332 VectorScale(model->surfmesh.num_morphmdlframescale, frameblend[blendnum].lerp, scale);
335 for (i = 0;i < numverts;i++)
337 vertex3f[i * 3 + 0] = translate[0] + verts[i].v[0] * scale[0];
338 vertex3f[i * 3 + 1] = translate[1] + verts[i].v[1] * scale[1];
339 vertex3f[i * 3 + 2] = translate[2] + verts[i].v[2] * scale[2];
344 for (i = 0;i < numverts;i++)
346 vertex3f[i * 3 + 0] += verts[i].v[0] * scale[0];
347 vertex3f[i * 3 + 1] += verts[i].v[1] * scale[1];
348 vertex3f[i * 3 + 2] += verts[i].v[2] * scale[2];
351 // the vertex normals in mdl models are an index into a table of
352 // 162 unique values, this very crude quantization reduces the
353 // vertex normal to only one byte, which saves a lot of space but
354 // also makes lighting pretty coarse
357 float lerp = frameblend[blendnum].lerp;
360 for (i = 0;i < numverts;i++)
362 const float *vn = m_bytenormals[verts[i].lightnormalindex];
363 VectorScale(vn, lerp, normal3f + i*3);
368 for (i = 0;i < numverts;i++)
370 const float *vn = m_bytenormals[verts[i].lightnormalindex];
371 VectorMA(normal3f + i*3, lerp, vn, normal3f + i*3);
377 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].frame;
378 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
381 for (i = 0;i < numverts;i++, texvecvert++)
383 VectorScale(texvecvert->svec, f, svector3f + i*3);
384 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
389 for (i = 0;i < numverts;i++, texvecvert++)
391 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
392 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
399 int Mod_Alias_GetTagMatrix(const dp_model_t *model, int poseframe, int tagindex, matrix4x4_t *outmatrix)
401 const float *boneframe;
402 float tempbonematrix[12], bonematrix[12];
403 *outmatrix = identitymatrix;
404 if (model->num_bones)
406 if (tagindex < 0 || tagindex >= model->num_bones)
408 if (poseframe >= model->num_poses)
410 boneframe = model->data_poses + poseframe * model->num_bones * 12;
411 memcpy(bonematrix, boneframe + tagindex * 12, sizeof(float[12]));
412 while (model->data_bones[tagindex].parent >= 0)
414 memcpy(tempbonematrix, bonematrix, sizeof(float[12]));
415 R_ConcatTransforms(boneframe + model->data_bones[tagindex].parent * 12, tempbonematrix, bonematrix);
416 tagindex = model->data_bones[tagindex].parent;
418 Matrix4x4_FromArray12FloatD3D(outmatrix, bonematrix);
420 else if (model->num_tags)
422 if (tagindex < 0 || tagindex >= model->num_tags)
424 if (poseframe >= model->num_tagframes)
426 Matrix4x4_FromArray12FloatGL(outmatrix, model->data_tags[poseframe * model->num_tags + tagindex].matrixgl);
429 if(!mod_alias_supporttagscale.integer)
430 Matrix4x4_Normalize3(outmatrix, outmatrix);
435 int Mod_Alias_GetTagIndexForName(const dp_model_t *model, unsigned int skin, const char *tagname)
438 if(skin >= (unsigned int)model->numskins)
440 if (model->num_bones)
441 for (i = 0;i < model->num_bones;i++)
442 if (!strcasecmp(tagname, model->data_bones[i].name))
445 for (i = 0;i < model->num_tags;i++)
446 if (!strcasecmp(tagname, model->data_tags[i].name))
451 static void Mod_BuildBaseBonePoses(void)
455 float *basebonepose = (float *) Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(float[12]));
456 float *in12f = loadmodel->data_poses;
457 float *out12f = basebonepose;
458 float *outinv12f = loadmodel->data_baseboneposeinverse;
459 for (i = 0;i < loadmodel->num_bones;i++, in12f += 12, out12f += 12, outinv12f += 12)
461 if (loadmodel->data_bones[i].parent >= 0)
462 R_ConcatTransforms(basebonepose + 12 * loadmodel->data_bones[i].parent, in12f, out12f);
464 for (k = 0;k < 12;k++)
465 out12f[k] = in12f[k];
469 // we only support uniform scaling, so assume the first row is enough
470 // (note the lack of sqrt here, because we're trying to undo the scaling,
471 // this means multiplying by the inverse scale twice - squaring it, which
472 // makes the sqrt a waste of time)
473 scale = 1.0 / (out12f[ 0] * out12f[ 0] + out12f[ 1] * out12f[ 1] + out12f[ 2] * out12f[ 2]);
475 // invert the rotation by transposing and multiplying by the squared
476 // recipricol of the input matrix scale as described above
477 outinv12f[ 0] = (float)(out12f[ 0] * scale);
478 outinv12f[ 1] = (float)(out12f[ 4] * scale);
479 outinv12f[ 2] = (float)(out12f[ 8] * scale);
480 outinv12f[ 4] = (float)(out12f[ 1] * scale);
481 outinv12f[ 5] = (float)(out12f[ 5] * scale);
482 outinv12f[ 6] = (float)(out12f[ 9] * scale);
483 outinv12f[ 8] = (float)(out12f[ 2] * scale);
484 outinv12f[ 9] = (float)(out12f[ 6] * scale);
485 outinv12f[10] = (float)(out12f[10] * scale);
487 // invert the translate
488 outinv12f[ 3] = -(out12f[ 3] * outinv12f[ 0] + out12f[ 7] * outinv12f[ 1] + out12f[11] * outinv12f[ 2]);
489 outinv12f[ 7] = -(out12f[ 3] * outinv12f[ 4] + out12f[ 7] * outinv12f[ 5] + out12f[11] * outinv12f[ 6]);
490 outinv12f[11] = -(out12f[ 3] * outinv12f[ 8] + out12f[ 7] * outinv12f[ 9] + out12f[11] * outinv12f[10]);
492 Mem_Free(basebonepose);
495 static void Mod_Alias_CalculateBoundingBox(void)
498 qboolean firstvertex = true;
499 float dist, yawradius, radius;
502 frameblend_t frameblend[4];
503 memset(frameblend, 0, sizeof(frameblend));
504 frameblend[0].lerp = 1;
505 vertex3f = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
506 VectorClear(loadmodel->normalmins);
507 VectorClear(loadmodel->normalmaxs);
510 for (frameblend[0].frame = 0;frameblend[0].frame < loadmodel->num_poses;frameblend[0].frame++)
512 loadmodel->AnimateVertices(loadmodel, frameblend, vertex3f, NULL, NULL, NULL);
513 for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
518 VectorCopy(v, loadmodel->normalmins);
519 VectorCopy(v, loadmodel->normalmaxs);
523 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
524 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
525 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
526 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
527 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
528 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
530 dist = v[0] * v[0] + v[1] * v[1];
531 if (yawradius < dist)
539 radius = sqrt(radius);
540 yawradius = sqrt(yawradius);
541 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
542 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
543 loadmodel->yawmins[2] = loadmodel->normalmins[2];
544 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
545 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
546 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
547 loadmodel->radius = radius;
548 loadmodel->radius2 = radius * radius;
551 static void Mod_Alias_MorphMesh_CompileFrames(void)
554 frameblend_t frameblend[4] = {{0, 1}, {0, 0}, {0, 0}, {0, 0}};
555 unsigned char *datapointer;
556 datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
557 loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
558 loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
559 loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
560 loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
561 loadmodel->surfmesh.data_morphtexvecvertex = (texvecvertex_t *)datapointer;datapointer += loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices * sizeof(texvecvertex_t);
562 // 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)
563 for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
565 frameblend[0].frame = i;
566 loadmodel->AnimateVertices(loadmodel, frameblend, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
567 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);
568 // encode the svector and tvector in 3 byte format for permanent storage
569 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
571 VectorScale(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
572 VectorScale(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
577 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)
580 float segmentmins[3], segmentmaxs[3];
581 frameblend_t frameblend[4];
583 static int maxvertices = 0;
584 static float *vertex3f = NULL;
585 memset(trace, 0, sizeof(*trace));
587 trace->realfraction = 1;
588 trace->hitsupercontentsmask = hitsupercontentsmask;
589 memset(frameblend, 0, sizeof(frameblend));
590 frameblend[0].frame = frame;
591 frameblend[0].lerp = 1;
592 if (maxvertices < model->surfmesh.num_vertices)
596 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
597 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
599 if (VectorLength2(boxmins) + VectorLength2(boxmaxs) == 0)
602 segmentmins[0] = min(start[0], end[0]) - 1;
603 segmentmins[1] = min(start[1], end[1]) - 1;
604 segmentmins[2] = min(start[2], end[2]) - 1;
605 segmentmaxs[0] = max(start[0], end[0]) + 1;
606 segmentmaxs[1] = max(start[1], end[1]) + 1;
607 segmentmaxs[2] = max(start[2], end[2]) + 1;
608 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
610 model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL);
611 Collision_TraceLineTriangleMeshFloat(trace, start, end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, SUPERCONTENTS_SOLID, 0, surface->texture, segmentmins, segmentmaxs);
616 // box trace, performed as brush trace
617 colbrushf_t *thisbrush_start, *thisbrush_end;
618 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
619 segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
620 segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
621 segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
622 segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
623 segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
624 segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
625 VectorAdd(start, boxmins, boxstartmins);
626 VectorAdd(start, boxmaxs, boxstartmaxs);
627 VectorAdd(end, boxmins, boxendmins);
628 VectorAdd(end, boxmaxs, boxendmaxs);
629 thisbrush_start = Collision_BrushForBox(&identitymatrix, boxstartmins, boxstartmaxs, 0, 0, NULL);
630 thisbrush_end = Collision_BrushForBox(&identitymatrix, boxendmins, boxendmaxs, 0, 0, NULL);
631 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
633 if (maxvertices < model->surfmesh.num_vertices)
637 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
638 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
640 model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL);
641 Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, SUPERCONTENTS_SOLID, 0, surface->texture, segmentmins, segmentmaxs);
646 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
649 for (i = 0;i < inverts;i++)
651 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
653 j = vertremap[i]; // not onseam
656 j = vertremap[i+inverts]; // onseam
662 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
664 int i, f, pose, groupframes;
666 daliasframetype_t *pframetype;
667 daliasframe_t *pinframe;
668 daliasgroup_t *group;
669 daliasinterval_t *intervals;
672 scene = loadmodel->animscenes;
673 for (f = 0;f < loadmodel->numframes;f++)
675 pframetype = (daliasframetype_t *)datapointer;
676 datapointer += sizeof(daliasframetype_t);
677 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
679 // a single frame is still treated as a group
686 group = (daliasgroup_t *)datapointer;
687 datapointer += sizeof(daliasgroup_t);
688 groupframes = LittleLong (group->numframes);
690 // intervals (time per frame)
691 intervals = (daliasinterval_t *)datapointer;
692 datapointer += sizeof(daliasinterval_t) * groupframes;
694 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
695 if (interval < 0.01f)
697 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
702 // get scene name from first frame
703 pinframe = (daliasframe_t *)datapointer;
705 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
706 scene->firstframe = pose;
707 scene->framecount = groupframes;
708 scene->framerate = 1.0f / interval;
713 for (i = 0;i < groupframes;i++)
715 pinframe = (daliasframe_t *)datapointer;
716 datapointer += sizeof(daliasframe_t);
717 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
718 datapointer += sizeof(trivertx_t) * inverts;
724 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
726 if (cls.state == ca_dedicated)
730 skinframe = R_SkinFrame_LoadMissing();
731 memset(texture, 0, sizeof(*texture));
732 texture->currentframe = texture;
733 //texture->animated = false;
734 texture->numskinframes = 1;
735 texture->skinframerate = 1;
736 texture->skinframes[0] = skinframe;
737 texture->currentskinframe = skinframe;
738 //texture->backgroundnumskinframes = 0;
739 //texture->customblendfunc[0] = 0;
740 //texture->customblendfunc[1] = 0;
741 //texture->surfaceflags = 0;
742 //texture->supercontents = 0;
743 //texture->surfaceparms = 0;
744 //texture->textureflags = 0;
746 texture->basematerialflags = MATERIALFLAG_WALL;
747 if (texture->currentskinframe->fog)
748 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
749 texture->currentmaterialflags = texture->basematerialflags;
752 static void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
755 skinfileitem_t *skinfileitem;
758 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
759 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
761 memset(skin, 0, sizeof(*skin));
763 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
765 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
766 if (!strcmp(skinfileitem->name, meshname))
768 Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
774 // don't render unmentioned meshes
775 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
776 skin->basematerialflags = skin->currentmaterialflags = 0;
781 Mod_LoadTextureFromQ3Shader(skin, shadername, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
784 #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);
785 #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);
786 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
788 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
789 float scales, scalet, interval;
793 stvert_t *pinstverts;
794 dtriangle_t *pintriangles;
795 daliasskintype_t *pinskintype;
796 daliasskingroup_t *pinskingroup;
797 daliasskininterval_t *pinskinintervals;
798 daliasframetype_t *pinframetype;
799 daliasgroup_t *pinframegroup;
800 unsigned char *datapointer, *startframes, *startskins;
801 char name[MAX_QPATH];
802 skinframe_t *tempskinframe;
803 animscene_t *tempskinscenes;
804 texture_t *tempaliasskins;
806 int *vertonseam, *vertremap;
807 skinfile_t *skinfiles;
809 datapointer = (unsigned char *)buffer;
810 pinmodel = (mdl_t *)datapointer;
811 datapointer += sizeof(mdl_t);
813 version = LittleLong (pinmodel->version);
814 if (version != ALIAS_VERSION)
815 Host_Error ("%s has wrong version number (%i should be %i)",
816 loadmodel->name, version, ALIAS_VERSION);
818 loadmodel->modeldatatypestring = "MDL";
820 loadmodel->type = mod_alias;
821 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
822 loadmodel->DrawSky = NULL;
823 loadmodel->DrawAddWaterPlanes = NULL;
824 loadmodel->Draw = R_Q1BSP_Draw;
825 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
826 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
827 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
828 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
829 loadmodel->DrawLight = R_Q1BSP_DrawLight;
830 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
831 loadmodel->PointSuperContents = NULL;
833 loadmodel->num_surfaces = 1;
834 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
835 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
836 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
837 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
838 loadmodel->surfacelist[0] = 0;
840 loadmodel->numskins = LittleLong(pinmodel->numskins);
841 BOUNDI(loadmodel->numskins,0,65536);
842 skinwidth = LittleLong (pinmodel->skinwidth);
843 BOUNDI(skinwidth,0,65536);
844 skinheight = LittleLong (pinmodel->skinheight);
845 BOUNDI(skinheight,0,65536);
846 numverts = LittleLong(pinmodel->numverts);
847 BOUNDI(numverts,0,65536);
848 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
849 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
850 loadmodel->numframes = LittleLong(pinmodel->numframes);
851 BOUNDI(loadmodel->numframes,0,65536);
852 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
853 BOUNDI(loadmodel->synctype,0,2);
854 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
855 i = LittleLong (pinmodel->flags);
856 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
858 for (i = 0;i < 3;i++)
860 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
861 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
864 startskins = datapointer;
866 for (i = 0;i < loadmodel->numskins;i++)
868 pinskintype = (daliasskintype_t *)datapointer;
869 datapointer += sizeof(daliasskintype_t);
870 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
874 pinskingroup = (daliasskingroup_t *)datapointer;
875 datapointer += sizeof(daliasskingroup_t);
876 groupskins = LittleLong(pinskingroup->numskins);
877 datapointer += sizeof(daliasskininterval_t) * groupskins;
880 for (j = 0;j < groupskins;j++)
882 datapointer += skinwidth * skinheight;
887 pinstverts = (stvert_t *)datapointer;
888 datapointer += sizeof(stvert_t) * numverts;
890 pintriangles = (dtriangle_t *)datapointer;
891 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
893 startframes = datapointer;
894 loadmodel->surfmesh.num_morphframes = 0;
895 for (i = 0;i < loadmodel->numframes;i++)
897 pinframetype = (daliasframetype_t *)datapointer;
898 datapointer += sizeof(daliasframetype_t);
899 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
903 pinframegroup = (daliasgroup_t *)datapointer;
904 datapointer += sizeof(daliasgroup_t);
905 groupframes = LittleLong(pinframegroup->numframes);
906 datapointer += sizeof(daliasinterval_t) * groupframes;
909 for (j = 0;j < groupframes;j++)
911 datapointer += sizeof(daliasframe_t);
912 datapointer += sizeof(trivertx_t) * numverts;
913 loadmodel->surfmesh.num_morphframes++;
916 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
918 // store texture coordinates into temporary array, they will be stored
919 // after usage is determined (triangle data)
920 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
921 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
922 vertonseam = vertremap + numverts * 2;
924 scales = 1.0 / skinwidth;
925 scalet = 1.0 / skinheight;
926 for (i = 0;i < numverts;i++)
928 vertonseam[i] = LittleLong(pinstverts[i].onseam);
929 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
930 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
931 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
932 vertst[(i+numverts)*2+1] = vertst[i*2+1];
935 // load triangle data
936 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
938 // read the triangle elements
939 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
940 for (j = 0;j < 3;j++)
941 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
942 // validate (note numverts is used because this is the original data)
943 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
944 // now butcher the elements according to vertonseam and tri->facesfront
945 // and then compact the vertex set to remove duplicates
946 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
947 if (!LittleLong(pintriangles[i].facesfront)) // backface
948 for (j = 0;j < 3;j++)
949 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
950 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
952 // (this uses vertremap to count usage to save some memory)
953 for (i = 0;i < numverts*2;i++)
955 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
956 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
957 // build remapping table and compact array
958 loadmodel->surfmesh.num_vertices = 0;
959 for (i = 0;i < numverts*2;i++)
963 vertremap[i] = loadmodel->surfmesh.num_vertices;
964 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
965 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
966 loadmodel->surfmesh.num_vertices++;
969 vertremap[i] = -1; // not used at all
971 // remap the elements to the new vertex set
972 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
973 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
974 // store the texture coordinates
975 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
976 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
978 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
979 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
982 // generate ushort elements array if possible
983 if (loadmodel->surfmesh.num_vertices <= 65536)
985 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
986 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
987 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
991 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
992 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
993 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
994 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
995 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
996 Mod_Alias_CalculateBoundingBox();
997 Mod_Alias_MorphMesh_CompileFrames();
1000 Mem_Free(vertremap);
1003 skinfiles = Mod_LoadSkinFiles();
1006 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1007 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1008 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1009 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1010 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1011 Mod_FreeSkinFiles(skinfiles);
1012 for (i = 0;i < loadmodel->numskins;i++)
1014 loadmodel->skinscenes[i].firstframe = i;
1015 loadmodel->skinscenes[i].framecount = 1;
1016 loadmodel->skinscenes[i].loop = true;
1017 loadmodel->skinscenes[i].framerate = 10;
1022 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1023 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1024 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1025 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1027 datapointer = startskins;
1028 for (i = 0;i < loadmodel->numskins;i++)
1030 pinskintype = (daliasskintype_t *)datapointer;
1031 datapointer += sizeof(daliasskintype_t);
1033 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1040 pinskingroup = (daliasskingroup_t *)datapointer;
1041 datapointer += sizeof(daliasskingroup_t);
1043 groupskins = LittleLong (pinskingroup->numskins);
1045 pinskinintervals = (daliasskininterval_t *)datapointer;
1046 datapointer += sizeof(daliasskininterval_t) * groupskins;
1048 interval = LittleFloat(pinskinintervals[0].interval);
1049 if (interval < 0.01f)
1051 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1056 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1057 loadmodel->skinscenes[i].firstframe = totalskins;
1058 loadmodel->skinscenes[i].framecount = groupskins;
1059 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1060 loadmodel->skinscenes[i].loop = true;
1062 for (j = 0;j < groupskins;j++)
1065 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1067 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1068 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))
1069 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));
1070 datapointer += skinwidth * skinheight;
1074 // check for skins that don't exist in the model, but do exist as external images
1075 // (this was added because yummyluv kept pestering me about support for it)
1076 // TODO: support shaders here?
1077 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)))
1079 // expand the arrays to make room
1080 tempskinscenes = loadmodel->skinscenes;
1081 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1082 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1083 Mem_Free(tempskinscenes);
1085 tempaliasskins = loadmodel->data_textures;
1086 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1087 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1088 Mem_Free(tempaliasskins);
1090 // store the info about the new skin
1091 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1092 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1093 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1094 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1095 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1096 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1098 //increase skin counts
1099 loadmodel->numskins++;
1102 // fix up the pointers since they are pointing at the old textures array
1103 // FIXME: this is a hack!
1104 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1105 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1109 surface = loadmodel->data_surfaces;
1110 surface->texture = loadmodel->data_textures;
1111 surface->num_firsttriangle = 0;
1112 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1113 surface->num_firstvertex = 0;
1114 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1116 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1119 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1121 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1122 float iskinwidth, iskinheight;
1123 unsigned char *data;
1124 msurface_t *surface;
1126 unsigned char *base, *datapointer;
1127 md2frame_t *pinframe;
1129 md2triangle_t *intri;
1130 unsigned short *inst;
1131 struct md2verthash_s
1133 struct md2verthash_s *next;
1137 *hash, **md2verthash, *md2verthashdata;
1138 skinfile_t *skinfiles;
1140 pinmodel = (md2_t *)buffer;
1141 base = (unsigned char *)buffer;
1143 version = LittleLong (pinmodel->version);
1144 if (version != MD2ALIAS_VERSION)
1145 Host_Error ("%s has wrong version number (%i should be %i)",
1146 loadmodel->name, version, MD2ALIAS_VERSION);
1148 loadmodel->modeldatatypestring = "MD2";
1150 loadmodel->type = mod_alias;
1151 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1152 loadmodel->DrawSky = NULL;
1153 loadmodel->DrawAddWaterPlanes = NULL;
1154 loadmodel->Draw = R_Q1BSP_Draw;
1155 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1156 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1157 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1158 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1159 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1160 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1161 loadmodel->PointSuperContents = NULL;
1163 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1164 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1165 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1166 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1167 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1168 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1169 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1170 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1172 end = LittleLong(pinmodel->ofs_end);
1173 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1174 Host_Error ("%s is not a valid model", loadmodel->name);
1175 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1176 Host_Error ("%s is not a valid model", loadmodel->name);
1177 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1178 Host_Error ("%s is not a valid model", loadmodel->name);
1179 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1180 Host_Error ("%s is not a valid model", loadmodel->name);
1181 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1182 Host_Error ("%s is not a valid model", loadmodel->name);
1184 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1185 numxyz = LittleLong(pinmodel->num_xyz);
1186 numst = LittleLong(pinmodel->num_st);
1187 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1188 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1189 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1190 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1191 skinwidth = LittleLong(pinmodel->skinwidth);
1192 skinheight = LittleLong(pinmodel->skinheight);
1193 iskinwidth = 1.0f / skinwidth;
1194 iskinheight = 1.0f / skinheight;
1196 loadmodel->num_surfaces = 1;
1197 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1198 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]));
1199 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1200 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1201 loadmodel->surfacelist[0] = 0;
1202 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1203 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1204 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1205 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1207 loadmodel->synctype = ST_RAND;
1210 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1211 skinfiles = Mod_LoadSkinFiles();
1214 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1215 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1216 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1217 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1218 Mod_FreeSkinFiles(skinfiles);
1220 else if (loadmodel->numskins)
1222 // skins found (most likely not a player model)
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 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1227 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);
1231 // no skins (most likely a player model)
1232 loadmodel->numskins = 1;
1233 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1234 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1235 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1236 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1239 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1240 for (i = 0;i < loadmodel->numskins;i++)
1242 loadmodel->skinscenes[i].firstframe = i;
1243 loadmodel->skinscenes[i].framecount = 1;
1244 loadmodel->skinscenes[i].loop = true;
1245 loadmodel->skinscenes[i].framerate = 10;
1248 // load the triangles and stvert data
1249 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1250 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1251 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1252 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1253 // swap the triangle list
1254 loadmodel->surfmesh.num_vertices = 0;
1255 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1257 for (j = 0;j < 3;j++)
1259 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1260 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1263 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1268 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1271 hashindex = (xyz * 256 + st) & 65535;
1272 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1273 if (hash->xyz == xyz && hash->st == st)
1277 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1280 hash->next = md2verthash[hashindex];
1281 md2verthash[hashindex] = hash;
1283 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1287 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1288 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));
1289 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1290 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1291 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1294 hash = md2verthashdata + i;
1295 vertremap[i] = hash->xyz;
1296 sts = LittleShort(inst[hash->st*2+0]);
1297 stt = LittleShort(inst[hash->st*2+1]);
1298 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1300 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1304 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1305 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1308 Mem_Free(md2verthash);
1309 Mem_Free(md2verthashdata);
1311 // generate ushort elements array if possible
1312 if (loadmodel->surfmesh.num_vertices <= 65536)
1314 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1315 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1316 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1320 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1321 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1326 pinframe = (md2frame_t *)datapointer;
1327 datapointer += sizeof(md2frame_t);
1328 // store the frame scale/translate into the appropriate array
1329 for (j = 0;j < 3;j++)
1331 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1332 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1334 // convert the vertices
1335 v = (trivertx_t *)datapointer;
1336 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1337 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1338 out[k] = v[vertremap[k]];
1339 datapointer += numxyz * sizeof(trivertx_t);
1341 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1342 loadmodel->animscenes[i].firstframe = i;
1343 loadmodel->animscenes[i].framecount = 1;
1344 loadmodel->animscenes[i].framerate = 10;
1345 loadmodel->animscenes[i].loop = true;
1348 Mem_Free(vertremap);
1350 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1351 Mod_Alias_CalculateBoundingBox();
1352 Mod_Alias_MorphMesh_CompileFrames();
1354 surface = loadmodel->data_surfaces;
1355 surface->texture = loadmodel->data_textures;
1356 surface->num_firsttriangle = 0;
1357 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1358 surface->num_firstvertex = 0;
1359 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1361 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1364 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1366 int i, j, k, version, meshvertices, meshtriangles;
1367 unsigned char *data;
1368 msurface_t *surface;
1369 md3modelheader_t *pinmodel;
1370 md3frameinfo_t *pinframe;
1373 skinfile_t *skinfiles;
1375 pinmodel = (md3modelheader_t *)buffer;
1377 if (memcmp(pinmodel->identifier, "IDP3", 4))
1378 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1379 version = LittleLong (pinmodel->version);
1380 if (version != MD3VERSION)
1381 Host_Error ("%s has wrong version number (%i should be %i)",
1382 loadmodel->name, version, MD3VERSION);
1384 skinfiles = Mod_LoadSkinFiles();
1385 if (loadmodel->numskins < 1)
1386 loadmodel->numskins = 1;
1388 loadmodel->modeldatatypestring = "MD3";
1390 loadmodel->type = mod_alias;
1391 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1392 loadmodel->DrawSky = NULL;
1393 loadmodel->DrawAddWaterPlanes = NULL;
1394 loadmodel->Draw = R_Q1BSP_Draw;
1395 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1396 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1397 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1398 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1399 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1400 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1401 loadmodel->PointSuperContents = NULL;
1402 loadmodel->synctype = ST_RAND;
1403 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1404 i = LittleLong (pinmodel->flags);
1405 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1407 // set up some global info about the model
1408 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1409 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1411 // make skinscenes for the skins (no groups)
1412 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1413 for (i = 0;i < loadmodel->numskins;i++)
1415 loadmodel->skinscenes[i].firstframe = i;
1416 loadmodel->skinscenes[i].framecount = 1;
1417 loadmodel->skinscenes[i].loop = true;
1418 loadmodel->skinscenes[i].framerate = 10;
1422 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1423 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1425 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1426 loadmodel->animscenes[i].firstframe = i;
1427 loadmodel->animscenes[i].framecount = 1;
1428 loadmodel->animscenes[i].framerate = 10;
1429 loadmodel->animscenes[i].loop = true;
1433 loadmodel->num_tagframes = loadmodel->numframes;
1434 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1435 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1436 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1438 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1439 for (j = 0;j < 9;j++)
1440 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1441 for (j = 0;j < 3;j++)
1442 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1443 //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);
1449 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)))
1451 if (memcmp(pinmesh->identifier, "IDP3", 4))
1452 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1453 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1454 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1455 meshvertices += LittleLong(pinmesh->num_vertices);
1456 meshtriangles += LittleLong(pinmesh->num_triangles);
1459 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1460 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1461 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1462 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));
1463 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1464 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1465 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1466 loadmodel->surfmesh.num_vertices = meshvertices;
1467 loadmodel->surfmesh.num_triangles = meshtriangles;
1468 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1469 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1470 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1471 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1472 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1473 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1474 if (meshvertices <= 65536)
1476 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1477 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1478 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1483 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)))
1485 if (memcmp(pinmesh->identifier, "IDP3", 4))
1486 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1487 loadmodel->surfacelist[i] = i;
1488 surface = loadmodel->data_surfaces + i;
1489 surface->texture = loadmodel->data_textures + i;
1490 surface->num_firsttriangle = meshtriangles;
1491 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1492 surface->num_firstvertex = meshvertices;
1493 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1494 meshvertices += surface->num_vertices;
1495 meshtriangles += surface->num_triangles;
1497 for (j = 0;j < surface->num_triangles * 3;j++)
1498 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1499 for (j = 0;j < surface->num_vertices;j++)
1501 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1502 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1504 for (j = 0;j < loadmodel->numframes;j++)
1506 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1507 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1508 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1510 out->origin[0] = LittleShort(in->origin[0]);
1511 out->origin[1] = LittleShort(in->origin[1]);
1512 out->origin[2] = LittleShort(in->origin[2]);
1513 out->pitch = in->pitch;
1518 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1520 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1522 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1523 Mod_Alias_MorphMesh_CompileFrames();
1524 Mod_Alias_CalculateBoundingBox();
1525 Mod_FreeSkinFiles(skinfiles);
1527 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1528 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1531 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1533 zymtype1header_t *pinmodel, *pheader;
1534 unsigned char *pbase;
1535 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1536 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose;
1537 zymvertex_t *verts, *vertdata;
1541 skinfile_t *skinfiles;
1542 unsigned char *data;
1543 msurface_t *surface;
1545 pinmodel = (zymtype1header_t *)buffer;
1546 pbase = (unsigned char *)buffer;
1547 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1548 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1549 if (BigLong(pinmodel->type) != 1)
1550 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1552 loadmodel->modeldatatypestring = "ZYM";
1554 loadmodel->type = mod_alias;
1555 loadmodel->synctype = ST_RAND;
1559 pheader->type = BigLong(pinmodel->type);
1560 pheader->filesize = BigLong(pinmodel->filesize);
1561 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1562 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1563 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1564 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1565 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1566 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1567 pheader->radius = BigFloat(pinmodel->radius);
1568 pheader->numverts = BigLong(pinmodel->numverts);
1569 pheader->numtris = BigLong(pinmodel->numtris);
1570 pheader->numshaders = BigLong(pinmodel->numshaders);
1571 pheader->numbones = BigLong(pinmodel->numbones);
1572 pheader->numscenes = BigLong(pinmodel->numscenes);
1573 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1574 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1575 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1576 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1577 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1578 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1579 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1580 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1581 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1582 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1583 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1584 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1585 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1586 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1587 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1588 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1589 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1590 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1592 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1594 Con_Printf("%s has no geometry\n", loadmodel->name);
1597 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1599 Con_Printf("%s has no animations\n", loadmodel->name);
1603 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1604 loadmodel->DrawSky = NULL;
1605 loadmodel->DrawAddWaterPlanes = NULL;
1606 loadmodel->Draw = R_Q1BSP_Draw;
1607 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1608 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1609 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1610 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1611 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1612 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1613 loadmodel->PointSuperContents = NULL;
1615 loadmodel->numframes = pheader->numscenes;
1616 loadmodel->num_surfaces = pheader->numshaders;
1618 skinfiles = Mod_LoadSkinFiles();
1619 if (loadmodel->numskins < 1)
1620 loadmodel->numskins = 1;
1622 // make skinscenes for the skins (no groups)
1623 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1624 for (i = 0;i < loadmodel->numskins;i++)
1626 loadmodel->skinscenes[i].firstframe = i;
1627 loadmodel->skinscenes[i].framecount = 1;
1628 loadmodel->skinscenes[i].loop = true;
1629 loadmodel->skinscenes[i].framerate = 10;
1633 modelradius = pheader->radius;
1634 for (i = 0;i < 3;i++)
1636 loadmodel->normalmins[i] = pheader->mins[i];
1637 loadmodel->normalmaxs[i] = pheader->maxs[i];
1638 loadmodel->rotatedmins[i] = -modelradius;
1639 loadmodel->rotatedmaxs[i] = modelradius;
1641 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1642 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1643 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1644 if (loadmodel->yawmaxs[0] > modelradius)
1645 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1646 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1647 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1648 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1649 loadmodel->radius = modelradius;
1650 loadmodel->radius2 = modelradius * modelradius;
1652 // go through the lumps, swapping things
1654 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1655 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1656 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1657 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1658 for (i = 0;i < pheader->numscenes;i++)
1660 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1661 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1662 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1663 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1664 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1665 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1666 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1667 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1668 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1669 if (loadmodel->animscenes[i].framerate < 0)
1670 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1674 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1675 loadmodel->num_bones = pheader->numbones;
1676 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, pheader->numbones * sizeof(aliasbone_t));
1677 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1678 for (i = 0;i < pheader->numbones;i++)
1680 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1681 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1682 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1683 if (loadmodel->data_bones[i].parent >= i)
1684 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1687 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1688 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1689 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1690 for (i = 0;i < pheader->numverts;i++)
1692 vertbonecounts[i] = BigLong(bonecount[i]);
1693 if (vertbonecounts[i] != 1)
1694 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1697 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]);
1699 meshvertices = pheader->numverts;
1700 meshtriangles = pheader->numtris;
1702 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1703 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1704 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1705 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]));
1706 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1707 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1708 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1709 loadmodel->surfmesh.num_vertices = meshvertices;
1710 loadmodel->surfmesh.num_triangles = meshtriangles;
1711 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1712 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1713 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1714 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1715 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1716 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1717 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1718 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1719 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1720 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
1721 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1722 if (loadmodel->surfmesh.num_vertices <= 65536)
1724 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1725 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1726 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1729 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1730 poses = (float *) (pheader->lump_poses.start + pbase);
1731 for (i = 0;i < pheader->lump_poses.length / 4;i++)
1732 loadmodel->data_poses[i] = BigFloat(poses[i]);
1734 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1735 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1736 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1737 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1738 // (converting from weight-blending skeletal animation to
1739 // deformation-based skeletal animation)
1740 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1741 for (i = 0;i < loadmodel->num_bones;i++)
1743 const float *m = loadmodel->data_poses + i * 12;
1744 if (loadmodel->data_bones[i].parent >= 0)
1745 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1747 for (k = 0;k < 12;k++)
1748 bonepose[12*i+k] = m[k];
1750 for (j = 0;j < pheader->numverts;j++)
1752 // this format really should have had a per vertexweight weight value...
1753 // but since it does not, the weighting is completely ignored and
1754 // only one weight is allowed per vertex
1755 int boneindex = BigLong(vertdata[j].bonenum);
1756 const float *m = bonepose + 12 * boneindex;
1757 float relativeorigin[3];
1758 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1759 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1760 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1761 // transform the vertex bone weight into the base mesh
1762 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1763 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1764 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1765 // store the weight as the primary weight on this vertex
1766 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
1767 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = 1;
1770 // normals and tangents are calculated after elements are loaded
1772 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1773 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1774 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1775 for (i = 0;i < pheader->numverts;i++)
1777 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1778 // flip T coordinate for OpenGL
1779 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1782 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1783 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1784 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1786 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1787 //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)
1788 // byteswap, validate, and swap winding order of tris
1789 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1790 if (pheader->lump_render.length != count)
1791 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1792 renderlist = (int *) (pheader->lump_render.start + pbase);
1793 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1795 for (i = 0;i < loadmodel->num_surfaces;i++)
1797 int firstvertex, lastvertex;
1798 if (renderlist >= renderlistend)
1799 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1800 count = BigLong(*renderlist);renderlist++;
1801 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1802 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1804 loadmodel->surfacelist[i] = i;
1805 surface = loadmodel->data_surfaces + i;
1806 surface->texture = loadmodel->data_textures + i;
1807 surface->num_firsttriangle = meshtriangles;
1808 surface->num_triangles = count;
1809 meshtriangles += surface->num_triangles;
1811 // load the elements
1812 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
1813 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
1815 outelements[j*3+2] = BigLong(renderlist[0]);
1816 outelements[j*3+1] = BigLong(renderlist[1]);
1817 outelements[j*3+0] = BigLong(renderlist[2]);
1819 // validate the elements and find the used vertex range
1820 firstvertex = meshvertices;
1822 for (j = 0;j < surface->num_triangles * 3;j++)
1824 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
1825 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
1826 firstvertex = min(firstvertex, outelements[j]);
1827 lastvertex = max(lastvertex, outelements[j]);
1829 surface->num_firstvertex = firstvertex;
1830 surface->num_vertices = lastvertex + 1 - firstvertex;
1832 // since zym models do not have named sections, reuse their shader
1833 // name as the section name
1834 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
1835 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
1837 Mod_FreeSkinFiles(skinfiles);
1838 Mem_Free(vertbonecounts);
1841 // compute all the mesh information that was not loaded from the file
1842 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
1843 Mod_BuildBaseBonePoses();
1844 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
1845 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);
1846 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1848 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1851 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1853 dpmheader_t *pheader;
1857 unsigned char *pbase;
1858 int i, j, k, meshvertices, meshtriangles;
1859 skinfile_t *skinfiles;
1860 unsigned char *data;
1863 pheader = (dpmheader_t *)buffer;
1864 pbase = (unsigned char *)buffer;
1865 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
1866 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
1867 if (BigLong(pheader->type) != 2)
1868 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1870 loadmodel->modeldatatypestring = "DPM";
1872 loadmodel->type = mod_alias;
1873 loadmodel->synctype = ST_RAND;
1876 pheader->type = BigLong(pheader->type);
1877 pheader->filesize = BigLong(pheader->filesize);
1878 pheader->mins[0] = BigFloat(pheader->mins[0]);
1879 pheader->mins[1] = BigFloat(pheader->mins[1]);
1880 pheader->mins[2] = BigFloat(pheader->mins[2]);
1881 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
1882 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
1883 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
1884 pheader->yawradius = BigFloat(pheader->yawradius);
1885 pheader->allradius = BigFloat(pheader->allradius);
1886 pheader->num_bones = BigLong(pheader->num_bones);
1887 pheader->num_meshs = BigLong(pheader->num_meshs);
1888 pheader->num_frames = BigLong(pheader->num_frames);
1889 pheader->ofs_bones = BigLong(pheader->ofs_bones);
1890 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
1891 pheader->ofs_frames = BigLong(pheader->ofs_frames);
1893 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
1895 Con_Printf("%s has no geometry\n", loadmodel->name);
1898 if (pheader->num_frames < 1)
1900 Con_Printf("%s has no frames\n", loadmodel->name);
1904 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1905 loadmodel->DrawSky = NULL;
1906 loadmodel->DrawAddWaterPlanes = NULL;
1907 loadmodel->Draw = R_Q1BSP_Draw;
1908 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1909 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1910 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1911 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1912 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1913 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1914 loadmodel->PointSuperContents = NULL;
1917 for (i = 0;i < 3;i++)
1919 loadmodel->normalmins[i] = pheader->mins[i];
1920 loadmodel->normalmaxs[i] = pheader->maxs[i];
1921 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
1922 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
1923 loadmodel->rotatedmins[i] = -pheader->allradius;
1924 loadmodel->rotatedmaxs[i] = pheader->allradius;
1926 loadmodel->radius = pheader->allradius;
1927 loadmodel->radius2 = pheader->allradius * pheader->allradius;
1929 // load external .skin files if present
1930 skinfiles = Mod_LoadSkinFiles();
1931 if (loadmodel->numskins < 1)
1932 loadmodel->numskins = 1;
1937 // gather combined statistics from the meshes
1938 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
1939 for (i = 0;i < (int)pheader->num_meshs;i++)
1941 int numverts = BigLong(dpmmesh->num_verts);
1942 meshvertices += numverts;
1943 meshtriangles += BigLong(dpmmesh->num_tris);
1947 loadmodel->numframes = pheader->num_frames;
1948 loadmodel->num_bones = pheader->num_bones;
1949 loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
1950 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
1951 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1952 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1953 // do most allocations as one merged chunk
1954 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));
1955 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1956 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1957 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1958 loadmodel->surfmesh.num_vertices = meshvertices;
1959 loadmodel->surfmesh.num_triangles = meshtriangles;
1960 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1961 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1962 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1963 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1964 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1965 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1966 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1967 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1968 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1969 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
1970 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1971 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
1972 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
1973 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1974 if (meshvertices <= 65536)
1976 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1977 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1978 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1981 for (i = 0;i < loadmodel->numskins;i++)
1983 loadmodel->skinscenes[i].firstframe = i;
1984 loadmodel->skinscenes[i].framecount = 1;
1985 loadmodel->skinscenes[i].loop = true;
1986 loadmodel->skinscenes[i].framerate = 10;
1989 // load the bone info
1990 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
1991 for (i = 0;i < loadmodel->num_bones;i++)
1993 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1994 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1995 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1996 if (loadmodel->data_bones[i].parent >= i)
1997 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2001 frame = (dpmframe_t *) (pbase + pheader->ofs_frames);
2002 for (i = 0;i < loadmodel->numframes;i++)
2005 memcpy(loadmodel->animscenes[i].name, frame->name, sizeof(frame->name));
2006 loadmodel->animscenes[i].firstframe = i;
2007 loadmodel->animscenes[i].framecount = 1;
2008 loadmodel->animscenes[i].loop = true;
2009 loadmodel->animscenes[i].framerate = 10;
2010 // load the bone poses for this frame
2011 poses = (float *) (pbase + BigLong(frame->ofs_bonepositions));
2012 for (j = 0;j < loadmodel->num_bones*12;j++)
2013 loadmodel->data_poses[i * loadmodel->num_bones*12 + j] = BigFloat(poses[j]);
2014 // stuff not processed here: mins, maxs, yawradius, allradius
2018 // load the meshes now
2019 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2022 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2023 // (converting from weight-blending skeletal animation to
2024 // deformation-based skeletal animation)
2025 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2026 for (i = 0;i < loadmodel->num_bones;i++)
2028 const float *m = loadmodel->data_poses + i * 12;
2029 if (loadmodel->data_bones[i].parent >= 0)
2030 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2032 for (k = 0;k < 12;k++)
2033 bonepose[12*i+k] = m[k];
2035 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2037 const int *inelements;
2039 const float *intexcoord;
2040 msurface_t *surface;
2042 loadmodel->surfacelist[i] = i;
2043 surface = loadmodel->data_surfaces + i;
2044 surface->texture = loadmodel->data_textures + i;
2045 surface->num_firsttriangle = meshtriangles;
2046 surface->num_triangles = BigLong(dpmmesh->num_tris);
2047 surface->num_firstvertex = meshvertices;
2048 surface->num_vertices = BigLong(dpmmesh->num_verts);
2049 meshvertices += surface->num_vertices;
2050 meshtriangles += surface->num_triangles;
2052 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2053 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2054 for (j = 0;j < surface->num_triangles;j++)
2056 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2057 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2058 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2059 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2064 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2065 for (j = 0;j < surface->num_vertices*2;j++)
2066 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2068 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2069 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2073 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2074 data += sizeof(dpmvertex_t);
2075 for (k = 0;k < numweights;k++)
2077 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2078 int boneindex = BigLong(vert->bonenum);
2079 const float *m = bonepose + 12 * boneindex;
2080 float influence = BigFloat(vert->influence);
2081 float relativeorigin[3], relativenormal[3];
2082 relativeorigin[0] = BigFloat(vert->origin[0]);
2083 relativeorigin[1] = BigFloat(vert->origin[1]);
2084 relativeorigin[2] = BigFloat(vert->origin[2]);
2085 relativenormal[0] = BigFloat(vert->normal[0]);
2086 relativenormal[1] = BigFloat(vert->normal[1]);
2087 relativenormal[2] = BigFloat(vert->normal[2]);
2088 // blend the vertex bone weights into the base mesh
2089 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2090 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2091 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2092 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2093 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2094 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2097 // store the first (and often only) weight
2098 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = influence;
2099 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
2103 // sort the new weight into this vertex's weight table
2104 // (which only accepts up to 4 bones per vertex)
2105 for (l = 0;l < 4;l++)
2107 if (loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] < influence)
2109 // move weaker influence weights out of the way first
2111 for (l2 = 3;l2 > l;l2--)
2113 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2-1];
2114 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2-1];
2116 // store the new weight
2117 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] = influence;
2118 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l] = boneindex;
2123 data += sizeof(dpmbonevert_t);
2126 for (l = 0;l < 4;l++)
2127 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l];
2128 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2130 float f = 1.0f / sum;
2131 for (l = 0;l < 4;l++)
2132 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] *= f;
2136 // since dpm models do not have named sections, reuse their shader name as the section name
2137 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2139 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2142 Mod_FreeSkinFiles(skinfiles);
2144 // compute all the mesh information that was not loaded from the file
2145 Mod_BuildBaseBonePoses();
2146 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);
2147 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2149 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2152 // no idea why PSK/PSA files contain weird quaternions but they do...
2153 #define PSKQUATNEGATIONS
2154 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2156 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2157 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2158 fs_offset_t filesize;
2163 pskboneinfo_t *bones;
2164 pskrawweights_t *rawweights;
2165 pskboneinfo_t *animbones;
2166 pskaniminfo_t *anims;
2167 pskanimkeys_t *animkeys;
2168 void *animfilebuffer, *animbuffer, *animbufferend;
2169 unsigned char *data;
2171 skinfile_t *skinfiles;
2172 char animname[MAX_QPATH];
2175 pchunk = (pskchunk_t *)buffer;
2176 if (strcmp(pchunk->id, "ACTRHEAD"))
2177 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2179 loadmodel->modeldatatypestring = "PSK";
2181 loadmodel->type = mod_alias;
2182 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2183 loadmodel->DrawSky = NULL;
2184 loadmodel->DrawAddWaterPlanes = NULL;
2185 loadmodel->Draw = R_Q1BSP_Draw;
2186 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2187 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2188 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2189 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2190 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2191 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2192 loadmodel->PointSuperContents = NULL;
2193 loadmodel->synctype = ST_RAND;
2195 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2196 strlcat(animname, ".psa", sizeof(animname));
2197 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2198 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2199 if (animbuffer == NULL)
2200 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2219 while (buffer < bufferend)
2221 pchunk = (pskchunk_t *)buffer;
2222 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2223 version = LittleLong(pchunk->version);
2224 recordsize = LittleLong(pchunk->recordsize);
2225 numrecords = LittleLong(pchunk->numrecords);
2226 if (developer.integer >= 100)
2227 Con_Printf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2228 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2229 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);
2230 if (!strcmp(pchunk->id, "ACTRHEAD"))
2234 else if (!strcmp(pchunk->id, "PNTS0000"))
2237 if (recordsize != sizeof(*p))
2238 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2239 // byteswap in place and keep the pointer
2240 numpnts = numrecords;
2241 pnts = (pskpnts_t *)buffer;
2242 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2244 p->origin[0] = LittleFloat(p->origin[0]);
2245 p->origin[1] = LittleFloat(p->origin[1]);
2246 p->origin[2] = LittleFloat(p->origin[2]);
2250 else if (!strcmp(pchunk->id, "VTXW0000"))
2253 if (recordsize != sizeof(*p))
2254 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2255 // byteswap in place and keep the pointer
2256 numvtxw = numrecords;
2257 vtxw = (pskvtxw_t *)buffer;
2258 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2260 p->pntsindex = LittleShort(p->pntsindex);
2261 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2262 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2263 if (p->pntsindex >= numpnts)
2265 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2271 else if (!strcmp(pchunk->id, "FACE0000"))
2274 if (recordsize != sizeof(*p))
2275 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2276 // byteswap in place and keep the pointer
2277 numfaces = numrecords;
2278 faces = (pskface_t *)buffer;
2279 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2281 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2282 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2283 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2284 p->group = LittleLong(p->group);
2285 if (p->vtxwindex[0] >= numvtxw)
2287 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2288 p->vtxwindex[0] = 0;
2290 if (p->vtxwindex[1] >= numvtxw)
2292 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2293 p->vtxwindex[1] = 0;
2295 if (p->vtxwindex[2] >= numvtxw)
2297 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2298 p->vtxwindex[2] = 0;
2303 else if (!strcmp(pchunk->id, "MATT0000"))
2306 if (recordsize != sizeof(*p))
2307 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2308 // byteswap in place and keep the pointer
2309 nummatts = numrecords;
2310 matts = (pskmatt_t *)buffer;
2311 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2317 else if (!strcmp(pchunk->id, "REFSKELT"))
2320 if (recordsize != sizeof(*p))
2321 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2322 // byteswap in place and keep the pointer
2323 numbones = numrecords;
2324 bones = (pskboneinfo_t *)buffer;
2325 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2327 p->numchildren = LittleLong(p->numchildren);
2328 p->parent = LittleLong(p->parent);
2329 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2330 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2331 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2332 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2333 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2334 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2335 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2336 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2337 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2338 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2339 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2340 #ifdef PSKQUATNEGATIONS
2343 p->basepose.quat[0] *= -1;
2344 p->basepose.quat[1] *= -1;
2345 p->basepose.quat[2] *= -1;
2349 p->basepose.quat[0] *= 1;
2350 p->basepose.quat[1] *= -1;
2351 p->basepose.quat[2] *= 1;
2354 if (p->parent < 0 || p->parent >= numbones)
2356 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2362 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2365 if (recordsize != sizeof(*p))
2366 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2367 // byteswap in place and keep the pointer
2368 numrawweights = numrecords;
2369 rawweights = (pskrawweights_t *)buffer;
2370 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2372 p->weight = LittleFloat(p->weight);
2373 p->pntsindex = LittleLong(p->pntsindex);
2374 p->boneindex = LittleLong(p->boneindex);
2375 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2377 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2380 if (p->boneindex < 0 || p->boneindex >= numbones)
2382 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2390 while (animbuffer < animbufferend)
2392 pchunk = (pskchunk_t *)animbuffer;
2393 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2394 version = LittleLong(pchunk->version);
2395 recordsize = LittleLong(pchunk->recordsize);
2396 numrecords = LittleLong(pchunk->numrecords);
2397 if (developer.integer >= 100)
2398 Con_Printf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2399 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2400 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);
2401 if (!strcmp(pchunk->id, "ANIMHEAD"))
2405 else if (!strcmp(pchunk->id, "BONENAMES"))
2408 if (recordsize != sizeof(*p))
2409 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2410 // byteswap in place and keep the pointer
2411 numanimbones = numrecords;
2412 animbones = (pskboneinfo_t *)animbuffer;
2413 // NOTE: supposedly psa does not need to match the psk model, the
2414 // bones missing from the psa would simply use their base
2415 // positions from the psk, but this is hard for me to implement
2416 // and people can easily make animations that match.
2417 if (numanimbones != numbones)
2418 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2419 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2421 p->numchildren = LittleLong(p->numchildren);
2422 p->parent = LittleLong(p->parent);
2423 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2424 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2425 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2426 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2427 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2428 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2429 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2430 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2431 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2432 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2433 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2434 #ifdef PSKQUATNEGATIONS
2437 p->basepose.quat[0] *= -1;
2438 p->basepose.quat[1] *= -1;
2439 p->basepose.quat[2] *= -1;
2443 p->basepose.quat[0] *= 1;
2444 p->basepose.quat[1] *= -1;
2445 p->basepose.quat[2] *= 1;
2448 if (p->parent < 0 || p->parent >= numanimbones)
2450 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2453 // check that bones are the same as in the base
2454 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2455 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2459 else if (!strcmp(pchunk->id, "ANIMINFO"))
2462 if (recordsize != sizeof(*p))
2463 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2464 // byteswap in place and keep the pointer
2465 numanims = numrecords;
2466 anims = (pskaniminfo_t *)animbuffer;
2467 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2469 p->numbones = LittleLong(p->numbones);
2470 p->playtime = LittleFloat(p->playtime);
2471 p->fps = LittleFloat(p->fps);
2472 p->firstframe = LittleLong(p->firstframe);
2473 p->numframes = LittleLong(p->numframes);
2474 if (p->numbones != numbones)
2475 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2479 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2482 if (recordsize != sizeof(*p))
2483 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2484 numanimkeys = numrecords;
2485 animkeys = (pskanimkeys_t *)animbuffer;
2486 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2488 p->origin[0] = LittleFloat(p->origin[0]);
2489 p->origin[1] = LittleFloat(p->origin[1]);
2490 p->origin[2] = LittleFloat(p->origin[2]);
2491 p->quat[0] = LittleFloat(p->quat[0]);
2492 p->quat[1] = LittleFloat(p->quat[1]);
2493 p->quat[2] = LittleFloat(p->quat[2]);
2494 p->quat[3] = LittleFloat(p->quat[3]);
2495 p->frametime = LittleFloat(p->frametime);
2496 #ifdef PSKQUATNEGATIONS
2497 if (index % numbones)
2512 // TODO: allocate bonepose stuff
2515 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2518 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2519 Host_Error("%s: missing required chunks", loadmodel->name);
2521 loadmodel->numframes = 0;
2522 for (index = 0;index < numanims;index++)
2523 loadmodel->numframes += anims[index].numframes;
2525 if (numanimkeys != numbones * loadmodel->numframes)
2526 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2528 meshvertices = numvtxw;
2529 meshtriangles = numfaces;
2531 // load external .skin files if present
2532 skinfiles = Mod_LoadSkinFiles();
2533 if (loadmodel->numskins < 1)
2534 loadmodel->numskins = 1;
2535 loadmodel->num_bones = numbones;
2536 loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
2537 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2538 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2539 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2540 loadmodel->surfmesh.num_vertices = meshvertices;
2541 loadmodel->surfmesh.num_triangles = meshtriangles;
2542 // do most allocations as one merged chunk
2543 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);
2544 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2545 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2546 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2547 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2548 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2549 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2550 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2551 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2552 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2553 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2554 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2555 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += loadmodel->surfmesh.num_vertices * sizeof(int[4]);
2556 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[4]);
2557 //loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
2558 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2559 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2560 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2561 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2562 if (loadmodel->surfmesh.num_vertices <= 65536)
2564 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2565 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2566 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2568 loadmodel->data_poses = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->num_poses * sizeof(float[12]));
2570 for (i = 0;i < loadmodel->numskins;i++)
2572 loadmodel->skinscenes[i].firstframe = i;
2573 loadmodel->skinscenes[i].framecount = 1;
2574 loadmodel->skinscenes[i].loop = true;
2575 loadmodel->skinscenes[i].framerate = 10;
2579 for (index = 0, i = 0;index < nummatts;index++)
2581 // since psk models do not have named sections, reuse their shader name as the section name
2582 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2583 loadmodel->surfacelist[index] = index;
2584 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2585 loadmodel->data_surfaces[index].num_firstvertex = 0;
2586 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2589 // copy over the vertex locations and texcoords
2590 for (index = 0;index < numvtxw;index++)
2592 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2593 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2594 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2595 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2596 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2599 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2600 for (index = 0;index < numfaces;index++)
2601 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2602 for (index = 0, i = 0;index < nummatts;index++)
2604 loadmodel->data_surfaces[index].num_firsttriangle = i;
2605 i += loadmodel->data_surfaces[index].num_triangles;
2606 loadmodel->data_surfaces[index].num_triangles = 0;
2608 for (index = 0;index < numfaces;index++)
2610 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2611 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2612 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2613 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2616 // copy over the bones
2617 for (index = 0;index < numbones;index++)
2619 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2620 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2621 if (loadmodel->data_bones[index].parent >= index)
2622 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2625 // sort the psk point weights into the vertex weight tables
2626 // (which only accept up to 4 bones per vertex)
2627 for (index = 0;index < numvtxw;index++)
2631 for (j = 0;j < numrawweights;j++)
2633 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2635 int boneindex = rawweights[j].boneindex;
2636 float influence = rawweights[j].weight;
2637 for (l = 0;l < 4;l++)
2639 if (loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] < influence)
2641 // move lower influence weights out of the way first
2643 for (l2 = 3;l2 > l;l2--)
2645 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2-1];
2646 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2-1];
2648 // store the new weight
2649 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] = influence;
2650 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l] = boneindex;
2657 for (l = 0;l < 4;l++)
2658 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l];
2659 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2661 float f = 1.0f / sum;
2662 for (l = 0;l < 4;l++)
2663 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] *= f;
2667 // set up the animscenes based on the anims
2668 for (index = 0, i = 0;index < numanims;index++)
2670 for (j = 0;j < anims[index].numframes;j++, i++)
2672 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2673 loadmodel->animscenes[i].firstframe = i;
2674 loadmodel->animscenes[i].framecount = 1;
2675 loadmodel->animscenes[i].loop = true;
2676 loadmodel->animscenes[i].framerate = 10;
2680 // load the poses from the animkeys
2681 for (index = 0;index < numanimkeys;index++)
2683 pskanimkeys_t *k = animkeys + index;
2685 Matrix4x4_FromOriginQuat(&matrix, k->origin[0], k->origin[1], k->origin[2], k->quat[0], k->quat[1], k->quat[2], k->quat[3]);
2686 Matrix4x4_ToArray12FloatD3D(&matrix, loadmodel->data_poses + index*12);
2688 Mod_FreeSkinFiles(skinfiles);
2689 Mem_Free(animfilebuffer);
2691 // compute all the mesh information that was not loaded from the file
2692 // TODO: honor smoothing groups somehow?
2693 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2694 Mod_BuildBaseBonePoses();
2695 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2696 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);
2697 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2698 Mod_Alias_CalculateBoundingBox();
2700 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;