2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 cvar_t r_skeletal_debugbone = {0, "r_skeletal_debugbone", "-1", "development cvar for testing skeletal model code"};
26 cvar_t r_skeletal_debugbonecomponent = {0, "r_skeletal_debugbonecomponent", "3", "development cvar for testing skeletal model code"};
27 cvar_t r_skeletal_debugbonevalue = {0, "r_skeletal_debugbonevalue", "100", "development cvar for testing skeletal model code"};
28 cvar_t r_skeletal_debugtranslatex = {0, "r_skeletal_debugtranslatex", "1", "development cvar for testing skeletal model code"};
29 cvar_t r_skeletal_debugtranslatey = {0, "r_skeletal_debugtranslatey", "1", "development cvar for testing skeletal model code"};
30 cvar_t r_skeletal_debugtranslatez = {0, "r_skeletal_debugtranslatez", "1", "development cvar for testing skeletal model code"};
31 cvar_t mod_alias_supporttagscale = {0, "mod_alias_supporttagscale", "1", "support scaling factors in bone/tag attachment matrices as supported by MD3"};
33 float mod_md3_sin[320];
35 void Mod_AliasInit (void)
38 Cvar_RegisterVariable(&r_skeletal_debugbone);
39 Cvar_RegisterVariable(&r_skeletal_debugbonecomponent);
40 Cvar_RegisterVariable(&r_skeletal_debugbonevalue);
41 Cvar_RegisterVariable(&r_skeletal_debugtranslatex);
42 Cvar_RegisterVariable(&r_skeletal_debugtranslatey);
43 Cvar_RegisterVariable(&r_skeletal_debugtranslatez);
44 Cvar_RegisterVariable(&mod_alias_supporttagscale);
45 for (i = 0;i < 320;i++)
46 mod_md3_sin[i] = sin(i * M_PI * 2.0f / 256.0);
49 void Mod_Skeletal_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
52 // vertex weighted skeletal
55 float desiredscale[3];
56 float boneposerelative[MAX_BONES][12];
57 float *matrix, m[12], bonepose[MAX_BONES][12];
59 // interpolate matrices and concatenate them to their parents
60 for (i = 0;i < model->num_bones;i++)
62 for (k = 0;k < 12;k++)
64 VectorClear(desiredscale);
65 for (blends = 0;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++)
67 matrix = model->data_poses + (frameblend[blends].subframe * model->num_bones + i) * 12;
68 for (k = 0;k < 12;k++)
69 m[k] += matrix[k] * frameblend[blends].lerp;
70 desiredscale[0] += frameblend[blends].lerp * VectorLength(matrix );
71 desiredscale[1] += frameblend[blends].lerp * VectorLength(matrix + 4);
72 desiredscale[2] += frameblend[blends].lerp * VectorLength(matrix + 8);
75 VectorNormalize(m + 4);
76 VectorNormalize(m + 8);
77 VectorScale(m , desiredscale[0], m );
78 VectorScale(m + 4, desiredscale[1], m + 4);
79 VectorScale(m + 8, desiredscale[2], m + 8);
80 if (i == r_skeletal_debugbone.integer)
81 m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
82 m[3] *= r_skeletal_debugtranslatex.value;
83 m[7] *= r_skeletal_debugtranslatey.value;
84 m[11] *= r_skeletal_debugtranslatez.value;
85 if (model->data_bones[i].parent >= 0)
86 R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
88 for (k = 0;k < 12;k++)
89 bonepose[i][k] = m[k];
90 // create a relative deformation matrix to describe displacement
91 // from the base mesh, which is used by the actual weighting
92 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]);
94 // blend the vertex bone weights
95 // special case for the extremely common wf[0] == 1 because it saves 3 multiplies per array when compared to the other case (w[0] is always 1 if only one bone controls this vertex, artists only use multiple bones for certain special cases)
96 // special case for the first bone because it avoids the need to memset the arrays before filling
99 const float *v = model->surfmesh.data_vertex3f;
100 const int *wi = model->surfmesh.data_vertexweightindex4i;
101 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
102 memset(vertex3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
103 for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, wi += 4, wf += 4, vertex3f += 3)
107 const float *m = boneposerelative[wi[0]];
108 vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
109 vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
110 vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
114 const float *m = boneposerelative[wi[0]];
116 vertex3f[0] = f * (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
117 vertex3f[1] = f * (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
118 vertex3f[2] = f * (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
119 for (k = 1;k < 4 && wf[k];k++)
121 const float *m = boneposerelative[wi[k]];
123 vertex3f[0] += f * (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
124 vertex3f[1] += f * (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
125 vertex3f[2] += f * (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
132 const float *n = model->surfmesh.data_normal3f;
133 const int *wi = model->surfmesh.data_vertexweightindex4i;
134 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
135 memset(normal3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
136 for (i = 0;i < model->surfmesh.num_vertices;i++, n += 3, wi += 4, wf += 4, normal3f += 3)
140 const float *m = boneposerelative[wi[0]];
141 normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
142 normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
143 normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
147 const float *m = boneposerelative[wi[0]];
149 normal3f[0] = f * (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
150 normal3f[1] = f * (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
151 normal3f[2] = f * (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
152 for (k = 1;k < 4 && wf[k];k++)
154 const float *m = boneposerelative[wi[k]];
156 normal3f[0] += f * (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
157 normal3f[1] += f * (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
158 normal3f[2] += f * (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
165 const float *sv = model->surfmesh.data_svector3f;
166 const int *wi = model->surfmesh.data_vertexweightindex4i;
167 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
168 memset(svector3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
169 for (i = 0;i < model->surfmesh.num_vertices;i++, sv += 3, wi += 4, wf += 4, svector3f += 3)
173 const float *m = boneposerelative[wi[0]];
174 svector3f[0] = (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
175 svector3f[1] = (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
176 svector3f[2] = (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
180 const float *m = boneposerelative[wi[0]];
182 svector3f[0] = f * (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
183 svector3f[1] = f * (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
184 svector3f[2] = f * (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
185 for (k = 1;k < 4 && wf[k];k++)
187 const float *m = boneposerelative[wi[k]];
189 svector3f[0] += f * (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
190 svector3f[1] += f * (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
191 svector3f[2] += f * (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
198 const float *tv = model->surfmesh.data_tvector3f;
199 const int *wi = model->surfmesh.data_vertexweightindex4i;
200 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
201 memset(tvector3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
202 for (i = 0;i < model->surfmesh.num_vertices;i++, tv += 3, wi += 4, wf += 4, tvector3f += 3)
206 const float *m = boneposerelative[wi[0]];
207 tvector3f[0] = (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
208 tvector3f[1] = (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
209 tvector3f[2] = (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
213 const float *m = boneposerelative[wi[0]];
215 tvector3f[0] = f * (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
216 tvector3f[1] = f * (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
217 tvector3f[2] = f * (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
218 for (k = 1;k < 4 && wf[k];k++)
220 const float *m = boneposerelative[wi[k]];
222 tvector3f[0] += f * (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
223 tvector3f[1] += f * (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
224 tvector3f[2] += f * (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
231 void Mod_MD3_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
234 int i, numblends, blendnum;
235 int numverts = model->surfmesh.num_vertices;
237 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
239 //VectorMA(translate, model->surfmesh.num_morphmdlframetranslate, frameblend[blendnum].lerp, translate);
240 if (frameblend[blendnum].lerp > 0)
241 numblends = blendnum + 1;
243 // special case for the first blend because it avoids some adds and the need to memset the arrays first
244 for (blendnum = 0;blendnum < numblends;blendnum++)
246 const md3vertex_t *verts = model->surfmesh.data_morphmd3vertex + numverts * frameblend[blendnum].subframe;
249 float scale = frameblend[blendnum].lerp * (1.0f / 64.0f);
252 for (i = 0;i < numverts;i++)
254 vertex3f[i * 3 + 0] = verts[i].origin[0] * scale;
255 vertex3f[i * 3 + 1] = verts[i].origin[1] * scale;
256 vertex3f[i * 3 + 2] = verts[i].origin[2] * scale;
261 for (i = 0;i < numverts;i++)
263 vertex3f[i * 3 + 0] += verts[i].origin[0] * scale;
264 vertex3f[i * 3 + 1] += verts[i].origin[1] * scale;
265 vertex3f[i * 3 + 2] += verts[i].origin[2] * scale;
269 // the yaw and pitch stored in md3 models are 8bit quantized angles
270 // (0-255), and as such a lookup table is very well suited to
271 // decoding them, and since cosine is equivilant to sine with an
272 // extra 45 degree rotation, this uses one lookup table for both
273 // sine and cosine with a +64 bias to get cosine.
276 float lerp = frameblend[blendnum].lerp;
279 for (i = 0;i < numverts;i++)
281 normal3f[i * 3 + 0] = mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
282 normal3f[i * 3 + 1] = mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
283 normal3f[i * 3 + 2] = mod_md3_sin[verts[i].pitch + 64] * lerp;
288 for (i = 0;i < numverts;i++)
290 normal3f[i * 3 + 0] += mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
291 normal3f[i * 3 + 1] += mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
292 normal3f[i * 3 + 2] += mod_md3_sin[verts[i].pitch + 64] * lerp;
298 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
299 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
302 for (i = 0;i < numverts;i++, texvecvert++)
304 VectorScale(texvecvert->svec, f, svector3f + i*3);
305 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
310 for (i = 0;i < numverts;i++, texvecvert++)
312 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
313 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
320 void Mod_MDL_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
323 int i, numblends, blendnum;
324 int numverts = model->surfmesh.num_vertices;
326 VectorClear(translate);
328 // blend the frame translates to avoid redundantly doing so on each vertex
329 // (a bit of a brain twister but it works)
330 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
332 if (model->surfmesh.data_morphmd2framesize6f)
333 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6 + 3, translate);
335 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.num_morphmdlframetranslate, translate);
336 if (frameblend[blendnum].lerp > 0)
337 numblends = blendnum + 1;
339 // special case for the first blend because it avoids some adds and the need to memset the arrays first
340 for (blendnum = 0;blendnum < numblends;blendnum++)
342 const trivertx_t *verts = model->surfmesh.data_morphmdlvertex + numverts * frameblend[blendnum].subframe;
346 if (model->surfmesh.data_morphmd2framesize6f)
347 VectorScale(model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6, frameblend[blendnum].lerp, scale);
349 VectorScale(model->surfmesh.num_morphmdlframescale, frameblend[blendnum].lerp, scale);
352 for (i = 0;i < numverts;i++)
354 vertex3f[i * 3 + 0] = translate[0] + verts[i].v[0] * scale[0];
355 vertex3f[i * 3 + 1] = translate[1] + verts[i].v[1] * scale[1];
356 vertex3f[i * 3 + 2] = translate[2] + verts[i].v[2] * scale[2];
361 for (i = 0;i < numverts;i++)
363 vertex3f[i * 3 + 0] += verts[i].v[0] * scale[0];
364 vertex3f[i * 3 + 1] += verts[i].v[1] * scale[1];
365 vertex3f[i * 3 + 2] += verts[i].v[2] * scale[2];
369 // the vertex normals in mdl models are an index into a table of
370 // 162 unique values, this very crude quantization reduces the
371 // vertex normal to only one byte, which saves a lot of space but
372 // also makes lighting pretty coarse
375 float lerp = frameblend[blendnum].lerp;
378 for (i = 0;i < numverts;i++)
380 const float *vn = m_bytenormals[verts[i].lightnormalindex];
381 VectorScale(vn, lerp, normal3f + i*3);
386 for (i = 0;i < numverts;i++)
388 const float *vn = m_bytenormals[verts[i].lightnormalindex];
389 VectorMA(normal3f + i*3, lerp, vn, normal3f + i*3);
395 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
396 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
399 for (i = 0;i < numverts;i++, texvecvert++)
401 VectorScale(texvecvert->svec, f, svector3f + i*3);
402 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
407 for (i = 0;i < numverts;i++, texvecvert++)
409 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
410 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
417 int Mod_Alias_GetTagMatrix(const dp_model_t *model, int poseframe, int tagindex, matrix4x4_t *outmatrix)
419 const float *boneframe;
420 float tempbonematrix[12], bonematrix[12];
421 *outmatrix = identitymatrix;
422 if (model->num_bones)
424 if (tagindex < 0 || tagindex >= model->num_bones)
426 if (poseframe >= model->num_poses)
428 boneframe = model->data_poses + poseframe * model->num_bones * 12;
429 memcpy(bonematrix, boneframe + tagindex * 12, sizeof(float[12]));
430 while (model->data_bones[tagindex].parent >= 0)
432 memcpy(tempbonematrix, bonematrix, sizeof(float[12]));
433 R_ConcatTransforms(boneframe + model->data_bones[tagindex].parent * 12, tempbonematrix, bonematrix);
434 tagindex = model->data_bones[tagindex].parent;
436 Matrix4x4_FromArray12FloatD3D(outmatrix, bonematrix);
438 else if (model->num_tags)
440 if (tagindex < 0 || tagindex >= model->num_tags)
442 if (poseframe >= model->num_tagframes)
444 Matrix4x4_FromArray12FloatGL(outmatrix, model->data_tags[poseframe * model->num_tags + tagindex].matrixgl);
447 if(!mod_alias_supporttagscale.integer)
448 Matrix4x4_Normalize3(outmatrix, outmatrix);
453 int Mod_Alias_GetExtendedTagInfoForIndex(const dp_model_t *model, unsigned int skin, int poseframe, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
455 const float *boneframe;
457 if(skin >= (unsigned int)model->numskins)
460 if (model->num_bones)
462 if(tagindex >= model->num_bones || tagindex < 0)
464 if (poseframe >= model->num_poses)
467 boneframe = model->data_poses + poseframe * model->num_bones * 12;
468 *parentindex = model->data_bones[tagindex].parent;
469 *tagname = model->data_bones[tagindex].name;
470 Matrix4x4_FromArray12FloatD3D(tag_localmatrix, boneframe + tagindex * 12);
476 if(tagindex >= model->num_tags || tagindex < 0)
478 if (poseframe >= model->num_tagframes)
480 *tagname = model->data_tags[tagindex].name;
481 Matrix4x4_FromArray12FloatGL(tag_localmatrix, model->data_tags[poseframe * model->num_tags + tagindex].matrixgl);
488 int Mod_Alias_GetTagIndexForName(const dp_model_t *model, unsigned int skin, const char *tagname)
491 if(skin >= (unsigned int)model->numskins)
493 if (model->num_bones)
494 for (i = 0;i < model->num_bones;i++)
495 if (!strcasecmp(tagname, model->data_bones[i].name))
498 for (i = 0;i < model->num_tags;i++)
499 if (!strcasecmp(tagname, model->data_tags[i].name))
504 static void Mod_BuildBaseBonePoses(void)
509 float *in12f = loadmodel->data_poses;
511 float *outinv12f = loadmodel->data_baseboneposeinverse;
512 if (!loadmodel->num_bones)
514 out12f = basebonepose = (float *) Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(float[12]));
515 for (i = 0;i < loadmodel->num_bones;i++, in12f += 12, out12f += 12, outinv12f += 12)
517 if (loadmodel->data_bones[i].parent >= 0)
518 R_ConcatTransforms(basebonepose + 12 * loadmodel->data_bones[i].parent, in12f, out12f);
520 for (k = 0;k < 12;k++)
521 out12f[k] = in12f[k];
525 // we only support uniform scaling, so assume the first row is enough
526 // (note the lack of sqrt here, because we're trying to undo the scaling,
527 // this means multiplying by the inverse scale twice - squaring it, which
528 // makes the sqrt a waste of time)
529 scale = 1.0 / (out12f[ 0] * out12f[ 0] + out12f[ 1] * out12f[ 1] + out12f[ 2] * out12f[ 2]);
531 // invert the rotation by transposing and multiplying by the squared
532 // recipricol of the input matrix scale as described above
533 outinv12f[ 0] = (float)(out12f[ 0] * scale);
534 outinv12f[ 1] = (float)(out12f[ 4] * scale);
535 outinv12f[ 2] = (float)(out12f[ 8] * scale);
536 outinv12f[ 4] = (float)(out12f[ 1] * scale);
537 outinv12f[ 5] = (float)(out12f[ 5] * scale);
538 outinv12f[ 6] = (float)(out12f[ 9] * scale);
539 outinv12f[ 8] = (float)(out12f[ 2] * scale);
540 outinv12f[ 9] = (float)(out12f[ 6] * scale);
541 outinv12f[10] = (float)(out12f[10] * scale);
543 // invert the translate
544 outinv12f[ 3] = -(out12f[ 3] * outinv12f[ 0] + out12f[ 7] * outinv12f[ 1] + out12f[11] * outinv12f[ 2]);
545 outinv12f[ 7] = -(out12f[ 3] * outinv12f[ 4] + out12f[ 7] * outinv12f[ 5] + out12f[11] * outinv12f[ 6]);
546 outinv12f[11] = -(out12f[ 3] * outinv12f[ 8] + out12f[ 7] * outinv12f[ 9] + out12f[11] * outinv12f[10]);
548 Mem_Free(basebonepose);
551 static void Mod_Alias_CalculateBoundingBox(void)
554 qboolean firstvertex = true;
555 float dist, yawradius, radius;
558 frameblend_t frameblend[MAX_FRAMEBLENDS];
559 memset(frameblend, 0, sizeof(frameblend));
560 frameblend[0].lerp = 1;
561 vertex3f = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
562 VectorClear(loadmodel->normalmins);
563 VectorClear(loadmodel->normalmaxs);
566 for (frameblend[0].subframe = 0;frameblend[0].subframe < loadmodel->num_poses;frameblend[0].subframe++)
568 loadmodel->AnimateVertices(loadmodel, frameblend, vertex3f, NULL, NULL, NULL);
569 for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
574 VectorCopy(v, loadmodel->normalmins);
575 VectorCopy(v, loadmodel->normalmaxs);
579 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
580 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
581 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
582 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
583 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
584 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
586 dist = v[0] * v[0] + v[1] * v[1];
587 if (yawradius < dist)
596 radius = sqrt(radius);
597 yawradius = sqrt(yawradius);
598 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
599 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
600 loadmodel->yawmins[2] = loadmodel->normalmins[2];
601 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
602 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
603 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
604 loadmodel->radius = radius;
605 loadmodel->radius2 = radius * radius;
608 static void Mod_Alias_MorphMesh_CompileFrames(void)
611 frameblend_t frameblend[MAX_FRAMEBLENDS];
612 unsigned char *datapointer;
613 memset(frameblend, 0, sizeof(frameblend));
614 frameblend[0].lerp = 1;
615 datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
616 loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
617 loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
618 loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
619 loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
620 loadmodel->surfmesh.data_morphtexvecvertex = (texvecvertex_t *)datapointer;datapointer += loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices * sizeof(texvecvertex_t);
621 // this counts down from the last frame to the first so that the final data in surfmesh is for frame zero (which is what the renderer expects to be there)
622 for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
624 frameblend[0].subframe = i;
625 loadmodel->AnimateVertices(loadmodel, frameblend, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
626 Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, r_smoothnormals_areaweighting.integer != 0);
627 // encode the svector and tvector in 3 byte format for permanent storage
628 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
630 VectorScaleCast(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
631 VectorScaleCast(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
636 static void Mod_MDLMD2MD3_TraceBox(dp_model_t *model, int frame, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask)
639 vec3_t shiftstart, shiftend;
640 float segmentmins[3], segmentmaxs[3];
641 frameblend_t frameblend[MAX_FRAMEBLENDS];
643 static int maxvertices = 0;
644 static float *vertex3f = NULL;
645 memset(trace, 0, sizeof(*trace));
647 trace->realfraction = 1;
648 trace->hitsupercontentsmask = hitsupercontentsmask;
649 memset(frameblend, 0, sizeof(frameblend));
650 frameblend[0].subframe = frame;
651 frameblend[0].lerp = 1;
652 if (maxvertices < model->surfmesh.num_vertices)
656 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
657 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
659 if (VectorCompare(boxmins, boxmaxs))
662 VectorAdd(start, boxmins, shiftstart);
663 VectorAdd(end, boxmins, shiftend);
664 segmentmins[0] = min(shiftstart[0], shiftend[0]) - 1;
665 segmentmins[1] = min(shiftstart[1], shiftend[1]) - 1;
666 segmentmins[2] = min(shiftstart[2], shiftend[2]) - 1;
667 segmentmaxs[0] = max(shiftstart[0], shiftend[0]) + 1;
668 segmentmaxs[1] = max(shiftstart[1], shiftend[1]) + 1;
669 segmentmaxs[2] = max(shiftstart[2], shiftend[2]) + 1;
670 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
672 model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL);
673 Collision_TraceLineTriangleMeshFloat(trace, shiftstart, shiftend, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs);
678 // box trace, performed as brush trace
679 colbrushf_t *thisbrush_start, *thisbrush_end;
680 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
681 segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
682 segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
683 segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
684 segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
685 segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
686 segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
687 VectorAdd(start, boxmins, boxstartmins);
688 VectorAdd(start, boxmaxs, boxstartmaxs);
689 VectorAdd(end, boxmins, boxendmins);
690 VectorAdd(end, boxmaxs, boxendmaxs);
691 thisbrush_start = Collision_BrushForBox(&identitymatrix, boxstartmins, boxstartmaxs, 0, 0, NULL);
692 thisbrush_end = Collision_BrushForBox(&identitymatrix, boxendmins, boxendmaxs, 0, 0, NULL);
693 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
695 if (maxvertices < model->surfmesh.num_vertices)
699 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
700 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
702 model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL);
703 Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs);
708 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
711 for (i = 0;i < inverts;i++)
713 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
715 j = vertremap[i]; // not onseam
718 j = vertremap[i+inverts]; // onseam
724 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
726 int i, f, pose, groupframes;
728 daliasframetype_t *pframetype;
729 daliasframe_t *pinframe;
730 daliasgroup_t *group;
731 daliasinterval_t *intervals;
734 scene = loadmodel->animscenes;
735 for (f = 0;f < loadmodel->numframes;f++)
737 pframetype = (daliasframetype_t *)datapointer;
738 datapointer += sizeof(daliasframetype_t);
739 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
741 // a single frame is still treated as a group
748 group = (daliasgroup_t *)datapointer;
749 datapointer += sizeof(daliasgroup_t);
750 groupframes = LittleLong (group->numframes);
752 // intervals (time per frame)
753 intervals = (daliasinterval_t *)datapointer;
754 datapointer += sizeof(daliasinterval_t) * groupframes;
756 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
757 if (interval < 0.01f)
759 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
764 // get scene name from first frame
765 pinframe = (daliasframe_t *)datapointer;
767 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
768 scene->firstframe = pose;
769 scene->framecount = groupframes;
770 scene->framerate = 1.0f / interval;
775 for (i = 0;i < groupframes;i++)
777 pinframe = (daliasframe_t *)datapointer;
778 datapointer += sizeof(daliasframe_t);
779 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
780 datapointer += sizeof(trivertx_t) * inverts;
786 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
788 if (cls.state == ca_dedicated)
792 skinframe = R_SkinFrame_LoadMissing();
793 memset(texture, 0, sizeof(*texture));
794 texture->currentframe = texture;
795 //texture->animated = false;
796 texture->numskinframes = 1;
797 texture->skinframerate = 1;
798 texture->skinframes[0] = skinframe;
799 texture->currentskinframe = skinframe;
800 //texture->backgroundnumskinframes = 0;
801 //texture->customblendfunc[0] = 0;
802 //texture->customblendfunc[1] = 0;
803 //texture->surfaceflags = 0;
804 //texture->supercontents = 0;
805 //texture->surfaceparms = 0;
806 //texture->textureflags = 0;
808 texture->basematerialflags = MATERIALFLAG_WALL;
809 if (texture->currentskinframe->fog)
810 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
811 texture->currentmaterialflags = texture->basematerialflags;
814 static void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
817 skinfileitem_t *skinfileitem;
820 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
821 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
823 memset(skin, 0, sizeof(*skin));
825 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
827 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
828 if (!strcmp(skinfileitem->name, meshname))
830 Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
836 // don't render unmentioned meshes
837 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
838 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
843 Mod_LoadTextureFromQ3Shader(skin, shadername, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
846 #define BOUNDI(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid ##VALUE (%d exceeds %d - %d)", loadmodel->name, VALUE, MIN, MAX);
847 #define BOUNDF(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid ##VALUE (%f exceeds %f - %f)", loadmodel->name, VALUE, MIN, MAX);
848 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
850 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
851 float scales, scalet, interval;
855 stvert_t *pinstverts;
856 dtriangle_t *pintriangles;
857 daliasskintype_t *pinskintype;
858 daliasskingroup_t *pinskingroup;
859 daliasskininterval_t *pinskinintervals;
860 daliasframetype_t *pinframetype;
861 daliasgroup_t *pinframegroup;
862 unsigned char *datapointer, *startframes, *startskins;
863 char name[MAX_QPATH];
864 skinframe_t *tempskinframe;
865 animscene_t *tempskinscenes;
866 texture_t *tempaliasskins;
868 int *vertonseam, *vertremap;
869 skinfile_t *skinfiles;
871 datapointer = (unsigned char *)buffer;
872 pinmodel = (mdl_t *)datapointer;
873 datapointer += sizeof(mdl_t);
875 version = LittleLong (pinmodel->version);
876 if (version != ALIAS_VERSION)
877 Host_Error ("%s has wrong version number (%i should be %i)",
878 loadmodel->name, version, ALIAS_VERSION);
880 loadmodel->modeldatatypestring = "MDL";
882 loadmodel->type = mod_alias;
883 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
884 loadmodel->DrawSky = NULL;
885 loadmodel->DrawAddWaterPlanes = NULL;
886 loadmodel->Draw = R_Q1BSP_Draw;
887 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
888 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
889 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
890 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
891 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
892 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
893 loadmodel->DrawLight = R_Q1BSP_DrawLight;
894 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
895 loadmodel->PointSuperContents = NULL;
897 loadmodel->num_surfaces = 1;
898 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
899 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
900 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
901 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
902 loadmodel->sortedmodelsurfaces[0] = 0;
904 loadmodel->numskins = LittleLong(pinmodel->numskins);
905 BOUNDI(loadmodel->numskins,0,65536);
906 skinwidth = LittleLong (pinmodel->skinwidth);
907 BOUNDI(skinwidth,0,65536);
908 skinheight = LittleLong (pinmodel->skinheight);
909 BOUNDI(skinheight,0,65536);
910 numverts = LittleLong(pinmodel->numverts);
911 BOUNDI(numverts,0,65536);
912 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
913 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
914 loadmodel->numframes = LittleLong(pinmodel->numframes);
915 BOUNDI(loadmodel->numframes,0,65536);
916 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
917 BOUNDI(loadmodel->synctype,0,2);
918 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
919 i = LittleLong (pinmodel->flags);
920 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
922 for (i = 0;i < 3;i++)
924 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
925 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
928 startskins = datapointer;
930 for (i = 0;i < loadmodel->numskins;i++)
932 pinskintype = (daliasskintype_t *)datapointer;
933 datapointer += sizeof(daliasskintype_t);
934 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
938 pinskingroup = (daliasskingroup_t *)datapointer;
939 datapointer += sizeof(daliasskingroup_t);
940 groupskins = LittleLong(pinskingroup->numskins);
941 datapointer += sizeof(daliasskininterval_t) * groupskins;
944 for (j = 0;j < groupskins;j++)
946 datapointer += skinwidth * skinheight;
951 pinstverts = (stvert_t *)datapointer;
952 datapointer += sizeof(stvert_t) * numverts;
954 pintriangles = (dtriangle_t *)datapointer;
955 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
957 startframes = datapointer;
958 loadmodel->surfmesh.num_morphframes = 0;
959 for (i = 0;i < loadmodel->numframes;i++)
961 pinframetype = (daliasframetype_t *)datapointer;
962 datapointer += sizeof(daliasframetype_t);
963 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
967 pinframegroup = (daliasgroup_t *)datapointer;
968 datapointer += sizeof(daliasgroup_t);
969 groupframes = LittleLong(pinframegroup->numframes);
970 datapointer += sizeof(daliasinterval_t) * groupframes;
973 for (j = 0;j < groupframes;j++)
975 datapointer += sizeof(daliasframe_t);
976 datapointer += sizeof(trivertx_t) * numverts;
977 loadmodel->surfmesh.num_morphframes++;
980 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
982 // store texture coordinates into temporary array, they will be stored
983 // after usage is determined (triangle data)
984 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
985 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
986 vertonseam = vertremap + numverts * 2;
988 scales = 1.0 / skinwidth;
989 scalet = 1.0 / skinheight;
990 for (i = 0;i < numverts;i++)
992 vertonseam[i] = LittleLong(pinstverts[i].onseam);
993 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
994 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
995 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
996 vertst[(i+numverts)*2+1] = vertst[i*2+1];
999 // load triangle data
1000 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1002 // read the triangle elements
1003 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1004 for (j = 0;j < 3;j++)
1005 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1006 // validate (note numverts is used because this is the original data)
1007 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1008 // now butcher the elements according to vertonseam and tri->facesfront
1009 // and then compact the vertex set to remove duplicates
1010 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1011 if (!LittleLong(pintriangles[i].facesfront)) // backface
1012 for (j = 0;j < 3;j++)
1013 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1014 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1016 // (this uses vertremap to count usage to save some memory)
1017 for (i = 0;i < numverts*2;i++)
1019 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1020 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1021 // build remapping table and compact array
1022 loadmodel->surfmesh.num_vertices = 0;
1023 for (i = 0;i < numverts*2;i++)
1027 vertremap[i] = loadmodel->surfmesh.num_vertices;
1028 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1029 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1030 loadmodel->surfmesh.num_vertices++;
1033 vertremap[i] = -1; // not used at all
1035 // remap the elements to the new vertex set
1036 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1037 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1038 // store the texture coordinates
1039 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1040 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1042 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1043 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1046 // generate ushort elements array if possible
1047 if (loadmodel->surfmesh.num_vertices <= 65536)
1049 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1050 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1051 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1055 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1056 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1057 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1058 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1059 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1060 Mod_Alias_CalculateBoundingBox();
1061 Mod_Alias_MorphMesh_CompileFrames();
1064 Mem_Free(vertremap);
1067 skinfiles = Mod_LoadSkinFiles();
1070 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1071 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1072 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1073 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1074 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1075 Mod_FreeSkinFiles(skinfiles);
1076 for (i = 0;i < loadmodel->numskins;i++)
1078 loadmodel->skinscenes[i].firstframe = i;
1079 loadmodel->skinscenes[i].framecount = 1;
1080 loadmodel->skinscenes[i].loop = true;
1081 loadmodel->skinscenes[i].framerate = 10;
1086 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1087 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1088 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1089 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1091 datapointer = startskins;
1092 for (i = 0;i < loadmodel->numskins;i++)
1094 pinskintype = (daliasskintype_t *)datapointer;
1095 datapointer += sizeof(daliasskintype_t);
1097 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1104 pinskingroup = (daliasskingroup_t *)datapointer;
1105 datapointer += sizeof(daliasskingroup_t);
1107 groupskins = LittleLong (pinskingroup->numskins);
1109 pinskinintervals = (daliasskininterval_t *)datapointer;
1110 datapointer += sizeof(daliasskininterval_t) * groupskins;
1112 interval = LittleFloat(pinskinintervals[0].interval);
1113 if (interval < 0.01f)
1115 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1120 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1121 loadmodel->skinscenes[i].firstframe = totalskins;
1122 loadmodel->skinscenes[i].framecount = groupskins;
1123 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1124 loadmodel->skinscenes[i].loop = true;
1126 for (j = 0;j < groupskins;j++)
1129 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1131 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1132 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))
1133 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));
1134 datapointer += skinwidth * skinheight;
1138 // check for skins that don't exist in the model, but do exist as external images
1139 // (this was added because yummyluv kept pestering me about support for it)
1140 // TODO: support shaders here?
1141 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)))
1143 // expand the arrays to make room
1144 tempskinscenes = loadmodel->skinscenes;
1145 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1146 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1147 Mem_Free(tempskinscenes);
1149 tempaliasskins = loadmodel->data_textures;
1150 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1151 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1152 Mem_Free(tempaliasskins);
1154 // store the info about the new skin
1155 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1156 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1157 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1158 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1159 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1160 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1162 //increase skin counts
1163 loadmodel->numskins++;
1166 // fix up the pointers since they are pointing at the old textures array
1167 // FIXME: this is a hack!
1168 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1169 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1173 surface = loadmodel->data_surfaces;
1174 surface->texture = loadmodel->data_textures;
1175 surface->num_firsttriangle = 0;
1176 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1177 surface->num_firstvertex = 0;
1178 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1180 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1183 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1185 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1186 float iskinwidth, iskinheight;
1187 unsigned char *data;
1188 msurface_t *surface;
1190 unsigned char *base, *datapointer;
1191 md2frame_t *pinframe;
1193 md2triangle_t *intri;
1194 unsigned short *inst;
1195 struct md2verthash_s
1197 struct md2verthash_s *next;
1201 *hash, **md2verthash, *md2verthashdata;
1202 skinfile_t *skinfiles;
1204 pinmodel = (md2_t *)buffer;
1205 base = (unsigned char *)buffer;
1207 version = LittleLong (pinmodel->version);
1208 if (version != MD2ALIAS_VERSION)
1209 Host_Error ("%s has wrong version number (%i should be %i)",
1210 loadmodel->name, version, MD2ALIAS_VERSION);
1212 loadmodel->modeldatatypestring = "MD2";
1214 loadmodel->type = mod_alias;
1215 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1216 loadmodel->DrawSky = NULL;
1217 loadmodel->DrawAddWaterPlanes = NULL;
1218 loadmodel->Draw = R_Q1BSP_Draw;
1219 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1220 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1221 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1222 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1223 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1224 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1225 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1226 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1227 loadmodel->PointSuperContents = NULL;
1229 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1230 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1231 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1232 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1233 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1234 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1235 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1236 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1238 end = LittleLong(pinmodel->ofs_end);
1239 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1240 Host_Error ("%s is not a valid model", loadmodel->name);
1241 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1242 Host_Error ("%s is not a valid model", loadmodel->name);
1243 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1244 Host_Error ("%s is not a valid model", loadmodel->name);
1245 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1246 Host_Error ("%s is not a valid model", loadmodel->name);
1247 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1248 Host_Error ("%s is not a valid model", loadmodel->name);
1250 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1251 numxyz = LittleLong(pinmodel->num_xyz);
1252 numst = LittleLong(pinmodel->num_st);
1253 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1254 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1255 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1256 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1257 skinwidth = LittleLong(pinmodel->skinwidth);
1258 skinheight = LittleLong(pinmodel->skinheight);
1259 iskinwidth = 1.0f / skinwidth;
1260 iskinheight = 1.0f / skinheight;
1262 loadmodel->num_surfaces = 1;
1263 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1264 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]));
1265 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1266 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1267 loadmodel->sortedmodelsurfaces[0] = 0;
1268 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1269 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1270 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1271 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1273 loadmodel->synctype = ST_RAND;
1276 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1277 skinfiles = Mod_LoadSkinFiles();
1280 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1281 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1282 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1283 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1284 Mod_FreeSkinFiles(skinfiles);
1286 else if (loadmodel->numskins)
1288 // skins found (most likely not a player model)
1289 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1290 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1291 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1292 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1293 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);
1297 // no skins (most likely a player model)
1298 loadmodel->numskins = 1;
1299 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1300 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1301 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1302 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1305 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1306 for (i = 0;i < loadmodel->numskins;i++)
1308 loadmodel->skinscenes[i].firstframe = i;
1309 loadmodel->skinscenes[i].framecount = 1;
1310 loadmodel->skinscenes[i].loop = true;
1311 loadmodel->skinscenes[i].framerate = 10;
1314 // load the triangles and stvert data
1315 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1316 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1317 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1318 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1319 // swap the triangle list
1320 loadmodel->surfmesh.num_vertices = 0;
1321 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1323 for (j = 0;j < 3;j++)
1325 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1326 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1329 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1334 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1337 hashindex = (xyz * 256 + st) & 65535;
1338 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1339 if (hash->xyz == xyz && hash->st == st)
1343 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1346 hash->next = md2verthash[hashindex];
1347 md2verthash[hashindex] = hash;
1349 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1353 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1354 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));
1355 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1356 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1357 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1360 hash = md2verthashdata + i;
1361 vertremap[i] = hash->xyz;
1362 sts = LittleShort(inst[hash->st*2+0]);
1363 stt = LittleShort(inst[hash->st*2+1]);
1364 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1366 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1370 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1371 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1374 Mem_Free(md2verthash);
1375 Mem_Free(md2verthashdata);
1377 // generate ushort elements array if possible
1378 if (loadmodel->surfmesh.num_vertices <= 65536)
1380 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1381 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1382 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1386 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1387 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1392 pinframe = (md2frame_t *)datapointer;
1393 datapointer += sizeof(md2frame_t);
1394 // store the frame scale/translate into the appropriate array
1395 for (j = 0;j < 3;j++)
1397 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1398 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1400 // convert the vertices
1401 v = (trivertx_t *)datapointer;
1402 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1403 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1404 out[k] = v[vertremap[k]];
1405 datapointer += numxyz * sizeof(trivertx_t);
1407 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1408 loadmodel->animscenes[i].firstframe = i;
1409 loadmodel->animscenes[i].framecount = 1;
1410 loadmodel->animscenes[i].framerate = 10;
1411 loadmodel->animscenes[i].loop = true;
1414 Mem_Free(vertremap);
1416 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1417 Mod_Alias_CalculateBoundingBox();
1418 Mod_Alias_MorphMesh_CompileFrames();
1420 surface = loadmodel->data_surfaces;
1421 surface->texture = loadmodel->data_textures;
1422 surface->num_firsttriangle = 0;
1423 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1424 surface->num_firstvertex = 0;
1425 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1427 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1430 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1432 int i, j, k, version, meshvertices, meshtriangles;
1433 unsigned char *data;
1434 msurface_t *surface;
1435 md3modelheader_t *pinmodel;
1436 md3frameinfo_t *pinframe;
1439 skinfile_t *skinfiles;
1441 pinmodel = (md3modelheader_t *)buffer;
1443 if (memcmp(pinmodel->identifier, "IDP3", 4))
1444 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1445 version = LittleLong (pinmodel->version);
1446 if (version != MD3VERSION)
1447 Host_Error ("%s has wrong version number (%i should be %i)",
1448 loadmodel->name, version, MD3VERSION);
1450 skinfiles = Mod_LoadSkinFiles();
1451 if (loadmodel->numskins < 1)
1452 loadmodel->numskins = 1;
1454 loadmodel->modeldatatypestring = "MD3";
1456 loadmodel->type = mod_alias;
1457 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1458 loadmodel->DrawSky = NULL;
1459 loadmodel->DrawAddWaterPlanes = NULL;
1460 loadmodel->Draw = R_Q1BSP_Draw;
1461 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1462 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1463 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1464 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1465 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1466 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1467 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1468 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1469 loadmodel->PointSuperContents = NULL;
1470 loadmodel->synctype = ST_RAND;
1471 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1472 i = LittleLong (pinmodel->flags);
1473 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1475 // set up some global info about the model
1476 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1477 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1479 // make skinscenes for the skins (no groups)
1480 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1481 for (i = 0;i < loadmodel->numskins;i++)
1483 loadmodel->skinscenes[i].firstframe = i;
1484 loadmodel->skinscenes[i].framecount = 1;
1485 loadmodel->skinscenes[i].loop = true;
1486 loadmodel->skinscenes[i].framerate = 10;
1490 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1491 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1493 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1494 loadmodel->animscenes[i].firstframe = i;
1495 loadmodel->animscenes[i].framecount = 1;
1496 loadmodel->animscenes[i].framerate = 10;
1497 loadmodel->animscenes[i].loop = true;
1501 loadmodel->num_tagframes = loadmodel->numframes;
1502 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1503 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1504 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1506 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1507 for (j = 0;j < 9;j++)
1508 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1509 for (j = 0;j < 3;j++)
1510 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1511 //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);
1517 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)))
1519 if (memcmp(pinmesh->identifier, "IDP3", 4))
1520 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1521 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1522 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1523 meshvertices += LittleLong(pinmesh->num_vertices);
1524 meshtriangles += LittleLong(pinmesh->num_triangles);
1527 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1528 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1529 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1530 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));
1531 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1532 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1533 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1534 loadmodel->surfmesh.num_vertices = meshvertices;
1535 loadmodel->surfmesh.num_triangles = meshtriangles;
1536 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1537 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1538 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1539 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1540 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1541 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1542 if (meshvertices <= 65536)
1544 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1545 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1546 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1551 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)))
1553 if (memcmp(pinmesh->identifier, "IDP3", 4))
1554 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1555 loadmodel->sortedmodelsurfaces[i] = i;
1556 surface = loadmodel->data_surfaces + i;
1557 surface->texture = loadmodel->data_textures + i;
1558 surface->num_firsttriangle = meshtriangles;
1559 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1560 surface->num_firstvertex = meshvertices;
1561 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1562 meshvertices += surface->num_vertices;
1563 meshtriangles += surface->num_triangles;
1565 for (j = 0;j < surface->num_triangles * 3;j++)
1566 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1567 for (j = 0;j < surface->num_vertices;j++)
1569 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1570 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1572 for (j = 0;j < loadmodel->numframes;j++)
1574 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1575 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1576 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1578 out->origin[0] = LittleShort(in->origin[0]);
1579 out->origin[1] = LittleShort(in->origin[1]);
1580 out->origin[2] = LittleShort(in->origin[2]);
1581 out->pitch = in->pitch;
1586 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1588 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1590 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1591 Mod_Alias_MorphMesh_CompileFrames();
1592 Mod_Alias_CalculateBoundingBox();
1593 Mod_FreeSkinFiles(skinfiles);
1594 Mod_MakeSortedSurfaces(loadmodel);
1596 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1597 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1600 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1602 zymtype1header_t *pinmodel, *pheader;
1603 unsigned char *pbase;
1604 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1605 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose;
1606 zymvertex_t *verts, *vertdata;
1610 skinfile_t *skinfiles;
1611 unsigned char *data;
1612 msurface_t *surface;
1614 pinmodel = (zymtype1header_t *)buffer;
1615 pbase = (unsigned char *)buffer;
1616 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1617 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1618 if (BigLong(pinmodel->type) != 1)
1619 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1621 loadmodel->modeldatatypestring = "ZYM";
1623 loadmodel->type = mod_alias;
1624 loadmodel->synctype = ST_RAND;
1628 pheader->type = BigLong(pinmodel->type);
1629 pheader->filesize = BigLong(pinmodel->filesize);
1630 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1631 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1632 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1633 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1634 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1635 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1636 pheader->radius = BigFloat(pinmodel->radius);
1637 pheader->numverts = BigLong(pinmodel->numverts);
1638 pheader->numtris = BigLong(pinmodel->numtris);
1639 pheader->numshaders = BigLong(pinmodel->numshaders);
1640 pheader->numbones = BigLong(pinmodel->numbones);
1641 pheader->numscenes = BigLong(pinmodel->numscenes);
1642 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1643 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1644 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1645 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1646 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1647 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1648 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1649 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1650 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1651 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1652 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1653 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1654 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1655 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1656 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1657 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1658 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1659 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1661 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1663 Con_Printf("%s has no geometry\n", loadmodel->name);
1666 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1668 Con_Printf("%s has no animations\n", loadmodel->name);
1672 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1673 loadmodel->DrawSky = NULL;
1674 loadmodel->DrawAddWaterPlanes = NULL;
1675 loadmodel->Draw = R_Q1BSP_Draw;
1676 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1677 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1678 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1679 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1680 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1681 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1682 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1683 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1684 loadmodel->PointSuperContents = NULL;
1686 loadmodel->numframes = pheader->numscenes;
1687 loadmodel->num_surfaces = pheader->numshaders;
1689 skinfiles = Mod_LoadSkinFiles();
1690 if (loadmodel->numskins < 1)
1691 loadmodel->numskins = 1;
1693 // make skinscenes for the skins (no groups)
1694 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1695 for (i = 0;i < loadmodel->numskins;i++)
1697 loadmodel->skinscenes[i].firstframe = i;
1698 loadmodel->skinscenes[i].framecount = 1;
1699 loadmodel->skinscenes[i].loop = true;
1700 loadmodel->skinscenes[i].framerate = 10;
1704 modelradius = pheader->radius;
1705 for (i = 0;i < 3;i++)
1707 loadmodel->normalmins[i] = pheader->mins[i];
1708 loadmodel->normalmaxs[i] = pheader->maxs[i];
1709 loadmodel->rotatedmins[i] = -modelradius;
1710 loadmodel->rotatedmaxs[i] = modelradius;
1712 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1713 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1714 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1715 if (loadmodel->yawmaxs[0] > modelradius)
1716 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1717 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1718 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1719 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1720 loadmodel->radius = modelradius;
1721 loadmodel->radius2 = modelradius * modelradius;
1723 // go through the lumps, swapping things
1725 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1726 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1727 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1728 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1729 for (i = 0;i < pheader->numscenes;i++)
1731 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1732 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1733 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1734 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1735 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1736 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1737 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1738 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1739 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1740 if (loadmodel->animscenes[i].framerate < 0)
1741 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1745 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1746 loadmodel->num_bones = pheader->numbones;
1747 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1748 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1749 for (i = 0;i < pheader->numbones;i++)
1751 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1752 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1753 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1754 if (loadmodel->data_bones[i].parent >= i)
1755 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1758 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1759 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1760 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1761 for (i = 0;i < pheader->numverts;i++)
1763 vertbonecounts[i] = BigLong(bonecount[i]);
1764 if (vertbonecounts[i] != 1)
1765 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1768 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1770 meshvertices = pheader->numverts;
1771 meshtriangles = pheader->numtris;
1773 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1774 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1775 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1776 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]));
1777 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1778 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1779 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1780 loadmodel->surfmesh.num_vertices = meshvertices;
1781 loadmodel->surfmesh.num_triangles = meshtriangles;
1782 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1783 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1784 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1785 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1786 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1787 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1788 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1789 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1790 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1791 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
1792 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1793 if (loadmodel->surfmesh.num_vertices <= 65536)
1795 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1796 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1797 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1800 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1801 poses = (float *) (pheader->lump_poses.start + pbase);
1802 for (i = 0;i < pheader->lump_poses.length / 4;i++)
1803 loadmodel->data_poses[i] = BigFloat(poses[i]);
1805 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1806 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1807 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1808 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1809 // (converting from weight-blending skeletal animation to
1810 // deformation-based skeletal animation)
1811 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1812 for (i = 0;i < loadmodel->num_bones;i++)
1814 const float *m = loadmodel->data_poses + i * 12;
1815 if (loadmodel->data_bones[i].parent >= 0)
1816 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1818 for (k = 0;k < 12;k++)
1819 bonepose[12*i+k] = m[k];
1821 for (j = 0;j < pheader->numverts;j++)
1823 // this format really should have had a per vertexweight weight value...
1824 // but since it does not, the weighting is completely ignored and
1825 // only one weight is allowed per vertex
1826 int boneindex = BigLong(vertdata[j].bonenum);
1827 const float *m = bonepose + 12 * boneindex;
1828 float relativeorigin[3];
1829 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1830 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1831 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1832 // transform the vertex bone weight into the base mesh
1833 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1834 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1835 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1836 // store the weight as the primary weight on this vertex
1837 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
1838 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = 1;
1841 // normals and tangents are calculated after elements are loaded
1843 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1844 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1845 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1846 for (i = 0;i < pheader->numverts;i++)
1848 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1849 // flip T coordinate for OpenGL
1850 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1853 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1854 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1855 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1857 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1858 //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)
1859 // byteswap, validate, and swap winding order of tris
1860 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1861 if (pheader->lump_render.length != count)
1862 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1863 renderlist = (int *) (pheader->lump_render.start + pbase);
1864 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1866 for (i = 0;i < loadmodel->num_surfaces;i++)
1868 int firstvertex, lastvertex;
1869 if (renderlist >= renderlistend)
1870 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1871 count = BigLong(*renderlist);renderlist++;
1872 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1873 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1875 loadmodel->sortedmodelsurfaces[i] = i;
1876 surface = loadmodel->data_surfaces + i;
1877 surface->texture = loadmodel->data_textures + i;
1878 surface->num_firsttriangle = meshtriangles;
1879 surface->num_triangles = count;
1880 meshtriangles += surface->num_triangles;
1882 // load the elements
1883 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
1884 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
1886 outelements[j*3+2] = BigLong(renderlist[0]);
1887 outelements[j*3+1] = BigLong(renderlist[1]);
1888 outelements[j*3+0] = BigLong(renderlist[2]);
1890 // validate the elements and find the used vertex range
1891 firstvertex = meshvertices;
1893 for (j = 0;j < surface->num_triangles * 3;j++)
1895 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
1896 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
1897 firstvertex = min(firstvertex, outelements[j]);
1898 lastvertex = max(lastvertex, outelements[j]);
1900 surface->num_firstvertex = firstvertex;
1901 surface->num_vertices = lastvertex + 1 - firstvertex;
1903 // since zym models do not have named sections, reuse their shader
1904 // name as the section name
1905 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
1906 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
1908 Mod_FreeSkinFiles(skinfiles);
1909 Mem_Free(vertbonecounts);
1911 Mod_MakeSortedSurfaces(loadmodel);
1913 // compute all the mesh information that was not loaded from the file
1914 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
1915 Mod_BuildBaseBonePoses();
1916 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
1917 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);
1918 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1920 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1923 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1925 dpmheader_t *pheader;
1929 unsigned char *pbase;
1930 int i, j, k, meshvertices, meshtriangles;
1931 skinfile_t *skinfiles;
1932 unsigned char *data;
1935 pheader = (dpmheader_t *)buffer;
1936 pbase = (unsigned char *)buffer;
1937 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
1938 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
1939 if (BigLong(pheader->type) != 2)
1940 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1942 loadmodel->modeldatatypestring = "DPM";
1944 loadmodel->type = mod_alias;
1945 loadmodel->synctype = ST_RAND;
1948 pheader->type = BigLong(pheader->type);
1949 pheader->filesize = BigLong(pheader->filesize);
1950 pheader->mins[0] = BigFloat(pheader->mins[0]);
1951 pheader->mins[1] = BigFloat(pheader->mins[1]);
1952 pheader->mins[2] = BigFloat(pheader->mins[2]);
1953 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
1954 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
1955 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
1956 pheader->yawradius = BigFloat(pheader->yawradius);
1957 pheader->allradius = BigFloat(pheader->allradius);
1958 pheader->num_bones = BigLong(pheader->num_bones);
1959 pheader->num_meshs = BigLong(pheader->num_meshs);
1960 pheader->num_frames = BigLong(pheader->num_frames);
1961 pheader->ofs_bones = BigLong(pheader->ofs_bones);
1962 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
1963 pheader->ofs_frames = BigLong(pheader->ofs_frames);
1965 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
1967 Con_Printf("%s has no geometry\n", loadmodel->name);
1970 if (pheader->num_frames < 1)
1972 Con_Printf("%s has no frames\n", loadmodel->name);
1976 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1977 loadmodel->DrawSky = NULL;
1978 loadmodel->DrawAddWaterPlanes = NULL;
1979 loadmodel->Draw = R_Q1BSP_Draw;
1980 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1981 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1982 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1983 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1984 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1985 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1986 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1987 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1988 loadmodel->PointSuperContents = NULL;
1991 for (i = 0;i < 3;i++)
1993 loadmodel->normalmins[i] = pheader->mins[i];
1994 loadmodel->normalmaxs[i] = pheader->maxs[i];
1995 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
1996 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
1997 loadmodel->rotatedmins[i] = -pheader->allradius;
1998 loadmodel->rotatedmaxs[i] = pheader->allradius;
2000 loadmodel->radius = pheader->allradius;
2001 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2003 // load external .skin files if present
2004 skinfiles = Mod_LoadSkinFiles();
2005 if (loadmodel->numskins < 1)
2006 loadmodel->numskins = 1;
2011 // gather combined statistics from the meshes
2012 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2013 for (i = 0;i < (int)pheader->num_meshs;i++)
2015 int numverts = BigLong(dpmmesh->num_verts);
2016 meshvertices += numverts;
2017 meshtriangles += BigLong(dpmmesh->num_tris);
2021 loadmodel->numframes = pheader->num_frames;
2022 loadmodel->num_bones = pheader->num_bones;
2023 loadmodel->num_poses = loadmodel->numframes;
2024 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2025 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2026 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2027 // do most allocations as one merged chunk
2028 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));
2029 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2030 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2031 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2032 loadmodel->surfmesh.num_vertices = meshvertices;
2033 loadmodel->surfmesh.num_triangles = meshtriangles;
2034 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2035 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2036 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2037 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2038 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2039 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2040 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2041 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
2042 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
2043 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
2044 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2045 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2046 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2047 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2048 if (meshvertices <= 65536)
2050 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2051 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2052 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2055 for (i = 0;i < loadmodel->numskins;i++)
2057 loadmodel->skinscenes[i].firstframe = i;
2058 loadmodel->skinscenes[i].framecount = 1;
2059 loadmodel->skinscenes[i].loop = true;
2060 loadmodel->skinscenes[i].framerate = 10;
2063 // load the bone info
2064 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2065 for (i = 0;i < loadmodel->num_bones;i++)
2067 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2068 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2069 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2070 if (loadmodel->data_bones[i].parent >= i)
2071 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2075 frame = (dpmframe_t *) (pbase + pheader->ofs_frames);
2076 for (i = 0;i < loadmodel->numframes;i++)
2079 memcpy(loadmodel->animscenes[i].name, frame->name, sizeof(frame->name));
2080 loadmodel->animscenes[i].firstframe = i;
2081 loadmodel->animscenes[i].framecount = 1;
2082 loadmodel->animscenes[i].loop = true;
2083 loadmodel->animscenes[i].framerate = 10;
2084 // load the bone poses for this frame
2085 poses = (float *) (pbase + BigLong(frame->ofs_bonepositions));
2086 for (j = 0;j < loadmodel->num_bones*12;j++)
2087 loadmodel->data_poses[i * loadmodel->num_bones*12 + j] = BigFloat(poses[j]);
2088 // stuff not processed here: mins, maxs, yawradius, allradius
2092 // load the meshes now
2093 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2096 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2097 // (converting from weight-blending skeletal animation to
2098 // deformation-based skeletal animation)
2099 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2100 for (i = 0;i < loadmodel->num_bones;i++)
2102 const float *m = loadmodel->data_poses + i * 12;
2103 if (loadmodel->data_bones[i].parent >= 0)
2104 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2106 for (k = 0;k < 12;k++)
2107 bonepose[12*i+k] = m[k];
2109 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2111 const int *inelements;
2113 const float *intexcoord;
2114 msurface_t *surface;
2116 loadmodel->sortedmodelsurfaces[i] = i;
2117 surface = loadmodel->data_surfaces + i;
2118 surface->texture = loadmodel->data_textures + i;
2119 surface->num_firsttriangle = meshtriangles;
2120 surface->num_triangles = BigLong(dpmmesh->num_tris);
2121 surface->num_firstvertex = meshvertices;
2122 surface->num_vertices = BigLong(dpmmesh->num_verts);
2123 meshvertices += surface->num_vertices;
2124 meshtriangles += surface->num_triangles;
2126 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2127 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2128 for (j = 0;j < surface->num_triangles;j++)
2130 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2131 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2132 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2133 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2138 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2139 for (j = 0;j < surface->num_vertices*2;j++)
2140 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2142 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2143 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2147 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2148 data += sizeof(dpmvertex_t);
2149 for (k = 0;k < numweights;k++)
2151 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2152 int boneindex = BigLong(vert->bonenum);
2153 const float *m = bonepose + 12 * boneindex;
2154 float influence = BigFloat(vert->influence);
2155 float relativeorigin[3], relativenormal[3];
2156 relativeorigin[0] = BigFloat(vert->origin[0]);
2157 relativeorigin[1] = BigFloat(vert->origin[1]);
2158 relativeorigin[2] = BigFloat(vert->origin[2]);
2159 relativenormal[0] = BigFloat(vert->normal[0]);
2160 relativenormal[1] = BigFloat(vert->normal[1]);
2161 relativenormal[2] = BigFloat(vert->normal[2]);
2162 // blend the vertex bone weights into the base mesh
2163 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2164 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2165 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2166 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2167 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2168 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2171 // store the first (and often only) weight
2172 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = influence;
2173 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
2177 // sort the new weight into this vertex's weight table
2178 // (which only accepts up to 4 bones per vertex)
2179 for (l = 0;l < 4;l++)
2181 if (loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] < influence)
2183 // move weaker influence weights out of the way first
2185 for (l2 = 3;l2 > l;l2--)
2187 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2-1];
2188 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2-1];
2190 // store the new weight
2191 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] = influence;
2192 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l] = boneindex;
2197 data += sizeof(dpmbonevert_t);
2200 for (l = 0;l < 4;l++)
2201 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l];
2202 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2204 float f = 1.0f / sum;
2205 for (l = 0;l < 4;l++)
2206 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] *= f;
2210 // since dpm models do not have named sections, reuse their shader name as the section name
2211 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2213 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2216 Mod_FreeSkinFiles(skinfiles);
2217 Mod_MakeSortedSurfaces(loadmodel);
2219 // compute all the mesh information that was not loaded from the file
2220 Mod_BuildBaseBonePoses();
2221 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);
2222 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2224 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2227 // no idea why PSK/PSA files contain weird quaternions but they do...
2228 #define PSKQUATNEGATIONS
2229 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2231 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2232 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2233 fs_offset_t filesize;
2238 pskboneinfo_t *bones;
2239 pskrawweights_t *rawweights;
2240 pskboneinfo_t *animbones;
2241 pskaniminfo_t *anims;
2242 pskanimkeys_t *animkeys;
2243 void *animfilebuffer, *animbuffer, *animbufferend;
2244 unsigned char *data;
2246 skinfile_t *skinfiles;
2247 char animname[MAX_QPATH];
2250 pchunk = (pskchunk_t *)buffer;
2251 if (strcmp(pchunk->id, "ACTRHEAD"))
2252 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2254 loadmodel->modeldatatypestring = "PSK";
2256 loadmodel->type = mod_alias;
2257 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2258 loadmodel->DrawSky = NULL;
2259 loadmodel->DrawAddWaterPlanes = NULL;
2260 loadmodel->Draw = R_Q1BSP_Draw;
2261 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2262 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2263 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2264 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2265 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2266 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2267 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2268 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2269 loadmodel->PointSuperContents = NULL;
2270 loadmodel->synctype = ST_RAND;
2272 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2273 strlcat(animname, ".psa", sizeof(animname));
2274 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2275 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2276 if (animbuffer == NULL)
2277 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2296 while (buffer < bufferend)
2298 pchunk = (pskchunk_t *)buffer;
2299 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2300 version = LittleLong(pchunk->version);
2301 recordsize = LittleLong(pchunk->recordsize);
2302 numrecords = LittleLong(pchunk->numrecords);
2303 if (developer.integer >= 100)
2304 Con_Printf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2305 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2306 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);
2307 if (!strcmp(pchunk->id, "ACTRHEAD"))
2311 else if (!strcmp(pchunk->id, "PNTS0000"))
2314 if (recordsize != sizeof(*p))
2315 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2316 // byteswap in place and keep the pointer
2317 numpnts = numrecords;
2318 pnts = (pskpnts_t *)buffer;
2319 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2321 p->origin[0] = LittleFloat(p->origin[0]);
2322 p->origin[1] = LittleFloat(p->origin[1]);
2323 p->origin[2] = LittleFloat(p->origin[2]);
2327 else if (!strcmp(pchunk->id, "VTXW0000"))
2330 if (recordsize != sizeof(*p))
2331 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2332 // byteswap in place and keep the pointer
2333 numvtxw = numrecords;
2334 vtxw = (pskvtxw_t *)buffer;
2335 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2337 p->pntsindex = LittleShort(p->pntsindex);
2338 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2339 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2340 if (p->pntsindex >= numpnts)
2342 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2348 else if (!strcmp(pchunk->id, "FACE0000"))
2351 if (recordsize != sizeof(*p))
2352 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2353 // byteswap in place and keep the pointer
2354 numfaces = numrecords;
2355 faces = (pskface_t *)buffer;
2356 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2358 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2359 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2360 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2361 p->group = LittleLong(p->group);
2362 if (p->vtxwindex[0] >= numvtxw)
2364 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2365 p->vtxwindex[0] = 0;
2367 if (p->vtxwindex[1] >= numvtxw)
2369 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2370 p->vtxwindex[1] = 0;
2372 if (p->vtxwindex[2] >= numvtxw)
2374 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2375 p->vtxwindex[2] = 0;
2380 else if (!strcmp(pchunk->id, "MATT0000"))
2383 if (recordsize != sizeof(*p))
2384 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2385 // byteswap in place and keep the pointer
2386 nummatts = numrecords;
2387 matts = (pskmatt_t *)buffer;
2388 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2394 else if (!strcmp(pchunk->id, "REFSKELT"))
2397 if (recordsize != sizeof(*p))
2398 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2399 // byteswap in place and keep the pointer
2400 numbones = numrecords;
2401 bones = (pskboneinfo_t *)buffer;
2402 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2404 p->numchildren = LittleLong(p->numchildren);
2405 p->parent = LittleLong(p->parent);
2406 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2407 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2408 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2409 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2410 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2411 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2412 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2413 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2414 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2415 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2416 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2417 #ifdef PSKQUATNEGATIONS
2420 p->basepose.quat[0] *= -1;
2421 p->basepose.quat[1] *= -1;
2422 p->basepose.quat[2] *= -1;
2426 p->basepose.quat[0] *= 1;
2427 p->basepose.quat[1] *= -1;
2428 p->basepose.quat[2] *= 1;
2431 if (p->parent < 0 || p->parent >= numbones)
2433 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2439 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2442 if (recordsize != sizeof(*p))
2443 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2444 // byteswap in place and keep the pointer
2445 numrawweights = numrecords;
2446 rawweights = (pskrawweights_t *)buffer;
2447 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2449 p->weight = LittleFloat(p->weight);
2450 p->pntsindex = LittleLong(p->pntsindex);
2451 p->boneindex = LittleLong(p->boneindex);
2452 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2454 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2457 if (p->boneindex < 0 || p->boneindex >= numbones)
2459 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2467 while (animbuffer < animbufferend)
2469 pchunk = (pskchunk_t *)animbuffer;
2470 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2471 version = LittleLong(pchunk->version);
2472 recordsize = LittleLong(pchunk->recordsize);
2473 numrecords = LittleLong(pchunk->numrecords);
2474 if (developer.integer >= 100)
2475 Con_Printf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2476 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2477 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);
2478 if (!strcmp(pchunk->id, "ANIMHEAD"))
2482 else if (!strcmp(pchunk->id, "BONENAMES"))
2485 if (recordsize != sizeof(*p))
2486 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2487 // byteswap in place and keep the pointer
2488 numanimbones = numrecords;
2489 animbones = (pskboneinfo_t *)animbuffer;
2490 // NOTE: supposedly psa does not need to match the psk model, the
2491 // bones missing from the psa would simply use their base
2492 // positions from the psk, but this is hard for me to implement
2493 // and people can easily make animations that match.
2494 if (numanimbones != numbones)
2495 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2496 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2498 p->numchildren = LittleLong(p->numchildren);
2499 p->parent = LittleLong(p->parent);
2500 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2501 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2502 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2503 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2504 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2505 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2506 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2507 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2508 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2509 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2510 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2511 #ifdef PSKQUATNEGATIONS
2514 p->basepose.quat[0] *= -1;
2515 p->basepose.quat[1] *= -1;
2516 p->basepose.quat[2] *= -1;
2520 p->basepose.quat[0] *= 1;
2521 p->basepose.quat[1] *= -1;
2522 p->basepose.quat[2] *= 1;
2525 if (p->parent < 0 || p->parent >= numanimbones)
2527 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2530 // check that bones are the same as in the base
2531 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2532 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2536 else if (!strcmp(pchunk->id, "ANIMINFO"))
2539 if (recordsize != sizeof(*p))
2540 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2541 // byteswap in place and keep the pointer
2542 numanims = numrecords;
2543 anims = (pskaniminfo_t *)animbuffer;
2544 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2546 p->numbones = LittleLong(p->numbones);
2547 p->playtime = LittleFloat(p->playtime);
2548 p->fps = LittleFloat(p->fps);
2549 p->firstframe = LittleLong(p->firstframe);
2550 p->numframes = LittleLong(p->numframes);
2551 if (p->numbones != numbones)
2552 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2556 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2559 if (recordsize != sizeof(*p))
2560 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2561 numanimkeys = numrecords;
2562 animkeys = (pskanimkeys_t *)animbuffer;
2563 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2565 p->origin[0] = LittleFloat(p->origin[0]);
2566 p->origin[1] = LittleFloat(p->origin[1]);
2567 p->origin[2] = LittleFloat(p->origin[2]);
2568 p->quat[0] = LittleFloat(p->quat[0]);
2569 p->quat[1] = LittleFloat(p->quat[1]);
2570 p->quat[2] = LittleFloat(p->quat[2]);
2571 p->quat[3] = LittleFloat(p->quat[3]);
2572 p->frametime = LittleFloat(p->frametime);
2573 #ifdef PSKQUATNEGATIONS
2574 if (index % numbones)
2589 // TODO: allocate bonepose stuff
2592 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2595 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2596 Host_Error("%s: missing required chunks", loadmodel->name);
2598 loadmodel->numframes = 0;
2599 for (index = 0;index < numanims;index++)
2600 loadmodel->numframes += anims[index].numframes;
2602 if (numanimkeys != numbones * loadmodel->numframes)
2603 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2605 meshvertices = numvtxw;
2606 meshtriangles = numfaces;
2608 // load external .skin files if present
2609 skinfiles = Mod_LoadSkinFiles();
2610 if (loadmodel->numskins < 1)
2611 loadmodel->numskins = 1;
2612 loadmodel->num_bones = numbones;
2613 loadmodel->num_poses = loadmodel->numframes;
2614 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2615 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2616 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2617 loadmodel->surfmesh.num_vertices = meshvertices;
2618 loadmodel->surfmesh.num_triangles = meshtriangles;
2619 // do most allocations as one merged chunk
2620 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);
2621 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2622 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2623 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2624 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2625 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2626 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2627 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2628 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2629 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2630 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2631 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2632 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += loadmodel->surfmesh.num_vertices * sizeof(int[4]);
2633 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[4]);
2634 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
2635 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2636 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2637 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2638 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2639 if (loadmodel->surfmesh.num_vertices <= 65536)
2641 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2642 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2643 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2646 for (i = 0;i < loadmodel->numskins;i++)
2648 loadmodel->skinscenes[i].firstframe = i;
2649 loadmodel->skinscenes[i].framecount = 1;
2650 loadmodel->skinscenes[i].loop = true;
2651 loadmodel->skinscenes[i].framerate = 10;
2655 for (index = 0, i = 0;index < nummatts;index++)
2657 // since psk models do not have named sections, reuse their shader name as the section name
2658 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2659 loadmodel->sortedmodelsurfaces[index] = index;
2660 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2661 loadmodel->data_surfaces[index].num_firstvertex = 0;
2662 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2665 // copy over the vertex locations and texcoords
2666 for (index = 0;index < numvtxw;index++)
2668 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2669 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2670 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2671 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2672 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2675 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2676 for (index = 0;index < numfaces;index++)
2677 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2678 for (index = 0, i = 0;index < nummatts;index++)
2680 loadmodel->data_surfaces[index].num_firsttriangle = i;
2681 i += loadmodel->data_surfaces[index].num_triangles;
2682 loadmodel->data_surfaces[index].num_triangles = 0;
2684 for (index = 0;index < numfaces;index++)
2686 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2687 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2688 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2689 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2692 // copy over the bones
2693 for (index = 0;index < numbones;index++)
2695 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2696 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2697 if (loadmodel->data_bones[index].parent >= index)
2698 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2701 // sort the psk point weights into the vertex weight tables
2702 // (which only accept up to 4 bones per vertex)
2703 for (index = 0;index < numvtxw;index++)
2707 for (j = 0;j < numrawweights;j++)
2709 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2711 int boneindex = rawweights[j].boneindex;
2712 float influence = rawweights[j].weight;
2713 for (l = 0;l < 4;l++)
2715 if (loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] < influence)
2717 // move lower influence weights out of the way first
2719 for (l2 = 3;l2 > l;l2--)
2721 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2-1];
2722 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2-1];
2724 // store the new weight
2725 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] = influence;
2726 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l] = boneindex;
2733 for (l = 0;l < 4;l++)
2734 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l];
2735 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2737 float f = 1.0f / sum;
2738 for (l = 0;l < 4;l++)
2739 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] *= f;
2743 // set up the animscenes based on the anims
2744 for (index = 0, i = 0;index < numanims;index++)
2746 for (j = 0;j < anims[index].numframes;j++, i++)
2748 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2749 loadmodel->animscenes[i].firstframe = i;
2750 loadmodel->animscenes[i].framecount = 1;
2751 loadmodel->animscenes[i].loop = true;
2752 loadmodel->animscenes[i].framerate = 10;
2756 // load the poses from the animkeys
2757 for (index = 0;index < numanimkeys;index++)
2759 pskanimkeys_t *k = animkeys + index;
2761 Matrix4x4_FromOriginQuat(&matrix, k->origin[0], k->origin[1], k->origin[2], k->quat[0], k->quat[1], k->quat[2], k->quat[3]);
2762 Matrix4x4_ToArray12FloatD3D(&matrix, loadmodel->data_poses + index*12);
2764 Mod_FreeSkinFiles(skinfiles);
2765 Mem_Free(animfilebuffer);
2766 Mod_MakeSortedSurfaces(loadmodel);
2768 // compute all the mesh information that was not loaded from the file
2769 // TODO: honor smoothing groups somehow?
2770 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2771 Mod_BuildBaseBonePoses();
2772 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2773 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);
2774 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2775 Mod_Alias_CalculateBoundingBox();
2777 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2780 void Mod_OBJ_Load(dp_model_t *mod, void *buffer, void *bufferend)
2783 const char *textbase = (char *)buffer, *text = textbase;
2787 char materialname[MAX_QPATH];
2788 int j, index1, index2, index3, first, prev, index;
2791 int numtriangles = 0;
2792 int maxtriangles = 32768;
2793 int *element3i = Mem_Alloc(tempmempool, maxtriangles * sizeof(int[3]));
2795 int numsurfaces = 0;
2796 int maxsurfaces = 0;
2797 msurface_t *surfaces = NULL;
2801 float *oldv, *oldvt, *oldvn;
2802 int maxv = 65536, numv = 1;
2803 int maxvt = 65536, numvt = 1;
2804 int maxvn = 65536, numvn = 1;
2805 int maxverthash = 65536, numverthash = 0;
2806 int numhashindex = 65536;
2807 struct objverthash_s
2809 struct objverthash_s *next;
2815 *hash, **verthash = Mem_Alloc(tempmempool, numhashindex * sizeof(*verthash)), *verthashdata = Mem_Alloc(tempmempool, maxverthash * sizeof(*verthashdata)), *oldverthashdata;
2816 skinfile_t *skinfiles;
2818 dpsnprintf(materialname, sizeof(materialname), "%s", loadmodel->name);
2820 skinfiles = Mod_LoadSkinFiles();
2822 loadmodel->modeldatatypestring = "OBJ";
2824 loadmodel->type = mod_alias;
2825 loadmodel->AnimateVertices = NULL;
2826 loadmodel->DrawSky = NULL;
2827 loadmodel->DrawAddWaterPlanes = NULL;
2828 loadmodel->Draw = R_Q1BSP_Draw;
2829 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2830 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2831 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2832 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2833 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2834 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2835 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2836 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2837 loadmodel->PointSuperContents = NULL;
2839 // parse the OBJ text now
2846 for (linelen = 0;text[linelen] && text[linelen] != '\r' && text[linelen] != '\n';linelen++)
2847 line[linelen] = text[linelen];
2849 for (argc = 0;argc < (int)(sizeof(argv)/sizeof(argv[0]));argc++)
2853 while (*s == ' ' || *s == '\t')
2863 while (*s == ' ' || *s == '\t')
2868 if (argv[0][0] == '#')
2870 if (!strcmp(argv[0], "v"))
2876 v = Mem_Alloc(tempmempool, maxv * sizeof(float[3]));
2879 memcpy(v, oldv, numv * sizeof(float[3]));
2883 v[numv*3+0] = atof(argv[1]);
2884 v[numv*3+1] = atof(argv[2]);
2885 v[numv*3+2] = atof(argv[3]);
2888 else if (!strcmp(argv[0], "vt"))
2894 vt = Mem_Alloc(tempmempool, maxvt * sizeof(float[2]));
2897 memcpy(vt, oldvt, numvt * sizeof(float[2]));
2901 vt[numvt*2+0] = atof(argv[1]);
2902 vt[numvt*2+1] = atof(argv[2]);
2905 else if (!strcmp(argv[0], "vn"))
2911 vn = Mem_Alloc(tempmempool, maxvn * sizeof(float[3]));
2914 memcpy(vn, oldvn, numvn * sizeof(float[3]));
2918 vn[numvn*3+0] = atof(argv[1]);
2919 vn[numvn*3+1] = atof(argv[2]);
2920 vn[numvn*3+2] = atof(argv[3]);
2923 else if (!strcmp(argv[0], "f"))
2927 if (maxsurfaces <= numsurfaces)
2930 oldsurfaces = surfaces;
2931 surfaces = Mem_Alloc(tempmempool, maxsurfaces * sizeof(*surfaces));
2934 memcpy(surfaces, oldsurfaces, numsurfaces * sizeof(*surfaces));
2935 Mem_Free(oldsurfaces);
2938 surface = surfaces + numsurfaces++;
2941 for (j = 1;j < argc;j++)
2943 index1 = atoi(argv[j]);
2944 while(argv[j][0] && argv[j][0] != '/')
2949 index1 = numv + 1 - index1;
2950 index2 = atoi(argv[j]);
2952 index2 = numvt + 1 - index2;
2953 while(argv[j][0] && argv[j][0] != '/')
2957 index3 = atoi(argv[j]);
2959 index3 = numvn + 1 - index3;
2960 hashindex = (index1 + index2 * 3571 + index3 * 42589) & (numhashindex - 1);
2961 for (hash = verthash[hashindex];hash;hash = hash->next)
2962 if (hash->surface == numsurfaces-1 && hash->v == index1 && hash->vt == index2 && hash->vn == index3)
2966 if (maxverthash <= numverthash)
2969 oldverthashdata = verthashdata;
2970 verthashdata = Mem_Alloc(tempmempool, maxverthash * sizeof(*verthashdata));
2971 if (oldverthashdata)
2973 memcpy(verthashdata, oldverthashdata, numverthash * sizeof(*verthashdata));
2974 Mem_Free(oldverthashdata);
2977 hash = verthashdata + numverthash++;
2978 hash->next = verthash[hashindex];
2979 hash->s = numsurfaces;
2983 verthash[hashindex] = hash;
2985 index = (int)((size_t)(hash - verthashdata));
2990 if (maxtriangles <= numtriangles)
2993 oldelement3i = element3i;
2994 element3i = Mem_Alloc(tempmempool, numtriangles * sizeof(int[3]));
2997 memcpy(element3i, oldelement3i, numtriangles * sizeof(int[3]));
2998 Mem_Free(oldelement3i);
3001 element3i[numtriangles*3+0] = first;
3002 element3i[numtriangles*3+1] = prev;
3003 element3i[numtriangles*3+2] = index;
3009 else if (!strcmp(argv[0], "o") || !strcmp(argv[0], "g"))
3011 else if (!!strcmp(argv[0], "usemtl"))
3014 strlcpy(materialname, argv[1], sizeof(materialname);
3024 Mod_FreeSkinFiles(skinfiles);
3026 // now that we have the OBJ data loaded as-is, we can convert it
3027 loadmodel->numskins = LittleLong(pinmodel->num_skins);
3028 numxyz = LittleLong(pinmodel->num_xyz);
3029 numst = LittleLong(pinmodel->num_st);
3030 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
3031 loadmodel->numframes = LittleLong(pinmodel->num_frames);
3032 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
3033 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
3034 skinwidth = LittleLong(pinmodel->skinwidth);
3035 skinheight = LittleLong(pinmodel->skinheight);
3036 iskinwidth = 1.0f / skinwidth;
3037 iskinheight = 1.0f / skinheight;
3039 loadmodel->num_surfaces = 1;
3040 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
3041 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]));
3042 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
3043 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
3044 loadmodel->sortedmodelsurfaces[0] = 0;
3045 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
3046 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
3047 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
3048 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
3050 loadmodel->synctype = ST_RAND;
3053 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
3054 skinfiles = Mod_LoadSkinFiles();
3057 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3058 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3059 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
3060 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
3061 Mod_FreeSkinFiles(skinfiles);
3063 else if (loadmodel->numskins)
3065 // skins found (most likely not a player model)
3066 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3067 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3068 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
3069 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
3070 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);
3074 // no skins (most likely a player model)
3075 loadmodel->numskins = 1;
3076 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3077 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3078 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
3079 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
3082 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
3083 for (i = 0;i < loadmodel->numskins;i++)
3085 loadmodel->skinscenes[i].firstframe = i;
3086 loadmodel->skinscenes[i].framecount = 1;
3087 loadmodel->skinscenes[i].loop = true;
3088 loadmodel->skinscenes[i].framerate = 10;
3091 // load the triangles and stvert data
3092 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
3093 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
3094 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
3095 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
3096 // swap the triangle list
3097 loadmodel->surfmesh.num_vertices = 0;
3098 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
3100 for (j = 0;j < 3;j++)
3102 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
3103 st = (unsigned short) LittleShort (intri[i].index_st[j]);
3106 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
3111 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
3114 hashindex = (xyz * 256 + st) & 65535;
3115 for (hash = md2verthash[hashindex];hash;hash = hash->next)
3116 if (hash->xyz == xyz && hash->st == st)
3120 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
3123 hash->next = md2verthash[hashindex];
3124 md2verthash[hashindex] = hash;
3126 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
3130 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
3131 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));
3132 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
3133 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
3134 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
3137 hash = md2verthashdata + i;
3138 vertremap[i] = hash->xyz;
3139 sts = LittleShort(inst[hash->st*2+0]);
3140 stt = LittleShort(inst[hash->st*2+1]);
3141 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
3143 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
3147 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
3148 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
3151 Mem_Free(md2verthash);
3152 Mem_Free(md2verthashdata);
3154 // generate ushort elements array if possible
3155 if (loadmodel->surfmesh.num_vertices <= 65536)
3157 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
3158 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3159 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3163 datapointer = (base + LittleLong(pinmodel->ofs_frames));
3164 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
3169 pinframe = (md2frame_t *)datapointer;
3170 datapointer += sizeof(md2frame_t);
3171 // store the frame scale/translate into the appropriate array
3172 for (j = 0;j < 3;j++)
3174 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
3175 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
3177 // convert the vertices
3178 v = (trivertx_t *)datapointer;
3179 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
3180 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
3181 out[k] = v[vertremap[k]];
3182 datapointer += numxyz * sizeof(trivertx_t);
3184 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
3185 loadmodel->animscenes[i].firstframe = i;
3186 loadmodel->animscenes[i].framecount = 1;
3187 loadmodel->animscenes[i].framerate = 10;
3188 loadmodel->animscenes[i].loop = true;
3191 Mem_Free(vertremap);
3193 Mod_MakeSortedSurfaces(loadmodel);
3194 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3195 Mod_Alias_CalculateBoundingBox();
3196 Mod_Alias_MorphMesh_CompileFrames();
3198 surface = loadmodel->data_surfaces;
3199 surface->texture = loadmodel->data_textures;
3200 surface->num_firsttriangle = 0;
3201 surface->num_triangles = loadmodel->surfmesh.num_triangles;
3202 surface->num_firstvertex = 0;
3203 surface->num_vertices = loadmodel->surfmesh.num_vertices;
3205 loadmodel->surfmesh.isanimated = false;