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_TraceLine(dp_model_t *model, int frame, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask)
639 float segmentmins[3], segmentmaxs[3];
640 frameblend_t frameblend[MAX_FRAMEBLENDS];
642 static int maxvertices = 0;
643 static float *vertex3f = NULL;
644 memset(trace, 0, sizeof(*trace));
646 trace->realfraction = 1;
647 trace->hitsupercontentsmask = hitsupercontentsmask;
648 memset(frameblend, 0, sizeof(frameblend));
649 frameblend[0].subframe = frame;
650 frameblend[0].lerp = 1;
651 if (maxvertices < model->surfmesh.num_vertices)
655 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
656 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
658 segmentmins[0] = min(start[0], end[0]) - 1;
659 segmentmins[1] = min(start[1], end[1]) - 1;
660 segmentmins[2] = min(start[2], end[2]) - 1;
661 segmentmaxs[0] = max(start[0], end[0]) + 1;
662 segmentmaxs[1] = max(start[1], end[1]) + 1;
663 segmentmaxs[2] = max(start[2], end[2]) + 1;
664 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
666 model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL);
667 Collision_TraceLineTriangleMeshFloat(trace, start, 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);
671 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)
674 vec3_t shiftstart, shiftend;
675 float segmentmins[3], segmentmaxs[3];
676 frameblend_t frameblend[MAX_FRAMEBLENDS];
678 static int maxvertices = 0;
679 static float *vertex3f = NULL;
680 colbrushf_t *thisbrush_start, *thisbrush_end;
681 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
683 if (VectorCompare(boxmins, boxmaxs))
685 VectorAdd(start, boxmins, shiftstart);
686 VectorAdd(end, boxmins, shiftend);
687 Mod_MDLMD2MD3_TraceLine(model, frame, trace, start, end, hitsupercontentsmask);
688 VectorSubtract(trace->endpos, boxmins, trace->endpos);
692 // box trace, performed as brush trace
693 memset(trace, 0, sizeof(*trace));
695 trace->realfraction = 1;
696 trace->hitsupercontentsmask = hitsupercontentsmask;
697 memset(frameblend, 0, sizeof(frameblend));
698 frameblend[0].subframe = frame;
699 frameblend[0].lerp = 1;
700 if (maxvertices < model->surfmesh.num_vertices)
704 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
705 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
707 segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
708 segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
709 segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
710 segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
711 segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
712 segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
713 VectorAdd(start, boxmins, boxstartmins);
714 VectorAdd(start, boxmaxs, boxstartmaxs);
715 VectorAdd(end, boxmins, boxendmins);
716 VectorAdd(end, boxmaxs, boxendmaxs);
717 thisbrush_start = Collision_BrushForBox(&identitymatrix, boxstartmins, boxstartmaxs, 0, 0, NULL);
718 thisbrush_end = Collision_BrushForBox(&identitymatrix, boxendmins, boxendmaxs, 0, 0, NULL);
719 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
721 if (maxvertices < model->surfmesh.num_vertices)
725 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
726 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
728 model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL);
729 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);
733 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
736 for (i = 0;i < inverts;i++)
738 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
740 j = vertremap[i]; // not onseam
743 j = vertremap[i+inverts]; // onseam
749 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
751 int i, f, pose, groupframes;
753 daliasframetype_t *pframetype;
754 daliasframe_t *pinframe;
755 daliasgroup_t *group;
756 daliasinterval_t *intervals;
759 scene = loadmodel->animscenes;
760 for (f = 0;f < loadmodel->numframes;f++)
762 pframetype = (daliasframetype_t *)datapointer;
763 datapointer += sizeof(daliasframetype_t);
764 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
766 // a single frame is still treated as a group
773 group = (daliasgroup_t *)datapointer;
774 datapointer += sizeof(daliasgroup_t);
775 groupframes = LittleLong (group->numframes);
777 // intervals (time per frame)
778 intervals = (daliasinterval_t *)datapointer;
779 datapointer += sizeof(daliasinterval_t) * groupframes;
781 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
782 if (interval < 0.01f)
784 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
789 // get scene name from first frame
790 pinframe = (daliasframe_t *)datapointer;
792 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
793 scene->firstframe = pose;
794 scene->framecount = groupframes;
795 scene->framerate = 1.0f / interval;
800 for (i = 0;i < groupframes;i++)
802 pinframe = (daliasframe_t *)datapointer;
803 datapointer += sizeof(daliasframe_t);
804 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
805 datapointer += sizeof(trivertx_t) * inverts;
811 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
813 if (cls.state == ca_dedicated)
817 skinframe = R_SkinFrame_LoadMissing();
818 memset(texture, 0, sizeof(*texture));
819 texture->currentframe = texture;
820 //texture->animated = false;
821 texture->numskinframes = 1;
822 texture->skinframerate = 1;
823 texture->skinframes[0] = skinframe;
824 texture->currentskinframe = skinframe;
825 //texture->backgroundnumskinframes = 0;
826 //texture->customblendfunc[0] = 0;
827 //texture->customblendfunc[1] = 0;
828 //texture->surfaceflags = 0;
829 //texture->supercontents = 0;
830 //texture->surfaceparms = 0;
831 //texture->textureflags = 0;
833 texture->basematerialflags = MATERIALFLAG_WALL;
834 if (texture->currentskinframe->fog)
835 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
836 texture->currentmaterialflags = texture->basematerialflags;
839 static void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
842 skinfileitem_t *skinfileitem;
845 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
846 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
848 memset(skin, 0, sizeof(*skin));
850 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
852 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
853 if (!strcmp(skinfileitem->name, meshname))
855 Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
861 // don't render unmentioned meshes
862 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
863 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
868 Mod_LoadTextureFromQ3Shader(skin, shadername, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
871 #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);
872 #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);
873 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
875 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
876 float scales, scalet, interval;
880 stvert_t *pinstverts;
881 dtriangle_t *pintriangles;
882 daliasskintype_t *pinskintype;
883 daliasskingroup_t *pinskingroup;
884 daliasskininterval_t *pinskinintervals;
885 daliasframetype_t *pinframetype;
886 daliasgroup_t *pinframegroup;
887 unsigned char *datapointer, *startframes, *startskins;
888 char name[MAX_QPATH];
889 skinframe_t *tempskinframe;
890 animscene_t *tempskinscenes;
891 texture_t *tempaliasskins;
893 int *vertonseam, *vertremap;
894 skinfile_t *skinfiles;
896 datapointer = (unsigned char *)buffer;
897 pinmodel = (mdl_t *)datapointer;
898 datapointer += sizeof(mdl_t);
900 version = LittleLong (pinmodel->version);
901 if (version != ALIAS_VERSION)
902 Host_Error ("%s has wrong version number (%i should be %i)",
903 loadmodel->name, version, ALIAS_VERSION);
905 loadmodel->modeldatatypestring = "MDL";
907 loadmodel->type = mod_alias;
908 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
909 loadmodel->DrawSky = NULL;
910 loadmodel->DrawAddWaterPlanes = NULL;
911 loadmodel->Draw = R_Q1BSP_Draw;
912 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
913 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
914 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
915 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
916 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
917 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
918 loadmodel->DrawLight = R_Q1BSP_DrawLight;
919 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
920 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
921 loadmodel->PointSuperContents = NULL;
923 loadmodel->num_surfaces = 1;
924 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
925 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
926 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
927 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
928 loadmodel->sortedmodelsurfaces[0] = 0;
930 loadmodel->numskins = LittleLong(pinmodel->numskins);
931 BOUNDI(loadmodel->numskins,0,65536);
932 skinwidth = LittleLong (pinmodel->skinwidth);
933 BOUNDI(skinwidth,0,65536);
934 skinheight = LittleLong (pinmodel->skinheight);
935 BOUNDI(skinheight,0,65536);
936 numverts = LittleLong(pinmodel->numverts);
937 BOUNDI(numverts,0,65536);
938 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
939 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
940 loadmodel->numframes = LittleLong(pinmodel->numframes);
941 BOUNDI(loadmodel->numframes,0,65536);
942 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
943 BOUNDI(loadmodel->synctype,0,2);
944 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
945 i = LittleLong (pinmodel->flags);
946 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
948 for (i = 0;i < 3;i++)
950 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
951 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
954 startskins = datapointer;
956 for (i = 0;i < loadmodel->numskins;i++)
958 pinskintype = (daliasskintype_t *)datapointer;
959 datapointer += sizeof(daliasskintype_t);
960 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
964 pinskingroup = (daliasskingroup_t *)datapointer;
965 datapointer += sizeof(daliasskingroup_t);
966 groupskins = LittleLong(pinskingroup->numskins);
967 datapointer += sizeof(daliasskininterval_t) * groupskins;
970 for (j = 0;j < groupskins;j++)
972 datapointer += skinwidth * skinheight;
977 pinstverts = (stvert_t *)datapointer;
978 datapointer += sizeof(stvert_t) * numverts;
980 pintriangles = (dtriangle_t *)datapointer;
981 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
983 startframes = datapointer;
984 loadmodel->surfmesh.num_morphframes = 0;
985 for (i = 0;i < loadmodel->numframes;i++)
987 pinframetype = (daliasframetype_t *)datapointer;
988 datapointer += sizeof(daliasframetype_t);
989 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
993 pinframegroup = (daliasgroup_t *)datapointer;
994 datapointer += sizeof(daliasgroup_t);
995 groupframes = LittleLong(pinframegroup->numframes);
996 datapointer += sizeof(daliasinterval_t) * groupframes;
999 for (j = 0;j < groupframes;j++)
1001 datapointer += sizeof(daliasframe_t);
1002 datapointer += sizeof(trivertx_t) * numverts;
1003 loadmodel->surfmesh.num_morphframes++;
1006 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1008 // store texture coordinates into temporary array, they will be stored
1009 // after usage is determined (triangle data)
1010 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
1011 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
1012 vertonseam = vertremap + numverts * 2;
1014 scales = 1.0 / skinwidth;
1015 scalet = 1.0 / skinheight;
1016 for (i = 0;i < numverts;i++)
1018 vertonseam[i] = LittleLong(pinstverts[i].onseam);
1019 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
1020 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
1021 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
1022 vertst[(i+numverts)*2+1] = vertst[i*2+1];
1025 // load triangle data
1026 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1028 // read the triangle elements
1029 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1030 for (j = 0;j < 3;j++)
1031 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1032 // validate (note numverts is used because this is the original data)
1033 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1034 // now butcher the elements according to vertonseam and tri->facesfront
1035 // and then compact the vertex set to remove duplicates
1036 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1037 if (!LittleLong(pintriangles[i].facesfront)) // backface
1038 for (j = 0;j < 3;j++)
1039 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1040 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1042 // (this uses vertremap to count usage to save some memory)
1043 for (i = 0;i < numverts*2;i++)
1045 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1046 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1047 // build remapping table and compact array
1048 loadmodel->surfmesh.num_vertices = 0;
1049 for (i = 0;i < numverts*2;i++)
1053 vertremap[i] = loadmodel->surfmesh.num_vertices;
1054 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1055 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1056 loadmodel->surfmesh.num_vertices++;
1059 vertremap[i] = -1; // not used at all
1061 // remap the elements to the new vertex set
1062 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1063 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1064 // store the texture coordinates
1065 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1066 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1068 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1069 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1072 // generate ushort elements array if possible
1073 if (loadmodel->surfmesh.num_vertices <= 65536)
1075 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1076 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1077 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1081 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1082 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1083 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1084 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1085 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1086 Mod_Alias_CalculateBoundingBox();
1087 Mod_Alias_MorphMesh_CompileFrames();
1090 Mem_Free(vertremap);
1093 skinfiles = Mod_LoadSkinFiles();
1096 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1097 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1098 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1099 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1100 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1101 Mod_FreeSkinFiles(skinfiles);
1102 for (i = 0;i < loadmodel->numskins;i++)
1104 loadmodel->skinscenes[i].firstframe = i;
1105 loadmodel->skinscenes[i].framecount = 1;
1106 loadmodel->skinscenes[i].loop = true;
1107 loadmodel->skinscenes[i].framerate = 10;
1112 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1113 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1114 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1115 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1117 datapointer = startskins;
1118 for (i = 0;i < loadmodel->numskins;i++)
1120 pinskintype = (daliasskintype_t *)datapointer;
1121 datapointer += sizeof(daliasskintype_t);
1123 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1130 pinskingroup = (daliasskingroup_t *)datapointer;
1131 datapointer += sizeof(daliasskingroup_t);
1133 groupskins = LittleLong (pinskingroup->numskins);
1135 pinskinintervals = (daliasskininterval_t *)datapointer;
1136 datapointer += sizeof(daliasskininterval_t) * groupskins;
1138 interval = LittleFloat(pinskinintervals[0].interval);
1139 if (interval < 0.01f)
1141 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1146 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1147 loadmodel->skinscenes[i].firstframe = totalskins;
1148 loadmodel->skinscenes[i].framecount = groupskins;
1149 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1150 loadmodel->skinscenes[i].loop = true;
1152 for (j = 0;j < groupskins;j++)
1155 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1157 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1158 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))
1159 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));
1160 datapointer += skinwidth * skinheight;
1164 // check for skins that don't exist in the model, but do exist as external images
1165 // (this was added because yummyluv kept pestering me about support for it)
1166 // TODO: support shaders here?
1167 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)))
1169 // expand the arrays to make room
1170 tempskinscenes = loadmodel->skinscenes;
1171 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1172 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1173 Mem_Free(tempskinscenes);
1175 tempaliasskins = loadmodel->data_textures;
1176 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1177 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1178 Mem_Free(tempaliasskins);
1180 // store the info about the new skin
1181 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1182 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1183 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1184 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1185 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1186 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1188 //increase skin counts
1189 loadmodel->numskins++;
1192 // fix up the pointers since they are pointing at the old textures array
1193 // FIXME: this is a hack!
1194 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1195 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1199 surface = loadmodel->data_surfaces;
1200 surface->texture = loadmodel->data_textures;
1201 surface->num_firsttriangle = 0;
1202 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1203 surface->num_firstvertex = 0;
1204 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1206 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1209 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1211 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1212 float iskinwidth, iskinheight;
1213 unsigned char *data;
1214 msurface_t *surface;
1216 unsigned char *base, *datapointer;
1217 md2frame_t *pinframe;
1219 md2triangle_t *intri;
1220 unsigned short *inst;
1221 struct md2verthash_s
1223 struct md2verthash_s *next;
1227 *hash, **md2verthash, *md2verthashdata;
1228 skinfile_t *skinfiles;
1230 pinmodel = (md2_t *)buffer;
1231 base = (unsigned char *)buffer;
1233 version = LittleLong (pinmodel->version);
1234 if (version != MD2ALIAS_VERSION)
1235 Host_Error ("%s has wrong version number (%i should be %i)",
1236 loadmodel->name, version, MD2ALIAS_VERSION);
1238 loadmodel->modeldatatypestring = "MD2";
1240 loadmodel->type = mod_alias;
1241 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1242 loadmodel->DrawSky = NULL;
1243 loadmodel->DrawAddWaterPlanes = NULL;
1244 loadmodel->Draw = R_Q1BSP_Draw;
1245 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1246 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1247 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1248 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1249 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1250 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1251 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1252 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1253 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1254 loadmodel->PointSuperContents = NULL;
1256 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1257 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1258 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1259 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1260 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1261 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1262 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1263 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1265 end = LittleLong(pinmodel->ofs_end);
1266 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1267 Host_Error ("%s is not a valid model", loadmodel->name);
1268 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1269 Host_Error ("%s is not a valid model", loadmodel->name);
1270 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1271 Host_Error ("%s is not a valid model", loadmodel->name);
1272 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1273 Host_Error ("%s is not a valid model", loadmodel->name);
1274 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1275 Host_Error ("%s is not a valid model", loadmodel->name);
1277 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1278 numxyz = LittleLong(pinmodel->num_xyz);
1279 numst = LittleLong(pinmodel->num_st);
1280 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1281 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1282 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1283 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1284 skinwidth = LittleLong(pinmodel->skinwidth);
1285 skinheight = LittleLong(pinmodel->skinheight);
1286 iskinwidth = 1.0f / skinwidth;
1287 iskinheight = 1.0f / skinheight;
1289 loadmodel->num_surfaces = 1;
1290 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1291 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]));
1292 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1293 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1294 loadmodel->sortedmodelsurfaces[0] = 0;
1295 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1296 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1297 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1298 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1300 loadmodel->synctype = ST_RAND;
1303 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1304 skinfiles = Mod_LoadSkinFiles();
1307 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1308 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1309 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1310 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1311 Mod_FreeSkinFiles(skinfiles);
1313 else if (loadmodel->numskins)
1315 // skins found (most likely not a player model)
1316 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1317 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1318 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1319 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1320 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);
1324 // no skins (most likely a player model)
1325 loadmodel->numskins = 1;
1326 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1327 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1328 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1329 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1332 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1333 for (i = 0;i < loadmodel->numskins;i++)
1335 loadmodel->skinscenes[i].firstframe = i;
1336 loadmodel->skinscenes[i].framecount = 1;
1337 loadmodel->skinscenes[i].loop = true;
1338 loadmodel->skinscenes[i].framerate = 10;
1341 // load the triangles and stvert data
1342 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1343 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1344 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1345 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1346 // swap the triangle list
1347 loadmodel->surfmesh.num_vertices = 0;
1348 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1350 for (j = 0;j < 3;j++)
1352 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1353 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1356 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1361 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1364 hashindex = (xyz * 256 + st) & 65535;
1365 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1366 if (hash->xyz == xyz && hash->st == st)
1370 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1373 hash->next = md2verthash[hashindex];
1374 md2verthash[hashindex] = hash;
1376 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1380 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1381 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));
1382 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1383 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1384 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1387 hash = md2verthashdata + i;
1388 vertremap[i] = hash->xyz;
1389 sts = LittleShort(inst[hash->st*2+0]);
1390 stt = LittleShort(inst[hash->st*2+1]);
1391 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1393 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1397 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1398 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1401 Mem_Free(md2verthash);
1402 Mem_Free(md2verthashdata);
1404 // generate ushort elements array if possible
1405 if (loadmodel->surfmesh.num_vertices <= 65536)
1407 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1408 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1409 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1413 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1414 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1419 pinframe = (md2frame_t *)datapointer;
1420 datapointer += sizeof(md2frame_t);
1421 // store the frame scale/translate into the appropriate array
1422 for (j = 0;j < 3;j++)
1424 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1425 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1427 // convert the vertices
1428 v = (trivertx_t *)datapointer;
1429 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1430 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1431 out[k] = v[vertremap[k]];
1432 datapointer += numxyz * sizeof(trivertx_t);
1434 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1435 loadmodel->animscenes[i].firstframe = i;
1436 loadmodel->animscenes[i].framecount = 1;
1437 loadmodel->animscenes[i].framerate = 10;
1438 loadmodel->animscenes[i].loop = true;
1441 Mem_Free(vertremap);
1443 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1444 Mod_Alias_CalculateBoundingBox();
1445 Mod_Alias_MorphMesh_CompileFrames();
1447 surface = loadmodel->data_surfaces;
1448 surface->texture = loadmodel->data_textures;
1449 surface->num_firsttriangle = 0;
1450 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1451 surface->num_firstvertex = 0;
1452 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1454 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1457 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1459 int i, j, k, version, meshvertices, meshtriangles;
1460 unsigned char *data;
1461 msurface_t *surface;
1462 md3modelheader_t *pinmodel;
1463 md3frameinfo_t *pinframe;
1466 skinfile_t *skinfiles;
1468 pinmodel = (md3modelheader_t *)buffer;
1470 if (memcmp(pinmodel->identifier, "IDP3", 4))
1471 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1472 version = LittleLong (pinmodel->version);
1473 if (version != MD3VERSION)
1474 Host_Error ("%s has wrong version number (%i should be %i)",
1475 loadmodel->name, version, MD3VERSION);
1477 skinfiles = Mod_LoadSkinFiles();
1478 if (loadmodel->numskins < 1)
1479 loadmodel->numskins = 1;
1481 loadmodel->modeldatatypestring = "MD3";
1483 loadmodel->type = mod_alias;
1484 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1485 loadmodel->DrawSky = NULL;
1486 loadmodel->DrawAddWaterPlanes = NULL;
1487 loadmodel->Draw = R_Q1BSP_Draw;
1488 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1489 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1490 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1491 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1492 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1493 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1494 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1495 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1496 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1497 loadmodel->PointSuperContents = NULL;
1498 loadmodel->synctype = ST_RAND;
1499 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1500 i = LittleLong (pinmodel->flags);
1501 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1503 // set up some global info about the model
1504 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1505 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1507 // make skinscenes for the skins (no groups)
1508 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1509 for (i = 0;i < loadmodel->numskins;i++)
1511 loadmodel->skinscenes[i].firstframe = i;
1512 loadmodel->skinscenes[i].framecount = 1;
1513 loadmodel->skinscenes[i].loop = true;
1514 loadmodel->skinscenes[i].framerate = 10;
1518 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1519 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1521 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1522 loadmodel->animscenes[i].firstframe = i;
1523 loadmodel->animscenes[i].framecount = 1;
1524 loadmodel->animscenes[i].framerate = 10;
1525 loadmodel->animscenes[i].loop = true;
1529 loadmodel->num_tagframes = loadmodel->numframes;
1530 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1531 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1532 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1534 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1535 for (j = 0;j < 9;j++)
1536 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1537 for (j = 0;j < 3;j++)
1538 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1539 //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);
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 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1550 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1551 meshvertices += LittleLong(pinmesh->num_vertices);
1552 meshtriangles += LittleLong(pinmesh->num_triangles);
1555 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1556 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1557 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1558 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));
1559 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1560 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1561 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1562 loadmodel->surfmesh.num_vertices = meshvertices;
1563 loadmodel->surfmesh.num_triangles = meshtriangles;
1564 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1565 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1566 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1567 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1568 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1569 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1570 if (meshvertices <= 65536)
1572 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1573 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1574 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1579 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)))
1581 if (memcmp(pinmesh->identifier, "IDP3", 4))
1582 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1583 loadmodel->sortedmodelsurfaces[i] = i;
1584 surface = loadmodel->data_surfaces + i;
1585 surface->texture = loadmodel->data_textures + i;
1586 surface->num_firsttriangle = meshtriangles;
1587 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1588 surface->num_firstvertex = meshvertices;
1589 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1590 meshvertices += surface->num_vertices;
1591 meshtriangles += surface->num_triangles;
1593 for (j = 0;j < surface->num_triangles * 3;j++)
1594 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1595 for (j = 0;j < surface->num_vertices;j++)
1597 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1598 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1600 for (j = 0;j < loadmodel->numframes;j++)
1602 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1603 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1604 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1606 out->origin[0] = LittleShort(in->origin[0]);
1607 out->origin[1] = LittleShort(in->origin[1]);
1608 out->origin[2] = LittleShort(in->origin[2]);
1609 out->pitch = in->pitch;
1614 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1616 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1618 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1619 Mod_Alias_MorphMesh_CompileFrames();
1620 Mod_Alias_CalculateBoundingBox();
1621 Mod_FreeSkinFiles(skinfiles);
1622 Mod_MakeSortedSurfaces(loadmodel);
1624 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1625 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1628 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1630 zymtype1header_t *pinmodel, *pheader;
1631 unsigned char *pbase;
1632 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1633 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose;
1634 zymvertex_t *verts, *vertdata;
1638 skinfile_t *skinfiles;
1639 unsigned char *data;
1640 msurface_t *surface;
1642 pinmodel = (zymtype1header_t *)buffer;
1643 pbase = (unsigned char *)buffer;
1644 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1645 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1646 if (BigLong(pinmodel->type) != 1)
1647 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1649 loadmodel->modeldatatypestring = "ZYM";
1651 loadmodel->type = mod_alias;
1652 loadmodel->synctype = ST_RAND;
1656 pheader->type = BigLong(pinmodel->type);
1657 pheader->filesize = BigLong(pinmodel->filesize);
1658 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1659 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1660 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1661 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1662 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1663 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1664 pheader->radius = BigFloat(pinmodel->radius);
1665 pheader->numverts = BigLong(pinmodel->numverts);
1666 pheader->numtris = BigLong(pinmodel->numtris);
1667 pheader->numshaders = BigLong(pinmodel->numshaders);
1668 pheader->numbones = BigLong(pinmodel->numbones);
1669 pheader->numscenes = BigLong(pinmodel->numscenes);
1670 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1671 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1672 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1673 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1674 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1675 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1676 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1677 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1678 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1679 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1680 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1681 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1682 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1683 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1684 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1685 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1686 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1687 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1689 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1691 Con_Printf("%s has no geometry\n", loadmodel->name);
1694 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1696 Con_Printf("%s has no animations\n", loadmodel->name);
1700 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1701 loadmodel->DrawSky = NULL;
1702 loadmodel->DrawAddWaterPlanes = NULL;
1703 loadmodel->Draw = R_Q1BSP_Draw;
1704 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1705 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1706 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1707 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1708 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1709 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1710 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1711 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1712 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1713 loadmodel->PointSuperContents = NULL;
1715 loadmodel->numframes = pheader->numscenes;
1716 loadmodel->num_surfaces = pheader->numshaders;
1718 skinfiles = Mod_LoadSkinFiles();
1719 if (loadmodel->numskins < 1)
1720 loadmodel->numskins = 1;
1722 // make skinscenes for the skins (no groups)
1723 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1724 for (i = 0;i < loadmodel->numskins;i++)
1726 loadmodel->skinscenes[i].firstframe = i;
1727 loadmodel->skinscenes[i].framecount = 1;
1728 loadmodel->skinscenes[i].loop = true;
1729 loadmodel->skinscenes[i].framerate = 10;
1733 modelradius = pheader->radius;
1734 for (i = 0;i < 3;i++)
1736 loadmodel->normalmins[i] = pheader->mins[i];
1737 loadmodel->normalmaxs[i] = pheader->maxs[i];
1738 loadmodel->rotatedmins[i] = -modelradius;
1739 loadmodel->rotatedmaxs[i] = modelradius;
1741 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1742 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1743 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1744 if (loadmodel->yawmaxs[0] > modelradius)
1745 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1746 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1747 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1748 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1749 loadmodel->radius = modelradius;
1750 loadmodel->radius2 = modelradius * modelradius;
1752 // go through the lumps, swapping things
1754 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1755 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1756 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1757 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1758 for (i = 0;i < pheader->numscenes;i++)
1760 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1761 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1762 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1763 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1764 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1765 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1766 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1767 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1768 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1769 if (loadmodel->animscenes[i].framerate < 0)
1770 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1774 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1775 loadmodel->num_bones = pheader->numbones;
1776 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1777 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1778 for (i = 0;i < pheader->numbones;i++)
1780 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1781 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1782 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1783 if (loadmodel->data_bones[i].parent >= i)
1784 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1787 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1788 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1789 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1790 for (i = 0;i < pheader->numverts;i++)
1792 vertbonecounts[i] = BigLong(bonecount[i]);
1793 if (vertbonecounts[i] != 1)
1794 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1797 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1799 meshvertices = pheader->numverts;
1800 meshtriangles = pheader->numtris;
1802 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1803 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1804 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1805 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]));
1806 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1807 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1808 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1809 loadmodel->surfmesh.num_vertices = meshvertices;
1810 loadmodel->surfmesh.num_triangles = meshtriangles;
1811 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1812 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1813 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1814 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1815 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1816 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1817 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1818 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1819 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1820 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
1821 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1822 if (loadmodel->surfmesh.num_vertices <= 65536)
1824 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1825 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1826 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1829 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1830 poses = (float *) (pheader->lump_poses.start + pbase);
1831 for (i = 0;i < pheader->lump_poses.length / 4;i++)
1832 loadmodel->data_poses[i] = BigFloat(poses[i]);
1834 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1835 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1836 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1837 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1838 // (converting from weight-blending skeletal animation to
1839 // deformation-based skeletal animation)
1840 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1841 for (i = 0;i < loadmodel->num_bones;i++)
1843 const float *m = loadmodel->data_poses + i * 12;
1844 if (loadmodel->data_bones[i].parent >= 0)
1845 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1847 for (k = 0;k < 12;k++)
1848 bonepose[12*i+k] = m[k];
1850 for (j = 0;j < pheader->numverts;j++)
1852 // this format really should have had a per vertexweight weight value...
1853 // but since it does not, the weighting is completely ignored and
1854 // only one weight is allowed per vertex
1855 int boneindex = BigLong(vertdata[j].bonenum);
1856 const float *m = bonepose + 12 * boneindex;
1857 float relativeorigin[3];
1858 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1859 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1860 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1861 // transform the vertex bone weight into the base mesh
1862 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1863 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1864 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1865 // store the weight as the primary weight on this vertex
1866 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
1867 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = 1;
1870 // normals and tangents are calculated after elements are loaded
1872 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1873 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1874 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1875 for (i = 0;i < pheader->numverts;i++)
1877 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1878 // flip T coordinate for OpenGL
1879 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1882 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1883 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1884 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1886 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1887 //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)
1888 // byteswap, validate, and swap winding order of tris
1889 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1890 if (pheader->lump_render.length != count)
1891 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1892 renderlist = (int *) (pheader->lump_render.start + pbase);
1893 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1895 for (i = 0;i < loadmodel->num_surfaces;i++)
1897 int firstvertex, lastvertex;
1898 if (renderlist >= renderlistend)
1899 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1900 count = BigLong(*renderlist);renderlist++;
1901 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1902 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1904 loadmodel->sortedmodelsurfaces[i] = i;
1905 surface = loadmodel->data_surfaces + i;
1906 surface->texture = loadmodel->data_textures + i;
1907 surface->num_firsttriangle = meshtriangles;
1908 surface->num_triangles = count;
1909 meshtriangles += surface->num_triangles;
1911 // load the elements
1912 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
1913 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
1915 outelements[j*3+2] = BigLong(renderlist[0]);
1916 outelements[j*3+1] = BigLong(renderlist[1]);
1917 outelements[j*3+0] = BigLong(renderlist[2]);
1919 // validate the elements and find the used vertex range
1920 firstvertex = meshvertices;
1922 for (j = 0;j < surface->num_triangles * 3;j++)
1924 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
1925 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
1926 firstvertex = min(firstvertex, outelements[j]);
1927 lastvertex = max(lastvertex, outelements[j]);
1929 surface->num_firstvertex = firstvertex;
1930 surface->num_vertices = lastvertex + 1 - firstvertex;
1932 // since zym models do not have named sections, reuse their shader
1933 // name as the section name
1934 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
1935 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
1937 Mod_FreeSkinFiles(skinfiles);
1938 Mem_Free(vertbonecounts);
1940 Mod_MakeSortedSurfaces(loadmodel);
1942 // compute all the mesh information that was not loaded from the file
1943 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
1944 Mod_BuildBaseBonePoses();
1945 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
1946 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);
1947 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1949 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1952 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1954 dpmheader_t *pheader;
1958 unsigned char *pbase;
1959 int i, j, k, meshvertices, meshtriangles;
1960 skinfile_t *skinfiles;
1961 unsigned char *data;
1964 pheader = (dpmheader_t *)buffer;
1965 pbase = (unsigned char *)buffer;
1966 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
1967 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
1968 if (BigLong(pheader->type) != 2)
1969 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1971 loadmodel->modeldatatypestring = "DPM";
1973 loadmodel->type = mod_alias;
1974 loadmodel->synctype = ST_RAND;
1977 pheader->type = BigLong(pheader->type);
1978 pheader->filesize = BigLong(pheader->filesize);
1979 pheader->mins[0] = BigFloat(pheader->mins[0]);
1980 pheader->mins[1] = BigFloat(pheader->mins[1]);
1981 pheader->mins[2] = BigFloat(pheader->mins[2]);
1982 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
1983 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
1984 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
1985 pheader->yawradius = BigFloat(pheader->yawradius);
1986 pheader->allradius = BigFloat(pheader->allradius);
1987 pheader->num_bones = BigLong(pheader->num_bones);
1988 pheader->num_meshs = BigLong(pheader->num_meshs);
1989 pheader->num_frames = BigLong(pheader->num_frames);
1990 pheader->ofs_bones = BigLong(pheader->ofs_bones);
1991 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
1992 pheader->ofs_frames = BigLong(pheader->ofs_frames);
1994 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
1996 Con_Printf("%s has no geometry\n", loadmodel->name);
1999 if (pheader->num_frames < 1)
2001 Con_Printf("%s has no frames\n", loadmodel->name);
2005 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2006 loadmodel->DrawSky = NULL;
2007 loadmodel->DrawAddWaterPlanes = NULL;
2008 loadmodel->Draw = R_Q1BSP_Draw;
2009 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2010 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2011 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2012 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2013 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2014 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2015 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2016 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2017 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2018 loadmodel->PointSuperContents = NULL;
2021 for (i = 0;i < 3;i++)
2023 loadmodel->normalmins[i] = pheader->mins[i];
2024 loadmodel->normalmaxs[i] = pheader->maxs[i];
2025 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2026 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2027 loadmodel->rotatedmins[i] = -pheader->allradius;
2028 loadmodel->rotatedmaxs[i] = pheader->allradius;
2030 loadmodel->radius = pheader->allradius;
2031 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2033 // load external .skin files if present
2034 skinfiles = Mod_LoadSkinFiles();
2035 if (loadmodel->numskins < 1)
2036 loadmodel->numskins = 1;
2041 // gather combined statistics from the meshes
2042 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2043 for (i = 0;i < (int)pheader->num_meshs;i++)
2045 int numverts = BigLong(dpmmesh->num_verts);
2046 meshvertices += numverts;
2047 meshtriangles += BigLong(dpmmesh->num_tris);
2051 loadmodel->numframes = pheader->num_frames;
2052 loadmodel->num_bones = pheader->num_bones;
2053 loadmodel->num_poses = loadmodel->numframes;
2054 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2055 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2056 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2057 // do most allocations as one merged chunk
2058 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));
2059 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2060 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2061 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2062 loadmodel->surfmesh.num_vertices = meshvertices;
2063 loadmodel->surfmesh.num_triangles = meshtriangles;
2064 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2065 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2066 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2067 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2068 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2069 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2070 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2071 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
2072 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
2073 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
2074 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2075 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2076 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2077 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2078 if (meshvertices <= 65536)
2080 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2081 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2082 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2085 for (i = 0;i < loadmodel->numskins;i++)
2087 loadmodel->skinscenes[i].firstframe = i;
2088 loadmodel->skinscenes[i].framecount = 1;
2089 loadmodel->skinscenes[i].loop = true;
2090 loadmodel->skinscenes[i].framerate = 10;
2093 // load the bone info
2094 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2095 for (i = 0;i < loadmodel->num_bones;i++)
2097 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2098 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2099 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2100 if (loadmodel->data_bones[i].parent >= i)
2101 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2105 frame = (dpmframe_t *) (pbase + pheader->ofs_frames);
2106 for (i = 0;i < loadmodel->numframes;i++)
2109 memcpy(loadmodel->animscenes[i].name, frame->name, sizeof(frame->name));
2110 loadmodel->animscenes[i].firstframe = i;
2111 loadmodel->animscenes[i].framecount = 1;
2112 loadmodel->animscenes[i].loop = true;
2113 loadmodel->animscenes[i].framerate = 10;
2114 // load the bone poses for this frame
2115 poses = (float *) (pbase + BigLong(frame->ofs_bonepositions));
2116 for (j = 0;j < loadmodel->num_bones*12;j++)
2117 loadmodel->data_poses[i * loadmodel->num_bones*12 + j] = BigFloat(poses[j]);
2118 // stuff not processed here: mins, maxs, yawradius, allradius
2122 // load the meshes now
2123 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2126 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2127 // (converting from weight-blending skeletal animation to
2128 // deformation-based skeletal animation)
2129 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2130 for (i = 0;i < loadmodel->num_bones;i++)
2132 const float *m = loadmodel->data_poses + i * 12;
2133 if (loadmodel->data_bones[i].parent >= 0)
2134 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2136 for (k = 0;k < 12;k++)
2137 bonepose[12*i+k] = m[k];
2139 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2141 const int *inelements;
2143 const float *intexcoord;
2144 msurface_t *surface;
2146 loadmodel->sortedmodelsurfaces[i] = i;
2147 surface = loadmodel->data_surfaces + i;
2148 surface->texture = loadmodel->data_textures + i;
2149 surface->num_firsttriangle = meshtriangles;
2150 surface->num_triangles = BigLong(dpmmesh->num_tris);
2151 surface->num_firstvertex = meshvertices;
2152 surface->num_vertices = BigLong(dpmmesh->num_verts);
2153 meshvertices += surface->num_vertices;
2154 meshtriangles += surface->num_triangles;
2156 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2157 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2158 for (j = 0;j < surface->num_triangles;j++)
2160 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2161 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2162 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2163 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2168 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2169 for (j = 0;j < surface->num_vertices*2;j++)
2170 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2172 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2173 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2177 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2178 data += sizeof(dpmvertex_t);
2179 for (k = 0;k < numweights;k++)
2181 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2182 int boneindex = BigLong(vert->bonenum);
2183 const float *m = bonepose + 12 * boneindex;
2184 float influence = BigFloat(vert->influence);
2185 float relativeorigin[3], relativenormal[3];
2186 relativeorigin[0] = BigFloat(vert->origin[0]);
2187 relativeorigin[1] = BigFloat(vert->origin[1]);
2188 relativeorigin[2] = BigFloat(vert->origin[2]);
2189 relativenormal[0] = BigFloat(vert->normal[0]);
2190 relativenormal[1] = BigFloat(vert->normal[1]);
2191 relativenormal[2] = BigFloat(vert->normal[2]);
2192 // blend the vertex bone weights into the base mesh
2193 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2194 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2195 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2196 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2197 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2198 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2201 // store the first (and often only) weight
2202 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = influence;
2203 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
2207 // sort the new weight into this vertex's weight table
2208 // (which only accepts up to 4 bones per vertex)
2209 for (l = 0;l < 4;l++)
2211 if (loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] < influence)
2213 // move weaker influence weights out of the way first
2215 for (l2 = 3;l2 > l;l2--)
2217 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2-1];
2218 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2-1];
2220 // store the new weight
2221 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] = influence;
2222 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l] = boneindex;
2227 data += sizeof(dpmbonevert_t);
2230 for (l = 0;l < 4;l++)
2231 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l];
2232 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2234 float f = 1.0f / sum;
2235 for (l = 0;l < 4;l++)
2236 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] *= f;
2240 // since dpm models do not have named sections, reuse their shader name as the section name
2241 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2243 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2246 Mod_FreeSkinFiles(skinfiles);
2247 Mod_MakeSortedSurfaces(loadmodel);
2249 // compute all the mesh information that was not loaded from the file
2250 Mod_BuildBaseBonePoses();
2251 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);
2252 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2254 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2257 // no idea why PSK/PSA files contain weird quaternions but they do...
2258 #define PSKQUATNEGATIONS
2259 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2261 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2262 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2263 fs_offset_t filesize;
2268 pskboneinfo_t *bones;
2269 pskrawweights_t *rawweights;
2270 pskboneinfo_t *animbones;
2271 pskaniminfo_t *anims;
2272 pskanimkeys_t *animkeys;
2273 void *animfilebuffer, *animbuffer, *animbufferend;
2274 unsigned char *data;
2276 skinfile_t *skinfiles;
2277 char animname[MAX_QPATH];
2280 pchunk = (pskchunk_t *)buffer;
2281 if (strcmp(pchunk->id, "ACTRHEAD"))
2282 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2284 loadmodel->modeldatatypestring = "PSK";
2286 loadmodel->type = mod_alias;
2287 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2288 loadmodel->DrawSky = NULL;
2289 loadmodel->DrawAddWaterPlanes = NULL;
2290 loadmodel->Draw = R_Q1BSP_Draw;
2291 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2292 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2293 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2294 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2295 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2296 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2297 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2298 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2299 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2300 loadmodel->PointSuperContents = NULL;
2301 loadmodel->synctype = ST_RAND;
2303 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2304 strlcat(animname, ".psa", sizeof(animname));
2305 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2306 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2307 if (animbuffer == NULL)
2308 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2327 while (buffer < bufferend)
2329 pchunk = (pskchunk_t *)buffer;
2330 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2331 version = LittleLong(pchunk->version);
2332 recordsize = LittleLong(pchunk->recordsize);
2333 numrecords = LittleLong(pchunk->numrecords);
2334 if (developer.integer >= 100)
2335 Con_Printf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2336 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2337 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);
2338 if (!strcmp(pchunk->id, "ACTRHEAD"))
2342 else if (!strcmp(pchunk->id, "PNTS0000"))
2345 if (recordsize != sizeof(*p))
2346 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2347 // byteswap in place and keep the pointer
2348 numpnts = numrecords;
2349 pnts = (pskpnts_t *)buffer;
2350 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2352 p->origin[0] = LittleFloat(p->origin[0]);
2353 p->origin[1] = LittleFloat(p->origin[1]);
2354 p->origin[2] = LittleFloat(p->origin[2]);
2358 else if (!strcmp(pchunk->id, "VTXW0000"))
2361 if (recordsize != sizeof(*p))
2362 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2363 // byteswap in place and keep the pointer
2364 numvtxw = numrecords;
2365 vtxw = (pskvtxw_t *)buffer;
2366 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2368 p->pntsindex = LittleShort(p->pntsindex);
2369 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2370 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2371 if (p->pntsindex >= numpnts)
2373 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2379 else if (!strcmp(pchunk->id, "FACE0000"))
2382 if (recordsize != sizeof(*p))
2383 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2384 // byteswap in place and keep the pointer
2385 numfaces = numrecords;
2386 faces = (pskface_t *)buffer;
2387 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2389 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2390 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2391 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2392 p->group = LittleLong(p->group);
2393 if (p->vtxwindex[0] >= numvtxw)
2395 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2396 p->vtxwindex[0] = 0;
2398 if (p->vtxwindex[1] >= numvtxw)
2400 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2401 p->vtxwindex[1] = 0;
2403 if (p->vtxwindex[2] >= numvtxw)
2405 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2406 p->vtxwindex[2] = 0;
2411 else if (!strcmp(pchunk->id, "MATT0000"))
2414 if (recordsize != sizeof(*p))
2415 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2416 // byteswap in place and keep the pointer
2417 nummatts = numrecords;
2418 matts = (pskmatt_t *)buffer;
2419 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2425 else if (!strcmp(pchunk->id, "REFSKELT"))
2428 if (recordsize != sizeof(*p))
2429 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2430 // byteswap in place and keep the pointer
2431 numbones = numrecords;
2432 bones = (pskboneinfo_t *)buffer;
2433 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2435 p->numchildren = LittleLong(p->numchildren);
2436 p->parent = LittleLong(p->parent);
2437 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2438 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2439 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2440 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2441 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2442 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2443 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2444 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2445 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2446 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2447 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2448 #ifdef PSKQUATNEGATIONS
2451 p->basepose.quat[0] *= -1;
2452 p->basepose.quat[1] *= -1;
2453 p->basepose.quat[2] *= -1;
2457 p->basepose.quat[0] *= 1;
2458 p->basepose.quat[1] *= -1;
2459 p->basepose.quat[2] *= 1;
2462 if (p->parent < 0 || p->parent >= numbones)
2464 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2470 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2473 if (recordsize != sizeof(*p))
2474 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2475 // byteswap in place and keep the pointer
2476 numrawweights = numrecords;
2477 rawweights = (pskrawweights_t *)buffer;
2478 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2480 p->weight = LittleFloat(p->weight);
2481 p->pntsindex = LittleLong(p->pntsindex);
2482 p->boneindex = LittleLong(p->boneindex);
2483 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2485 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2488 if (p->boneindex < 0 || p->boneindex >= numbones)
2490 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2498 while (animbuffer < animbufferend)
2500 pchunk = (pskchunk_t *)animbuffer;
2501 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2502 version = LittleLong(pchunk->version);
2503 recordsize = LittleLong(pchunk->recordsize);
2504 numrecords = LittleLong(pchunk->numrecords);
2505 if (developer.integer >= 100)
2506 Con_Printf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2507 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2508 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);
2509 if (!strcmp(pchunk->id, "ANIMHEAD"))
2513 else if (!strcmp(pchunk->id, "BONENAMES"))
2516 if (recordsize != sizeof(*p))
2517 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2518 // byteswap in place and keep the pointer
2519 numanimbones = numrecords;
2520 animbones = (pskboneinfo_t *)animbuffer;
2521 // NOTE: supposedly psa does not need to match the psk model, the
2522 // bones missing from the psa would simply use their base
2523 // positions from the psk, but this is hard for me to implement
2524 // and people can easily make animations that match.
2525 if (numanimbones != numbones)
2526 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2527 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2529 p->numchildren = LittleLong(p->numchildren);
2530 p->parent = LittleLong(p->parent);
2531 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2532 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2533 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2534 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2535 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2536 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2537 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2538 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2539 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2540 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2541 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2542 #ifdef PSKQUATNEGATIONS
2545 p->basepose.quat[0] *= -1;
2546 p->basepose.quat[1] *= -1;
2547 p->basepose.quat[2] *= -1;
2551 p->basepose.quat[0] *= 1;
2552 p->basepose.quat[1] *= -1;
2553 p->basepose.quat[2] *= 1;
2556 if (p->parent < 0 || p->parent >= numanimbones)
2558 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2561 // check that bones are the same as in the base
2562 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2563 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2567 else if (!strcmp(pchunk->id, "ANIMINFO"))
2570 if (recordsize != sizeof(*p))
2571 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2572 // byteswap in place and keep the pointer
2573 numanims = numrecords;
2574 anims = (pskaniminfo_t *)animbuffer;
2575 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2577 p->numbones = LittleLong(p->numbones);
2578 p->playtime = LittleFloat(p->playtime);
2579 p->fps = LittleFloat(p->fps);
2580 p->firstframe = LittleLong(p->firstframe);
2581 p->numframes = LittleLong(p->numframes);
2582 if (p->numbones != numbones)
2583 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2587 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2590 if (recordsize != sizeof(*p))
2591 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2592 numanimkeys = numrecords;
2593 animkeys = (pskanimkeys_t *)animbuffer;
2594 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2596 p->origin[0] = LittleFloat(p->origin[0]);
2597 p->origin[1] = LittleFloat(p->origin[1]);
2598 p->origin[2] = LittleFloat(p->origin[2]);
2599 p->quat[0] = LittleFloat(p->quat[0]);
2600 p->quat[1] = LittleFloat(p->quat[1]);
2601 p->quat[2] = LittleFloat(p->quat[2]);
2602 p->quat[3] = LittleFloat(p->quat[3]);
2603 p->frametime = LittleFloat(p->frametime);
2604 #ifdef PSKQUATNEGATIONS
2605 if (index % numbones)
2620 // TODO: allocate bonepose stuff
2623 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2626 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2627 Host_Error("%s: missing required chunks", loadmodel->name);
2629 loadmodel->numframes = 0;
2630 for (index = 0;index < numanims;index++)
2631 loadmodel->numframes += anims[index].numframes;
2633 if (numanimkeys != numbones * loadmodel->numframes)
2634 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2636 meshvertices = numvtxw;
2637 meshtriangles = numfaces;
2639 // load external .skin files if present
2640 skinfiles = Mod_LoadSkinFiles();
2641 if (loadmodel->numskins < 1)
2642 loadmodel->numskins = 1;
2643 loadmodel->num_bones = numbones;
2644 loadmodel->num_poses = loadmodel->numframes;
2645 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2646 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2647 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2648 loadmodel->surfmesh.num_vertices = meshvertices;
2649 loadmodel->surfmesh.num_triangles = meshtriangles;
2650 // do most allocations as one merged chunk
2651 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);
2652 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2653 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2654 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2655 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2656 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2657 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2658 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2659 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2660 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2661 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2662 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2663 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += loadmodel->surfmesh.num_vertices * sizeof(int[4]);
2664 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[4]);
2665 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
2666 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2667 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2668 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2669 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2670 if (loadmodel->surfmesh.num_vertices <= 65536)
2672 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2673 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2674 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2677 for (i = 0;i < loadmodel->numskins;i++)
2679 loadmodel->skinscenes[i].firstframe = i;
2680 loadmodel->skinscenes[i].framecount = 1;
2681 loadmodel->skinscenes[i].loop = true;
2682 loadmodel->skinscenes[i].framerate = 10;
2686 for (index = 0, i = 0;index < nummatts;index++)
2688 // since psk models do not have named sections, reuse their shader name as the section name
2689 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2690 loadmodel->sortedmodelsurfaces[index] = index;
2691 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2692 loadmodel->data_surfaces[index].num_firstvertex = 0;
2693 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2696 // copy over the vertex locations and texcoords
2697 for (index = 0;index < numvtxw;index++)
2699 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2700 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2701 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2702 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2703 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2706 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2707 for (index = 0;index < numfaces;index++)
2708 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2709 for (index = 0, i = 0;index < nummatts;index++)
2711 loadmodel->data_surfaces[index].num_firsttriangle = i;
2712 i += loadmodel->data_surfaces[index].num_triangles;
2713 loadmodel->data_surfaces[index].num_triangles = 0;
2715 for (index = 0;index < numfaces;index++)
2717 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2718 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2719 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2720 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2723 // copy over the bones
2724 for (index = 0;index < numbones;index++)
2726 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2727 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2728 if (loadmodel->data_bones[index].parent >= index)
2729 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2732 // sort the psk point weights into the vertex weight tables
2733 // (which only accept up to 4 bones per vertex)
2734 for (index = 0;index < numvtxw;index++)
2738 for (j = 0;j < numrawweights;j++)
2740 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2742 int boneindex = rawweights[j].boneindex;
2743 float influence = rawweights[j].weight;
2744 for (l = 0;l < 4;l++)
2746 if (loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] < influence)
2748 // move lower influence weights out of the way first
2750 for (l2 = 3;l2 > l;l2--)
2752 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2-1];
2753 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2-1];
2755 // store the new weight
2756 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] = influence;
2757 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l] = boneindex;
2764 for (l = 0;l < 4;l++)
2765 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l];
2766 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2768 float f = 1.0f / sum;
2769 for (l = 0;l < 4;l++)
2770 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] *= f;
2774 // set up the animscenes based on the anims
2775 for (index = 0, i = 0;index < numanims;index++)
2777 for (j = 0;j < anims[index].numframes;j++, i++)
2779 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2780 loadmodel->animscenes[i].firstframe = i;
2781 loadmodel->animscenes[i].framecount = 1;
2782 loadmodel->animscenes[i].loop = true;
2783 loadmodel->animscenes[i].framerate = 10;
2787 // load the poses from the animkeys
2788 for (index = 0;index < numanimkeys;index++)
2790 pskanimkeys_t *k = animkeys + index;
2792 Matrix4x4_FromOriginQuat(&matrix, k->origin[0], k->origin[1], k->origin[2], k->quat[0], k->quat[1], k->quat[2], k->quat[3]);
2793 Matrix4x4_ToArray12FloatD3D(&matrix, loadmodel->data_poses + index*12);
2795 Mod_FreeSkinFiles(skinfiles);
2796 Mem_Free(animfilebuffer);
2797 Mod_MakeSortedSurfaces(loadmodel);
2799 // compute all the mesh information that was not loaded from the file
2800 // TODO: honor smoothing groups somehow?
2801 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2802 Mod_BuildBaseBonePoses();
2803 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2804 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);
2805 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2806 Mod_Alias_CalculateBoundingBox();
2808 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2811 void Mod_OBJ_Load(dp_model_t *mod, void *buffer, void *bufferend)
2814 const char *textbase = (char *)buffer, *text = textbase;
2818 char materialname[MAX_QPATH];
2819 int j, index1, index2, index3, first, prev, index;
2822 int numtriangles = 0;
2823 int maxtriangles = 32768;
2824 int *element3i = Mem_Alloc(tempmempool, maxtriangles * sizeof(int[3]));
2826 int numsurfaces = 0;
2827 int maxsurfaces = 0;
2828 msurface_t *surfaces = NULL;
2832 float *oldv, *oldvt, *oldvn;
2833 int maxv = 65536, numv = 1;
2834 int maxvt = 65536, numvt = 1;
2835 int maxvn = 65536, numvn = 1;
2836 int maxverthash = 65536, numverthash = 0;
2837 int numhashindex = 65536;
2838 struct objverthash_s
2840 struct objverthash_s *next;
2846 *hash, **verthash = Mem_Alloc(tempmempool, numhashindex * sizeof(*verthash)), *verthashdata = Mem_Alloc(tempmempool, maxverthash * sizeof(*verthashdata)), *oldverthashdata;
2847 skinfile_t *skinfiles;
2849 dpsnprintf(materialname, sizeof(materialname), "%s", loadmodel->name);
2851 skinfiles = Mod_LoadSkinFiles();
2853 loadmodel->modeldatatypestring = "OBJ";
2855 loadmodel->type = mod_alias;
2856 loadmodel->AnimateVertices = NULL;
2857 loadmodel->DrawSky = NULL;
2858 loadmodel->DrawAddWaterPlanes = NULL;
2859 loadmodel->Draw = R_Q1BSP_Draw;
2860 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2861 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2862 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2863 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2864 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2865 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2866 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2867 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2868 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2869 loadmodel->PointSuperContents = NULL;
2871 // parse the OBJ text now
2878 for (linelen = 0;text[linelen] && text[linelen] != '\r' && text[linelen] != '\n';linelen++)
2879 line[linelen] = text[linelen];
2881 for (argc = 0;argc < (int)(sizeof(argv)/sizeof(argv[0]));argc++)
2885 while (*s == ' ' || *s == '\t')
2895 while (*s == ' ' || *s == '\t')
2900 if (argv[0][0] == '#')
2902 if (!strcmp(argv[0], "v"))
2908 v = Mem_Alloc(tempmempool, maxv * sizeof(float[3]));
2911 memcpy(v, oldv, numv * sizeof(float[3]));
2915 v[numv*3+0] = atof(argv[1]);
2916 v[numv*3+1] = atof(argv[2]);
2917 v[numv*3+2] = atof(argv[3]);
2920 else if (!strcmp(argv[0], "vt"))
2926 vt = Mem_Alloc(tempmempool, maxvt * sizeof(float[2]));
2929 memcpy(vt, oldvt, numvt * sizeof(float[2]));
2933 vt[numvt*2+0] = atof(argv[1]);
2934 vt[numvt*2+1] = atof(argv[2]);
2937 else if (!strcmp(argv[0], "vn"))
2943 vn = Mem_Alloc(tempmempool, maxvn * sizeof(float[3]));
2946 memcpy(vn, oldvn, numvn * sizeof(float[3]));
2950 vn[numvn*3+0] = atof(argv[1]);
2951 vn[numvn*3+1] = atof(argv[2]);
2952 vn[numvn*3+2] = atof(argv[3]);
2955 else if (!strcmp(argv[0], "f"))
2959 if (maxsurfaces <= numsurfaces)
2962 oldsurfaces = surfaces;
2963 surfaces = Mem_Alloc(tempmempool, maxsurfaces * sizeof(*surfaces));
2966 memcpy(surfaces, oldsurfaces, numsurfaces * sizeof(*surfaces));
2967 Mem_Free(oldsurfaces);
2970 surface = surfaces + numsurfaces++;
2973 for (j = 1;j < argc;j++)
2975 index1 = atoi(argv[j]);
2976 while(argv[j][0] && argv[j][0] != '/')
2981 index1 = numv + 1 - index1;
2982 index2 = atoi(argv[j]);
2984 index2 = numvt + 1 - index2;
2985 while(argv[j][0] && argv[j][0] != '/')
2989 index3 = atoi(argv[j]);
2991 index3 = numvn + 1 - index3;
2992 hashindex = (index1 + index2 * 3571 + index3 * 42589) & (numhashindex - 1);
2993 for (hash = verthash[hashindex];hash;hash = hash->next)
2994 if (hash->surface == numsurfaces-1 && hash->v == index1 && hash->vt == index2 && hash->vn == index3)
2998 if (maxverthash <= numverthash)
3001 oldverthashdata = verthashdata;
3002 verthashdata = Mem_Alloc(tempmempool, maxverthash * sizeof(*verthashdata));
3003 if (oldverthashdata)
3005 memcpy(verthashdata, oldverthashdata, numverthash * sizeof(*verthashdata));
3006 Mem_Free(oldverthashdata);
3009 hash = verthashdata + numverthash++;
3010 hash->next = verthash[hashindex];
3011 hash->s = numsurfaces;
3015 verthash[hashindex] = hash;
3017 index = (int)((size_t)(hash - verthashdata));
3022 if (maxtriangles <= numtriangles)
3025 oldelement3i = element3i;
3026 element3i = Mem_Alloc(tempmempool, numtriangles * sizeof(int[3]));
3029 memcpy(element3i, oldelement3i, numtriangles * sizeof(int[3]));
3030 Mem_Free(oldelement3i);
3033 element3i[numtriangles*3+0] = first;
3034 element3i[numtriangles*3+1] = prev;
3035 element3i[numtriangles*3+2] = index;
3041 else if (!strcmp(argv[0], "o") || !strcmp(argv[0], "g"))
3043 else if (!!strcmp(argv[0], "usemtl"))
3046 strlcpy(materialname, argv[1], sizeof(materialname);
3056 Mod_FreeSkinFiles(skinfiles);
3058 // now that we have the OBJ data loaded as-is, we can convert it
3059 loadmodel->numskins = LittleLong(pinmodel->num_skins);
3060 numxyz = LittleLong(pinmodel->num_xyz);
3061 numst = LittleLong(pinmodel->num_st);
3062 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
3063 loadmodel->numframes = LittleLong(pinmodel->num_frames);
3064 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
3065 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
3066 skinwidth = LittleLong(pinmodel->skinwidth);
3067 skinheight = LittleLong(pinmodel->skinheight);
3068 iskinwidth = 1.0f / skinwidth;
3069 iskinheight = 1.0f / skinheight;
3071 loadmodel->num_surfaces = 1;
3072 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
3073 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]));
3074 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
3075 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
3076 loadmodel->sortedmodelsurfaces[0] = 0;
3077 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
3078 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
3079 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
3080 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
3082 loadmodel->synctype = ST_RAND;
3085 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
3086 skinfiles = Mod_LoadSkinFiles();
3089 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3090 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3091 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
3092 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
3093 Mod_FreeSkinFiles(skinfiles);
3095 else if (loadmodel->numskins)
3097 // skins found (most likely not a player model)
3098 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3099 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3100 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
3101 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
3102 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);
3106 // no skins (most likely a player model)
3107 loadmodel->numskins = 1;
3108 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3109 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3110 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
3111 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
3114 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
3115 for (i = 0;i < loadmodel->numskins;i++)
3117 loadmodel->skinscenes[i].firstframe = i;
3118 loadmodel->skinscenes[i].framecount = 1;
3119 loadmodel->skinscenes[i].loop = true;
3120 loadmodel->skinscenes[i].framerate = 10;
3123 // load the triangles and stvert data
3124 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
3125 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
3126 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
3127 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
3128 // swap the triangle list
3129 loadmodel->surfmesh.num_vertices = 0;
3130 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
3132 for (j = 0;j < 3;j++)
3134 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
3135 st = (unsigned short) LittleShort (intri[i].index_st[j]);
3138 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
3143 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
3146 hashindex = (xyz * 256 + st) & 65535;
3147 for (hash = md2verthash[hashindex];hash;hash = hash->next)
3148 if (hash->xyz == xyz && hash->st == st)
3152 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
3155 hash->next = md2verthash[hashindex];
3156 md2verthash[hashindex] = hash;
3158 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
3162 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
3163 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));
3164 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
3165 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
3166 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
3169 hash = md2verthashdata + i;
3170 vertremap[i] = hash->xyz;
3171 sts = LittleShort(inst[hash->st*2+0]);
3172 stt = LittleShort(inst[hash->st*2+1]);
3173 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
3175 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
3179 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
3180 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
3183 Mem_Free(md2verthash);
3184 Mem_Free(md2verthashdata);
3186 // generate ushort elements array if possible
3187 if (loadmodel->surfmesh.num_vertices <= 65536)
3189 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
3190 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3191 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3195 datapointer = (base + LittleLong(pinmodel->ofs_frames));
3196 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
3201 pinframe = (md2frame_t *)datapointer;
3202 datapointer += sizeof(md2frame_t);
3203 // store the frame scale/translate into the appropriate array
3204 for (j = 0;j < 3;j++)
3206 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
3207 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
3209 // convert the vertices
3210 v = (trivertx_t *)datapointer;
3211 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
3212 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
3213 out[k] = v[vertremap[k]];
3214 datapointer += numxyz * sizeof(trivertx_t);
3216 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
3217 loadmodel->animscenes[i].firstframe = i;
3218 loadmodel->animscenes[i].framecount = 1;
3219 loadmodel->animscenes[i].framerate = 10;
3220 loadmodel->animscenes[i].loop = true;
3223 Mem_Free(vertremap);
3225 Mod_MakeSortedSurfaces(loadmodel);
3226 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3227 Mod_Alias_CalculateBoundingBox();
3228 Mod_Alias_MorphMesh_CompileFrames();
3230 surface = loadmodel->data_surfaces;
3231 surface->texture = loadmodel->data_textures;
3232 surface->num_firsttriangle = 0;
3233 surface->num_triangles = loadmodel->surfmesh.num_triangles;
3234 surface->num_firstvertex = 0;
3235 surface->num_vertices = loadmodel->surfmesh.num_vertices;
3237 loadmodel->surfmesh.isanimated = false;