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 desiredscale[3];
56 float boneposerelative[MAX_BONES][12];
57 float *matrix, m[12], bonepose[MAX_BONES][12];
59 // interpolate matrices and concatenate them to their parents
60 for (i = 0;i < model->num_bones;i++)
62 for (k = 0;k < 12;k++)
64 VectorClear(desiredscale);
65 for (blends = 0;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++)
67 matrix = model->data_poses + (frameblend[blends].subframe * model->num_bones + i) * 12;
68 for (k = 0;k < 12;k++)
69 m[k] += matrix[k] * frameblend[blends].lerp;
70 desiredscale[0] += frameblend[blends].lerp * VectorLength(matrix );
71 desiredscale[1] += frameblend[blends].lerp * VectorLength(matrix + 4);
72 desiredscale[2] += frameblend[blends].lerp * VectorLength(matrix + 8);
75 VectorNormalize(m + 4);
76 VectorNormalize(m + 8);
77 VectorScale(m , desiredscale[0], m );
78 VectorScale(m + 4, desiredscale[1], m + 4);
79 VectorScale(m + 8, desiredscale[2], m + 8);
80 if (i == r_skeletal_debugbone.integer)
81 m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
82 m[3] *= r_skeletal_debugtranslatex.value;
83 m[7] *= r_skeletal_debugtranslatey.value;
84 m[11] *= r_skeletal_debugtranslatez.value;
85 if (model->data_bones[i].parent >= 0)
86 R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
88 for (k = 0;k < 12;k++)
89 bonepose[i][k] = m[k];
90 // create a relative deformation matrix to describe displacement
91 // from the base mesh, which is used by the actual weighting
92 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]);
94 // blend the vertex bone weights
95 // 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)
96 // special case for the first bone because it avoids the need to memset the arrays before filling
99 const float *v = model->surfmesh.data_vertex3f;
100 const int *wi = model->surfmesh.data_vertexweightindex4i;
101 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
102 memset(vertex3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
103 for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, wi += 4, wf += 4, vertex3f += 3)
107 const float *m = boneposerelative[wi[0]];
108 vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
109 vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
110 vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
114 const float *m = boneposerelative[wi[0]];
116 vertex3f[0] = f * (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
117 vertex3f[1] = f * (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
118 vertex3f[2] = f * (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
119 for (k = 1;k < 4 && wf[k];k++)
121 const float *m = boneposerelative[wi[k]];
123 vertex3f[0] += f * (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
124 vertex3f[1] += f * (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
125 vertex3f[2] += f * (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
132 const float *n = model->surfmesh.data_normal3f;
133 const int *wi = model->surfmesh.data_vertexweightindex4i;
134 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
135 memset(normal3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
136 for (i = 0;i < model->surfmesh.num_vertices;i++, n += 3, wi += 4, wf += 4, normal3f += 3)
140 const float *m = boneposerelative[wi[0]];
141 normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
142 normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
143 normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
147 const float *m = boneposerelative[wi[0]];
149 normal3f[0] = f * (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
150 normal3f[1] = f * (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
151 normal3f[2] = f * (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
152 for (k = 1;k < 4 && wf[k];k++)
154 const float *m = boneposerelative[wi[k]];
156 normal3f[0] += f * (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
157 normal3f[1] += f * (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
158 normal3f[2] += f * (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
165 const float *sv = model->surfmesh.data_svector3f;
166 const int *wi = model->surfmesh.data_vertexweightindex4i;
167 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
168 memset(svector3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
169 for (i = 0;i < model->surfmesh.num_vertices;i++, sv += 3, wi += 4, wf += 4, svector3f += 3)
173 const float *m = boneposerelative[wi[0]];
174 svector3f[0] = (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
175 svector3f[1] = (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
176 svector3f[2] = (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
180 const float *m = boneposerelative[wi[0]];
182 svector3f[0] = f * (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
183 svector3f[1] = f * (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
184 svector3f[2] = f * (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
185 for (k = 1;k < 4 && wf[k];k++)
187 const float *m = boneposerelative[wi[k]];
189 svector3f[0] += f * (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
190 svector3f[1] += f * (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
191 svector3f[2] += f * (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
198 const float *tv = model->surfmesh.data_tvector3f;
199 const int *wi = model->surfmesh.data_vertexweightindex4i;
200 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
201 memset(tvector3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
202 for (i = 0;i < model->surfmesh.num_vertices;i++, tv += 3, wi += 4, wf += 4, tvector3f += 3)
206 const float *m = boneposerelative[wi[0]];
207 tvector3f[0] = (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
208 tvector3f[1] = (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
209 tvector3f[2] = (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
213 const float *m = boneposerelative[wi[0]];
215 tvector3f[0] = f * (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
216 tvector3f[1] = f * (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
217 tvector3f[2] = f * (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
218 for (k = 1;k < 4 && wf[k];k++)
220 const float *m = boneposerelative[wi[k]];
222 tvector3f[0] += f * (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
223 tvector3f[1] += f * (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
224 tvector3f[2] += f * (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
231 void Mod_MD3_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
234 int i, numblends, blendnum;
235 int numverts = model->surfmesh.num_vertices;
237 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
239 //VectorMA(translate, model->surfmesh.num_morphmdlframetranslate, frameblend[blendnum].lerp, translate);
240 if (frameblend[blendnum].lerp > 0)
241 numblends = blendnum + 1;
243 // special case for the first blend because it avoids some adds and the need to memset the arrays first
244 for (blendnum = 0;blendnum < numblends;blendnum++)
246 const md3vertex_t *verts = model->surfmesh.data_morphmd3vertex + numverts * frameblend[blendnum].subframe;
249 float scale = frameblend[blendnum].lerp * (1.0f / 64.0f);
252 for (i = 0;i < numverts;i++)
254 vertex3f[i * 3 + 0] = verts[i].origin[0] * scale;
255 vertex3f[i * 3 + 1] = verts[i].origin[1] * scale;
256 vertex3f[i * 3 + 2] = verts[i].origin[2] * scale;
261 for (i = 0;i < numverts;i++)
263 vertex3f[i * 3 + 0] += verts[i].origin[0] * scale;
264 vertex3f[i * 3 + 1] += verts[i].origin[1] * scale;
265 vertex3f[i * 3 + 2] += verts[i].origin[2] * scale;
269 // the yaw and pitch stored in md3 models are 8bit quantized angles
270 // (0-255), and as such a lookup table is very well suited to
271 // decoding them, and since cosine is equivilant to sine with an
272 // extra 45 degree rotation, this uses one lookup table for both
273 // sine and cosine with a +64 bias to get cosine.
276 float lerp = frameblend[blendnum].lerp;
279 for (i = 0;i < numverts;i++)
281 normal3f[i * 3 + 0] = mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
282 normal3f[i * 3 + 1] = mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
283 normal3f[i * 3 + 2] = mod_md3_sin[verts[i].pitch + 64] * lerp;
288 for (i = 0;i < numverts;i++)
290 normal3f[i * 3 + 0] += mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
291 normal3f[i * 3 + 1] += mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
292 normal3f[i * 3 + 2] += mod_md3_sin[verts[i].pitch + 64] * lerp;
298 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
299 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
302 for (i = 0;i < numverts;i++, texvecvert++)
304 VectorScale(texvecvert->svec, f, svector3f + i*3);
305 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
310 for (i = 0;i < numverts;i++, texvecvert++)
312 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
313 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
320 void Mod_MDL_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
323 int i, numblends, blendnum;
324 int numverts = model->surfmesh.num_vertices;
326 VectorClear(translate);
328 // blend the frame translates to avoid redundantly doing so on each vertex
329 // (a bit of a brain twister but it works)
330 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
332 if (model->surfmesh.data_morphmd2framesize6f)
333 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6 + 3, translate);
335 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.num_morphmdlframetranslate, translate);
336 if (frameblend[blendnum].lerp > 0)
337 numblends = blendnum + 1;
339 // special case for the first blend because it avoids some adds and the need to memset the arrays first
340 for (blendnum = 0;blendnum < numblends;blendnum++)
342 const trivertx_t *verts = model->surfmesh.data_morphmdlvertex + numverts * frameblend[blendnum].subframe;
346 if (model->surfmesh.data_morphmd2framesize6f)
347 VectorScale(model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6, frameblend[blendnum].lerp, scale);
349 VectorScale(model->surfmesh.num_morphmdlframescale, frameblend[blendnum].lerp, scale);
352 for (i = 0;i < numverts;i++)
354 vertex3f[i * 3 + 0] = translate[0] + verts[i].v[0] * scale[0];
355 vertex3f[i * 3 + 1] = translate[1] + verts[i].v[1] * scale[1];
356 vertex3f[i * 3 + 2] = translate[2] + verts[i].v[2] * scale[2];
361 for (i = 0;i < numverts;i++)
363 vertex3f[i * 3 + 0] += verts[i].v[0] * scale[0];
364 vertex3f[i * 3 + 1] += verts[i].v[1] * scale[1];
365 vertex3f[i * 3 + 2] += verts[i].v[2] * scale[2];
369 // the vertex normals in mdl models are an index into a table of
370 // 162 unique values, this very crude quantization reduces the
371 // vertex normal to only one byte, which saves a lot of space but
372 // also makes lighting pretty coarse
375 float lerp = frameblend[blendnum].lerp;
378 for (i = 0;i < numverts;i++)
380 const float *vn = m_bytenormals[verts[i].lightnormalindex];
381 VectorScale(vn, lerp, normal3f + i*3);
386 for (i = 0;i < numverts;i++)
388 const float *vn = m_bytenormals[verts[i].lightnormalindex];
389 VectorMA(normal3f + i*3, lerp, vn, normal3f + i*3);
395 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
396 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
399 for (i = 0;i < numverts;i++, texvecvert++)
401 VectorScale(texvecvert->svec, f, svector3f + i*3);
402 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
407 for (i = 0;i < numverts;i++, texvecvert++)
409 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
410 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
417 int Mod_Alias_GetTagMatrix(const dp_model_t *model, int poseframe, int tagindex, matrix4x4_t *outmatrix)
419 const float *boneframe;
420 float tempbonematrix[12], bonematrix[12];
421 *outmatrix = identitymatrix;
422 if (model->num_bones)
424 if (tagindex < 0 || tagindex >= model->num_bones)
426 if (poseframe >= model->num_poses)
428 boneframe = model->data_poses + poseframe * model->num_bones * 12;
429 memcpy(bonematrix, boneframe + tagindex * 12, sizeof(float[12]));
430 while (model->data_bones[tagindex].parent >= 0)
432 memcpy(tempbonematrix, bonematrix, sizeof(float[12]));
433 R_ConcatTransforms(boneframe + model->data_bones[tagindex].parent * 12, tempbonematrix, bonematrix);
434 tagindex = model->data_bones[tagindex].parent;
436 Matrix4x4_FromArray12FloatD3D(outmatrix, bonematrix);
438 else if (model->num_tags)
440 if (tagindex < 0 || tagindex >= model->num_tags)
442 if (poseframe >= model->num_tagframes)
444 Matrix4x4_FromArray12FloatGL(outmatrix, model->data_tags[poseframe * model->num_tags + tagindex].matrixgl);
447 if(!mod_alias_supporttagscale.integer)
448 Matrix4x4_Normalize3(outmatrix, outmatrix);
453 int Mod_Alias_GetExtendedTagInfoForIndex(const dp_model_t *model, unsigned int skin, int poseframe, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
455 const float *boneframe;
457 if(skin >= (unsigned int)model->numskins)
460 if (model->num_bones)
462 if(tagindex >= model->num_bones || tagindex < 0)
464 if (poseframe >= model->num_poses)
467 boneframe = model->data_poses + poseframe * model->num_bones * 12;
468 *parentindex = model->data_bones[tagindex].parent;
469 *tagname = model->data_bones[tagindex].name;
470 Matrix4x4_FromArray12FloatD3D(tag_localmatrix, boneframe + tagindex * 12);
476 if(tagindex >= model->num_tags || tagindex < 0)
478 if (poseframe >= model->num_tagframes)
480 *tagname = model->data_tags[tagindex].name;
481 Matrix4x4_FromArray12FloatGL(tag_localmatrix, model->data_tags[poseframe * model->num_tags + tagindex].matrixgl);
488 int Mod_Alias_GetTagIndexForName(const dp_model_t *model, unsigned int skin, const char *tagname)
491 if(skin >= (unsigned int)model->numskins)
493 if (model->num_bones)
494 for (i = 0;i < model->num_bones;i++)
495 if (!strcasecmp(tagname, model->data_bones[i].name))
498 for (i = 0;i < model->num_tags;i++)
499 if (!strcasecmp(tagname, model->data_tags[i].name))
504 static void Mod_BuildBaseBonePoses(void)
508 float *basebonepose = (float *) Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(float[12]));
509 float *in12f = loadmodel->data_poses;
510 float *out12f = basebonepose;
511 float *outinv12f = loadmodel->data_baseboneposeinverse;
512 for (i = 0;i < loadmodel->num_bones;i++, in12f += 12, out12f += 12, outinv12f += 12)
514 if (loadmodel->data_bones[i].parent >= 0)
515 R_ConcatTransforms(basebonepose + 12 * loadmodel->data_bones[i].parent, in12f, out12f);
517 for (k = 0;k < 12;k++)
518 out12f[k] = in12f[k];
522 // we only support uniform scaling, so assume the first row is enough
523 // (note the lack of sqrt here, because we're trying to undo the scaling,
524 // this means multiplying by the inverse scale twice - squaring it, which
525 // makes the sqrt a waste of time)
526 scale = 1.0 / (out12f[ 0] * out12f[ 0] + out12f[ 1] * out12f[ 1] + out12f[ 2] * out12f[ 2]);
528 // invert the rotation by transposing and multiplying by the squared
529 // recipricol of the input matrix scale as described above
530 outinv12f[ 0] = (float)(out12f[ 0] * scale);
531 outinv12f[ 1] = (float)(out12f[ 4] * scale);
532 outinv12f[ 2] = (float)(out12f[ 8] * scale);
533 outinv12f[ 4] = (float)(out12f[ 1] * scale);
534 outinv12f[ 5] = (float)(out12f[ 5] * scale);
535 outinv12f[ 6] = (float)(out12f[ 9] * scale);
536 outinv12f[ 8] = (float)(out12f[ 2] * scale);
537 outinv12f[ 9] = (float)(out12f[ 6] * scale);
538 outinv12f[10] = (float)(out12f[10] * scale);
540 // invert the translate
541 outinv12f[ 3] = -(out12f[ 3] * outinv12f[ 0] + out12f[ 7] * outinv12f[ 1] + out12f[11] * outinv12f[ 2]);
542 outinv12f[ 7] = -(out12f[ 3] * outinv12f[ 4] + out12f[ 7] * outinv12f[ 5] + out12f[11] * outinv12f[ 6]);
543 outinv12f[11] = -(out12f[ 3] * outinv12f[ 8] + out12f[ 7] * outinv12f[ 9] + out12f[11] * outinv12f[10]);
545 Mem_Free(basebonepose);
548 static void Mod_Alias_CalculateBoundingBox(void)
551 qboolean firstvertex = true;
552 float dist, yawradius, radius;
555 frameblend_t frameblend[MAX_FRAMEBLENDS];
556 memset(frameblend, 0, sizeof(frameblend));
557 frameblend[0].lerp = 1;
558 vertex3f = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
559 VectorClear(loadmodel->normalmins);
560 VectorClear(loadmodel->normalmaxs);
563 for (frameblend[0].subframe = 0;frameblend[0].subframe < loadmodel->num_poses;frameblend[0].subframe++)
565 loadmodel->AnimateVertices(loadmodel, frameblend, vertex3f, NULL, NULL, NULL);
566 for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
571 VectorCopy(v, loadmodel->normalmins);
572 VectorCopy(v, loadmodel->normalmaxs);
576 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
577 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
578 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
579 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
580 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
581 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
583 dist = v[0] * v[0] + v[1] * v[1];
584 if (yawradius < dist)
593 radius = sqrt(radius);
594 yawradius = sqrt(yawradius);
595 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
596 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
597 loadmodel->yawmins[2] = loadmodel->normalmins[2];
598 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
599 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
600 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
601 loadmodel->radius = radius;
602 loadmodel->radius2 = radius * radius;
605 static void Mod_Alias_MorphMesh_CompileFrames(void)
608 frameblend_t frameblend[MAX_FRAMEBLENDS];
609 unsigned char *datapointer;
610 memset(frameblend, 0, sizeof(frameblend));
611 frameblend[0].lerp = 1;
612 datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
613 loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
614 loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
615 loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
616 loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
617 loadmodel->surfmesh.data_morphtexvecvertex = (texvecvertex_t *)datapointer;datapointer += loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices * sizeof(texvecvertex_t);
618 // 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)
619 for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
621 frameblend[0].subframe = i;
622 loadmodel->AnimateVertices(loadmodel, frameblend, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
623 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);
624 // encode the svector and tvector in 3 byte format for permanent storage
625 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
627 VectorScaleCast(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
628 VectorScaleCast(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
633 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)
636 vec3_t shiftstart, shiftend;
637 float segmentmins[3], segmentmaxs[3];
638 frameblend_t frameblend[MAX_FRAMEBLENDS];
640 static int maxvertices = 0;
641 static float *vertex3f = NULL;
642 memset(trace, 0, sizeof(*trace));
644 trace->realfraction = 1;
645 trace->hitsupercontentsmask = hitsupercontentsmask;
646 memset(frameblend, 0, sizeof(frameblend));
647 frameblend[0].subframe = frame;
648 frameblend[0].lerp = 1;
649 if (maxvertices < model->surfmesh.num_vertices)
653 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
654 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
656 if (VectorCompare(boxmins, boxmaxs))
659 VectorAdd(start, boxmins, shiftstart);
660 VectorAdd(end, boxmins, shiftend);
661 segmentmins[0] = min(shiftstart[0], shiftend[0]) - 1;
662 segmentmins[1] = min(shiftstart[1], shiftend[1]) - 1;
663 segmentmins[2] = min(shiftstart[2], shiftend[2]) - 1;
664 segmentmaxs[0] = max(shiftstart[0], shiftend[0]) + 1;
665 segmentmaxs[1] = max(shiftstart[1], shiftend[1]) + 1;
666 segmentmaxs[2] = max(shiftstart[2], shiftend[2]) + 1;
667 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
669 model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL);
670 Collision_TraceLineTriangleMeshFloat(trace, shiftstart, shiftend, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs);
675 // box trace, performed as brush trace
676 colbrushf_t *thisbrush_start, *thisbrush_end;
677 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
678 segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
679 segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
680 segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
681 segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
682 segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
683 segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
684 VectorAdd(start, boxmins, boxstartmins);
685 VectorAdd(start, boxmaxs, boxstartmaxs);
686 VectorAdd(end, boxmins, boxendmins);
687 VectorAdd(end, boxmaxs, boxendmaxs);
688 thisbrush_start = Collision_BrushForBox(&identitymatrix, boxstartmins, boxstartmaxs, 0, 0, NULL);
689 thisbrush_end = Collision_BrushForBox(&identitymatrix, boxendmins, boxendmaxs, 0, 0, NULL);
690 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
692 if (maxvertices < model->surfmesh.num_vertices)
696 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
697 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
699 model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL);
700 Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs);
705 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
708 for (i = 0;i < inverts;i++)
710 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
712 j = vertremap[i]; // not onseam
715 j = vertremap[i+inverts]; // onseam
721 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
723 int i, f, pose, groupframes;
725 daliasframetype_t *pframetype;
726 daliasframe_t *pinframe;
727 daliasgroup_t *group;
728 daliasinterval_t *intervals;
731 scene = loadmodel->animscenes;
732 for (f = 0;f < loadmodel->numframes;f++)
734 pframetype = (daliasframetype_t *)datapointer;
735 datapointer += sizeof(daliasframetype_t);
736 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
738 // a single frame is still treated as a group
745 group = (daliasgroup_t *)datapointer;
746 datapointer += sizeof(daliasgroup_t);
747 groupframes = LittleLong (group->numframes);
749 // intervals (time per frame)
750 intervals = (daliasinterval_t *)datapointer;
751 datapointer += sizeof(daliasinterval_t) * groupframes;
753 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
754 if (interval < 0.01f)
756 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
761 // get scene name from first frame
762 pinframe = (daliasframe_t *)datapointer;
764 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
765 scene->firstframe = pose;
766 scene->framecount = groupframes;
767 scene->framerate = 1.0f / interval;
772 for (i = 0;i < groupframes;i++)
774 pinframe = (daliasframe_t *)datapointer;
775 datapointer += sizeof(daliasframe_t);
776 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
777 datapointer += sizeof(trivertx_t) * inverts;
783 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
785 if (cls.state == ca_dedicated)
789 skinframe = R_SkinFrame_LoadMissing();
790 memset(texture, 0, sizeof(*texture));
791 texture->currentframe = texture;
792 //texture->animated = false;
793 texture->numskinframes = 1;
794 texture->skinframerate = 1;
795 texture->skinframes[0] = skinframe;
796 texture->currentskinframe = skinframe;
797 //texture->backgroundnumskinframes = 0;
798 //texture->customblendfunc[0] = 0;
799 //texture->customblendfunc[1] = 0;
800 //texture->surfaceflags = 0;
801 //texture->supercontents = 0;
802 //texture->surfaceparms = 0;
803 //texture->textureflags = 0;
805 texture->basematerialflags = MATERIALFLAG_WALL;
806 if (texture->currentskinframe->fog)
807 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
808 texture->currentmaterialflags = texture->basematerialflags;
811 static void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
814 skinfileitem_t *skinfileitem;
817 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
818 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
820 memset(skin, 0, sizeof(*skin));
822 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
824 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
825 if (!strcmp(skinfileitem->name, meshname))
827 Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
833 // don't render unmentioned meshes
834 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
835 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
840 Mod_LoadTextureFromQ3Shader(skin, shadername, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
843 #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);
844 #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);
845 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
847 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
848 float scales, scalet, interval;
852 stvert_t *pinstverts;
853 dtriangle_t *pintriangles;
854 daliasskintype_t *pinskintype;
855 daliasskingroup_t *pinskingroup;
856 daliasskininterval_t *pinskinintervals;
857 daliasframetype_t *pinframetype;
858 daliasgroup_t *pinframegroup;
859 unsigned char *datapointer, *startframes, *startskins;
860 char name[MAX_QPATH];
861 skinframe_t *tempskinframe;
862 animscene_t *tempskinscenes;
863 texture_t *tempaliasskins;
865 int *vertonseam, *vertremap;
866 skinfile_t *skinfiles;
868 datapointer = (unsigned char *)buffer;
869 pinmodel = (mdl_t *)datapointer;
870 datapointer += sizeof(mdl_t);
872 version = LittleLong (pinmodel->version);
873 if (version != ALIAS_VERSION)
874 Host_Error ("%s has wrong version number (%i should be %i)",
875 loadmodel->name, version, ALIAS_VERSION);
877 loadmodel->modeldatatypestring = "MDL";
879 loadmodel->type = mod_alias;
880 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
881 loadmodel->DrawSky = NULL;
882 loadmodel->DrawAddWaterPlanes = NULL;
883 loadmodel->Draw = R_Q1BSP_Draw;
884 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
885 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
886 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
887 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
888 loadmodel->DrawLight = R_Q1BSP_DrawLight;
889 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
890 loadmodel->PointSuperContents = NULL;
892 loadmodel->num_surfaces = 1;
893 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
894 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
895 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
896 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
897 loadmodel->sortedmodelsurfaces[0] = 0;
899 loadmodel->numskins = LittleLong(pinmodel->numskins);
900 BOUNDI(loadmodel->numskins,0,65536);
901 skinwidth = LittleLong (pinmodel->skinwidth);
902 BOUNDI(skinwidth,0,65536);
903 skinheight = LittleLong (pinmodel->skinheight);
904 BOUNDI(skinheight,0,65536);
905 numverts = LittleLong(pinmodel->numverts);
906 BOUNDI(numverts,0,65536);
907 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
908 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
909 loadmodel->numframes = LittleLong(pinmodel->numframes);
910 BOUNDI(loadmodel->numframes,0,65536);
911 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
912 BOUNDI(loadmodel->synctype,0,2);
913 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
914 i = LittleLong (pinmodel->flags);
915 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
917 for (i = 0;i < 3;i++)
919 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
920 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
923 startskins = datapointer;
925 for (i = 0;i < loadmodel->numskins;i++)
927 pinskintype = (daliasskintype_t *)datapointer;
928 datapointer += sizeof(daliasskintype_t);
929 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
933 pinskingroup = (daliasskingroup_t *)datapointer;
934 datapointer += sizeof(daliasskingroup_t);
935 groupskins = LittleLong(pinskingroup->numskins);
936 datapointer += sizeof(daliasskininterval_t) * groupskins;
939 for (j = 0;j < groupskins;j++)
941 datapointer += skinwidth * skinheight;
946 pinstverts = (stvert_t *)datapointer;
947 datapointer += sizeof(stvert_t) * numverts;
949 pintriangles = (dtriangle_t *)datapointer;
950 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
952 startframes = datapointer;
953 loadmodel->surfmesh.num_morphframes = 0;
954 for (i = 0;i < loadmodel->numframes;i++)
956 pinframetype = (daliasframetype_t *)datapointer;
957 datapointer += sizeof(daliasframetype_t);
958 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
962 pinframegroup = (daliasgroup_t *)datapointer;
963 datapointer += sizeof(daliasgroup_t);
964 groupframes = LittleLong(pinframegroup->numframes);
965 datapointer += sizeof(daliasinterval_t) * groupframes;
968 for (j = 0;j < groupframes;j++)
970 datapointer += sizeof(daliasframe_t);
971 datapointer += sizeof(trivertx_t) * numverts;
972 loadmodel->surfmesh.num_morphframes++;
975 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
977 // store texture coordinates into temporary array, they will be stored
978 // after usage is determined (triangle data)
979 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
980 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
981 vertonseam = vertremap + numverts * 2;
983 scales = 1.0 / skinwidth;
984 scalet = 1.0 / skinheight;
985 for (i = 0;i < numverts;i++)
987 vertonseam[i] = LittleLong(pinstverts[i].onseam);
988 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
989 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
990 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
991 vertst[(i+numverts)*2+1] = vertst[i*2+1];
994 // load triangle data
995 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
997 // read the triangle elements
998 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
999 for (j = 0;j < 3;j++)
1000 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1001 // validate (note numverts is used because this is the original data)
1002 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1003 // now butcher the elements according to vertonseam and tri->facesfront
1004 // and then compact the vertex set to remove duplicates
1005 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1006 if (!LittleLong(pintriangles[i].facesfront)) // backface
1007 for (j = 0;j < 3;j++)
1008 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1009 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1011 // (this uses vertremap to count usage to save some memory)
1012 for (i = 0;i < numverts*2;i++)
1014 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1015 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1016 // build remapping table and compact array
1017 loadmodel->surfmesh.num_vertices = 0;
1018 for (i = 0;i < numverts*2;i++)
1022 vertremap[i] = loadmodel->surfmesh.num_vertices;
1023 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1024 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1025 loadmodel->surfmesh.num_vertices++;
1028 vertremap[i] = -1; // not used at all
1030 // remap the elements to the new vertex set
1031 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1032 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1033 // store the texture coordinates
1034 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1035 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1037 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1038 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1041 // generate ushort elements array if possible
1042 if (loadmodel->surfmesh.num_vertices <= 65536)
1044 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1045 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1046 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1050 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1051 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1052 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1053 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1054 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1055 Mod_Alias_CalculateBoundingBox();
1056 Mod_Alias_MorphMesh_CompileFrames();
1059 Mem_Free(vertremap);
1062 skinfiles = Mod_LoadSkinFiles();
1065 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1066 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1067 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1068 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1069 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1070 Mod_FreeSkinFiles(skinfiles);
1071 for (i = 0;i < loadmodel->numskins;i++)
1073 loadmodel->skinscenes[i].firstframe = i;
1074 loadmodel->skinscenes[i].framecount = 1;
1075 loadmodel->skinscenes[i].loop = true;
1076 loadmodel->skinscenes[i].framerate = 10;
1081 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1082 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1083 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1084 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1086 datapointer = startskins;
1087 for (i = 0;i < loadmodel->numskins;i++)
1089 pinskintype = (daliasskintype_t *)datapointer;
1090 datapointer += sizeof(daliasskintype_t);
1092 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1099 pinskingroup = (daliasskingroup_t *)datapointer;
1100 datapointer += sizeof(daliasskingroup_t);
1102 groupskins = LittleLong (pinskingroup->numskins);
1104 pinskinintervals = (daliasskininterval_t *)datapointer;
1105 datapointer += sizeof(daliasskininterval_t) * groupskins;
1107 interval = LittleFloat(pinskinintervals[0].interval);
1108 if (interval < 0.01f)
1110 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1115 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1116 loadmodel->skinscenes[i].firstframe = totalskins;
1117 loadmodel->skinscenes[i].framecount = groupskins;
1118 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1119 loadmodel->skinscenes[i].loop = true;
1121 for (j = 0;j < groupskins;j++)
1124 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1126 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1127 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))
1128 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));
1129 datapointer += skinwidth * skinheight;
1133 // check for skins that don't exist in the model, but do exist as external images
1134 // (this was added because yummyluv kept pestering me about support for it)
1135 // TODO: support shaders here?
1136 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)))
1138 // expand the arrays to make room
1139 tempskinscenes = loadmodel->skinscenes;
1140 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1141 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1142 Mem_Free(tempskinscenes);
1144 tempaliasskins = loadmodel->data_textures;
1145 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1146 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1147 Mem_Free(tempaliasskins);
1149 // store the info about the new skin
1150 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1151 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1152 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1153 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1154 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1155 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1157 //increase skin counts
1158 loadmodel->numskins++;
1161 // fix up the pointers since they are pointing at the old textures array
1162 // FIXME: this is a hack!
1163 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1164 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1168 surface = loadmodel->data_surfaces;
1169 surface->texture = loadmodel->data_textures;
1170 surface->num_firsttriangle = 0;
1171 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1172 surface->num_firstvertex = 0;
1173 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1175 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1178 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1180 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1181 float iskinwidth, iskinheight;
1182 unsigned char *data;
1183 msurface_t *surface;
1185 unsigned char *base, *datapointer;
1186 md2frame_t *pinframe;
1188 md2triangle_t *intri;
1189 unsigned short *inst;
1190 struct md2verthash_s
1192 struct md2verthash_s *next;
1196 *hash, **md2verthash, *md2verthashdata;
1197 skinfile_t *skinfiles;
1199 pinmodel = (md2_t *)buffer;
1200 base = (unsigned char *)buffer;
1202 version = LittleLong (pinmodel->version);
1203 if (version != MD2ALIAS_VERSION)
1204 Host_Error ("%s has wrong version number (%i should be %i)",
1205 loadmodel->name, version, MD2ALIAS_VERSION);
1207 loadmodel->modeldatatypestring = "MD2";
1209 loadmodel->type = mod_alias;
1210 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1211 loadmodel->DrawSky = NULL;
1212 loadmodel->DrawAddWaterPlanes = NULL;
1213 loadmodel->Draw = R_Q1BSP_Draw;
1214 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1215 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1216 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1217 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1218 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1219 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1220 loadmodel->PointSuperContents = NULL;
1222 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1223 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1224 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1225 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1226 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1227 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1228 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1229 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1231 end = LittleLong(pinmodel->ofs_end);
1232 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1233 Host_Error ("%s is not a valid model", loadmodel->name);
1234 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1235 Host_Error ("%s is not a valid model", loadmodel->name);
1236 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1237 Host_Error ("%s is not a valid model", loadmodel->name);
1238 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1239 Host_Error ("%s is not a valid model", loadmodel->name);
1240 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1241 Host_Error ("%s is not a valid model", loadmodel->name);
1243 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1244 numxyz = LittleLong(pinmodel->num_xyz);
1245 numst = LittleLong(pinmodel->num_st);
1246 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1247 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1248 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1249 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1250 skinwidth = LittleLong(pinmodel->skinwidth);
1251 skinheight = LittleLong(pinmodel->skinheight);
1252 iskinwidth = 1.0f / skinwidth;
1253 iskinheight = 1.0f / skinheight;
1255 loadmodel->num_surfaces = 1;
1256 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1257 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]));
1258 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1259 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1260 loadmodel->sortedmodelsurfaces[0] = 0;
1261 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1262 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1263 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1264 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1266 loadmodel->synctype = ST_RAND;
1269 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1270 skinfiles = Mod_LoadSkinFiles();
1273 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1274 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1275 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1276 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1277 Mod_FreeSkinFiles(skinfiles);
1279 else if (loadmodel->numskins)
1281 // skins found (most likely not a player model)
1282 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1283 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1284 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1285 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1286 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);
1290 // no skins (most likely a player model)
1291 loadmodel->numskins = 1;
1292 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1293 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1294 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1295 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1298 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1299 for (i = 0;i < loadmodel->numskins;i++)
1301 loadmodel->skinscenes[i].firstframe = i;
1302 loadmodel->skinscenes[i].framecount = 1;
1303 loadmodel->skinscenes[i].loop = true;
1304 loadmodel->skinscenes[i].framerate = 10;
1307 // load the triangles and stvert data
1308 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1309 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1310 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1311 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1312 // swap the triangle list
1313 loadmodel->surfmesh.num_vertices = 0;
1314 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1316 for (j = 0;j < 3;j++)
1318 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1319 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1322 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1327 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1330 hashindex = (xyz * 256 + st) & 65535;
1331 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1332 if (hash->xyz == xyz && hash->st == st)
1336 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1339 hash->next = md2verthash[hashindex];
1340 md2verthash[hashindex] = hash;
1342 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1346 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1347 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));
1348 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1349 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1350 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1353 hash = md2verthashdata + i;
1354 vertremap[i] = hash->xyz;
1355 sts = LittleShort(inst[hash->st*2+0]);
1356 stt = LittleShort(inst[hash->st*2+1]);
1357 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1359 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1363 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1364 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1367 Mem_Free(md2verthash);
1368 Mem_Free(md2verthashdata);
1370 // generate ushort elements array if possible
1371 if (loadmodel->surfmesh.num_vertices <= 65536)
1373 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1374 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1375 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1379 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1380 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1385 pinframe = (md2frame_t *)datapointer;
1386 datapointer += sizeof(md2frame_t);
1387 // store the frame scale/translate into the appropriate array
1388 for (j = 0;j < 3;j++)
1390 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1391 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1393 // convert the vertices
1394 v = (trivertx_t *)datapointer;
1395 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1396 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1397 out[k] = v[vertremap[k]];
1398 datapointer += numxyz * sizeof(trivertx_t);
1400 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1401 loadmodel->animscenes[i].firstframe = i;
1402 loadmodel->animscenes[i].framecount = 1;
1403 loadmodel->animscenes[i].framerate = 10;
1404 loadmodel->animscenes[i].loop = true;
1407 Mem_Free(vertremap);
1409 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1410 Mod_Alias_CalculateBoundingBox();
1411 Mod_Alias_MorphMesh_CompileFrames();
1413 surface = loadmodel->data_surfaces;
1414 surface->texture = loadmodel->data_textures;
1415 surface->num_firsttriangle = 0;
1416 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1417 surface->num_firstvertex = 0;
1418 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1420 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1423 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1425 int i, j, k, version, meshvertices, meshtriangles;
1426 unsigned char *data;
1427 msurface_t *surface;
1428 md3modelheader_t *pinmodel;
1429 md3frameinfo_t *pinframe;
1432 skinfile_t *skinfiles;
1434 pinmodel = (md3modelheader_t *)buffer;
1436 if (memcmp(pinmodel->identifier, "IDP3", 4))
1437 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1438 version = LittleLong (pinmodel->version);
1439 if (version != MD3VERSION)
1440 Host_Error ("%s has wrong version number (%i should be %i)",
1441 loadmodel->name, version, MD3VERSION);
1443 skinfiles = Mod_LoadSkinFiles();
1444 if (loadmodel->numskins < 1)
1445 loadmodel->numskins = 1;
1447 loadmodel->modeldatatypestring = "MD3";
1449 loadmodel->type = mod_alias;
1450 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1451 loadmodel->DrawSky = NULL;
1452 loadmodel->DrawAddWaterPlanes = NULL;
1453 loadmodel->Draw = R_Q1BSP_Draw;
1454 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1455 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1456 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1457 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1458 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1459 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1460 loadmodel->PointSuperContents = NULL;
1461 loadmodel->synctype = ST_RAND;
1462 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1463 i = LittleLong (pinmodel->flags);
1464 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1466 // set up some global info about the model
1467 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1468 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1470 // make skinscenes for the skins (no groups)
1471 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1472 for (i = 0;i < loadmodel->numskins;i++)
1474 loadmodel->skinscenes[i].firstframe = i;
1475 loadmodel->skinscenes[i].framecount = 1;
1476 loadmodel->skinscenes[i].loop = true;
1477 loadmodel->skinscenes[i].framerate = 10;
1481 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1482 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1484 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1485 loadmodel->animscenes[i].firstframe = i;
1486 loadmodel->animscenes[i].framecount = 1;
1487 loadmodel->animscenes[i].framerate = 10;
1488 loadmodel->animscenes[i].loop = true;
1492 loadmodel->num_tagframes = loadmodel->numframes;
1493 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1494 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1495 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1497 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1498 for (j = 0;j < 9;j++)
1499 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1500 for (j = 0;j < 3;j++)
1501 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1502 //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);
1508 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)))
1510 if (memcmp(pinmesh->identifier, "IDP3", 4))
1511 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1512 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1513 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1514 meshvertices += LittleLong(pinmesh->num_vertices);
1515 meshtriangles += LittleLong(pinmesh->num_triangles);
1518 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1519 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1520 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1521 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));
1522 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1523 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1524 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1525 loadmodel->surfmesh.num_vertices = meshvertices;
1526 loadmodel->surfmesh.num_triangles = meshtriangles;
1527 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1528 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1529 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1530 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1531 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1532 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1533 if (meshvertices <= 65536)
1535 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1536 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1537 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1542 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)))
1544 if (memcmp(pinmesh->identifier, "IDP3", 4))
1545 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1546 loadmodel->sortedmodelsurfaces[i] = i;
1547 surface = loadmodel->data_surfaces + i;
1548 surface->texture = loadmodel->data_textures + i;
1549 surface->num_firsttriangle = meshtriangles;
1550 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1551 surface->num_firstvertex = meshvertices;
1552 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1553 meshvertices += surface->num_vertices;
1554 meshtriangles += surface->num_triangles;
1556 for (j = 0;j < surface->num_triangles * 3;j++)
1557 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1558 for (j = 0;j < surface->num_vertices;j++)
1560 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1561 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1563 for (j = 0;j < loadmodel->numframes;j++)
1565 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1566 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1567 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1569 out->origin[0] = LittleShort(in->origin[0]);
1570 out->origin[1] = LittleShort(in->origin[1]);
1571 out->origin[2] = LittleShort(in->origin[2]);
1572 out->pitch = in->pitch;
1577 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1579 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1581 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1582 Mod_Alias_MorphMesh_CompileFrames();
1583 Mod_Alias_CalculateBoundingBox();
1584 Mod_FreeSkinFiles(skinfiles);
1585 Mod_MakeSortedSurfaces(loadmodel);
1587 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1588 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1591 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1593 zymtype1header_t *pinmodel, *pheader;
1594 unsigned char *pbase;
1595 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1596 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose;
1597 zymvertex_t *verts, *vertdata;
1601 skinfile_t *skinfiles;
1602 unsigned char *data;
1603 msurface_t *surface;
1605 pinmodel = (zymtype1header_t *)buffer;
1606 pbase = (unsigned char *)buffer;
1607 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1608 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1609 if (BigLong(pinmodel->type) != 1)
1610 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1612 loadmodel->modeldatatypestring = "ZYM";
1614 loadmodel->type = mod_alias;
1615 loadmodel->synctype = ST_RAND;
1619 pheader->type = BigLong(pinmodel->type);
1620 pheader->filesize = BigLong(pinmodel->filesize);
1621 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1622 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1623 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1624 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1625 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1626 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1627 pheader->radius = BigFloat(pinmodel->radius);
1628 pheader->numverts = BigLong(pinmodel->numverts);
1629 pheader->numtris = BigLong(pinmodel->numtris);
1630 pheader->numshaders = BigLong(pinmodel->numshaders);
1631 pheader->numbones = BigLong(pinmodel->numbones);
1632 pheader->numscenes = BigLong(pinmodel->numscenes);
1633 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1634 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1635 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1636 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1637 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1638 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1639 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1640 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1641 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1642 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1643 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1644 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1645 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1646 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1647 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1648 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1649 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1650 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1652 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1654 Con_Printf("%s has no geometry\n", loadmodel->name);
1657 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1659 Con_Printf("%s has no animations\n", loadmodel->name);
1663 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1664 loadmodel->DrawSky = NULL;
1665 loadmodel->DrawAddWaterPlanes = NULL;
1666 loadmodel->Draw = R_Q1BSP_Draw;
1667 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1668 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1669 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1670 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1671 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1672 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1673 loadmodel->PointSuperContents = NULL;
1675 loadmodel->numframes = pheader->numscenes;
1676 loadmodel->num_surfaces = pheader->numshaders;
1678 skinfiles = Mod_LoadSkinFiles();
1679 if (loadmodel->numskins < 1)
1680 loadmodel->numskins = 1;
1682 // make skinscenes for the skins (no groups)
1683 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1684 for (i = 0;i < loadmodel->numskins;i++)
1686 loadmodel->skinscenes[i].firstframe = i;
1687 loadmodel->skinscenes[i].framecount = 1;
1688 loadmodel->skinscenes[i].loop = true;
1689 loadmodel->skinscenes[i].framerate = 10;
1693 modelradius = pheader->radius;
1694 for (i = 0;i < 3;i++)
1696 loadmodel->normalmins[i] = pheader->mins[i];
1697 loadmodel->normalmaxs[i] = pheader->maxs[i];
1698 loadmodel->rotatedmins[i] = -modelradius;
1699 loadmodel->rotatedmaxs[i] = modelradius;
1701 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1702 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1703 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1704 if (loadmodel->yawmaxs[0] > modelradius)
1705 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1706 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1707 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1708 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1709 loadmodel->radius = modelradius;
1710 loadmodel->radius2 = modelradius * modelradius;
1712 // go through the lumps, swapping things
1714 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1715 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1716 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1717 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1718 for (i = 0;i < pheader->numscenes;i++)
1720 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1721 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1722 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1723 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1724 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1725 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1726 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1727 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1728 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1729 if (loadmodel->animscenes[i].framerate < 0)
1730 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1734 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1735 loadmodel->num_bones = pheader->numbones;
1736 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1737 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1738 for (i = 0;i < pheader->numbones;i++)
1740 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1741 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1742 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1743 if (loadmodel->data_bones[i].parent >= i)
1744 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1747 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1748 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1749 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1750 for (i = 0;i < pheader->numverts;i++)
1752 vertbonecounts[i] = BigLong(bonecount[i]);
1753 if (vertbonecounts[i] != 1)
1754 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1757 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1759 meshvertices = pheader->numverts;
1760 meshtriangles = pheader->numtris;
1762 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1763 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1764 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1765 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 * loadmodel->num_bones * sizeof(float[12]) + loadmodel->num_bones * sizeof(float[12]));
1766 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1767 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1768 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1769 loadmodel->surfmesh.num_vertices = meshvertices;
1770 loadmodel->surfmesh.num_triangles = meshtriangles;
1771 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1772 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1773 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1774 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1775 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1776 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1777 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1778 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1779 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1780 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
1781 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1782 if (loadmodel->surfmesh.num_vertices <= 65536)
1784 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1785 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1786 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1789 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1790 poses = (float *) (pheader->lump_poses.start + pbase);
1791 for (i = 0;i < pheader->lump_poses.length / 4;i++)
1792 loadmodel->data_poses[i] = BigFloat(poses[i]);
1794 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1795 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1796 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1797 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1798 // (converting from weight-blending skeletal animation to
1799 // deformation-based skeletal animation)
1800 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1801 for (i = 0;i < loadmodel->num_bones;i++)
1803 const float *m = loadmodel->data_poses + i * 12;
1804 if (loadmodel->data_bones[i].parent >= 0)
1805 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1807 for (k = 0;k < 12;k++)
1808 bonepose[12*i+k] = m[k];
1810 for (j = 0;j < pheader->numverts;j++)
1812 // this format really should have had a per vertexweight weight value...
1813 // but since it does not, the weighting is completely ignored and
1814 // only one weight is allowed per vertex
1815 int boneindex = BigLong(vertdata[j].bonenum);
1816 const float *m = bonepose + 12 * boneindex;
1817 float relativeorigin[3];
1818 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1819 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1820 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1821 // transform the vertex bone weight into the base mesh
1822 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1823 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1824 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1825 // store the weight as the primary weight on this vertex
1826 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
1827 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = 1;
1830 // normals and tangents are calculated after elements are loaded
1832 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1833 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1834 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1835 for (i = 0;i < pheader->numverts;i++)
1837 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1838 // flip T coordinate for OpenGL
1839 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1842 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1843 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1844 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1846 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1847 //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)
1848 // byteswap, validate, and swap winding order of tris
1849 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1850 if (pheader->lump_render.length != count)
1851 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1852 renderlist = (int *) (pheader->lump_render.start + pbase);
1853 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1855 for (i = 0;i < loadmodel->num_surfaces;i++)
1857 int firstvertex, lastvertex;
1858 if (renderlist >= renderlistend)
1859 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1860 count = BigLong(*renderlist);renderlist++;
1861 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1862 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1864 loadmodel->sortedmodelsurfaces[i] = i;
1865 surface = loadmodel->data_surfaces + i;
1866 surface->texture = loadmodel->data_textures + i;
1867 surface->num_firsttriangle = meshtriangles;
1868 surface->num_triangles = count;
1869 meshtriangles += surface->num_triangles;
1871 // load the elements
1872 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
1873 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
1875 outelements[j*3+2] = BigLong(renderlist[0]);
1876 outelements[j*3+1] = BigLong(renderlist[1]);
1877 outelements[j*3+0] = BigLong(renderlist[2]);
1879 // validate the elements and find the used vertex range
1880 firstvertex = meshvertices;
1882 for (j = 0;j < surface->num_triangles * 3;j++)
1884 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
1885 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
1886 firstvertex = min(firstvertex, outelements[j]);
1887 lastvertex = max(lastvertex, outelements[j]);
1889 surface->num_firstvertex = firstvertex;
1890 surface->num_vertices = lastvertex + 1 - firstvertex;
1892 // since zym models do not have named sections, reuse their shader
1893 // name as the section name
1894 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
1895 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
1897 Mod_FreeSkinFiles(skinfiles);
1898 Mem_Free(vertbonecounts);
1900 Mod_MakeSortedSurfaces(loadmodel);
1902 // compute all the mesh information that was not loaded from the file
1903 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
1904 Mod_BuildBaseBonePoses();
1905 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
1906 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);
1907 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1909 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1912 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1914 dpmheader_t *pheader;
1918 unsigned char *pbase;
1919 int i, j, k, meshvertices, meshtriangles;
1920 skinfile_t *skinfiles;
1921 unsigned char *data;
1924 pheader = (dpmheader_t *)buffer;
1925 pbase = (unsigned char *)buffer;
1926 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
1927 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
1928 if (BigLong(pheader->type) != 2)
1929 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1931 loadmodel->modeldatatypestring = "DPM";
1933 loadmodel->type = mod_alias;
1934 loadmodel->synctype = ST_RAND;
1937 pheader->type = BigLong(pheader->type);
1938 pheader->filesize = BigLong(pheader->filesize);
1939 pheader->mins[0] = BigFloat(pheader->mins[0]);
1940 pheader->mins[1] = BigFloat(pheader->mins[1]);
1941 pheader->mins[2] = BigFloat(pheader->mins[2]);
1942 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
1943 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
1944 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
1945 pheader->yawradius = BigFloat(pheader->yawradius);
1946 pheader->allradius = BigFloat(pheader->allradius);
1947 pheader->num_bones = BigLong(pheader->num_bones);
1948 pheader->num_meshs = BigLong(pheader->num_meshs);
1949 pheader->num_frames = BigLong(pheader->num_frames);
1950 pheader->ofs_bones = BigLong(pheader->ofs_bones);
1951 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
1952 pheader->ofs_frames = BigLong(pheader->ofs_frames);
1954 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
1956 Con_Printf("%s has no geometry\n", loadmodel->name);
1959 if (pheader->num_frames < 1)
1961 Con_Printf("%s has no frames\n", loadmodel->name);
1965 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1966 loadmodel->DrawSky = NULL;
1967 loadmodel->DrawAddWaterPlanes = NULL;
1968 loadmodel->Draw = R_Q1BSP_Draw;
1969 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1970 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1971 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1972 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1973 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1974 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1975 loadmodel->PointSuperContents = NULL;
1978 for (i = 0;i < 3;i++)
1980 loadmodel->normalmins[i] = pheader->mins[i];
1981 loadmodel->normalmaxs[i] = pheader->maxs[i];
1982 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
1983 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
1984 loadmodel->rotatedmins[i] = -pheader->allradius;
1985 loadmodel->rotatedmaxs[i] = pheader->allradius;
1987 loadmodel->radius = pheader->allradius;
1988 loadmodel->radius2 = pheader->allradius * pheader->allradius;
1990 // load external .skin files if present
1991 skinfiles = Mod_LoadSkinFiles();
1992 if (loadmodel->numskins < 1)
1993 loadmodel->numskins = 1;
1998 // gather combined statistics from the meshes
1999 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2000 for (i = 0;i < (int)pheader->num_meshs;i++)
2002 int numverts = BigLong(dpmmesh->num_verts);
2003 meshvertices += numverts;
2004 meshtriangles += BigLong(dpmmesh->num_tris);
2008 loadmodel->numframes = pheader->num_frames;
2009 loadmodel->num_bones = pheader->num_bones;
2010 loadmodel->num_poses = loadmodel->numframes;
2011 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2012 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2013 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2014 // do most allocations as one merged chunk
2015 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 * loadmodel->num_bones * 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));
2016 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2017 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2018 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2019 loadmodel->surfmesh.num_vertices = meshvertices;
2020 loadmodel->surfmesh.num_triangles = meshtriangles;
2021 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2022 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2023 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2024 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2025 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2026 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2027 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2028 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
2029 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
2030 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
2031 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2032 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2033 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2034 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2035 if (meshvertices <= 65536)
2037 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2038 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2039 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2042 for (i = 0;i < loadmodel->numskins;i++)
2044 loadmodel->skinscenes[i].firstframe = i;
2045 loadmodel->skinscenes[i].framecount = 1;
2046 loadmodel->skinscenes[i].loop = true;
2047 loadmodel->skinscenes[i].framerate = 10;
2050 // load the bone info
2051 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2052 for (i = 0;i < loadmodel->num_bones;i++)
2054 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2055 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2056 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2057 if (loadmodel->data_bones[i].parent >= i)
2058 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2062 frame = (dpmframe_t *) (pbase + pheader->ofs_frames);
2063 for (i = 0;i < loadmodel->numframes;i++)
2066 memcpy(loadmodel->animscenes[i].name, frame->name, sizeof(frame->name));
2067 loadmodel->animscenes[i].firstframe = i;
2068 loadmodel->animscenes[i].framecount = 1;
2069 loadmodel->animscenes[i].loop = true;
2070 loadmodel->animscenes[i].framerate = 10;
2071 // load the bone poses for this frame
2072 poses = (float *) (pbase + BigLong(frame->ofs_bonepositions));
2073 for (j = 0;j < loadmodel->num_bones*12;j++)
2074 loadmodel->data_poses[i * loadmodel->num_bones*12 + j] = BigFloat(poses[j]);
2075 // stuff not processed here: mins, maxs, yawradius, allradius
2079 // load the meshes now
2080 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2083 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2084 // (converting from weight-blending skeletal animation to
2085 // deformation-based skeletal animation)
2086 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2087 for (i = 0;i < loadmodel->num_bones;i++)
2089 const float *m = loadmodel->data_poses + i * 12;
2090 if (loadmodel->data_bones[i].parent >= 0)
2091 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2093 for (k = 0;k < 12;k++)
2094 bonepose[12*i+k] = m[k];
2096 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2098 const int *inelements;
2100 const float *intexcoord;
2101 msurface_t *surface;
2103 loadmodel->sortedmodelsurfaces[i] = i;
2104 surface = loadmodel->data_surfaces + i;
2105 surface->texture = loadmodel->data_textures + i;
2106 surface->num_firsttriangle = meshtriangles;
2107 surface->num_triangles = BigLong(dpmmesh->num_tris);
2108 surface->num_firstvertex = meshvertices;
2109 surface->num_vertices = BigLong(dpmmesh->num_verts);
2110 meshvertices += surface->num_vertices;
2111 meshtriangles += surface->num_triangles;
2113 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2114 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2115 for (j = 0;j < surface->num_triangles;j++)
2117 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2118 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2119 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2120 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2125 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2126 for (j = 0;j < surface->num_vertices*2;j++)
2127 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2129 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2130 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2134 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2135 data += sizeof(dpmvertex_t);
2136 for (k = 0;k < numweights;k++)
2138 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2139 int boneindex = BigLong(vert->bonenum);
2140 const float *m = bonepose + 12 * boneindex;
2141 float influence = BigFloat(vert->influence);
2142 float relativeorigin[3], relativenormal[3];
2143 relativeorigin[0] = BigFloat(vert->origin[0]);
2144 relativeorigin[1] = BigFloat(vert->origin[1]);
2145 relativeorigin[2] = BigFloat(vert->origin[2]);
2146 relativenormal[0] = BigFloat(vert->normal[0]);
2147 relativenormal[1] = BigFloat(vert->normal[1]);
2148 relativenormal[2] = BigFloat(vert->normal[2]);
2149 // blend the vertex bone weights into the base mesh
2150 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2151 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2152 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2153 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2154 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2155 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2158 // store the first (and often only) weight
2159 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = influence;
2160 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
2164 // sort the new weight into this vertex's weight table
2165 // (which only accepts up to 4 bones per vertex)
2166 for (l = 0;l < 4;l++)
2168 if (loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] < influence)
2170 // move weaker influence weights out of the way first
2172 for (l2 = 3;l2 > l;l2--)
2174 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2-1];
2175 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2-1];
2177 // store the new weight
2178 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] = influence;
2179 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l] = boneindex;
2184 data += sizeof(dpmbonevert_t);
2187 for (l = 0;l < 4;l++)
2188 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l];
2189 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2191 float f = 1.0f / sum;
2192 for (l = 0;l < 4;l++)
2193 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] *= f;
2197 // since dpm models do not have named sections, reuse their shader name as the section name
2198 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2200 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2203 Mod_FreeSkinFiles(skinfiles);
2204 Mod_MakeSortedSurfaces(loadmodel);
2206 // compute all the mesh information that was not loaded from the file
2207 Mod_BuildBaseBonePoses();
2208 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);
2209 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2211 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2214 // no idea why PSK/PSA files contain weird quaternions but they do...
2215 #define PSKQUATNEGATIONS
2216 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2218 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2219 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2220 fs_offset_t filesize;
2225 pskboneinfo_t *bones;
2226 pskrawweights_t *rawweights;
2227 pskboneinfo_t *animbones;
2228 pskaniminfo_t *anims;
2229 pskanimkeys_t *animkeys;
2230 void *animfilebuffer, *animbuffer, *animbufferend;
2231 unsigned char *data;
2233 skinfile_t *skinfiles;
2234 char animname[MAX_QPATH];
2237 pchunk = (pskchunk_t *)buffer;
2238 if (strcmp(pchunk->id, "ACTRHEAD"))
2239 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2241 loadmodel->modeldatatypestring = "PSK";
2243 loadmodel->type = mod_alias;
2244 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2245 loadmodel->DrawSky = NULL;
2246 loadmodel->DrawAddWaterPlanes = NULL;
2247 loadmodel->Draw = R_Q1BSP_Draw;
2248 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2249 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2250 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2251 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2252 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2253 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2254 loadmodel->PointSuperContents = NULL;
2255 loadmodel->synctype = ST_RAND;
2257 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2258 strlcat(animname, ".psa", sizeof(animname));
2259 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2260 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2261 if (animbuffer == NULL)
2262 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2281 while (buffer < bufferend)
2283 pchunk = (pskchunk_t *)buffer;
2284 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2285 version = LittleLong(pchunk->version);
2286 recordsize = LittleLong(pchunk->recordsize);
2287 numrecords = LittleLong(pchunk->numrecords);
2288 if (developer.integer >= 100)
2289 Con_Printf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2290 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2291 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);
2292 if (!strcmp(pchunk->id, "ACTRHEAD"))
2296 else if (!strcmp(pchunk->id, "PNTS0000"))
2299 if (recordsize != sizeof(*p))
2300 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2301 // byteswap in place and keep the pointer
2302 numpnts = numrecords;
2303 pnts = (pskpnts_t *)buffer;
2304 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2306 p->origin[0] = LittleFloat(p->origin[0]);
2307 p->origin[1] = LittleFloat(p->origin[1]);
2308 p->origin[2] = LittleFloat(p->origin[2]);
2312 else if (!strcmp(pchunk->id, "VTXW0000"))
2315 if (recordsize != sizeof(*p))
2316 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2317 // byteswap in place and keep the pointer
2318 numvtxw = numrecords;
2319 vtxw = (pskvtxw_t *)buffer;
2320 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2322 p->pntsindex = LittleShort(p->pntsindex);
2323 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2324 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2325 if (p->pntsindex >= numpnts)
2327 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2333 else if (!strcmp(pchunk->id, "FACE0000"))
2336 if (recordsize != sizeof(*p))
2337 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2338 // byteswap in place and keep the pointer
2339 numfaces = numrecords;
2340 faces = (pskface_t *)buffer;
2341 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2343 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2344 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2345 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2346 p->group = LittleLong(p->group);
2347 if (p->vtxwindex[0] >= numvtxw)
2349 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2350 p->vtxwindex[0] = 0;
2352 if (p->vtxwindex[1] >= numvtxw)
2354 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2355 p->vtxwindex[1] = 0;
2357 if (p->vtxwindex[2] >= numvtxw)
2359 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2360 p->vtxwindex[2] = 0;
2365 else if (!strcmp(pchunk->id, "MATT0000"))
2368 if (recordsize != sizeof(*p))
2369 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2370 // byteswap in place and keep the pointer
2371 nummatts = numrecords;
2372 matts = (pskmatt_t *)buffer;
2373 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2379 else if (!strcmp(pchunk->id, "REFSKELT"))
2382 if (recordsize != sizeof(*p))
2383 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2384 // byteswap in place and keep the pointer
2385 numbones = numrecords;
2386 bones = (pskboneinfo_t *)buffer;
2387 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2389 p->numchildren = LittleLong(p->numchildren);
2390 p->parent = LittleLong(p->parent);
2391 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2392 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2393 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2394 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2395 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2396 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2397 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2398 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2399 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2400 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2401 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2402 #ifdef PSKQUATNEGATIONS
2405 p->basepose.quat[0] *= -1;
2406 p->basepose.quat[1] *= -1;
2407 p->basepose.quat[2] *= -1;
2411 p->basepose.quat[0] *= 1;
2412 p->basepose.quat[1] *= -1;
2413 p->basepose.quat[2] *= 1;
2416 if (p->parent < 0 || p->parent >= numbones)
2418 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2424 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2427 if (recordsize != sizeof(*p))
2428 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2429 // byteswap in place and keep the pointer
2430 numrawweights = numrecords;
2431 rawweights = (pskrawweights_t *)buffer;
2432 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2434 p->weight = LittleFloat(p->weight);
2435 p->pntsindex = LittleLong(p->pntsindex);
2436 p->boneindex = LittleLong(p->boneindex);
2437 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2439 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2442 if (p->boneindex < 0 || p->boneindex >= numbones)
2444 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2452 while (animbuffer < animbufferend)
2454 pchunk = (pskchunk_t *)animbuffer;
2455 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2456 version = LittleLong(pchunk->version);
2457 recordsize = LittleLong(pchunk->recordsize);
2458 numrecords = LittleLong(pchunk->numrecords);
2459 if (developer.integer >= 100)
2460 Con_Printf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2461 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2462 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);
2463 if (!strcmp(pchunk->id, "ANIMHEAD"))
2467 else if (!strcmp(pchunk->id, "BONENAMES"))
2470 if (recordsize != sizeof(*p))
2471 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2472 // byteswap in place and keep the pointer
2473 numanimbones = numrecords;
2474 animbones = (pskboneinfo_t *)animbuffer;
2475 // NOTE: supposedly psa does not need to match the psk model, the
2476 // bones missing from the psa would simply use their base
2477 // positions from the psk, but this is hard for me to implement
2478 // and people can easily make animations that match.
2479 if (numanimbones != numbones)
2480 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2481 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2483 p->numchildren = LittleLong(p->numchildren);
2484 p->parent = LittleLong(p->parent);
2485 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2486 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2487 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2488 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2489 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2490 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2491 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2492 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2493 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2494 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2495 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2496 #ifdef PSKQUATNEGATIONS
2499 p->basepose.quat[0] *= -1;
2500 p->basepose.quat[1] *= -1;
2501 p->basepose.quat[2] *= -1;
2505 p->basepose.quat[0] *= 1;
2506 p->basepose.quat[1] *= -1;
2507 p->basepose.quat[2] *= 1;
2510 if (p->parent < 0 || p->parent >= numanimbones)
2512 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2515 // check that bones are the same as in the base
2516 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2517 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2521 else if (!strcmp(pchunk->id, "ANIMINFO"))
2524 if (recordsize != sizeof(*p))
2525 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2526 // byteswap in place and keep the pointer
2527 numanims = numrecords;
2528 anims = (pskaniminfo_t *)animbuffer;
2529 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2531 p->numbones = LittleLong(p->numbones);
2532 p->playtime = LittleFloat(p->playtime);
2533 p->fps = LittleFloat(p->fps);
2534 p->firstframe = LittleLong(p->firstframe);
2535 p->numframes = LittleLong(p->numframes);
2536 if (p->numbones != numbones)
2537 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2541 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2544 if (recordsize != sizeof(*p))
2545 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2546 numanimkeys = numrecords;
2547 animkeys = (pskanimkeys_t *)animbuffer;
2548 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2550 p->origin[0] = LittleFloat(p->origin[0]);
2551 p->origin[1] = LittleFloat(p->origin[1]);
2552 p->origin[2] = LittleFloat(p->origin[2]);
2553 p->quat[0] = LittleFloat(p->quat[0]);
2554 p->quat[1] = LittleFloat(p->quat[1]);
2555 p->quat[2] = LittleFloat(p->quat[2]);
2556 p->quat[3] = LittleFloat(p->quat[3]);
2557 p->frametime = LittleFloat(p->frametime);
2558 #ifdef PSKQUATNEGATIONS
2559 if (index % numbones)
2574 // TODO: allocate bonepose stuff
2577 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2580 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2581 Host_Error("%s: missing required chunks", loadmodel->name);
2583 loadmodel->numframes = 0;
2584 for (index = 0;index < numanims;index++)
2585 loadmodel->numframes += anims[index].numframes;
2587 if (numanimkeys != numbones * loadmodel->numframes)
2588 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2590 meshvertices = numvtxw;
2591 meshtriangles = numfaces;
2593 // load external .skin files if present
2594 skinfiles = Mod_LoadSkinFiles();
2595 if (loadmodel->numskins < 1)
2596 loadmodel->numskins = 1;
2597 loadmodel->num_bones = numbones;
2598 loadmodel->num_poses = loadmodel->numframes;
2599 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2600 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2601 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2602 loadmodel->surfmesh.num_vertices = meshvertices;
2603 loadmodel->surfmesh.num_triangles = meshtriangles;
2604 // do most allocations as one merged chunk
2605 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 * loadmodel->num_bones * 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);
2606 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2607 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2608 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2609 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2610 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2611 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2612 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2613 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2614 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2615 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2616 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2617 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += loadmodel->surfmesh.num_vertices * sizeof(int[4]);
2618 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[4]);
2619 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
2620 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2621 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2622 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2623 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2624 if (loadmodel->surfmesh.num_vertices <= 65536)
2626 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2627 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2628 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2631 for (i = 0;i < loadmodel->numskins;i++)
2633 loadmodel->skinscenes[i].firstframe = i;
2634 loadmodel->skinscenes[i].framecount = 1;
2635 loadmodel->skinscenes[i].loop = true;
2636 loadmodel->skinscenes[i].framerate = 10;
2640 for (index = 0, i = 0;index < nummatts;index++)
2642 // since psk models do not have named sections, reuse their shader name as the section name
2643 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2644 loadmodel->sortedmodelsurfaces[index] = index;
2645 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2646 loadmodel->data_surfaces[index].num_firstvertex = 0;
2647 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2650 // copy over the vertex locations and texcoords
2651 for (index = 0;index < numvtxw;index++)
2653 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2654 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2655 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2656 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2657 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2660 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2661 for (index = 0;index < numfaces;index++)
2662 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2663 for (index = 0, i = 0;index < nummatts;index++)
2665 loadmodel->data_surfaces[index].num_firsttriangle = i;
2666 i += loadmodel->data_surfaces[index].num_triangles;
2667 loadmodel->data_surfaces[index].num_triangles = 0;
2669 for (index = 0;index < numfaces;index++)
2671 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2672 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2673 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2674 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2677 // copy over the bones
2678 for (index = 0;index < numbones;index++)
2680 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2681 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2682 if (loadmodel->data_bones[index].parent >= index)
2683 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2686 // sort the psk point weights into the vertex weight tables
2687 // (which only accept up to 4 bones per vertex)
2688 for (index = 0;index < numvtxw;index++)
2692 for (j = 0;j < numrawweights;j++)
2694 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2696 int boneindex = rawweights[j].boneindex;
2697 float influence = rawweights[j].weight;
2698 for (l = 0;l < 4;l++)
2700 if (loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] < influence)
2702 // move lower influence weights out of the way first
2704 for (l2 = 3;l2 > l;l2--)
2706 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2-1];
2707 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2-1];
2709 // store the new weight
2710 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] = influence;
2711 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l] = boneindex;
2718 for (l = 0;l < 4;l++)
2719 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l];
2720 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2722 float f = 1.0f / sum;
2723 for (l = 0;l < 4;l++)
2724 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] *= f;
2728 // set up the animscenes based on the anims
2729 for (index = 0, i = 0;index < numanims;index++)
2731 for (j = 0;j < anims[index].numframes;j++, i++)
2733 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2734 loadmodel->animscenes[i].firstframe = i;
2735 loadmodel->animscenes[i].framecount = 1;
2736 loadmodel->animscenes[i].loop = true;
2737 loadmodel->animscenes[i].framerate = 10;
2741 // load the poses from the animkeys
2742 for (index = 0;index < numanimkeys;index++)
2744 pskanimkeys_t *k = animkeys + index;
2746 Matrix4x4_FromOriginQuat(&matrix, k->origin[0], k->origin[1], k->origin[2], k->quat[0], k->quat[1], k->quat[2], k->quat[3]);
2747 Matrix4x4_ToArray12FloatD3D(&matrix, loadmodel->data_poses + index*12);
2749 Mod_FreeSkinFiles(skinfiles);
2750 Mem_Free(animfilebuffer);
2751 Mod_MakeSortedSurfaces(loadmodel);
2753 // compute all the mesh information that was not loaded from the file
2754 // TODO: honor smoothing groups somehow?
2755 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2756 Mod_BuildBaseBonePoses();
2757 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2758 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);
2759 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2760 Mod_Alias_CalculateBoundingBox();
2762 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2765 void Mod_OBJ_Load(dp_model_t *mod, void *buffer, void *bufferend)
2768 const char *textbase = (char *)buffer, *text = textbase;
2772 char materialname[MAX_QPATH];
2773 int j, index1, index2, index3, first, prev, index;
2776 int numtriangles = 0;
2777 int maxtriangles = 32768;
2778 int *element3i = Mem_Alloc(tempmempool, maxtriangles * sizeof(int[3]));
2780 int numsurfaces = 0;
2781 int maxsurfaces = 0;
2782 msurface_t *surfaces = NULL;
2786 float *oldv, *oldvt, *oldvn;
2787 int maxv = 65536, numv = 1;
2788 int maxvt = 65536, numvt = 1;
2789 int maxvn = 65536, numvn = 1;
2790 int maxverthash = 65536, numverthash = 0;
2791 int numhashindex = 65536;
2792 struct objverthash_s
2794 struct objverthash_s *next;
2800 *hash, **verthash = Mem_Alloc(tempmempool, numhashindex * sizeof(*verthash)), *verthashdata = Mem_Alloc(tempmempool, maxverthash * sizeof(*verthashdata)), *oldverthashdata;
2801 skinfile_t *skinfiles;
2803 dpsnprintf(materialname, sizeof(materialname), "%s", loadmodel->name);
2805 skinfiles = Mod_LoadSkinFiles();
2807 loadmodel->modeldatatypestring = "OBJ";
2809 loadmodel->type = mod_alias;
2810 loadmodel->AnimateVertices = NULL;
2811 loadmodel->DrawSky = NULL;
2812 loadmodel->DrawAddWaterPlanes = NULL;
2813 loadmodel->Draw = R_Q1BSP_Draw;
2814 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2815 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2816 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2817 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2818 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2819 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2820 loadmodel->PointSuperContents = NULL;
2822 // parse the OBJ text now
2829 for (linelen = 0;text[linelen] && text[linelen] != '\r' && text[linelen] != '\n';linelen++)
2830 line[linelen] = text[linelen];
2832 for (argc = 0;argc < (int)(sizeof(argv)/sizeof(argv[0]));argc++)
2836 while (*s == ' ' || *s == '\t')
2846 while (*s == ' ' || *s == '\t')
2851 if (argv[0][0] == '#')
2853 if (!strcmp(argv[0], "v"))
2859 v = Mem_Alloc(tempmempool, maxv * sizeof(float[3]));
2862 memcpy(v, oldv, numv * sizeof(float[3]));
2866 v[numv*3+0] = atof(argv[1]);
2867 v[numv*3+1] = atof(argv[2]);
2868 v[numv*3+2] = atof(argv[3]);
2871 else if (!strcmp(argv[0], "vt"))
2877 vt = Mem_Alloc(tempmempool, maxvt * sizeof(float[2]));
2880 memcpy(vt, oldvt, numvt * sizeof(float[2]));
2884 vt[numvt*2+0] = atof(argv[1]);
2885 vt[numvt*2+1] = atof(argv[2]);
2888 else if (!strcmp(argv[0], "vn"))
2894 vn = Mem_Alloc(tempmempool, maxvn * sizeof(float[3]));
2897 memcpy(vn, oldvn, numvn * sizeof(float[3]));
2901 vn[numvn*3+0] = atof(argv[1]);
2902 vn[numvn*3+1] = atof(argv[2]);
2903 vn[numvn*3+2] = atof(argv[3]);
2906 else if (!strcmp(argv[0], "f"))
2910 if (maxsurfaces <= numsurfaces)
2913 oldsurfaces = surfaces;
2914 surfaces = Mem_Alloc(tempmempool, maxsurfaces * sizeof(*surfaces));
2917 memcpy(surfaces, oldsurfaces, numsurfaces * sizeof(*surfaces));
2918 Mem_Free(oldsurfaces);
2921 surface = surfaces + numsurfaces++;
2924 for (j = 1;j < argc;j++)
2926 index1 = atoi(argv[j]);
2927 while(argv[j][0] && argv[j][0] != '/')
2932 index1 = numv + 1 - index1;
2933 index2 = atoi(argv[j]);
2935 index2 = numvt + 1 - index2;
2936 while(argv[j][0] && argv[j][0] != '/')
2940 index3 = atoi(argv[j]);
2942 index3 = numvn + 1 - index3;
2943 hashindex = (index1 + index2 * 3571 + index3 * 42589) & (numhashindex - 1);
2944 for (hash = verthash[hashindex];hash;hash = hash->next)
2945 if (hash->surface == numsurfaces-1 && hash->v == index1 && hash->vt == index2 && hash->vn == index3)
2949 if (maxverthash <= numverthash)
2952 oldverthashdata = verthashdata;
2953 verthashdata = Mem_Alloc(tempmempool, maxverthash * sizeof(*verthashdata));
2954 if (oldverthashdata)
2956 memcpy(verthashdata, oldverthashdata, numverthash * sizeof(*verthashdata));
2957 Mem_Free(oldverthashdata);
2960 hash = verthashdata + numverthash++;
2961 hash->next = verthash[hashindex];
2962 hash->s = numsurfaces;
2966 verthash[hashindex] = hash;
2968 index = (int)((size_t)(hash - verthashdata));
2973 if (maxtriangles <= numtriangles)
2976 oldelement3i = element3i;
2977 element3i = Mem_Alloc(tempmempool, numtriangles * sizeof(int[3]));
2980 memcpy(element3i, oldelement3i, numtriangles * sizeof(int[3]));
2981 Mem_Free(oldelement3i);
2984 element3i[numtriangles*3+0] = first;
2985 element3i[numtriangles*3+1] = prev;
2986 element3i[numtriangles*3+2] = index;
2992 else if (!strcmp(argv[0], "o") || !strcmp(argv[0], "g"))
2994 else if (!!strcmp(argv[0], "usemtl"))
2997 strlcpy(materialname, argv[1], sizeof(materialname);
3007 Mod_FreeSkinFiles(skinfiles);
3009 // now that we have the OBJ data loaded as-is, we can convert it
3010 loadmodel->numskins = LittleLong(pinmodel->num_skins);
3011 numxyz = LittleLong(pinmodel->num_xyz);
3012 numst = LittleLong(pinmodel->num_st);
3013 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
3014 loadmodel->numframes = LittleLong(pinmodel->num_frames);
3015 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
3016 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
3017 skinwidth = LittleLong(pinmodel->skinwidth);
3018 skinheight = LittleLong(pinmodel->skinheight);
3019 iskinwidth = 1.0f / skinwidth;
3020 iskinheight = 1.0f / skinheight;
3022 loadmodel->num_surfaces = 1;
3023 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
3024 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]));
3025 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
3026 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
3027 loadmodel->sortedmodelsurfaces[0] = 0;
3028 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
3029 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
3030 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
3031 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
3033 loadmodel->synctype = ST_RAND;
3036 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
3037 skinfiles = Mod_LoadSkinFiles();
3040 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3041 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3042 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
3043 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
3044 Mod_FreeSkinFiles(skinfiles);
3046 else if (loadmodel->numskins)
3048 // skins found (most likely not a player model)
3049 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3050 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3051 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
3052 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
3053 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);
3057 // no skins (most likely a player model)
3058 loadmodel->numskins = 1;
3059 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3060 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3061 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
3062 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
3065 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
3066 for (i = 0;i < loadmodel->numskins;i++)
3068 loadmodel->skinscenes[i].firstframe = i;
3069 loadmodel->skinscenes[i].framecount = 1;
3070 loadmodel->skinscenes[i].loop = true;
3071 loadmodel->skinscenes[i].framerate = 10;
3074 // load the triangles and stvert data
3075 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
3076 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
3077 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
3078 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
3079 // swap the triangle list
3080 loadmodel->surfmesh.num_vertices = 0;
3081 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
3083 for (j = 0;j < 3;j++)
3085 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
3086 st = (unsigned short) LittleShort (intri[i].index_st[j]);
3089 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
3094 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
3097 hashindex = (xyz * 256 + st) & 65535;
3098 for (hash = md2verthash[hashindex];hash;hash = hash->next)
3099 if (hash->xyz == xyz && hash->st == st)
3103 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
3106 hash->next = md2verthash[hashindex];
3107 md2verthash[hashindex] = hash;
3109 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
3113 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
3114 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));
3115 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
3116 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
3117 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
3120 hash = md2verthashdata + i;
3121 vertremap[i] = hash->xyz;
3122 sts = LittleShort(inst[hash->st*2+0]);
3123 stt = LittleShort(inst[hash->st*2+1]);
3124 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
3126 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
3130 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
3131 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
3134 Mem_Free(md2verthash);
3135 Mem_Free(md2verthashdata);
3137 // generate ushort elements array if possible
3138 if (loadmodel->surfmesh.num_vertices <= 65536)
3140 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
3141 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3142 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3146 datapointer = (base + LittleLong(pinmodel->ofs_frames));
3147 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
3152 pinframe = (md2frame_t *)datapointer;
3153 datapointer += sizeof(md2frame_t);
3154 // store the frame scale/translate into the appropriate array
3155 for (j = 0;j < 3;j++)
3157 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
3158 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
3160 // convert the vertices
3161 v = (trivertx_t *)datapointer;
3162 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
3163 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
3164 out[k] = v[vertremap[k]];
3165 datapointer += numxyz * sizeof(trivertx_t);
3167 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
3168 loadmodel->animscenes[i].firstframe = i;
3169 loadmodel->animscenes[i].framecount = 1;
3170 loadmodel->animscenes[i].framerate = 10;
3171 loadmodel->animscenes[i].loop = true;
3174 Mem_Free(vertremap);
3176 Mod_MakeSortedSurfaces(loadmodel);
3177 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3178 Mod_Alias_CalculateBoundingBox();
3179 Mod_Alias_MorphMesh_CompileFrames();
3181 surface = loadmodel->data_surfaces;
3182 surface->texture = loadmodel->data_textures;
3183 surface->num_firsttriangle = 0;
3184 surface->num_triangles = loadmodel->surfmesh.num_triangles;
3185 surface->num_firstvertex = 0;
3186 surface->num_vertices = loadmodel->surfmesh.num_vertices;
3188 loadmodel->surfmesh.isanimated = false;