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->DrawShadowMap = R_Q1BSP_DrawShadowMap;
890 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
891 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
892 loadmodel->DrawLight = R_Q1BSP_DrawLight;
893 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
894 loadmodel->PointSuperContents = NULL;
896 loadmodel->num_surfaces = 1;
897 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
898 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
899 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
900 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
901 loadmodel->sortedmodelsurfaces[0] = 0;
903 loadmodel->numskins = LittleLong(pinmodel->numskins);
904 BOUNDI(loadmodel->numskins,0,65536);
905 skinwidth = LittleLong (pinmodel->skinwidth);
906 BOUNDI(skinwidth,0,65536);
907 skinheight = LittleLong (pinmodel->skinheight);
908 BOUNDI(skinheight,0,65536);
909 numverts = LittleLong(pinmodel->numverts);
910 BOUNDI(numverts,0,65536);
911 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
912 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
913 loadmodel->numframes = LittleLong(pinmodel->numframes);
914 BOUNDI(loadmodel->numframes,0,65536);
915 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
916 BOUNDI(loadmodel->synctype,0,2);
917 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
918 i = LittleLong (pinmodel->flags);
919 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
921 for (i = 0;i < 3;i++)
923 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
924 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
927 startskins = datapointer;
929 for (i = 0;i < loadmodel->numskins;i++)
931 pinskintype = (daliasskintype_t *)datapointer;
932 datapointer += sizeof(daliasskintype_t);
933 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
937 pinskingroup = (daliasskingroup_t *)datapointer;
938 datapointer += sizeof(daliasskingroup_t);
939 groupskins = LittleLong(pinskingroup->numskins);
940 datapointer += sizeof(daliasskininterval_t) * groupskins;
943 for (j = 0;j < groupskins;j++)
945 datapointer += skinwidth * skinheight;
950 pinstverts = (stvert_t *)datapointer;
951 datapointer += sizeof(stvert_t) * numverts;
953 pintriangles = (dtriangle_t *)datapointer;
954 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
956 startframes = datapointer;
957 loadmodel->surfmesh.num_morphframes = 0;
958 for (i = 0;i < loadmodel->numframes;i++)
960 pinframetype = (daliasframetype_t *)datapointer;
961 datapointer += sizeof(daliasframetype_t);
962 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
966 pinframegroup = (daliasgroup_t *)datapointer;
967 datapointer += sizeof(daliasgroup_t);
968 groupframes = LittleLong(pinframegroup->numframes);
969 datapointer += sizeof(daliasinterval_t) * groupframes;
972 for (j = 0;j < groupframes;j++)
974 datapointer += sizeof(daliasframe_t);
975 datapointer += sizeof(trivertx_t) * numverts;
976 loadmodel->surfmesh.num_morphframes++;
979 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
981 // store texture coordinates into temporary array, they will be stored
982 // after usage is determined (triangle data)
983 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
984 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
985 vertonseam = vertremap + numverts * 2;
987 scales = 1.0 / skinwidth;
988 scalet = 1.0 / skinheight;
989 for (i = 0;i < numverts;i++)
991 vertonseam[i] = LittleLong(pinstverts[i].onseam);
992 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
993 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
994 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
995 vertst[(i+numverts)*2+1] = vertst[i*2+1];
998 // load triangle data
999 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1001 // read the triangle elements
1002 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1003 for (j = 0;j < 3;j++)
1004 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1005 // validate (note numverts is used because this is the original data)
1006 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1007 // now butcher the elements according to vertonseam and tri->facesfront
1008 // and then compact the vertex set to remove duplicates
1009 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1010 if (!LittleLong(pintriangles[i].facesfront)) // backface
1011 for (j = 0;j < 3;j++)
1012 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1013 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1015 // (this uses vertremap to count usage to save some memory)
1016 for (i = 0;i < numverts*2;i++)
1018 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1019 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1020 // build remapping table and compact array
1021 loadmodel->surfmesh.num_vertices = 0;
1022 for (i = 0;i < numverts*2;i++)
1026 vertremap[i] = loadmodel->surfmesh.num_vertices;
1027 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1028 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1029 loadmodel->surfmesh.num_vertices++;
1032 vertremap[i] = -1; // not used at all
1034 // remap the elements to the new vertex set
1035 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1036 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1037 // store the texture coordinates
1038 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1039 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1041 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1042 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1045 // generate ushort elements array if possible
1046 if (loadmodel->surfmesh.num_vertices <= 65536)
1048 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1049 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1050 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1054 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1055 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1056 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1057 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1058 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1059 Mod_Alias_CalculateBoundingBox();
1060 Mod_Alias_MorphMesh_CompileFrames();
1063 Mem_Free(vertremap);
1066 skinfiles = Mod_LoadSkinFiles();
1069 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1070 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1071 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1072 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1073 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1074 Mod_FreeSkinFiles(skinfiles);
1075 for (i = 0;i < loadmodel->numskins;i++)
1077 loadmodel->skinscenes[i].firstframe = i;
1078 loadmodel->skinscenes[i].framecount = 1;
1079 loadmodel->skinscenes[i].loop = true;
1080 loadmodel->skinscenes[i].framerate = 10;
1085 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1086 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1087 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1088 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1090 datapointer = startskins;
1091 for (i = 0;i < loadmodel->numskins;i++)
1093 pinskintype = (daliasskintype_t *)datapointer;
1094 datapointer += sizeof(daliasskintype_t);
1096 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1103 pinskingroup = (daliasskingroup_t *)datapointer;
1104 datapointer += sizeof(daliasskingroup_t);
1106 groupskins = LittleLong (pinskingroup->numskins);
1108 pinskinintervals = (daliasskininterval_t *)datapointer;
1109 datapointer += sizeof(daliasskininterval_t) * groupskins;
1111 interval = LittleFloat(pinskinintervals[0].interval);
1112 if (interval < 0.01f)
1114 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1119 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1120 loadmodel->skinscenes[i].firstframe = totalskins;
1121 loadmodel->skinscenes[i].framecount = groupskins;
1122 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1123 loadmodel->skinscenes[i].loop = true;
1125 for (j = 0;j < groupskins;j++)
1128 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1130 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1131 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))
1132 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));
1133 datapointer += skinwidth * skinheight;
1137 // check for skins that don't exist in the model, but do exist as external images
1138 // (this was added because yummyluv kept pestering me about support for it)
1139 // TODO: support shaders here?
1140 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)))
1142 // expand the arrays to make room
1143 tempskinscenes = loadmodel->skinscenes;
1144 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1145 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1146 Mem_Free(tempskinscenes);
1148 tempaliasskins = loadmodel->data_textures;
1149 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1150 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1151 Mem_Free(tempaliasskins);
1153 // store the info about the new skin
1154 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1155 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1156 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1157 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1158 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1159 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1161 //increase skin counts
1162 loadmodel->numskins++;
1165 // fix up the pointers since they are pointing at the old textures array
1166 // FIXME: this is a hack!
1167 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1168 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1172 surface = loadmodel->data_surfaces;
1173 surface->texture = loadmodel->data_textures;
1174 surface->num_firsttriangle = 0;
1175 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1176 surface->num_firstvertex = 0;
1177 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1179 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1182 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1184 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1185 float iskinwidth, iskinheight;
1186 unsigned char *data;
1187 msurface_t *surface;
1189 unsigned char *base, *datapointer;
1190 md2frame_t *pinframe;
1192 md2triangle_t *intri;
1193 unsigned short *inst;
1194 struct md2verthash_s
1196 struct md2verthash_s *next;
1200 *hash, **md2verthash, *md2verthashdata;
1201 skinfile_t *skinfiles;
1203 pinmodel = (md2_t *)buffer;
1204 base = (unsigned char *)buffer;
1206 version = LittleLong (pinmodel->version);
1207 if (version != MD2ALIAS_VERSION)
1208 Host_Error ("%s has wrong version number (%i should be %i)",
1209 loadmodel->name, version, MD2ALIAS_VERSION);
1211 loadmodel->modeldatatypestring = "MD2";
1213 loadmodel->type = mod_alias;
1214 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1215 loadmodel->DrawSky = NULL;
1216 loadmodel->DrawAddWaterPlanes = NULL;
1217 loadmodel->Draw = R_Q1BSP_Draw;
1218 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1219 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1220 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1221 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1222 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1223 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1224 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1225 loadmodel->PointSuperContents = NULL;
1227 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1228 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1229 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1230 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1231 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1232 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1233 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1234 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1236 end = LittleLong(pinmodel->ofs_end);
1237 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1238 Host_Error ("%s is not a valid model", loadmodel->name);
1239 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1240 Host_Error ("%s is not a valid model", loadmodel->name);
1241 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1242 Host_Error ("%s is not a valid model", loadmodel->name);
1243 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1244 Host_Error ("%s is not a valid model", loadmodel->name);
1245 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1246 Host_Error ("%s is not a valid model", loadmodel->name);
1248 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1249 numxyz = LittleLong(pinmodel->num_xyz);
1250 numst = LittleLong(pinmodel->num_st);
1251 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1252 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1253 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1254 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1255 skinwidth = LittleLong(pinmodel->skinwidth);
1256 skinheight = LittleLong(pinmodel->skinheight);
1257 iskinwidth = 1.0f / skinwidth;
1258 iskinheight = 1.0f / skinheight;
1260 loadmodel->num_surfaces = 1;
1261 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1262 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]));
1263 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1264 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1265 loadmodel->sortedmodelsurfaces[0] = 0;
1266 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1267 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1268 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1269 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1271 loadmodel->synctype = ST_RAND;
1274 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1275 skinfiles = Mod_LoadSkinFiles();
1278 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1279 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1280 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1281 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1282 Mod_FreeSkinFiles(skinfiles);
1284 else if (loadmodel->numskins)
1286 // skins found (most likely not a player model)
1287 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1288 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1289 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1290 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1291 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);
1295 // no skins (most likely a player model)
1296 loadmodel->numskins = 1;
1297 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1298 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1299 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1300 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1303 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1304 for (i = 0;i < loadmodel->numskins;i++)
1306 loadmodel->skinscenes[i].firstframe = i;
1307 loadmodel->skinscenes[i].framecount = 1;
1308 loadmodel->skinscenes[i].loop = true;
1309 loadmodel->skinscenes[i].framerate = 10;
1312 // load the triangles and stvert data
1313 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1314 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1315 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1316 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1317 // swap the triangle list
1318 loadmodel->surfmesh.num_vertices = 0;
1319 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1321 for (j = 0;j < 3;j++)
1323 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1324 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1327 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1332 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1335 hashindex = (xyz * 256 + st) & 65535;
1336 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1337 if (hash->xyz == xyz && hash->st == st)
1341 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1344 hash->next = md2verthash[hashindex];
1345 md2verthash[hashindex] = hash;
1347 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1351 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1352 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));
1353 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1354 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1355 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1358 hash = md2verthashdata + i;
1359 vertremap[i] = hash->xyz;
1360 sts = LittleShort(inst[hash->st*2+0]);
1361 stt = LittleShort(inst[hash->st*2+1]);
1362 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1364 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1368 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1369 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1372 Mem_Free(md2verthash);
1373 Mem_Free(md2verthashdata);
1375 // generate ushort elements array if possible
1376 if (loadmodel->surfmesh.num_vertices <= 65536)
1378 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1379 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1380 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1384 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1385 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1390 pinframe = (md2frame_t *)datapointer;
1391 datapointer += sizeof(md2frame_t);
1392 // store the frame scale/translate into the appropriate array
1393 for (j = 0;j < 3;j++)
1395 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1396 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1398 // convert the vertices
1399 v = (trivertx_t *)datapointer;
1400 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1401 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1402 out[k] = v[vertremap[k]];
1403 datapointer += numxyz * sizeof(trivertx_t);
1405 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1406 loadmodel->animscenes[i].firstframe = i;
1407 loadmodel->animscenes[i].framecount = 1;
1408 loadmodel->animscenes[i].framerate = 10;
1409 loadmodel->animscenes[i].loop = true;
1412 Mem_Free(vertremap);
1414 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1415 Mod_Alias_CalculateBoundingBox();
1416 Mod_Alias_MorphMesh_CompileFrames();
1418 surface = loadmodel->data_surfaces;
1419 surface->texture = loadmodel->data_textures;
1420 surface->num_firsttriangle = 0;
1421 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1422 surface->num_firstvertex = 0;
1423 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1425 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1428 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1430 int i, j, k, version, meshvertices, meshtriangles;
1431 unsigned char *data;
1432 msurface_t *surface;
1433 md3modelheader_t *pinmodel;
1434 md3frameinfo_t *pinframe;
1437 skinfile_t *skinfiles;
1439 pinmodel = (md3modelheader_t *)buffer;
1441 if (memcmp(pinmodel->identifier, "IDP3", 4))
1442 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1443 version = LittleLong (pinmodel->version);
1444 if (version != MD3VERSION)
1445 Host_Error ("%s has wrong version number (%i should be %i)",
1446 loadmodel->name, version, MD3VERSION);
1448 skinfiles = Mod_LoadSkinFiles();
1449 if (loadmodel->numskins < 1)
1450 loadmodel->numskins = 1;
1452 loadmodel->modeldatatypestring = "MD3";
1454 loadmodel->type = mod_alias;
1455 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1456 loadmodel->DrawSky = NULL;
1457 loadmodel->DrawAddWaterPlanes = NULL;
1458 loadmodel->Draw = R_Q1BSP_Draw;
1459 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1460 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1461 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1462 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1463 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1464 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1465 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1466 loadmodel->PointSuperContents = NULL;
1467 loadmodel->synctype = ST_RAND;
1468 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1469 i = LittleLong (pinmodel->flags);
1470 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1472 // set up some global info about the model
1473 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1474 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1476 // make skinscenes for the skins (no groups)
1477 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1478 for (i = 0;i < loadmodel->numskins;i++)
1480 loadmodel->skinscenes[i].firstframe = i;
1481 loadmodel->skinscenes[i].framecount = 1;
1482 loadmodel->skinscenes[i].loop = true;
1483 loadmodel->skinscenes[i].framerate = 10;
1487 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1488 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1490 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1491 loadmodel->animscenes[i].firstframe = i;
1492 loadmodel->animscenes[i].framecount = 1;
1493 loadmodel->animscenes[i].framerate = 10;
1494 loadmodel->animscenes[i].loop = true;
1498 loadmodel->num_tagframes = loadmodel->numframes;
1499 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1500 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1501 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1503 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1504 for (j = 0;j < 9;j++)
1505 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1506 for (j = 0;j < 3;j++)
1507 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1508 //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);
1514 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)))
1516 if (memcmp(pinmesh->identifier, "IDP3", 4))
1517 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1518 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1519 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1520 meshvertices += LittleLong(pinmesh->num_vertices);
1521 meshtriangles += LittleLong(pinmesh->num_triangles);
1524 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1525 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1526 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1527 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));
1528 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1529 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1530 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1531 loadmodel->surfmesh.num_vertices = meshvertices;
1532 loadmodel->surfmesh.num_triangles = meshtriangles;
1533 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1534 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1535 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1536 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1537 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1538 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1539 if (meshvertices <= 65536)
1541 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1542 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1543 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1548 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)))
1550 if (memcmp(pinmesh->identifier, "IDP3", 4))
1551 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1552 loadmodel->sortedmodelsurfaces[i] = i;
1553 surface = loadmodel->data_surfaces + i;
1554 surface->texture = loadmodel->data_textures + i;
1555 surface->num_firsttriangle = meshtriangles;
1556 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1557 surface->num_firstvertex = meshvertices;
1558 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1559 meshvertices += surface->num_vertices;
1560 meshtriangles += surface->num_triangles;
1562 for (j = 0;j < surface->num_triangles * 3;j++)
1563 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1564 for (j = 0;j < surface->num_vertices;j++)
1566 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1567 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1569 for (j = 0;j < loadmodel->numframes;j++)
1571 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1572 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1573 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1575 out->origin[0] = LittleShort(in->origin[0]);
1576 out->origin[1] = LittleShort(in->origin[1]);
1577 out->origin[2] = LittleShort(in->origin[2]);
1578 out->pitch = in->pitch;
1583 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1585 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1587 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1588 Mod_Alias_MorphMesh_CompileFrames();
1589 Mod_Alias_CalculateBoundingBox();
1590 Mod_FreeSkinFiles(skinfiles);
1591 Mod_MakeSortedSurfaces(loadmodel);
1593 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1594 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1597 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1599 zymtype1header_t *pinmodel, *pheader;
1600 unsigned char *pbase;
1601 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1602 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose;
1603 zymvertex_t *verts, *vertdata;
1607 skinfile_t *skinfiles;
1608 unsigned char *data;
1609 msurface_t *surface;
1611 pinmodel = (zymtype1header_t *)buffer;
1612 pbase = (unsigned char *)buffer;
1613 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1614 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1615 if (BigLong(pinmodel->type) != 1)
1616 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1618 loadmodel->modeldatatypestring = "ZYM";
1620 loadmodel->type = mod_alias;
1621 loadmodel->synctype = ST_RAND;
1625 pheader->type = BigLong(pinmodel->type);
1626 pheader->filesize = BigLong(pinmodel->filesize);
1627 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1628 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1629 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1630 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1631 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1632 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1633 pheader->radius = BigFloat(pinmodel->radius);
1634 pheader->numverts = BigLong(pinmodel->numverts);
1635 pheader->numtris = BigLong(pinmodel->numtris);
1636 pheader->numshaders = BigLong(pinmodel->numshaders);
1637 pheader->numbones = BigLong(pinmodel->numbones);
1638 pheader->numscenes = BigLong(pinmodel->numscenes);
1639 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1640 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1641 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1642 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1643 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1644 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1645 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1646 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1647 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1648 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1649 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1650 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1651 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1652 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1653 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1654 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1655 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1656 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1658 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1660 Con_Printf("%s has no geometry\n", loadmodel->name);
1663 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1665 Con_Printf("%s has no animations\n", loadmodel->name);
1669 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1670 loadmodel->DrawSky = NULL;
1671 loadmodel->DrawAddWaterPlanes = NULL;
1672 loadmodel->Draw = R_Q1BSP_Draw;
1673 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1674 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1675 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1676 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1677 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1678 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1679 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1680 loadmodel->PointSuperContents = NULL;
1682 loadmodel->numframes = pheader->numscenes;
1683 loadmodel->num_surfaces = pheader->numshaders;
1685 skinfiles = Mod_LoadSkinFiles();
1686 if (loadmodel->numskins < 1)
1687 loadmodel->numskins = 1;
1689 // make skinscenes for the skins (no groups)
1690 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1691 for (i = 0;i < loadmodel->numskins;i++)
1693 loadmodel->skinscenes[i].firstframe = i;
1694 loadmodel->skinscenes[i].framecount = 1;
1695 loadmodel->skinscenes[i].loop = true;
1696 loadmodel->skinscenes[i].framerate = 10;
1700 modelradius = pheader->radius;
1701 for (i = 0;i < 3;i++)
1703 loadmodel->normalmins[i] = pheader->mins[i];
1704 loadmodel->normalmaxs[i] = pheader->maxs[i];
1705 loadmodel->rotatedmins[i] = -modelradius;
1706 loadmodel->rotatedmaxs[i] = modelradius;
1708 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1709 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1710 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1711 if (loadmodel->yawmaxs[0] > modelradius)
1712 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1713 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1714 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1715 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1716 loadmodel->radius = modelradius;
1717 loadmodel->radius2 = modelradius * modelradius;
1719 // go through the lumps, swapping things
1721 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1722 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1723 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1724 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1725 for (i = 0;i < pheader->numscenes;i++)
1727 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1728 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1729 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1730 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1731 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1732 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1733 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1734 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1735 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1736 if (loadmodel->animscenes[i].framerate < 0)
1737 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1741 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1742 loadmodel->num_bones = pheader->numbones;
1743 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1744 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1745 for (i = 0;i < pheader->numbones;i++)
1747 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1748 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1749 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1750 if (loadmodel->data_bones[i].parent >= i)
1751 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1754 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1755 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1756 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1757 for (i = 0;i < pheader->numverts;i++)
1759 vertbonecounts[i] = BigLong(bonecount[i]);
1760 if (vertbonecounts[i] != 1)
1761 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1764 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1766 meshvertices = pheader->numverts;
1767 meshtriangles = pheader->numtris;
1769 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1770 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1771 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1772 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]));
1773 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1774 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1775 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1776 loadmodel->surfmesh.num_vertices = meshvertices;
1777 loadmodel->surfmesh.num_triangles = meshtriangles;
1778 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1779 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1780 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1781 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1782 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1783 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1784 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1785 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1786 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1787 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
1788 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1789 if (loadmodel->surfmesh.num_vertices <= 65536)
1791 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1792 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1793 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1796 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1797 poses = (float *) (pheader->lump_poses.start + pbase);
1798 for (i = 0;i < pheader->lump_poses.length / 4;i++)
1799 loadmodel->data_poses[i] = BigFloat(poses[i]);
1801 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1802 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1803 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1804 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1805 // (converting from weight-blending skeletal animation to
1806 // deformation-based skeletal animation)
1807 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1808 for (i = 0;i < loadmodel->num_bones;i++)
1810 const float *m = loadmodel->data_poses + i * 12;
1811 if (loadmodel->data_bones[i].parent >= 0)
1812 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1814 for (k = 0;k < 12;k++)
1815 bonepose[12*i+k] = m[k];
1817 for (j = 0;j < pheader->numverts;j++)
1819 // this format really should have had a per vertexweight weight value...
1820 // but since it does not, the weighting is completely ignored and
1821 // only one weight is allowed per vertex
1822 int boneindex = BigLong(vertdata[j].bonenum);
1823 const float *m = bonepose + 12 * boneindex;
1824 float relativeorigin[3];
1825 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1826 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1827 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1828 // transform the vertex bone weight into the base mesh
1829 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1830 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1831 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1832 // store the weight as the primary weight on this vertex
1833 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
1834 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = 1;
1837 // normals and tangents are calculated after elements are loaded
1839 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1840 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1841 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1842 for (i = 0;i < pheader->numverts;i++)
1844 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1845 // flip T coordinate for OpenGL
1846 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1849 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1850 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1851 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1853 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1854 //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)
1855 // byteswap, validate, and swap winding order of tris
1856 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1857 if (pheader->lump_render.length != count)
1858 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1859 renderlist = (int *) (pheader->lump_render.start + pbase);
1860 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1862 for (i = 0;i < loadmodel->num_surfaces;i++)
1864 int firstvertex, lastvertex;
1865 if (renderlist >= renderlistend)
1866 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1867 count = BigLong(*renderlist);renderlist++;
1868 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1869 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1871 loadmodel->sortedmodelsurfaces[i] = i;
1872 surface = loadmodel->data_surfaces + i;
1873 surface->texture = loadmodel->data_textures + i;
1874 surface->num_firsttriangle = meshtriangles;
1875 surface->num_triangles = count;
1876 meshtriangles += surface->num_triangles;
1878 // load the elements
1879 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
1880 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
1882 outelements[j*3+2] = BigLong(renderlist[0]);
1883 outelements[j*3+1] = BigLong(renderlist[1]);
1884 outelements[j*3+0] = BigLong(renderlist[2]);
1886 // validate the elements and find the used vertex range
1887 firstvertex = meshvertices;
1889 for (j = 0;j < surface->num_triangles * 3;j++)
1891 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
1892 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
1893 firstvertex = min(firstvertex, outelements[j]);
1894 lastvertex = max(lastvertex, outelements[j]);
1896 surface->num_firstvertex = firstvertex;
1897 surface->num_vertices = lastvertex + 1 - firstvertex;
1899 // since zym models do not have named sections, reuse their shader
1900 // name as the section name
1901 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
1902 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
1904 Mod_FreeSkinFiles(skinfiles);
1905 Mem_Free(vertbonecounts);
1907 Mod_MakeSortedSurfaces(loadmodel);
1909 // compute all the mesh information that was not loaded from the file
1910 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
1911 Mod_BuildBaseBonePoses();
1912 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
1913 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);
1914 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1916 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1919 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1921 dpmheader_t *pheader;
1925 unsigned char *pbase;
1926 int i, j, k, meshvertices, meshtriangles;
1927 skinfile_t *skinfiles;
1928 unsigned char *data;
1931 pheader = (dpmheader_t *)buffer;
1932 pbase = (unsigned char *)buffer;
1933 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
1934 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
1935 if (BigLong(pheader->type) != 2)
1936 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1938 loadmodel->modeldatatypestring = "DPM";
1940 loadmodel->type = mod_alias;
1941 loadmodel->synctype = ST_RAND;
1944 pheader->type = BigLong(pheader->type);
1945 pheader->filesize = BigLong(pheader->filesize);
1946 pheader->mins[0] = BigFloat(pheader->mins[0]);
1947 pheader->mins[1] = BigFloat(pheader->mins[1]);
1948 pheader->mins[2] = BigFloat(pheader->mins[2]);
1949 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
1950 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
1951 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
1952 pheader->yawradius = BigFloat(pheader->yawradius);
1953 pheader->allradius = BigFloat(pheader->allradius);
1954 pheader->num_bones = BigLong(pheader->num_bones);
1955 pheader->num_meshs = BigLong(pheader->num_meshs);
1956 pheader->num_frames = BigLong(pheader->num_frames);
1957 pheader->ofs_bones = BigLong(pheader->ofs_bones);
1958 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
1959 pheader->ofs_frames = BigLong(pheader->ofs_frames);
1961 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
1963 Con_Printf("%s has no geometry\n", loadmodel->name);
1966 if (pheader->num_frames < 1)
1968 Con_Printf("%s has no frames\n", loadmodel->name);
1972 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1973 loadmodel->DrawSky = NULL;
1974 loadmodel->DrawAddWaterPlanes = NULL;
1975 loadmodel->Draw = R_Q1BSP_Draw;
1976 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1977 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1978 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1979 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1980 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1981 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1982 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1983 loadmodel->PointSuperContents = NULL;
1986 for (i = 0;i < 3;i++)
1988 loadmodel->normalmins[i] = pheader->mins[i];
1989 loadmodel->normalmaxs[i] = pheader->maxs[i];
1990 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
1991 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
1992 loadmodel->rotatedmins[i] = -pheader->allradius;
1993 loadmodel->rotatedmaxs[i] = pheader->allradius;
1995 loadmodel->radius = pheader->allradius;
1996 loadmodel->radius2 = pheader->allradius * pheader->allradius;
1998 // load external .skin files if present
1999 skinfiles = Mod_LoadSkinFiles();
2000 if (loadmodel->numskins < 1)
2001 loadmodel->numskins = 1;
2006 // gather combined statistics from the meshes
2007 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2008 for (i = 0;i < (int)pheader->num_meshs;i++)
2010 int numverts = BigLong(dpmmesh->num_verts);
2011 meshvertices += numverts;
2012 meshtriangles += BigLong(dpmmesh->num_tris);
2016 loadmodel->numframes = pheader->num_frames;
2017 loadmodel->num_bones = pheader->num_bones;
2018 loadmodel->num_poses = loadmodel->numframes;
2019 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2020 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2021 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2022 // do most allocations as one merged chunk
2023 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));
2024 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2025 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2026 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2027 loadmodel->surfmesh.num_vertices = meshvertices;
2028 loadmodel->surfmesh.num_triangles = meshtriangles;
2029 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2030 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2031 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2032 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2033 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2034 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2035 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2036 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
2037 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
2038 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
2039 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2040 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2041 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2042 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2043 if (meshvertices <= 65536)
2045 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2046 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2047 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2050 for (i = 0;i < loadmodel->numskins;i++)
2052 loadmodel->skinscenes[i].firstframe = i;
2053 loadmodel->skinscenes[i].framecount = 1;
2054 loadmodel->skinscenes[i].loop = true;
2055 loadmodel->skinscenes[i].framerate = 10;
2058 // load the bone info
2059 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2060 for (i = 0;i < loadmodel->num_bones;i++)
2062 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2063 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2064 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2065 if (loadmodel->data_bones[i].parent >= i)
2066 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2070 frame = (dpmframe_t *) (pbase + pheader->ofs_frames);
2071 for (i = 0;i < loadmodel->numframes;i++)
2074 memcpy(loadmodel->animscenes[i].name, frame->name, sizeof(frame->name));
2075 loadmodel->animscenes[i].firstframe = i;
2076 loadmodel->animscenes[i].framecount = 1;
2077 loadmodel->animscenes[i].loop = true;
2078 loadmodel->animscenes[i].framerate = 10;
2079 // load the bone poses for this frame
2080 poses = (float *) (pbase + BigLong(frame->ofs_bonepositions));
2081 for (j = 0;j < loadmodel->num_bones*12;j++)
2082 loadmodel->data_poses[i * loadmodel->num_bones*12 + j] = BigFloat(poses[j]);
2083 // stuff not processed here: mins, maxs, yawradius, allradius
2087 // load the meshes now
2088 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2091 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2092 // (converting from weight-blending skeletal animation to
2093 // deformation-based skeletal animation)
2094 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2095 for (i = 0;i < loadmodel->num_bones;i++)
2097 const float *m = loadmodel->data_poses + i * 12;
2098 if (loadmodel->data_bones[i].parent >= 0)
2099 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2101 for (k = 0;k < 12;k++)
2102 bonepose[12*i+k] = m[k];
2104 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2106 const int *inelements;
2108 const float *intexcoord;
2109 msurface_t *surface;
2111 loadmodel->sortedmodelsurfaces[i] = i;
2112 surface = loadmodel->data_surfaces + i;
2113 surface->texture = loadmodel->data_textures + i;
2114 surface->num_firsttriangle = meshtriangles;
2115 surface->num_triangles = BigLong(dpmmesh->num_tris);
2116 surface->num_firstvertex = meshvertices;
2117 surface->num_vertices = BigLong(dpmmesh->num_verts);
2118 meshvertices += surface->num_vertices;
2119 meshtriangles += surface->num_triangles;
2121 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2122 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2123 for (j = 0;j < surface->num_triangles;j++)
2125 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2126 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2127 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2128 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2133 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2134 for (j = 0;j < surface->num_vertices*2;j++)
2135 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2137 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2138 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2142 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2143 data += sizeof(dpmvertex_t);
2144 for (k = 0;k < numweights;k++)
2146 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2147 int boneindex = BigLong(vert->bonenum);
2148 const float *m = bonepose + 12 * boneindex;
2149 float influence = BigFloat(vert->influence);
2150 float relativeorigin[3], relativenormal[3];
2151 relativeorigin[0] = BigFloat(vert->origin[0]);
2152 relativeorigin[1] = BigFloat(vert->origin[1]);
2153 relativeorigin[2] = BigFloat(vert->origin[2]);
2154 relativenormal[0] = BigFloat(vert->normal[0]);
2155 relativenormal[1] = BigFloat(vert->normal[1]);
2156 relativenormal[2] = BigFloat(vert->normal[2]);
2157 // blend the vertex bone weights into the base mesh
2158 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2159 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2160 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2161 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2162 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2163 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2166 // store the first (and often only) weight
2167 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = influence;
2168 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
2172 // sort the new weight into this vertex's weight table
2173 // (which only accepts up to 4 bones per vertex)
2174 for (l = 0;l < 4;l++)
2176 if (loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] < influence)
2178 // move weaker influence weights out of the way first
2180 for (l2 = 3;l2 > l;l2--)
2182 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2-1];
2183 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2-1];
2185 // store the new weight
2186 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] = influence;
2187 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l] = boneindex;
2192 data += sizeof(dpmbonevert_t);
2195 for (l = 0;l < 4;l++)
2196 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l];
2197 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2199 float f = 1.0f / sum;
2200 for (l = 0;l < 4;l++)
2201 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] *= f;
2205 // since dpm models do not have named sections, reuse their shader name as the section name
2206 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2208 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2211 Mod_FreeSkinFiles(skinfiles);
2212 Mod_MakeSortedSurfaces(loadmodel);
2214 // compute all the mesh information that was not loaded from the file
2215 Mod_BuildBaseBonePoses();
2216 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);
2217 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2219 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2222 // no idea why PSK/PSA files contain weird quaternions but they do...
2223 #define PSKQUATNEGATIONS
2224 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2226 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2227 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2228 fs_offset_t filesize;
2233 pskboneinfo_t *bones;
2234 pskrawweights_t *rawweights;
2235 pskboneinfo_t *animbones;
2236 pskaniminfo_t *anims;
2237 pskanimkeys_t *animkeys;
2238 void *animfilebuffer, *animbuffer, *animbufferend;
2239 unsigned char *data;
2241 skinfile_t *skinfiles;
2242 char animname[MAX_QPATH];
2245 pchunk = (pskchunk_t *)buffer;
2246 if (strcmp(pchunk->id, "ACTRHEAD"))
2247 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2249 loadmodel->modeldatatypestring = "PSK";
2251 loadmodel->type = mod_alias;
2252 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2253 loadmodel->DrawSky = NULL;
2254 loadmodel->DrawAddWaterPlanes = NULL;
2255 loadmodel->Draw = R_Q1BSP_Draw;
2256 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2257 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2258 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2259 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2260 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2261 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2262 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2263 loadmodel->PointSuperContents = NULL;
2264 loadmodel->synctype = ST_RAND;
2266 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2267 strlcat(animname, ".psa", sizeof(animname));
2268 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2269 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2270 if (animbuffer == NULL)
2271 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2290 while (buffer < bufferend)
2292 pchunk = (pskchunk_t *)buffer;
2293 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2294 version = LittleLong(pchunk->version);
2295 recordsize = LittleLong(pchunk->recordsize);
2296 numrecords = LittleLong(pchunk->numrecords);
2297 if (developer.integer >= 100)
2298 Con_Printf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2299 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2300 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);
2301 if (!strcmp(pchunk->id, "ACTRHEAD"))
2305 else if (!strcmp(pchunk->id, "PNTS0000"))
2308 if (recordsize != sizeof(*p))
2309 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2310 // byteswap in place and keep the pointer
2311 numpnts = numrecords;
2312 pnts = (pskpnts_t *)buffer;
2313 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2315 p->origin[0] = LittleFloat(p->origin[0]);
2316 p->origin[1] = LittleFloat(p->origin[1]);
2317 p->origin[2] = LittleFloat(p->origin[2]);
2321 else if (!strcmp(pchunk->id, "VTXW0000"))
2324 if (recordsize != sizeof(*p))
2325 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2326 // byteswap in place and keep the pointer
2327 numvtxw = numrecords;
2328 vtxw = (pskvtxw_t *)buffer;
2329 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2331 p->pntsindex = LittleShort(p->pntsindex);
2332 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2333 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2334 if (p->pntsindex >= numpnts)
2336 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2342 else if (!strcmp(pchunk->id, "FACE0000"))
2345 if (recordsize != sizeof(*p))
2346 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2347 // byteswap in place and keep the pointer
2348 numfaces = numrecords;
2349 faces = (pskface_t *)buffer;
2350 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2352 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2353 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2354 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2355 p->group = LittleLong(p->group);
2356 if (p->vtxwindex[0] >= numvtxw)
2358 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2359 p->vtxwindex[0] = 0;
2361 if (p->vtxwindex[1] >= numvtxw)
2363 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2364 p->vtxwindex[1] = 0;
2366 if (p->vtxwindex[2] >= numvtxw)
2368 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2369 p->vtxwindex[2] = 0;
2374 else if (!strcmp(pchunk->id, "MATT0000"))
2377 if (recordsize != sizeof(*p))
2378 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2379 // byteswap in place and keep the pointer
2380 nummatts = numrecords;
2381 matts = (pskmatt_t *)buffer;
2382 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2388 else if (!strcmp(pchunk->id, "REFSKELT"))
2391 if (recordsize != sizeof(*p))
2392 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2393 // byteswap in place and keep the pointer
2394 numbones = numrecords;
2395 bones = (pskboneinfo_t *)buffer;
2396 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2398 p->numchildren = LittleLong(p->numchildren);
2399 p->parent = LittleLong(p->parent);
2400 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2401 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2402 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2403 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2404 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2405 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2406 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2407 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2408 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2409 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2410 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2411 #ifdef PSKQUATNEGATIONS
2414 p->basepose.quat[0] *= -1;
2415 p->basepose.quat[1] *= -1;
2416 p->basepose.quat[2] *= -1;
2420 p->basepose.quat[0] *= 1;
2421 p->basepose.quat[1] *= -1;
2422 p->basepose.quat[2] *= 1;
2425 if (p->parent < 0 || p->parent >= numbones)
2427 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2433 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2436 if (recordsize != sizeof(*p))
2437 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2438 // byteswap in place and keep the pointer
2439 numrawweights = numrecords;
2440 rawweights = (pskrawweights_t *)buffer;
2441 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2443 p->weight = LittleFloat(p->weight);
2444 p->pntsindex = LittleLong(p->pntsindex);
2445 p->boneindex = LittleLong(p->boneindex);
2446 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2448 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2451 if (p->boneindex < 0 || p->boneindex >= numbones)
2453 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2461 while (animbuffer < animbufferend)
2463 pchunk = (pskchunk_t *)animbuffer;
2464 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2465 version = LittleLong(pchunk->version);
2466 recordsize = LittleLong(pchunk->recordsize);
2467 numrecords = LittleLong(pchunk->numrecords);
2468 if (developer.integer >= 100)
2469 Con_Printf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2470 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2471 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);
2472 if (!strcmp(pchunk->id, "ANIMHEAD"))
2476 else if (!strcmp(pchunk->id, "BONENAMES"))
2479 if (recordsize != sizeof(*p))
2480 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2481 // byteswap in place and keep the pointer
2482 numanimbones = numrecords;
2483 animbones = (pskboneinfo_t *)animbuffer;
2484 // NOTE: supposedly psa does not need to match the psk model, the
2485 // bones missing from the psa would simply use their base
2486 // positions from the psk, but this is hard for me to implement
2487 // and people can easily make animations that match.
2488 if (numanimbones != numbones)
2489 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2490 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2492 p->numchildren = LittleLong(p->numchildren);
2493 p->parent = LittleLong(p->parent);
2494 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2495 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2496 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2497 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2498 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2499 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2500 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2501 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2502 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2503 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2504 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2505 #ifdef PSKQUATNEGATIONS
2508 p->basepose.quat[0] *= -1;
2509 p->basepose.quat[1] *= -1;
2510 p->basepose.quat[2] *= -1;
2514 p->basepose.quat[0] *= 1;
2515 p->basepose.quat[1] *= -1;
2516 p->basepose.quat[2] *= 1;
2519 if (p->parent < 0 || p->parent >= numanimbones)
2521 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2524 // check that bones are the same as in the base
2525 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2526 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2530 else if (!strcmp(pchunk->id, "ANIMINFO"))
2533 if (recordsize != sizeof(*p))
2534 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2535 // byteswap in place and keep the pointer
2536 numanims = numrecords;
2537 anims = (pskaniminfo_t *)animbuffer;
2538 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2540 p->numbones = LittleLong(p->numbones);
2541 p->playtime = LittleFloat(p->playtime);
2542 p->fps = LittleFloat(p->fps);
2543 p->firstframe = LittleLong(p->firstframe);
2544 p->numframes = LittleLong(p->numframes);
2545 if (p->numbones != numbones)
2546 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2550 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2553 if (recordsize != sizeof(*p))
2554 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2555 numanimkeys = numrecords;
2556 animkeys = (pskanimkeys_t *)animbuffer;
2557 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2559 p->origin[0] = LittleFloat(p->origin[0]);
2560 p->origin[1] = LittleFloat(p->origin[1]);
2561 p->origin[2] = LittleFloat(p->origin[2]);
2562 p->quat[0] = LittleFloat(p->quat[0]);
2563 p->quat[1] = LittleFloat(p->quat[1]);
2564 p->quat[2] = LittleFloat(p->quat[2]);
2565 p->quat[3] = LittleFloat(p->quat[3]);
2566 p->frametime = LittleFloat(p->frametime);
2567 #ifdef PSKQUATNEGATIONS
2568 if (index % numbones)
2583 // TODO: allocate bonepose stuff
2586 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2589 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2590 Host_Error("%s: missing required chunks", loadmodel->name);
2592 loadmodel->numframes = 0;
2593 for (index = 0;index < numanims;index++)
2594 loadmodel->numframes += anims[index].numframes;
2596 if (numanimkeys != numbones * loadmodel->numframes)
2597 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2599 meshvertices = numvtxw;
2600 meshtriangles = numfaces;
2602 // load external .skin files if present
2603 skinfiles = Mod_LoadSkinFiles();
2604 if (loadmodel->numskins < 1)
2605 loadmodel->numskins = 1;
2606 loadmodel->num_bones = numbones;
2607 loadmodel->num_poses = loadmodel->numframes;
2608 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2609 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2610 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2611 loadmodel->surfmesh.num_vertices = meshvertices;
2612 loadmodel->surfmesh.num_triangles = meshtriangles;
2613 // do most allocations as one merged chunk
2614 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);
2615 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2616 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2617 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2618 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2619 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2620 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2621 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2622 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2623 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2624 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2625 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2626 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += loadmodel->surfmesh.num_vertices * sizeof(int[4]);
2627 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[4]);
2628 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
2629 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2630 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2631 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2632 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2633 if (loadmodel->surfmesh.num_vertices <= 65536)
2635 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2636 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2637 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2640 for (i = 0;i < loadmodel->numskins;i++)
2642 loadmodel->skinscenes[i].firstframe = i;
2643 loadmodel->skinscenes[i].framecount = 1;
2644 loadmodel->skinscenes[i].loop = true;
2645 loadmodel->skinscenes[i].framerate = 10;
2649 for (index = 0, i = 0;index < nummatts;index++)
2651 // since psk models do not have named sections, reuse their shader name as the section name
2652 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2653 loadmodel->sortedmodelsurfaces[index] = index;
2654 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2655 loadmodel->data_surfaces[index].num_firstvertex = 0;
2656 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2659 // copy over the vertex locations and texcoords
2660 for (index = 0;index < numvtxw;index++)
2662 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2663 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2664 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2665 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2666 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2669 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2670 for (index = 0;index < numfaces;index++)
2671 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2672 for (index = 0, i = 0;index < nummatts;index++)
2674 loadmodel->data_surfaces[index].num_firsttriangle = i;
2675 i += loadmodel->data_surfaces[index].num_triangles;
2676 loadmodel->data_surfaces[index].num_triangles = 0;
2678 for (index = 0;index < numfaces;index++)
2680 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2681 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2682 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2683 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2686 // copy over the bones
2687 for (index = 0;index < numbones;index++)
2689 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2690 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2691 if (loadmodel->data_bones[index].parent >= index)
2692 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2695 // sort the psk point weights into the vertex weight tables
2696 // (which only accept up to 4 bones per vertex)
2697 for (index = 0;index < numvtxw;index++)
2701 for (j = 0;j < numrawweights;j++)
2703 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2705 int boneindex = rawweights[j].boneindex;
2706 float influence = rawweights[j].weight;
2707 for (l = 0;l < 4;l++)
2709 if (loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] < influence)
2711 // move lower influence weights out of the way first
2713 for (l2 = 3;l2 > l;l2--)
2715 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2-1];
2716 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2-1];
2718 // store the new weight
2719 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] = influence;
2720 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l] = boneindex;
2727 for (l = 0;l < 4;l++)
2728 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l];
2729 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2731 float f = 1.0f / sum;
2732 for (l = 0;l < 4;l++)
2733 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] *= f;
2737 // set up the animscenes based on the anims
2738 for (index = 0, i = 0;index < numanims;index++)
2740 for (j = 0;j < anims[index].numframes;j++, i++)
2742 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2743 loadmodel->animscenes[i].firstframe = i;
2744 loadmodel->animscenes[i].framecount = 1;
2745 loadmodel->animscenes[i].loop = true;
2746 loadmodel->animscenes[i].framerate = 10;
2750 // load the poses from the animkeys
2751 for (index = 0;index < numanimkeys;index++)
2753 pskanimkeys_t *k = animkeys + index;
2755 Matrix4x4_FromOriginQuat(&matrix, k->origin[0], k->origin[1], k->origin[2], k->quat[0], k->quat[1], k->quat[2], k->quat[3]);
2756 Matrix4x4_ToArray12FloatD3D(&matrix, loadmodel->data_poses + index*12);
2758 Mod_FreeSkinFiles(skinfiles);
2759 Mem_Free(animfilebuffer);
2760 Mod_MakeSortedSurfaces(loadmodel);
2762 // compute all the mesh information that was not loaded from the file
2763 // TODO: honor smoothing groups somehow?
2764 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2765 Mod_BuildBaseBonePoses();
2766 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2767 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);
2768 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2769 Mod_Alias_CalculateBoundingBox();
2771 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2774 void Mod_OBJ_Load(dp_model_t *mod, void *buffer, void *bufferend)
2777 const char *textbase = (char *)buffer, *text = textbase;
2781 char materialname[MAX_QPATH];
2782 int j, index1, index2, index3, first, prev, index;
2785 int numtriangles = 0;
2786 int maxtriangles = 32768;
2787 int *element3i = Mem_Alloc(tempmempool, maxtriangles * sizeof(int[3]));
2789 int numsurfaces = 0;
2790 int maxsurfaces = 0;
2791 msurface_t *surfaces = NULL;
2795 float *oldv, *oldvt, *oldvn;
2796 int maxv = 65536, numv = 1;
2797 int maxvt = 65536, numvt = 1;
2798 int maxvn = 65536, numvn = 1;
2799 int maxverthash = 65536, numverthash = 0;
2800 int numhashindex = 65536;
2801 struct objverthash_s
2803 struct objverthash_s *next;
2809 *hash, **verthash = Mem_Alloc(tempmempool, numhashindex * sizeof(*verthash)), *verthashdata = Mem_Alloc(tempmempool, maxverthash * sizeof(*verthashdata)), *oldverthashdata;
2810 skinfile_t *skinfiles;
2812 dpsnprintf(materialname, sizeof(materialname), "%s", loadmodel->name);
2814 skinfiles = Mod_LoadSkinFiles();
2816 loadmodel->modeldatatypestring = "OBJ";
2818 loadmodel->type = mod_alias;
2819 loadmodel->AnimateVertices = NULL;
2820 loadmodel->DrawSky = NULL;
2821 loadmodel->DrawAddWaterPlanes = NULL;
2822 loadmodel->Draw = R_Q1BSP_Draw;
2823 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2824 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2825 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2826 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2827 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2828 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2829 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2830 loadmodel->PointSuperContents = NULL;
2832 // parse the OBJ text now
2839 for (linelen = 0;text[linelen] && text[linelen] != '\r' && text[linelen] != '\n';linelen++)
2840 line[linelen] = text[linelen];
2842 for (argc = 0;argc < (int)(sizeof(argv)/sizeof(argv[0]));argc++)
2846 while (*s == ' ' || *s == '\t')
2856 while (*s == ' ' || *s == '\t')
2861 if (argv[0][0] == '#')
2863 if (!strcmp(argv[0], "v"))
2869 v = Mem_Alloc(tempmempool, maxv * sizeof(float[3]));
2872 memcpy(v, oldv, numv * sizeof(float[3]));
2876 v[numv*3+0] = atof(argv[1]);
2877 v[numv*3+1] = atof(argv[2]);
2878 v[numv*3+2] = atof(argv[3]);
2881 else if (!strcmp(argv[0], "vt"))
2887 vt = Mem_Alloc(tempmempool, maxvt * sizeof(float[2]));
2890 memcpy(vt, oldvt, numvt * sizeof(float[2]));
2894 vt[numvt*2+0] = atof(argv[1]);
2895 vt[numvt*2+1] = atof(argv[2]);
2898 else if (!strcmp(argv[0], "vn"))
2904 vn = Mem_Alloc(tempmempool, maxvn * sizeof(float[3]));
2907 memcpy(vn, oldvn, numvn * sizeof(float[3]));
2911 vn[numvn*3+0] = atof(argv[1]);
2912 vn[numvn*3+1] = atof(argv[2]);
2913 vn[numvn*3+2] = atof(argv[3]);
2916 else if (!strcmp(argv[0], "f"))
2920 if (maxsurfaces <= numsurfaces)
2923 oldsurfaces = surfaces;
2924 surfaces = Mem_Alloc(tempmempool, maxsurfaces * sizeof(*surfaces));
2927 memcpy(surfaces, oldsurfaces, numsurfaces * sizeof(*surfaces));
2928 Mem_Free(oldsurfaces);
2931 surface = surfaces + numsurfaces++;
2934 for (j = 1;j < argc;j++)
2936 index1 = atoi(argv[j]);
2937 while(argv[j][0] && argv[j][0] != '/')
2942 index1 = numv + 1 - index1;
2943 index2 = atoi(argv[j]);
2945 index2 = numvt + 1 - index2;
2946 while(argv[j][0] && argv[j][0] != '/')
2950 index3 = atoi(argv[j]);
2952 index3 = numvn + 1 - index3;
2953 hashindex = (index1 + index2 * 3571 + index3 * 42589) & (numhashindex - 1);
2954 for (hash = verthash[hashindex];hash;hash = hash->next)
2955 if (hash->surface == numsurfaces-1 && hash->v == index1 && hash->vt == index2 && hash->vn == index3)
2959 if (maxverthash <= numverthash)
2962 oldverthashdata = verthashdata;
2963 verthashdata = Mem_Alloc(tempmempool, maxverthash * sizeof(*verthashdata));
2964 if (oldverthashdata)
2966 memcpy(verthashdata, oldverthashdata, numverthash * sizeof(*verthashdata));
2967 Mem_Free(oldverthashdata);
2970 hash = verthashdata + numverthash++;
2971 hash->next = verthash[hashindex];
2972 hash->s = numsurfaces;
2976 verthash[hashindex] = hash;
2978 index = (int)((size_t)(hash - verthashdata));
2983 if (maxtriangles <= numtriangles)
2986 oldelement3i = element3i;
2987 element3i = Mem_Alloc(tempmempool, numtriangles * sizeof(int[3]));
2990 memcpy(element3i, oldelement3i, numtriangles * sizeof(int[3]));
2991 Mem_Free(oldelement3i);
2994 element3i[numtriangles*3+0] = first;
2995 element3i[numtriangles*3+1] = prev;
2996 element3i[numtriangles*3+2] = index;
3002 else if (!strcmp(argv[0], "o") || !strcmp(argv[0], "g"))
3004 else if (!!strcmp(argv[0], "usemtl"))
3007 strlcpy(materialname, argv[1], sizeof(materialname);
3017 Mod_FreeSkinFiles(skinfiles);
3019 // now that we have the OBJ data loaded as-is, we can convert it
3020 loadmodel->numskins = LittleLong(pinmodel->num_skins);
3021 numxyz = LittleLong(pinmodel->num_xyz);
3022 numst = LittleLong(pinmodel->num_st);
3023 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
3024 loadmodel->numframes = LittleLong(pinmodel->num_frames);
3025 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
3026 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
3027 skinwidth = LittleLong(pinmodel->skinwidth);
3028 skinheight = LittleLong(pinmodel->skinheight);
3029 iskinwidth = 1.0f / skinwidth;
3030 iskinheight = 1.0f / skinheight;
3032 loadmodel->num_surfaces = 1;
3033 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
3034 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]));
3035 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
3036 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
3037 loadmodel->sortedmodelsurfaces[0] = 0;
3038 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
3039 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
3040 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
3041 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
3043 loadmodel->synctype = ST_RAND;
3046 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
3047 skinfiles = Mod_LoadSkinFiles();
3050 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3051 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3052 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
3053 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
3054 Mod_FreeSkinFiles(skinfiles);
3056 else if (loadmodel->numskins)
3058 // skins found (most likely not a player model)
3059 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3060 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3061 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
3062 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
3063 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);
3067 // no skins (most likely a player model)
3068 loadmodel->numskins = 1;
3069 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3070 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3071 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
3072 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
3075 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
3076 for (i = 0;i < loadmodel->numskins;i++)
3078 loadmodel->skinscenes[i].firstframe = i;
3079 loadmodel->skinscenes[i].framecount = 1;
3080 loadmodel->skinscenes[i].loop = true;
3081 loadmodel->skinscenes[i].framerate = 10;
3084 // load the triangles and stvert data
3085 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
3086 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
3087 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
3088 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
3089 // swap the triangle list
3090 loadmodel->surfmesh.num_vertices = 0;
3091 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
3093 for (j = 0;j < 3;j++)
3095 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
3096 st = (unsigned short) LittleShort (intri[i].index_st[j]);
3099 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
3104 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
3107 hashindex = (xyz * 256 + st) & 65535;
3108 for (hash = md2verthash[hashindex];hash;hash = hash->next)
3109 if (hash->xyz == xyz && hash->st == st)
3113 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
3116 hash->next = md2verthash[hashindex];
3117 md2verthash[hashindex] = hash;
3119 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
3123 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
3124 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));
3125 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
3126 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
3127 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
3130 hash = md2verthashdata + i;
3131 vertremap[i] = hash->xyz;
3132 sts = LittleShort(inst[hash->st*2+0]);
3133 stt = LittleShort(inst[hash->st*2+1]);
3134 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
3136 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
3140 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
3141 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
3144 Mem_Free(md2verthash);
3145 Mem_Free(md2verthashdata);
3147 // generate ushort elements array if possible
3148 if (loadmodel->surfmesh.num_vertices <= 65536)
3150 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
3151 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3152 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3156 datapointer = (base + LittleLong(pinmodel->ofs_frames));
3157 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
3162 pinframe = (md2frame_t *)datapointer;
3163 datapointer += sizeof(md2frame_t);
3164 // store the frame scale/translate into the appropriate array
3165 for (j = 0;j < 3;j++)
3167 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
3168 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
3170 // convert the vertices
3171 v = (trivertx_t *)datapointer;
3172 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
3173 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
3174 out[k] = v[vertremap[k]];
3175 datapointer += numxyz * sizeof(trivertx_t);
3177 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
3178 loadmodel->animscenes[i].firstframe = i;
3179 loadmodel->animscenes[i].framecount = 1;
3180 loadmodel->animscenes[i].framerate = 10;
3181 loadmodel->animscenes[i].loop = true;
3184 Mem_Free(vertremap);
3186 Mod_MakeSortedSurfaces(loadmodel);
3187 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3188 Mod_Alias_CalculateBoundingBox();
3189 Mod_Alias_MorphMesh_CompileFrames();
3191 surface = loadmodel->data_surfaces;
3192 surface->texture = loadmodel->data_textures;
3193 surface->num_firsttriangle = 0;
3194 surface->num_triangles = loadmodel->surfmesh.num_triangles;
3195 surface->num_firstvertex = 0;
3196 surface->num_vertices = loadmodel->surfmesh.num_vertices;
3198 loadmodel->surfmesh.isanimated = false;