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)
509 float *in12f = loadmodel->data_poses;
511 float *outinv12f = loadmodel->data_baseboneposeinverse;
512 if (!loadmodel->num_bones)
514 out12f = basebonepose = (float *) Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(float[12]));
515 for (i = 0;i < loadmodel->num_bones;i++, in12f += 12, out12f += 12, outinv12f += 12)
517 if (loadmodel->data_bones[i].parent >= 0)
518 R_ConcatTransforms(basebonepose + 12 * loadmodel->data_bones[i].parent, in12f, out12f);
520 for (k = 0;k < 12;k++)
521 out12f[k] = in12f[k];
525 // we only support uniform scaling, so assume the first row is enough
526 // (note the lack of sqrt here, because we're trying to undo the scaling,
527 // this means multiplying by the inverse scale twice - squaring it, which
528 // makes the sqrt a waste of time)
529 scale = 1.0 / (out12f[ 0] * out12f[ 0] + out12f[ 1] * out12f[ 1] + out12f[ 2] * out12f[ 2]);
531 // invert the rotation by transposing and multiplying by the squared
532 // recipricol of the input matrix scale as described above
533 outinv12f[ 0] = (float)(out12f[ 0] * scale);
534 outinv12f[ 1] = (float)(out12f[ 4] * scale);
535 outinv12f[ 2] = (float)(out12f[ 8] * scale);
536 outinv12f[ 4] = (float)(out12f[ 1] * scale);
537 outinv12f[ 5] = (float)(out12f[ 5] * scale);
538 outinv12f[ 6] = (float)(out12f[ 9] * scale);
539 outinv12f[ 8] = (float)(out12f[ 2] * scale);
540 outinv12f[ 9] = (float)(out12f[ 6] * scale);
541 outinv12f[10] = (float)(out12f[10] * scale);
543 // invert the translate
544 outinv12f[ 3] = -(out12f[ 3] * outinv12f[ 0] + out12f[ 7] * outinv12f[ 1] + out12f[11] * outinv12f[ 2]);
545 outinv12f[ 7] = -(out12f[ 3] * outinv12f[ 4] + out12f[ 7] * outinv12f[ 5] + out12f[11] * outinv12f[ 6]);
546 outinv12f[11] = -(out12f[ 3] * outinv12f[ 8] + out12f[ 7] * outinv12f[ 9] + out12f[11] * outinv12f[10]);
548 Mem_Free(basebonepose);
551 static void Mod_Alias_CalculateBoundingBox(void)
554 qboolean firstvertex = true;
555 float dist, yawradius, radius;
558 frameblend_t frameblend[MAX_FRAMEBLENDS];
559 memset(frameblend, 0, sizeof(frameblend));
560 frameblend[0].lerp = 1;
561 vertex3f = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
562 VectorClear(loadmodel->normalmins);
563 VectorClear(loadmodel->normalmaxs);
566 for (frameblend[0].subframe = 0;frameblend[0].subframe < loadmodel->num_poses;frameblend[0].subframe++)
568 loadmodel->AnimateVertices(loadmodel, frameblend, vertex3f, NULL, NULL, NULL);
569 for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
574 VectorCopy(v, loadmodel->normalmins);
575 VectorCopy(v, loadmodel->normalmaxs);
579 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
580 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
581 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
582 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
583 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
584 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
586 dist = v[0] * v[0] + v[1] * v[1];
587 if (yawradius < dist)
596 radius = sqrt(radius);
597 yawradius = sqrt(yawradius);
598 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
599 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
600 loadmodel->yawmins[2] = loadmodel->normalmins[2];
601 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
602 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
603 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
604 loadmodel->radius = radius;
605 loadmodel->radius2 = radius * radius;
608 static void Mod_Alias_MorphMesh_CompileFrames(void)
611 frameblend_t frameblend[MAX_FRAMEBLENDS];
612 unsigned char *datapointer;
613 memset(frameblend, 0, sizeof(frameblend));
614 frameblend[0].lerp = 1;
615 datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
616 loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
617 loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
618 loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
619 loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
620 loadmodel->surfmesh.data_morphtexvecvertex = (texvecvertex_t *)datapointer;datapointer += loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices * sizeof(texvecvertex_t);
621 // 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)
622 for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
624 frameblend[0].subframe = i;
625 loadmodel->AnimateVertices(loadmodel, frameblend, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
626 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 != 0);
627 // encode the svector and tvector in 3 byte format for permanent storage
628 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
630 VectorScaleCast(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
631 VectorScaleCast(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
636 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)
639 vec3_t shiftstart, shiftend;
640 float segmentmins[3], segmentmaxs[3];
641 frameblend_t frameblend[MAX_FRAMEBLENDS];
643 static int maxvertices = 0;
644 static float *vertex3f = NULL;
645 memset(trace, 0, sizeof(*trace));
647 trace->realfraction = 1;
648 trace->hitsupercontentsmask = hitsupercontentsmask;
649 memset(frameblend, 0, sizeof(frameblend));
650 frameblend[0].subframe = frame;
651 frameblend[0].lerp = 1;
652 if (maxvertices < model->surfmesh.num_vertices)
656 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
657 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
659 if (VectorCompare(boxmins, boxmaxs))
662 VectorAdd(start, boxmins, shiftstart);
663 VectorAdd(end, boxmins, shiftend);
664 segmentmins[0] = min(shiftstart[0], shiftend[0]) - 1;
665 segmentmins[1] = min(shiftstart[1], shiftend[1]) - 1;
666 segmentmins[2] = min(shiftstart[2], shiftend[2]) - 1;
667 segmentmaxs[0] = max(shiftstart[0], shiftend[0]) + 1;
668 segmentmaxs[1] = max(shiftstart[1], shiftend[1]) + 1;
669 segmentmaxs[2] = max(shiftstart[2], shiftend[2]) + 1;
670 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
672 model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL);
673 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);
678 // box trace, performed as brush trace
679 colbrushf_t *thisbrush_start, *thisbrush_end;
680 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
681 segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
682 segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
683 segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
684 segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
685 segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
686 segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
687 VectorAdd(start, boxmins, boxstartmins);
688 VectorAdd(start, boxmaxs, boxstartmaxs);
689 VectorAdd(end, boxmins, boxendmins);
690 VectorAdd(end, boxmaxs, boxendmaxs);
691 thisbrush_start = Collision_BrushForBox(&identitymatrix, boxstartmins, boxstartmaxs, 0, 0, NULL);
692 thisbrush_end = Collision_BrushForBox(&identitymatrix, boxendmins, boxendmaxs, 0, 0, NULL);
693 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
695 if (maxvertices < model->surfmesh.num_vertices)
699 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
700 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
702 model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL);
703 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);
708 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
711 for (i = 0;i < inverts;i++)
713 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
715 j = vertremap[i]; // not onseam
718 j = vertremap[i+inverts]; // onseam
724 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
726 int i, f, pose, groupframes;
728 daliasframetype_t *pframetype;
729 daliasframe_t *pinframe;
730 daliasgroup_t *group;
731 daliasinterval_t *intervals;
734 scene = loadmodel->animscenes;
735 for (f = 0;f < loadmodel->numframes;f++)
737 pframetype = (daliasframetype_t *)datapointer;
738 datapointer += sizeof(daliasframetype_t);
739 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
741 // a single frame is still treated as a group
748 group = (daliasgroup_t *)datapointer;
749 datapointer += sizeof(daliasgroup_t);
750 groupframes = LittleLong (group->numframes);
752 // intervals (time per frame)
753 intervals = (daliasinterval_t *)datapointer;
754 datapointer += sizeof(daliasinterval_t) * groupframes;
756 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
757 if (interval < 0.01f)
759 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
764 // get scene name from first frame
765 pinframe = (daliasframe_t *)datapointer;
767 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
768 scene->firstframe = pose;
769 scene->framecount = groupframes;
770 scene->framerate = 1.0f / interval;
775 for (i = 0;i < groupframes;i++)
777 pinframe = (daliasframe_t *)datapointer;
778 datapointer += sizeof(daliasframe_t);
779 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
780 datapointer += sizeof(trivertx_t) * inverts;
786 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
788 if (cls.state == ca_dedicated)
792 skinframe = R_SkinFrame_LoadMissing();
793 memset(texture, 0, sizeof(*texture));
794 texture->currentframe = texture;
795 //texture->animated = false;
796 texture->numskinframes = 1;
797 texture->skinframerate = 1;
798 texture->skinframes[0] = skinframe;
799 texture->currentskinframe = skinframe;
800 //texture->backgroundnumskinframes = 0;
801 //texture->customblendfunc[0] = 0;
802 //texture->customblendfunc[1] = 0;
803 //texture->surfaceflags = 0;
804 //texture->supercontents = 0;
805 //texture->surfaceparms = 0;
806 //texture->textureflags = 0;
808 texture->basematerialflags = MATERIALFLAG_WALL;
809 if (texture->currentskinframe->fog)
810 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
811 texture->currentmaterialflags = texture->basematerialflags;
814 static void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
817 skinfileitem_t *skinfileitem;
820 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
821 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
823 memset(skin, 0, sizeof(*skin));
825 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
827 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
828 if (!strcmp(skinfileitem->name, meshname))
830 Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
836 // don't render unmentioned meshes
837 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
838 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
843 Mod_LoadTextureFromQ3Shader(skin, shadername, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
846 #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);
847 #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);
848 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
850 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
851 float scales, scalet, interval;
855 stvert_t *pinstverts;
856 dtriangle_t *pintriangles;
857 daliasskintype_t *pinskintype;
858 daliasskingroup_t *pinskingroup;
859 daliasskininterval_t *pinskinintervals;
860 daliasframetype_t *pinframetype;
861 daliasgroup_t *pinframegroup;
862 unsigned char *datapointer, *startframes, *startskins;
863 char name[MAX_QPATH];
864 skinframe_t *tempskinframe;
865 animscene_t *tempskinscenes;
866 texture_t *tempaliasskins;
868 int *vertonseam, *vertremap;
869 skinfile_t *skinfiles;
871 datapointer = (unsigned char *)buffer;
872 pinmodel = (mdl_t *)datapointer;
873 datapointer += sizeof(mdl_t);
875 version = LittleLong (pinmodel->version);
876 if (version != ALIAS_VERSION)
877 Host_Error ("%s has wrong version number (%i should be %i)",
878 loadmodel->name, version, ALIAS_VERSION);
880 loadmodel->modeldatatypestring = "MDL";
882 loadmodel->type = mod_alias;
883 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
884 loadmodel->DrawSky = NULL;
885 loadmodel->DrawAddWaterPlanes = NULL;
886 loadmodel->Draw = R_Q1BSP_Draw;
887 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
888 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
889 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
890 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
891 loadmodel->DrawLight = R_Q1BSP_DrawLight;
892 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
893 loadmodel->PointSuperContents = NULL;
895 loadmodel->num_surfaces = 1;
896 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
897 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
898 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
899 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
900 loadmodel->sortedmodelsurfaces[0] = 0;
902 loadmodel->numskins = LittleLong(pinmodel->numskins);
903 BOUNDI(loadmodel->numskins,0,65536);
904 skinwidth = LittleLong (pinmodel->skinwidth);
905 BOUNDI(skinwidth,0,65536);
906 skinheight = LittleLong (pinmodel->skinheight);
907 BOUNDI(skinheight,0,65536);
908 numverts = LittleLong(pinmodel->numverts);
909 BOUNDI(numverts,0,65536);
910 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
911 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
912 loadmodel->numframes = LittleLong(pinmodel->numframes);
913 BOUNDI(loadmodel->numframes,0,65536);
914 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
915 BOUNDI(loadmodel->synctype,0,2);
916 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
917 i = LittleLong (pinmodel->flags);
918 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
920 for (i = 0;i < 3;i++)
922 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
923 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
926 startskins = datapointer;
928 for (i = 0;i < loadmodel->numskins;i++)
930 pinskintype = (daliasskintype_t *)datapointer;
931 datapointer += sizeof(daliasskintype_t);
932 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
936 pinskingroup = (daliasskingroup_t *)datapointer;
937 datapointer += sizeof(daliasskingroup_t);
938 groupskins = LittleLong(pinskingroup->numskins);
939 datapointer += sizeof(daliasskininterval_t) * groupskins;
942 for (j = 0;j < groupskins;j++)
944 datapointer += skinwidth * skinheight;
949 pinstverts = (stvert_t *)datapointer;
950 datapointer += sizeof(stvert_t) * numverts;
952 pintriangles = (dtriangle_t *)datapointer;
953 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
955 startframes = datapointer;
956 loadmodel->surfmesh.num_morphframes = 0;
957 for (i = 0;i < loadmodel->numframes;i++)
959 pinframetype = (daliasframetype_t *)datapointer;
960 datapointer += sizeof(daliasframetype_t);
961 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
965 pinframegroup = (daliasgroup_t *)datapointer;
966 datapointer += sizeof(daliasgroup_t);
967 groupframes = LittleLong(pinframegroup->numframes);
968 datapointer += sizeof(daliasinterval_t) * groupframes;
971 for (j = 0;j < groupframes;j++)
973 datapointer += sizeof(daliasframe_t);
974 datapointer += sizeof(trivertx_t) * numverts;
975 loadmodel->surfmesh.num_morphframes++;
978 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
980 // store texture coordinates into temporary array, they will be stored
981 // after usage is determined (triangle data)
982 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
983 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
984 vertonseam = vertremap + numverts * 2;
986 scales = 1.0 / skinwidth;
987 scalet = 1.0 / skinheight;
988 for (i = 0;i < numverts;i++)
990 vertonseam[i] = LittleLong(pinstverts[i].onseam);
991 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
992 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
993 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
994 vertst[(i+numverts)*2+1] = vertst[i*2+1];
997 // load triangle data
998 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1000 // read the triangle elements
1001 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1002 for (j = 0;j < 3;j++)
1003 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1004 // validate (note numverts is used because this is the original data)
1005 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1006 // now butcher the elements according to vertonseam and tri->facesfront
1007 // and then compact the vertex set to remove duplicates
1008 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1009 if (!LittleLong(pintriangles[i].facesfront)) // backface
1010 for (j = 0;j < 3;j++)
1011 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1012 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1014 // (this uses vertremap to count usage to save some memory)
1015 for (i = 0;i < numverts*2;i++)
1017 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1018 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1019 // build remapping table and compact array
1020 loadmodel->surfmesh.num_vertices = 0;
1021 for (i = 0;i < numverts*2;i++)
1025 vertremap[i] = loadmodel->surfmesh.num_vertices;
1026 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1027 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1028 loadmodel->surfmesh.num_vertices++;
1031 vertremap[i] = -1; // not used at all
1033 // remap the elements to the new vertex set
1034 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1035 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1036 // store the texture coordinates
1037 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1038 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1040 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1041 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1044 // generate ushort elements array if possible
1045 if (loadmodel->surfmesh.num_vertices <= 65536)
1047 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1048 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1049 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1053 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1054 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1055 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1056 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1057 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1058 Mod_Alias_CalculateBoundingBox();
1059 Mod_Alias_MorphMesh_CompileFrames();
1062 Mem_Free(vertremap);
1065 skinfiles = Mod_LoadSkinFiles();
1068 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1069 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1070 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1071 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1072 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1073 Mod_FreeSkinFiles(skinfiles);
1074 for (i = 0;i < loadmodel->numskins;i++)
1076 loadmodel->skinscenes[i].firstframe = i;
1077 loadmodel->skinscenes[i].framecount = 1;
1078 loadmodel->skinscenes[i].loop = true;
1079 loadmodel->skinscenes[i].framerate = 10;
1084 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1085 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1086 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1087 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1089 datapointer = startskins;
1090 for (i = 0;i < loadmodel->numskins;i++)
1092 pinskintype = (daliasskintype_t *)datapointer;
1093 datapointer += sizeof(daliasskintype_t);
1095 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1102 pinskingroup = (daliasskingroup_t *)datapointer;
1103 datapointer += sizeof(daliasskingroup_t);
1105 groupskins = LittleLong (pinskingroup->numskins);
1107 pinskinintervals = (daliasskininterval_t *)datapointer;
1108 datapointer += sizeof(daliasskininterval_t) * groupskins;
1110 interval = LittleFloat(pinskinintervals[0].interval);
1111 if (interval < 0.01f)
1113 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1118 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1119 loadmodel->skinscenes[i].firstframe = totalskins;
1120 loadmodel->skinscenes[i].framecount = groupskins;
1121 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1122 loadmodel->skinscenes[i].loop = true;
1124 for (j = 0;j < groupskins;j++)
1127 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1129 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1130 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))
1131 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));
1132 datapointer += skinwidth * skinheight;
1136 // check for skins that don't exist in the model, but do exist as external images
1137 // (this was added because yummyluv kept pestering me about support for it)
1138 // TODO: support shaders here?
1139 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)))
1141 // expand the arrays to make room
1142 tempskinscenes = loadmodel->skinscenes;
1143 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1144 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1145 Mem_Free(tempskinscenes);
1147 tempaliasskins = loadmodel->data_textures;
1148 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1149 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1150 Mem_Free(tempaliasskins);
1152 // store the info about the new skin
1153 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1154 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1155 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1156 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1157 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1158 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1160 //increase skin counts
1161 loadmodel->numskins++;
1164 // fix up the pointers since they are pointing at the old textures array
1165 // FIXME: this is a hack!
1166 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1167 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1171 surface = loadmodel->data_surfaces;
1172 surface->texture = loadmodel->data_textures;
1173 surface->num_firsttriangle = 0;
1174 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1175 surface->num_firstvertex = 0;
1176 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1178 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1181 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1183 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1184 float iskinwidth, iskinheight;
1185 unsigned char *data;
1186 msurface_t *surface;
1188 unsigned char *base, *datapointer;
1189 md2frame_t *pinframe;
1191 md2triangle_t *intri;
1192 unsigned short *inst;
1193 struct md2verthash_s
1195 struct md2verthash_s *next;
1199 *hash, **md2verthash, *md2verthashdata;
1200 skinfile_t *skinfiles;
1202 pinmodel = (md2_t *)buffer;
1203 base = (unsigned char *)buffer;
1205 version = LittleLong (pinmodel->version);
1206 if (version != MD2ALIAS_VERSION)
1207 Host_Error ("%s has wrong version number (%i should be %i)",
1208 loadmodel->name, version, MD2ALIAS_VERSION);
1210 loadmodel->modeldatatypestring = "MD2";
1212 loadmodel->type = mod_alias;
1213 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1214 loadmodel->DrawSky = NULL;
1215 loadmodel->DrawAddWaterPlanes = NULL;
1216 loadmodel->Draw = R_Q1BSP_Draw;
1217 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1218 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1219 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1220 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1221 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1222 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1223 loadmodel->PointSuperContents = NULL;
1225 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1226 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1227 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1228 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1229 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1230 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1231 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1232 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1234 end = LittleLong(pinmodel->ofs_end);
1235 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1236 Host_Error ("%s is not a valid model", loadmodel->name);
1237 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1238 Host_Error ("%s is not a valid model", loadmodel->name);
1239 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1240 Host_Error ("%s is not a valid model", loadmodel->name);
1241 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1242 Host_Error ("%s is not a valid model", loadmodel->name);
1243 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1244 Host_Error ("%s is not a valid model", loadmodel->name);
1246 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1247 numxyz = LittleLong(pinmodel->num_xyz);
1248 numst = LittleLong(pinmodel->num_st);
1249 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1250 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1251 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1252 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1253 skinwidth = LittleLong(pinmodel->skinwidth);
1254 skinheight = LittleLong(pinmodel->skinheight);
1255 iskinwidth = 1.0f / skinwidth;
1256 iskinheight = 1.0f / skinheight;
1258 loadmodel->num_surfaces = 1;
1259 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1260 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]));
1261 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1262 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1263 loadmodel->sortedmodelsurfaces[0] = 0;
1264 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1265 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1266 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1267 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1269 loadmodel->synctype = ST_RAND;
1272 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1273 skinfiles = Mod_LoadSkinFiles();
1276 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1277 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1278 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1279 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1280 Mod_FreeSkinFiles(skinfiles);
1282 else if (loadmodel->numskins)
1284 // skins found (most likely not a player model)
1285 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1286 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1287 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1288 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1289 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);
1293 // no skins (most likely a player model)
1294 loadmodel->numskins = 1;
1295 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1296 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1297 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1298 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1301 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1302 for (i = 0;i < loadmodel->numskins;i++)
1304 loadmodel->skinscenes[i].firstframe = i;
1305 loadmodel->skinscenes[i].framecount = 1;
1306 loadmodel->skinscenes[i].loop = true;
1307 loadmodel->skinscenes[i].framerate = 10;
1310 // load the triangles and stvert data
1311 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1312 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1313 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1314 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1315 // swap the triangle list
1316 loadmodel->surfmesh.num_vertices = 0;
1317 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1319 for (j = 0;j < 3;j++)
1321 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1322 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1325 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1330 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1333 hashindex = (xyz * 256 + st) & 65535;
1334 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1335 if (hash->xyz == xyz && hash->st == st)
1339 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1342 hash->next = md2verthash[hashindex];
1343 md2verthash[hashindex] = hash;
1345 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1349 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1350 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));
1351 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1352 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1353 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1356 hash = md2verthashdata + i;
1357 vertremap[i] = hash->xyz;
1358 sts = LittleShort(inst[hash->st*2+0]);
1359 stt = LittleShort(inst[hash->st*2+1]);
1360 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1362 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1366 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1367 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1370 Mem_Free(md2verthash);
1371 Mem_Free(md2verthashdata);
1373 // generate ushort elements array if possible
1374 if (loadmodel->surfmesh.num_vertices <= 65536)
1376 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1377 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1378 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1382 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1383 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1388 pinframe = (md2frame_t *)datapointer;
1389 datapointer += sizeof(md2frame_t);
1390 // store the frame scale/translate into the appropriate array
1391 for (j = 0;j < 3;j++)
1393 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1394 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1396 // convert the vertices
1397 v = (trivertx_t *)datapointer;
1398 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1399 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1400 out[k] = v[vertremap[k]];
1401 datapointer += numxyz * sizeof(trivertx_t);
1403 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1404 loadmodel->animscenes[i].firstframe = i;
1405 loadmodel->animscenes[i].framecount = 1;
1406 loadmodel->animscenes[i].framerate = 10;
1407 loadmodel->animscenes[i].loop = true;
1410 Mem_Free(vertremap);
1412 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1413 Mod_Alias_CalculateBoundingBox();
1414 Mod_Alias_MorphMesh_CompileFrames();
1416 surface = loadmodel->data_surfaces;
1417 surface->texture = loadmodel->data_textures;
1418 surface->num_firsttriangle = 0;
1419 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1420 surface->num_firstvertex = 0;
1421 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1423 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1426 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1428 int i, j, k, version, meshvertices, meshtriangles;
1429 unsigned char *data;
1430 msurface_t *surface;
1431 md3modelheader_t *pinmodel;
1432 md3frameinfo_t *pinframe;
1435 skinfile_t *skinfiles;
1437 pinmodel = (md3modelheader_t *)buffer;
1439 if (memcmp(pinmodel->identifier, "IDP3", 4))
1440 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1441 version = LittleLong (pinmodel->version);
1442 if (version != MD3VERSION)
1443 Host_Error ("%s has wrong version number (%i should be %i)",
1444 loadmodel->name, version, MD3VERSION);
1446 skinfiles = Mod_LoadSkinFiles();
1447 if (loadmodel->numskins < 1)
1448 loadmodel->numskins = 1;
1450 loadmodel->modeldatatypestring = "MD3";
1452 loadmodel->type = mod_alias;
1453 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1454 loadmodel->DrawSky = NULL;
1455 loadmodel->DrawAddWaterPlanes = NULL;
1456 loadmodel->Draw = R_Q1BSP_Draw;
1457 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1458 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1459 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1460 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1461 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1462 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1463 loadmodel->PointSuperContents = NULL;
1464 loadmodel->synctype = ST_RAND;
1465 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1466 i = LittleLong (pinmodel->flags);
1467 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1469 // set up some global info about the model
1470 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1471 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1473 // make skinscenes for the skins (no groups)
1474 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1475 for (i = 0;i < loadmodel->numskins;i++)
1477 loadmodel->skinscenes[i].firstframe = i;
1478 loadmodel->skinscenes[i].framecount = 1;
1479 loadmodel->skinscenes[i].loop = true;
1480 loadmodel->skinscenes[i].framerate = 10;
1484 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1485 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1487 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1488 loadmodel->animscenes[i].firstframe = i;
1489 loadmodel->animscenes[i].framecount = 1;
1490 loadmodel->animscenes[i].framerate = 10;
1491 loadmodel->animscenes[i].loop = true;
1495 loadmodel->num_tagframes = loadmodel->numframes;
1496 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1497 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1498 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1500 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1501 for (j = 0;j < 9;j++)
1502 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1503 for (j = 0;j < 3;j++)
1504 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1505 //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);
1511 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)))
1513 if (memcmp(pinmesh->identifier, "IDP3", 4))
1514 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1515 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1516 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1517 meshvertices += LittleLong(pinmesh->num_vertices);
1518 meshtriangles += LittleLong(pinmesh->num_triangles);
1521 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1522 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1523 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1524 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));
1525 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1526 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1527 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1528 loadmodel->surfmesh.num_vertices = meshvertices;
1529 loadmodel->surfmesh.num_triangles = meshtriangles;
1530 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1531 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1532 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1533 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1534 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1535 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1536 if (meshvertices <= 65536)
1538 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1539 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1540 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1545 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)))
1547 if (memcmp(pinmesh->identifier, "IDP3", 4))
1548 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1549 loadmodel->sortedmodelsurfaces[i] = i;
1550 surface = loadmodel->data_surfaces + i;
1551 surface->texture = loadmodel->data_textures + i;
1552 surface->num_firsttriangle = meshtriangles;
1553 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1554 surface->num_firstvertex = meshvertices;
1555 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1556 meshvertices += surface->num_vertices;
1557 meshtriangles += surface->num_triangles;
1559 for (j = 0;j < surface->num_triangles * 3;j++)
1560 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1561 for (j = 0;j < surface->num_vertices;j++)
1563 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1564 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1566 for (j = 0;j < loadmodel->numframes;j++)
1568 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1569 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1570 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1572 out->origin[0] = LittleShort(in->origin[0]);
1573 out->origin[1] = LittleShort(in->origin[1]);
1574 out->origin[2] = LittleShort(in->origin[2]);
1575 out->pitch = in->pitch;
1580 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1582 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1584 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1585 Mod_Alias_MorphMesh_CompileFrames();
1586 Mod_Alias_CalculateBoundingBox();
1587 Mod_FreeSkinFiles(skinfiles);
1588 Mod_MakeSortedSurfaces(loadmodel);
1590 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1591 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1594 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1596 zymtype1header_t *pinmodel, *pheader;
1597 unsigned char *pbase;
1598 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1599 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose;
1600 zymvertex_t *verts, *vertdata;
1604 skinfile_t *skinfiles;
1605 unsigned char *data;
1606 msurface_t *surface;
1608 pinmodel = (zymtype1header_t *)buffer;
1609 pbase = (unsigned char *)buffer;
1610 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1611 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1612 if (BigLong(pinmodel->type) != 1)
1613 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1615 loadmodel->modeldatatypestring = "ZYM";
1617 loadmodel->type = mod_alias;
1618 loadmodel->synctype = ST_RAND;
1622 pheader->type = BigLong(pinmodel->type);
1623 pheader->filesize = BigLong(pinmodel->filesize);
1624 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1625 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1626 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1627 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1628 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1629 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1630 pheader->radius = BigFloat(pinmodel->radius);
1631 pheader->numverts = BigLong(pinmodel->numverts);
1632 pheader->numtris = BigLong(pinmodel->numtris);
1633 pheader->numshaders = BigLong(pinmodel->numshaders);
1634 pheader->numbones = BigLong(pinmodel->numbones);
1635 pheader->numscenes = BigLong(pinmodel->numscenes);
1636 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1637 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1638 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1639 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1640 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1641 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1642 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1643 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1644 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1645 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1646 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1647 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1648 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1649 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1650 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1651 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1652 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1653 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1655 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1657 Con_Printf("%s has no geometry\n", loadmodel->name);
1660 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1662 Con_Printf("%s has no animations\n", loadmodel->name);
1666 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1667 loadmodel->DrawSky = NULL;
1668 loadmodel->DrawAddWaterPlanes = NULL;
1669 loadmodel->Draw = R_Q1BSP_Draw;
1670 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1671 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1672 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1673 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1674 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1675 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1676 loadmodel->PointSuperContents = NULL;
1678 loadmodel->numframes = pheader->numscenes;
1679 loadmodel->num_surfaces = pheader->numshaders;
1681 skinfiles = Mod_LoadSkinFiles();
1682 if (loadmodel->numskins < 1)
1683 loadmodel->numskins = 1;
1685 // make skinscenes for the skins (no groups)
1686 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1687 for (i = 0;i < loadmodel->numskins;i++)
1689 loadmodel->skinscenes[i].firstframe = i;
1690 loadmodel->skinscenes[i].framecount = 1;
1691 loadmodel->skinscenes[i].loop = true;
1692 loadmodel->skinscenes[i].framerate = 10;
1696 modelradius = pheader->radius;
1697 for (i = 0;i < 3;i++)
1699 loadmodel->normalmins[i] = pheader->mins[i];
1700 loadmodel->normalmaxs[i] = pheader->maxs[i];
1701 loadmodel->rotatedmins[i] = -modelradius;
1702 loadmodel->rotatedmaxs[i] = modelradius;
1704 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1705 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1706 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1707 if (loadmodel->yawmaxs[0] > modelradius)
1708 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1709 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1710 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1711 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1712 loadmodel->radius = modelradius;
1713 loadmodel->radius2 = modelradius * modelradius;
1715 // go through the lumps, swapping things
1717 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1718 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1719 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1720 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1721 for (i = 0;i < pheader->numscenes;i++)
1723 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1724 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1725 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1726 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1727 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1728 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1729 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1730 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1731 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1732 if (loadmodel->animscenes[i].framerate < 0)
1733 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1737 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1738 loadmodel->num_bones = pheader->numbones;
1739 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1740 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1741 for (i = 0;i < pheader->numbones;i++)
1743 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1744 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1745 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1746 if (loadmodel->data_bones[i].parent >= i)
1747 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1750 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1751 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1752 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1753 for (i = 0;i < pheader->numverts;i++)
1755 vertbonecounts[i] = BigLong(bonecount[i]);
1756 if (vertbonecounts[i] != 1)
1757 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1760 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1762 meshvertices = pheader->numverts;
1763 meshtriangles = pheader->numtris;
1765 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1766 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1767 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1768 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]));
1769 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1770 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1771 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1772 loadmodel->surfmesh.num_vertices = meshvertices;
1773 loadmodel->surfmesh.num_triangles = meshtriangles;
1774 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1775 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1776 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1777 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1778 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1779 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1780 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1781 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1782 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1783 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
1784 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1785 if (loadmodel->surfmesh.num_vertices <= 65536)
1787 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1788 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1789 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1792 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1793 poses = (float *) (pheader->lump_poses.start + pbase);
1794 for (i = 0;i < pheader->lump_poses.length / 4;i++)
1795 loadmodel->data_poses[i] = BigFloat(poses[i]);
1797 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1798 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1799 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1800 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1801 // (converting from weight-blending skeletal animation to
1802 // deformation-based skeletal animation)
1803 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1804 for (i = 0;i < loadmodel->num_bones;i++)
1806 const float *m = loadmodel->data_poses + i * 12;
1807 if (loadmodel->data_bones[i].parent >= 0)
1808 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1810 for (k = 0;k < 12;k++)
1811 bonepose[12*i+k] = m[k];
1813 for (j = 0;j < pheader->numverts;j++)
1815 // this format really should have had a per vertexweight weight value...
1816 // but since it does not, the weighting is completely ignored and
1817 // only one weight is allowed per vertex
1818 int boneindex = BigLong(vertdata[j].bonenum);
1819 const float *m = bonepose + 12 * boneindex;
1820 float relativeorigin[3];
1821 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1822 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1823 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1824 // transform the vertex bone weight into the base mesh
1825 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1826 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1827 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1828 // store the weight as the primary weight on this vertex
1829 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
1830 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = 1;
1833 // normals and tangents are calculated after elements are loaded
1835 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1836 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1837 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1838 for (i = 0;i < pheader->numverts;i++)
1840 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1841 // flip T coordinate for OpenGL
1842 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1845 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1846 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1847 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1849 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1850 //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)
1851 // byteswap, validate, and swap winding order of tris
1852 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1853 if (pheader->lump_render.length != count)
1854 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1855 renderlist = (int *) (pheader->lump_render.start + pbase);
1856 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1858 for (i = 0;i < loadmodel->num_surfaces;i++)
1860 int firstvertex, lastvertex;
1861 if (renderlist >= renderlistend)
1862 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1863 count = BigLong(*renderlist);renderlist++;
1864 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1865 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1867 loadmodel->sortedmodelsurfaces[i] = i;
1868 surface = loadmodel->data_surfaces + i;
1869 surface->texture = loadmodel->data_textures + i;
1870 surface->num_firsttriangle = meshtriangles;
1871 surface->num_triangles = count;
1872 meshtriangles += surface->num_triangles;
1874 // load the elements
1875 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
1876 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
1878 outelements[j*3+2] = BigLong(renderlist[0]);
1879 outelements[j*3+1] = BigLong(renderlist[1]);
1880 outelements[j*3+0] = BigLong(renderlist[2]);
1882 // validate the elements and find the used vertex range
1883 firstvertex = meshvertices;
1885 for (j = 0;j < surface->num_triangles * 3;j++)
1887 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
1888 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
1889 firstvertex = min(firstvertex, outelements[j]);
1890 lastvertex = max(lastvertex, outelements[j]);
1892 surface->num_firstvertex = firstvertex;
1893 surface->num_vertices = lastvertex + 1 - firstvertex;
1895 // since zym models do not have named sections, reuse their shader
1896 // name as the section name
1897 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
1898 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
1900 Mod_FreeSkinFiles(skinfiles);
1901 Mem_Free(vertbonecounts);
1903 Mod_MakeSortedSurfaces(loadmodel);
1905 // compute all the mesh information that was not loaded from the file
1906 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
1907 Mod_BuildBaseBonePoses();
1908 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
1909 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);
1910 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1912 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1915 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1917 dpmheader_t *pheader;
1921 unsigned char *pbase;
1922 int i, j, k, meshvertices, meshtriangles;
1923 skinfile_t *skinfiles;
1924 unsigned char *data;
1927 pheader = (dpmheader_t *)buffer;
1928 pbase = (unsigned char *)buffer;
1929 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
1930 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
1931 if (BigLong(pheader->type) != 2)
1932 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1934 loadmodel->modeldatatypestring = "DPM";
1936 loadmodel->type = mod_alias;
1937 loadmodel->synctype = ST_RAND;
1940 pheader->type = BigLong(pheader->type);
1941 pheader->filesize = BigLong(pheader->filesize);
1942 pheader->mins[0] = BigFloat(pheader->mins[0]);
1943 pheader->mins[1] = BigFloat(pheader->mins[1]);
1944 pheader->mins[2] = BigFloat(pheader->mins[2]);
1945 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
1946 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
1947 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
1948 pheader->yawradius = BigFloat(pheader->yawradius);
1949 pheader->allradius = BigFloat(pheader->allradius);
1950 pheader->num_bones = BigLong(pheader->num_bones);
1951 pheader->num_meshs = BigLong(pheader->num_meshs);
1952 pheader->num_frames = BigLong(pheader->num_frames);
1953 pheader->ofs_bones = BigLong(pheader->ofs_bones);
1954 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
1955 pheader->ofs_frames = BigLong(pheader->ofs_frames);
1957 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
1959 Con_Printf("%s has no geometry\n", loadmodel->name);
1962 if (pheader->num_frames < 1)
1964 Con_Printf("%s has no frames\n", loadmodel->name);
1968 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1969 loadmodel->DrawSky = NULL;
1970 loadmodel->DrawAddWaterPlanes = NULL;
1971 loadmodel->Draw = R_Q1BSP_Draw;
1972 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1973 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1974 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1975 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1976 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1977 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1978 loadmodel->PointSuperContents = NULL;
1981 for (i = 0;i < 3;i++)
1983 loadmodel->normalmins[i] = pheader->mins[i];
1984 loadmodel->normalmaxs[i] = pheader->maxs[i];
1985 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
1986 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
1987 loadmodel->rotatedmins[i] = -pheader->allradius;
1988 loadmodel->rotatedmaxs[i] = pheader->allradius;
1990 loadmodel->radius = pheader->allradius;
1991 loadmodel->radius2 = pheader->allradius * pheader->allradius;
1993 // load external .skin files if present
1994 skinfiles = Mod_LoadSkinFiles();
1995 if (loadmodel->numskins < 1)
1996 loadmodel->numskins = 1;
2001 // gather combined statistics from the meshes
2002 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2003 for (i = 0;i < (int)pheader->num_meshs;i++)
2005 int numverts = BigLong(dpmmesh->num_verts);
2006 meshvertices += numverts;
2007 meshtriangles += BigLong(dpmmesh->num_tris);
2011 loadmodel->numframes = pheader->num_frames;
2012 loadmodel->num_bones = pheader->num_bones;
2013 loadmodel->num_poses = loadmodel->numframes;
2014 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2015 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2016 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2017 // do most allocations as one merged chunk
2018 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));
2019 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2020 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2021 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2022 loadmodel->surfmesh.num_vertices = meshvertices;
2023 loadmodel->surfmesh.num_triangles = meshtriangles;
2024 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2025 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2026 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2027 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2028 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2029 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2030 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2031 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
2032 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
2033 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
2034 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2035 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2036 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2037 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2038 if (meshvertices <= 65536)
2040 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2041 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2042 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2045 for (i = 0;i < loadmodel->numskins;i++)
2047 loadmodel->skinscenes[i].firstframe = i;
2048 loadmodel->skinscenes[i].framecount = 1;
2049 loadmodel->skinscenes[i].loop = true;
2050 loadmodel->skinscenes[i].framerate = 10;
2053 // load the bone info
2054 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2055 for (i = 0;i < loadmodel->num_bones;i++)
2057 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2058 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2059 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2060 if (loadmodel->data_bones[i].parent >= i)
2061 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2065 frame = (dpmframe_t *) (pbase + pheader->ofs_frames);
2066 for (i = 0;i < loadmodel->numframes;i++)
2069 memcpy(loadmodel->animscenes[i].name, frame->name, sizeof(frame->name));
2070 loadmodel->animscenes[i].firstframe = i;
2071 loadmodel->animscenes[i].framecount = 1;
2072 loadmodel->animscenes[i].loop = true;
2073 loadmodel->animscenes[i].framerate = 10;
2074 // load the bone poses for this frame
2075 poses = (float *) (pbase + BigLong(frame->ofs_bonepositions));
2076 for (j = 0;j < loadmodel->num_bones*12;j++)
2077 loadmodel->data_poses[i * loadmodel->num_bones*12 + j] = BigFloat(poses[j]);
2078 // stuff not processed here: mins, maxs, yawradius, allradius
2082 // load the meshes now
2083 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2086 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2087 // (converting from weight-blending skeletal animation to
2088 // deformation-based skeletal animation)
2089 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2090 for (i = 0;i < loadmodel->num_bones;i++)
2092 const float *m = loadmodel->data_poses + i * 12;
2093 if (loadmodel->data_bones[i].parent >= 0)
2094 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2096 for (k = 0;k < 12;k++)
2097 bonepose[12*i+k] = m[k];
2099 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2101 const int *inelements;
2103 const float *intexcoord;
2104 msurface_t *surface;
2106 loadmodel->sortedmodelsurfaces[i] = i;
2107 surface = loadmodel->data_surfaces + i;
2108 surface->texture = loadmodel->data_textures + i;
2109 surface->num_firsttriangle = meshtriangles;
2110 surface->num_triangles = BigLong(dpmmesh->num_tris);
2111 surface->num_firstvertex = meshvertices;
2112 surface->num_vertices = BigLong(dpmmesh->num_verts);
2113 meshvertices += surface->num_vertices;
2114 meshtriangles += surface->num_triangles;
2116 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2117 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2118 for (j = 0;j < surface->num_triangles;j++)
2120 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2121 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2122 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2123 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2128 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2129 for (j = 0;j < surface->num_vertices*2;j++)
2130 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2132 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2133 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2137 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2138 data += sizeof(dpmvertex_t);
2139 for (k = 0;k < numweights;k++)
2141 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2142 int boneindex = BigLong(vert->bonenum);
2143 const float *m = bonepose + 12 * boneindex;
2144 float influence = BigFloat(vert->influence);
2145 float relativeorigin[3], relativenormal[3];
2146 relativeorigin[0] = BigFloat(vert->origin[0]);
2147 relativeorigin[1] = BigFloat(vert->origin[1]);
2148 relativeorigin[2] = BigFloat(vert->origin[2]);
2149 relativenormal[0] = BigFloat(vert->normal[0]);
2150 relativenormal[1] = BigFloat(vert->normal[1]);
2151 relativenormal[2] = BigFloat(vert->normal[2]);
2152 // blend the vertex bone weights into the base mesh
2153 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2154 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2155 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2156 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2157 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2158 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2161 // store the first (and often only) weight
2162 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = influence;
2163 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
2167 // sort the new weight into this vertex's weight table
2168 // (which only accepts up to 4 bones per vertex)
2169 for (l = 0;l < 4;l++)
2171 if (loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] < influence)
2173 // move weaker influence weights out of the way first
2175 for (l2 = 3;l2 > l;l2--)
2177 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2-1];
2178 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2-1];
2180 // store the new weight
2181 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] = influence;
2182 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l] = boneindex;
2187 data += sizeof(dpmbonevert_t);
2190 for (l = 0;l < 4;l++)
2191 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l];
2192 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2194 float f = 1.0f / sum;
2195 for (l = 0;l < 4;l++)
2196 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] *= f;
2200 // since dpm models do not have named sections, reuse their shader name as the section name
2201 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2203 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2206 Mod_FreeSkinFiles(skinfiles);
2207 Mod_MakeSortedSurfaces(loadmodel);
2209 // compute all the mesh information that was not loaded from the file
2210 Mod_BuildBaseBonePoses();
2211 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);
2212 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2214 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2217 // no idea why PSK/PSA files contain weird quaternions but they do...
2218 #define PSKQUATNEGATIONS
2219 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2221 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2222 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2223 fs_offset_t filesize;
2228 pskboneinfo_t *bones;
2229 pskrawweights_t *rawweights;
2230 pskboneinfo_t *animbones;
2231 pskaniminfo_t *anims;
2232 pskanimkeys_t *animkeys;
2233 void *animfilebuffer, *animbuffer, *animbufferend;
2234 unsigned char *data;
2236 skinfile_t *skinfiles;
2237 char animname[MAX_QPATH];
2240 pchunk = (pskchunk_t *)buffer;
2241 if (strcmp(pchunk->id, "ACTRHEAD"))
2242 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2244 loadmodel->modeldatatypestring = "PSK";
2246 loadmodel->type = mod_alias;
2247 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2248 loadmodel->DrawSky = NULL;
2249 loadmodel->DrawAddWaterPlanes = NULL;
2250 loadmodel->Draw = R_Q1BSP_Draw;
2251 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2252 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2253 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2254 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2255 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2256 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2257 loadmodel->PointSuperContents = NULL;
2258 loadmodel->synctype = ST_RAND;
2260 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2261 strlcat(animname, ".psa", sizeof(animname));
2262 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2263 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2264 if (animbuffer == NULL)
2265 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2284 while (buffer < bufferend)
2286 pchunk = (pskchunk_t *)buffer;
2287 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2288 version = LittleLong(pchunk->version);
2289 recordsize = LittleLong(pchunk->recordsize);
2290 numrecords = LittleLong(pchunk->numrecords);
2291 if (developer.integer >= 100)
2292 Con_Printf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2293 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2294 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);
2295 if (!strcmp(pchunk->id, "ACTRHEAD"))
2299 else if (!strcmp(pchunk->id, "PNTS0000"))
2302 if (recordsize != sizeof(*p))
2303 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2304 // byteswap in place and keep the pointer
2305 numpnts = numrecords;
2306 pnts = (pskpnts_t *)buffer;
2307 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2309 p->origin[0] = LittleFloat(p->origin[0]);
2310 p->origin[1] = LittleFloat(p->origin[1]);
2311 p->origin[2] = LittleFloat(p->origin[2]);
2315 else if (!strcmp(pchunk->id, "VTXW0000"))
2318 if (recordsize != sizeof(*p))
2319 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2320 // byteswap in place and keep the pointer
2321 numvtxw = numrecords;
2322 vtxw = (pskvtxw_t *)buffer;
2323 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2325 p->pntsindex = LittleShort(p->pntsindex);
2326 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2327 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2328 if (p->pntsindex >= numpnts)
2330 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2336 else if (!strcmp(pchunk->id, "FACE0000"))
2339 if (recordsize != sizeof(*p))
2340 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2341 // byteswap in place and keep the pointer
2342 numfaces = numrecords;
2343 faces = (pskface_t *)buffer;
2344 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2346 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2347 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2348 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2349 p->group = LittleLong(p->group);
2350 if (p->vtxwindex[0] >= numvtxw)
2352 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2353 p->vtxwindex[0] = 0;
2355 if (p->vtxwindex[1] >= numvtxw)
2357 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2358 p->vtxwindex[1] = 0;
2360 if (p->vtxwindex[2] >= numvtxw)
2362 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2363 p->vtxwindex[2] = 0;
2368 else if (!strcmp(pchunk->id, "MATT0000"))
2371 if (recordsize != sizeof(*p))
2372 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2373 // byteswap in place and keep the pointer
2374 nummatts = numrecords;
2375 matts = (pskmatt_t *)buffer;
2376 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2382 else if (!strcmp(pchunk->id, "REFSKELT"))
2385 if (recordsize != sizeof(*p))
2386 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2387 // byteswap in place and keep the pointer
2388 numbones = numrecords;
2389 bones = (pskboneinfo_t *)buffer;
2390 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2392 p->numchildren = LittleLong(p->numchildren);
2393 p->parent = LittleLong(p->parent);
2394 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2395 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2396 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2397 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2398 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2399 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2400 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2401 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2402 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2403 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2404 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2405 #ifdef PSKQUATNEGATIONS
2408 p->basepose.quat[0] *= -1;
2409 p->basepose.quat[1] *= -1;
2410 p->basepose.quat[2] *= -1;
2414 p->basepose.quat[0] *= 1;
2415 p->basepose.quat[1] *= -1;
2416 p->basepose.quat[2] *= 1;
2419 if (p->parent < 0 || p->parent >= numbones)
2421 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2427 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2430 if (recordsize != sizeof(*p))
2431 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2432 // byteswap in place and keep the pointer
2433 numrawweights = numrecords;
2434 rawweights = (pskrawweights_t *)buffer;
2435 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2437 p->weight = LittleFloat(p->weight);
2438 p->pntsindex = LittleLong(p->pntsindex);
2439 p->boneindex = LittleLong(p->boneindex);
2440 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2442 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2445 if (p->boneindex < 0 || p->boneindex >= numbones)
2447 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2455 while (animbuffer < animbufferend)
2457 pchunk = (pskchunk_t *)animbuffer;
2458 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2459 version = LittleLong(pchunk->version);
2460 recordsize = LittleLong(pchunk->recordsize);
2461 numrecords = LittleLong(pchunk->numrecords);
2462 if (developer.integer >= 100)
2463 Con_Printf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2464 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2465 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);
2466 if (!strcmp(pchunk->id, "ANIMHEAD"))
2470 else if (!strcmp(pchunk->id, "BONENAMES"))
2473 if (recordsize != sizeof(*p))
2474 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2475 // byteswap in place and keep the pointer
2476 numanimbones = numrecords;
2477 animbones = (pskboneinfo_t *)animbuffer;
2478 // NOTE: supposedly psa does not need to match the psk model, the
2479 // bones missing from the psa would simply use their base
2480 // positions from the psk, but this is hard for me to implement
2481 // and people can easily make animations that match.
2482 if (numanimbones != numbones)
2483 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2484 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2486 p->numchildren = LittleLong(p->numchildren);
2487 p->parent = LittleLong(p->parent);
2488 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2489 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2490 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2491 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2492 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2493 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2494 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2495 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2496 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2497 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2498 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2499 #ifdef PSKQUATNEGATIONS
2502 p->basepose.quat[0] *= -1;
2503 p->basepose.quat[1] *= -1;
2504 p->basepose.quat[2] *= -1;
2508 p->basepose.quat[0] *= 1;
2509 p->basepose.quat[1] *= -1;
2510 p->basepose.quat[2] *= 1;
2513 if (p->parent < 0 || p->parent >= numanimbones)
2515 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2518 // check that bones are the same as in the base
2519 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2520 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2524 else if (!strcmp(pchunk->id, "ANIMINFO"))
2527 if (recordsize != sizeof(*p))
2528 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2529 // byteswap in place and keep the pointer
2530 numanims = numrecords;
2531 anims = (pskaniminfo_t *)animbuffer;
2532 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2534 p->numbones = LittleLong(p->numbones);
2535 p->playtime = LittleFloat(p->playtime);
2536 p->fps = LittleFloat(p->fps);
2537 p->firstframe = LittleLong(p->firstframe);
2538 p->numframes = LittleLong(p->numframes);
2539 if (p->numbones != numbones)
2540 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2544 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2547 if (recordsize != sizeof(*p))
2548 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2549 numanimkeys = numrecords;
2550 animkeys = (pskanimkeys_t *)animbuffer;
2551 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2553 p->origin[0] = LittleFloat(p->origin[0]);
2554 p->origin[1] = LittleFloat(p->origin[1]);
2555 p->origin[2] = LittleFloat(p->origin[2]);
2556 p->quat[0] = LittleFloat(p->quat[0]);
2557 p->quat[1] = LittleFloat(p->quat[1]);
2558 p->quat[2] = LittleFloat(p->quat[2]);
2559 p->quat[3] = LittleFloat(p->quat[3]);
2560 p->frametime = LittleFloat(p->frametime);
2561 #ifdef PSKQUATNEGATIONS
2562 if (index % numbones)
2577 // TODO: allocate bonepose stuff
2580 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2583 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2584 Host_Error("%s: missing required chunks", loadmodel->name);
2586 loadmodel->numframes = 0;
2587 for (index = 0;index < numanims;index++)
2588 loadmodel->numframes += anims[index].numframes;
2590 if (numanimkeys != numbones * loadmodel->numframes)
2591 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2593 meshvertices = numvtxw;
2594 meshtriangles = numfaces;
2596 // load external .skin files if present
2597 skinfiles = Mod_LoadSkinFiles();
2598 if (loadmodel->numskins < 1)
2599 loadmodel->numskins = 1;
2600 loadmodel->num_bones = numbones;
2601 loadmodel->num_poses = loadmodel->numframes;
2602 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2603 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2604 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2605 loadmodel->surfmesh.num_vertices = meshvertices;
2606 loadmodel->surfmesh.num_triangles = meshtriangles;
2607 // do most allocations as one merged chunk
2608 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);
2609 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2610 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2611 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2612 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2613 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2614 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2615 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2616 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2617 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2618 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2619 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2620 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += loadmodel->surfmesh.num_vertices * sizeof(int[4]);
2621 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[4]);
2622 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
2623 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2624 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2625 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2626 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2627 if (loadmodel->surfmesh.num_vertices <= 65536)
2629 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2630 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2631 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2634 for (i = 0;i < loadmodel->numskins;i++)
2636 loadmodel->skinscenes[i].firstframe = i;
2637 loadmodel->skinscenes[i].framecount = 1;
2638 loadmodel->skinscenes[i].loop = true;
2639 loadmodel->skinscenes[i].framerate = 10;
2643 for (index = 0, i = 0;index < nummatts;index++)
2645 // since psk models do not have named sections, reuse their shader name as the section name
2646 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2647 loadmodel->sortedmodelsurfaces[index] = index;
2648 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2649 loadmodel->data_surfaces[index].num_firstvertex = 0;
2650 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2653 // copy over the vertex locations and texcoords
2654 for (index = 0;index < numvtxw;index++)
2656 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2657 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2658 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2659 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2660 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2663 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2664 for (index = 0;index < numfaces;index++)
2665 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2666 for (index = 0, i = 0;index < nummatts;index++)
2668 loadmodel->data_surfaces[index].num_firsttriangle = i;
2669 i += loadmodel->data_surfaces[index].num_triangles;
2670 loadmodel->data_surfaces[index].num_triangles = 0;
2672 for (index = 0;index < numfaces;index++)
2674 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2675 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2676 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2677 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2680 // copy over the bones
2681 for (index = 0;index < numbones;index++)
2683 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2684 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2685 if (loadmodel->data_bones[index].parent >= index)
2686 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2689 // sort the psk point weights into the vertex weight tables
2690 // (which only accept up to 4 bones per vertex)
2691 for (index = 0;index < numvtxw;index++)
2695 for (j = 0;j < numrawweights;j++)
2697 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2699 int boneindex = rawweights[j].boneindex;
2700 float influence = rawweights[j].weight;
2701 for (l = 0;l < 4;l++)
2703 if (loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] < influence)
2705 // move lower influence weights out of the way first
2707 for (l2 = 3;l2 > l;l2--)
2709 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2-1];
2710 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2-1];
2712 // store the new weight
2713 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] = influence;
2714 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l] = boneindex;
2721 for (l = 0;l < 4;l++)
2722 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l];
2723 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2725 float f = 1.0f / sum;
2726 for (l = 0;l < 4;l++)
2727 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] *= f;
2731 // set up the animscenes based on the anims
2732 for (index = 0, i = 0;index < numanims;index++)
2734 for (j = 0;j < anims[index].numframes;j++, i++)
2736 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2737 loadmodel->animscenes[i].firstframe = i;
2738 loadmodel->animscenes[i].framecount = 1;
2739 loadmodel->animscenes[i].loop = true;
2740 loadmodel->animscenes[i].framerate = 10;
2744 // load the poses from the animkeys
2745 for (index = 0;index < numanimkeys;index++)
2747 pskanimkeys_t *k = animkeys + index;
2749 Matrix4x4_FromOriginQuat(&matrix, k->origin[0], k->origin[1], k->origin[2], k->quat[0], k->quat[1], k->quat[2], k->quat[3]);
2750 Matrix4x4_ToArray12FloatD3D(&matrix, loadmodel->data_poses + index*12);
2752 Mod_FreeSkinFiles(skinfiles);
2753 Mem_Free(animfilebuffer);
2754 Mod_MakeSortedSurfaces(loadmodel);
2756 // compute all the mesh information that was not loaded from the file
2757 // TODO: honor smoothing groups somehow?
2758 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2759 Mod_BuildBaseBonePoses();
2760 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2761 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);
2762 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2763 Mod_Alias_CalculateBoundingBox();
2765 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2768 void Mod_OBJ_Load(dp_model_t *mod, void *buffer, void *bufferend)
2771 const char *textbase = (char *)buffer, *text = textbase;
2775 char materialname[MAX_QPATH];
2776 int j, index1, index2, index3, first, prev, index;
2779 int numtriangles = 0;
2780 int maxtriangles = 32768;
2781 int *element3i = Mem_Alloc(tempmempool, maxtriangles * sizeof(int[3]));
2783 int numsurfaces = 0;
2784 int maxsurfaces = 0;
2785 msurface_t *surfaces = NULL;
2789 float *oldv, *oldvt, *oldvn;
2790 int maxv = 65536, numv = 1;
2791 int maxvt = 65536, numvt = 1;
2792 int maxvn = 65536, numvn = 1;
2793 int maxverthash = 65536, numverthash = 0;
2794 int numhashindex = 65536;
2795 struct objverthash_s
2797 struct objverthash_s *next;
2803 *hash, **verthash = Mem_Alloc(tempmempool, numhashindex * sizeof(*verthash)), *verthashdata = Mem_Alloc(tempmempool, maxverthash * sizeof(*verthashdata)), *oldverthashdata;
2804 skinfile_t *skinfiles;
2806 dpsnprintf(materialname, sizeof(materialname), "%s", loadmodel->name);
2808 skinfiles = Mod_LoadSkinFiles();
2810 loadmodel->modeldatatypestring = "OBJ";
2812 loadmodel->type = mod_alias;
2813 loadmodel->AnimateVertices = NULL;
2814 loadmodel->DrawSky = NULL;
2815 loadmodel->DrawAddWaterPlanes = NULL;
2816 loadmodel->Draw = R_Q1BSP_Draw;
2817 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2818 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2819 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2820 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2821 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2822 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2823 loadmodel->PointSuperContents = NULL;
2825 // parse the OBJ text now
2832 for (linelen = 0;text[linelen] && text[linelen] != '\r' && text[linelen] != '\n';linelen++)
2833 line[linelen] = text[linelen];
2835 for (argc = 0;argc < (int)(sizeof(argv)/sizeof(argv[0]));argc++)
2839 while (*s == ' ' || *s == '\t')
2849 while (*s == ' ' || *s == '\t')
2854 if (argv[0][0] == '#')
2856 if (!strcmp(argv[0], "v"))
2862 v = Mem_Alloc(tempmempool, maxv * sizeof(float[3]));
2865 memcpy(v, oldv, numv * sizeof(float[3]));
2869 v[numv*3+0] = atof(argv[1]);
2870 v[numv*3+1] = atof(argv[2]);
2871 v[numv*3+2] = atof(argv[3]);
2874 else if (!strcmp(argv[0], "vt"))
2880 vt = Mem_Alloc(tempmempool, maxvt * sizeof(float[2]));
2883 memcpy(vt, oldvt, numvt * sizeof(float[2]));
2887 vt[numvt*2+0] = atof(argv[1]);
2888 vt[numvt*2+1] = atof(argv[2]);
2891 else if (!strcmp(argv[0], "vn"))
2897 vn = Mem_Alloc(tempmempool, maxvn * sizeof(float[3]));
2900 memcpy(vn, oldvn, numvn * sizeof(float[3]));
2904 vn[numvn*3+0] = atof(argv[1]);
2905 vn[numvn*3+1] = atof(argv[2]);
2906 vn[numvn*3+2] = atof(argv[3]);
2909 else if (!strcmp(argv[0], "f"))
2913 if (maxsurfaces <= numsurfaces)
2916 oldsurfaces = surfaces;
2917 surfaces = Mem_Alloc(tempmempool, maxsurfaces * sizeof(*surfaces));
2920 memcpy(surfaces, oldsurfaces, numsurfaces * sizeof(*surfaces));
2921 Mem_Free(oldsurfaces);
2924 surface = surfaces + numsurfaces++;
2927 for (j = 1;j < argc;j++)
2929 index1 = atoi(argv[j]);
2930 while(argv[j][0] && argv[j][0] != '/')
2935 index1 = numv + 1 - index1;
2936 index2 = atoi(argv[j]);
2938 index2 = numvt + 1 - index2;
2939 while(argv[j][0] && argv[j][0] != '/')
2943 index3 = atoi(argv[j]);
2945 index3 = numvn + 1 - index3;
2946 hashindex = (index1 + index2 * 3571 + index3 * 42589) & (numhashindex - 1);
2947 for (hash = verthash[hashindex];hash;hash = hash->next)
2948 if (hash->surface == numsurfaces-1 && hash->v == index1 && hash->vt == index2 && hash->vn == index3)
2952 if (maxverthash <= numverthash)
2955 oldverthashdata = verthashdata;
2956 verthashdata = Mem_Alloc(tempmempool, maxverthash * sizeof(*verthashdata));
2957 if (oldverthashdata)
2959 memcpy(verthashdata, oldverthashdata, numverthash * sizeof(*verthashdata));
2960 Mem_Free(oldverthashdata);
2963 hash = verthashdata + numverthash++;
2964 hash->next = verthash[hashindex];
2965 hash->s = numsurfaces;
2969 verthash[hashindex] = hash;
2971 index = (int)((size_t)(hash - verthashdata));
2976 if (maxtriangles <= numtriangles)
2979 oldelement3i = element3i;
2980 element3i = Mem_Alloc(tempmempool, numtriangles * sizeof(int[3]));
2983 memcpy(element3i, oldelement3i, numtriangles * sizeof(int[3]));
2984 Mem_Free(oldelement3i);
2987 element3i[numtriangles*3+0] = first;
2988 element3i[numtriangles*3+1] = prev;
2989 element3i[numtriangles*3+2] = index;
2995 else if (!strcmp(argv[0], "o") || !strcmp(argv[0], "g"))
2997 else if (!!strcmp(argv[0], "usemtl"))
3000 strlcpy(materialname, argv[1], sizeof(materialname);
3010 Mod_FreeSkinFiles(skinfiles);
3012 // now that we have the OBJ data loaded as-is, we can convert it
3013 loadmodel->numskins = LittleLong(pinmodel->num_skins);
3014 numxyz = LittleLong(pinmodel->num_xyz);
3015 numst = LittleLong(pinmodel->num_st);
3016 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
3017 loadmodel->numframes = LittleLong(pinmodel->num_frames);
3018 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
3019 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
3020 skinwidth = LittleLong(pinmodel->skinwidth);
3021 skinheight = LittleLong(pinmodel->skinheight);
3022 iskinwidth = 1.0f / skinwidth;
3023 iskinheight = 1.0f / skinheight;
3025 loadmodel->num_surfaces = 1;
3026 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
3027 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]));
3028 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
3029 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
3030 loadmodel->sortedmodelsurfaces[0] = 0;
3031 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
3032 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
3033 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
3034 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
3036 loadmodel->synctype = ST_RAND;
3039 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
3040 skinfiles = Mod_LoadSkinFiles();
3043 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3044 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3045 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
3046 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
3047 Mod_FreeSkinFiles(skinfiles);
3049 else if (loadmodel->numskins)
3051 // skins found (most likely not a player model)
3052 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3053 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3054 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
3055 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
3056 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);
3060 // no skins (most likely a player model)
3061 loadmodel->numskins = 1;
3062 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3063 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3064 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
3065 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
3068 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
3069 for (i = 0;i < loadmodel->numskins;i++)
3071 loadmodel->skinscenes[i].firstframe = i;
3072 loadmodel->skinscenes[i].framecount = 1;
3073 loadmodel->skinscenes[i].loop = true;
3074 loadmodel->skinscenes[i].framerate = 10;
3077 // load the triangles and stvert data
3078 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
3079 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
3080 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
3081 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
3082 // swap the triangle list
3083 loadmodel->surfmesh.num_vertices = 0;
3084 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
3086 for (j = 0;j < 3;j++)
3088 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
3089 st = (unsigned short) LittleShort (intri[i].index_st[j]);
3092 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
3097 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
3100 hashindex = (xyz * 256 + st) & 65535;
3101 for (hash = md2verthash[hashindex];hash;hash = hash->next)
3102 if (hash->xyz == xyz && hash->st == st)
3106 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
3109 hash->next = md2verthash[hashindex];
3110 md2verthash[hashindex] = hash;
3112 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
3116 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
3117 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));
3118 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
3119 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
3120 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
3123 hash = md2verthashdata + i;
3124 vertremap[i] = hash->xyz;
3125 sts = LittleShort(inst[hash->st*2+0]);
3126 stt = LittleShort(inst[hash->st*2+1]);
3127 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
3129 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
3133 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
3134 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
3137 Mem_Free(md2verthash);
3138 Mem_Free(md2verthashdata);
3140 // generate ushort elements array if possible
3141 if (loadmodel->surfmesh.num_vertices <= 65536)
3143 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
3144 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3145 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3149 datapointer = (base + LittleLong(pinmodel->ofs_frames));
3150 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
3155 pinframe = (md2frame_t *)datapointer;
3156 datapointer += sizeof(md2frame_t);
3157 // store the frame scale/translate into the appropriate array
3158 for (j = 0;j < 3;j++)
3160 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
3161 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
3163 // convert the vertices
3164 v = (trivertx_t *)datapointer;
3165 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
3166 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
3167 out[k] = v[vertremap[k]];
3168 datapointer += numxyz * sizeof(trivertx_t);
3170 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
3171 loadmodel->animscenes[i].firstframe = i;
3172 loadmodel->animscenes[i].framecount = 1;
3173 loadmodel->animscenes[i].framerate = 10;
3174 loadmodel->animscenes[i].loop = true;
3177 Mem_Free(vertremap);
3179 Mod_MakeSortedSurfaces(loadmodel);
3180 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3181 Mod_Alias_CalculateBoundingBox();
3182 Mod_Alias_MorphMesh_CompileFrames();
3184 surface = loadmodel->data_surfaces;
3185 surface->texture = loadmodel->data_textures;
3186 surface->num_firsttriangle = 0;
3187 surface->num_triangles = loadmodel->surfmesh.num_triangles;
3188 surface->num_firstvertex = 0;
3189 surface->num_vertices = loadmodel->surfmesh.num_vertices;
3191 loadmodel->surfmesh.isanimated = false;