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 int Mod_Skeletal_AddBlend(dp_model_t *model, const int *newindex, const float *newinfluence)
53 blendweights_t *weights;
54 blendweights_t newweights;
59 scale += newinfluence[i];
60 scale = 255.0f / scale;
64 newweights.index[i] = newindex[i];
65 newweights.influence[i] = (unsigned char)(newinfluence[i] * scale);
66 total += newweights.influence[i];
72 if(newweights.influence[i] > 0 && total > 255)
74 newweights.influence[i]--;
81 for (i = 0; i < 4;i++)
83 if(newweights.influence[i] < 255 && total < 255)
85 newweights.influence[i]++;
90 weights = model->surfmesh.data_blendweights;
91 for (i = 0;i < model->surfmesh.num_blends;i++, weights++)
93 if (!memcmp(weights, &newweights, sizeof(blendweights_t)))
94 return model->num_bones + i;
96 model->surfmesh.num_blends++;
97 memcpy(weights, &newweights, sizeof(blendweights_t));
98 return model->num_bones + i;
101 static int maxbonepose = 0;
102 static float (*bonepose)[12] = NULL;
104 void Mod_Skeletal_FreeBuffers(void)
112 void Mod_Skeletal_AnimateVertices(const dp_model_t * RESTRICT model, const frameblend_t * RESTRICT frameblend, const skeleton_t *skeleton, float * RESTRICT vertex3f, float * RESTRICT normal3f, float * RESTRICT svector3f, float * RESTRICT tvector3f)
114 // vertex weighted skeletal
118 float (*boneposerelative)[12];
119 const blendweights_t * RESTRICT weights;
121 if (maxbonepose < model->num_bones*2 + model->surfmesh.num_blends)
125 maxbonepose = model->num_bones*2 + model->surfmesh.num_blends;
126 bonepose = (float (*)[12])Mem_Alloc(r_main_mempool, maxbonepose * sizeof(float[12]));
129 boneposerelative = bonepose + model->num_bones;
131 if (skeleton && !skeleton->relativetransforms)
134 // interpolate matrices
137 for (i = 0;i < model->num_bones;i++)
139 Matrix4x4_ToArray12FloatD3D(&skeleton->relativetransforms[i], m);
140 if (model->data_bones[i].parent >= 0)
141 R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
143 memcpy(bonepose[i], m, sizeof(m));
145 // create a relative deformation matrix to describe displacement
146 // from the base mesh, which is used by the actual weighting
147 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]);
152 float originscale = model->num_posescale;
154 const short * RESTRICT pose6s;
155 for (i = 0;i < model->num_bones;i++)
157 memset(m, 0, sizeof(m));
158 for (blends = 0;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++)
160 pose6s = model->data_poses6s + 6 * (frameblend[blends].subframe * model->num_bones + i);
161 lerp = frameblend[blends].lerp;
162 x = pose6s[3] * (1.0f / 32767.0f);
163 y = pose6s[4] * (1.0f / 32767.0f);
164 z = pose6s[5] * (1.0f / 32767.0f);
165 w = 1.0f - (x*x+y*y+z*z);
166 w = w > 0.0f ? -sqrt(w) : 0.0f;
167 m[ 0] += (1-2*(y*y+z*z)) * lerp;
168 m[ 1] += ( 2*(x*y-z*w)) * lerp;
169 m[ 2] += ( 2*(x*z+y*w)) * lerp;
170 m[ 3] += (pose6s[0] * originscale) * lerp;
171 m[ 4] += ( 2*(x*y+z*w)) * lerp;
172 m[ 5] += (1-2*(x*x+z*z)) * lerp;
173 m[ 6] += ( 2*(y*z-x*w)) * lerp;
174 m[ 7] += (pose6s[1] * originscale) * lerp;
175 m[ 8] += ( 2*(x*z-y*w)) * lerp;
176 m[ 9] += ( 2*(y*z+x*w)) * lerp;
177 m[10] += (1-2*(x*x+y*y)) * lerp;
178 m[11] += (pose6s[2] * originscale) * lerp;
181 VectorNormalize(m + 4);
182 VectorNormalize(m + 8);
183 if (i == r_skeletal_debugbone.integer)
184 m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
185 m[3] *= r_skeletal_debugtranslatex.value;
186 m[7] *= r_skeletal_debugtranslatey.value;
187 m[11] *= r_skeletal_debugtranslatez.value;
188 if (model->data_bones[i].parent >= 0)
189 R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
191 memcpy(bonepose[i], m, sizeof(m));
192 // create a relative deformation matrix to describe displacement
193 // from the base mesh, which is used by the actual weighting
194 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]);
198 // generate matrices for all blend combinations
199 weights = model->surfmesh.data_blendweights;
200 for (i = 0;i < model->surfmesh.num_blends;i++, weights++)
202 float * RESTRICT b = boneposerelative[model->num_bones + i];
203 const float * RESTRICT m = boneposerelative[weights->index[0]];
204 float f = weights->influence[0] * (1.0f / 255.0f);
205 b[ 0] = f*m[ 0]; b[ 1] = f*m[ 1]; b[ 2] = f*m[ 2]; b[ 3] = f*m[ 3];
206 b[ 4] = f*m[ 4]; b[ 5] = f*m[ 5]; b[ 6] = f*m[ 6]; b[ 7] = f*m[ 7];
207 b[ 8] = f*m[ 8]; b[ 9] = f*m[ 9]; b[10] = f*m[10]; b[11] = f*m[11];
208 for (k = 1;k < 4 && weights->influence[k];k++)
210 m = boneposerelative[weights->index[k]];
211 f = weights->influence[k] * (1.0f / 255.0f);
212 b[ 0] += f*m[ 0]; b[ 1] += f*m[ 1]; b[ 2] += f*m[ 2]; b[ 3] += f*m[ 3];
213 b[ 4] += f*m[ 4]; b[ 5] += f*m[ 5]; b[ 6] += f*m[ 6]; b[ 7] += f*m[ 7];
214 b[ 8] += f*m[ 8]; b[ 9] += f*m[ 9]; b[10] += f*m[10]; b[11] += f*m[11];
218 // transform vertex attributes by blended matrices
221 const float * RESTRICT v = model->surfmesh.data_vertex3f;
222 const unsigned short * RESTRICT b = model->surfmesh.blends;
223 // special case common combinations of attributes to avoid repeated loading of matrices
226 const float * RESTRICT n = model->surfmesh.data_normal3f;
227 if (svector3f && tvector3f)
229 const float * RESTRICT sv = model->surfmesh.data_svector3f;
230 const float * RESTRICT tv = model->surfmesh.data_tvector3f;
231 for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, n += 3, sv += 3, tv += 3, b++, vertex3f += 3, normal3f += 3, svector3f += 3, tvector3f += 3)
233 const float * RESTRICT m = boneposerelative[*b];
234 vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
235 vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
236 vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
237 normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
238 normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
239 normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
240 svector3f[0] = (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
241 svector3f[1] = (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
242 svector3f[2] = (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
243 tvector3f[0] = (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
244 tvector3f[1] = (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
245 tvector3f[2] = (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
249 for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, n += 3, b++, vertex3f += 3, normal3f += 3)
251 const float * RESTRICT m = boneposerelative[*b];
252 vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
253 vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
254 vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
255 normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
256 normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
257 normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
262 for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, b++, vertex3f += 3)
264 const float * RESTRICT m = boneposerelative[*b];
265 vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
266 vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
267 vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
273 const float * RESTRICT n = model->surfmesh.data_normal3f;
274 const unsigned short * RESTRICT b = model->surfmesh.blends;
275 for (i = 0;i < model->surfmesh.num_vertices;i++, n += 3, b++, normal3f += 3)
277 const float * RESTRICT m = boneposerelative[*b];
278 normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
279 normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
280 normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
286 const float * RESTRICT sv = model->surfmesh.data_svector3f;
287 const unsigned short * RESTRICT b = model->surfmesh.blends;
288 for (i = 0;i < model->surfmesh.num_vertices;i++, sv += 3, b++, svector3f += 3)
290 const float * RESTRICT m = boneposerelative[*b];
291 svector3f[0] = (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
292 svector3f[1] = (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
293 svector3f[2] = (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
299 const float * RESTRICT tv = model->surfmesh.data_tvector3f;
300 const unsigned short * RESTRICT b = model->surfmesh.blends;
301 for (i = 0;i < model->surfmesh.num_vertices;i++, tv += 3, b++, tvector3f += 3)
303 const float * RESTRICT m = boneposerelative[*b];
304 tvector3f[0] = (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
305 tvector3f[1] = (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
306 tvector3f[2] = (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
311 void Mod_MD3_AnimateVertices(const dp_model_t * RESTRICT model, const frameblend_t * RESTRICT frameblend, const skeleton_t *skeleton, float * RESTRICT vertex3f, float * RESTRICT normal3f, float * RESTRICT svector3f, float * RESTRICT tvector3f)
314 int i, numblends, blendnum;
315 int numverts = model->surfmesh.num_vertices;
317 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
319 //VectorMA(translate, model->surfmesh.num_morphmdlframetranslate, frameblend[blendnum].lerp, translate);
320 if (frameblend[blendnum].lerp > 0)
321 numblends = blendnum + 1;
323 // special case for the first blend because it avoids some adds and the need to memset the arrays first
324 for (blendnum = 0;blendnum < numblends;blendnum++)
326 const md3vertex_t *verts = model->surfmesh.data_morphmd3vertex + numverts * frameblend[blendnum].subframe;
329 float scale = frameblend[blendnum].lerp * (1.0f / 64.0f);
332 for (i = 0;i < numverts;i++)
334 vertex3f[i * 3 + 0] = verts[i].origin[0] * scale;
335 vertex3f[i * 3 + 1] = verts[i].origin[1] * scale;
336 vertex3f[i * 3 + 2] = verts[i].origin[2] * scale;
341 for (i = 0;i < numverts;i++)
343 vertex3f[i * 3 + 0] += verts[i].origin[0] * scale;
344 vertex3f[i * 3 + 1] += verts[i].origin[1] * scale;
345 vertex3f[i * 3 + 2] += verts[i].origin[2] * scale;
349 // the yaw and pitch stored in md3 models are 8bit quantized angles
350 // (0-255), and as such a lookup table is very well suited to
351 // decoding them, and since cosine is equivilant to sine with an
352 // extra 45 degree rotation, this uses one lookup table for both
353 // sine and cosine with a +64 bias to get cosine.
356 float lerp = frameblend[blendnum].lerp;
359 for (i = 0;i < numverts;i++)
361 normal3f[i * 3 + 0] = mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
362 normal3f[i * 3 + 1] = mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
363 normal3f[i * 3 + 2] = mod_md3_sin[verts[i].pitch + 64] * lerp;
368 for (i = 0;i < numverts;i++)
370 normal3f[i * 3 + 0] += mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
371 normal3f[i * 3 + 1] += mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
372 normal3f[i * 3 + 2] += mod_md3_sin[verts[i].pitch + 64] * lerp;
378 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
379 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
382 for (i = 0;i < numverts;i++, texvecvert++)
384 VectorScale(texvecvert->svec, f, svector3f + i*3);
385 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
390 for (i = 0;i < numverts;i++, texvecvert++)
392 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
393 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
400 void Mod_MDL_AnimateVertices(const dp_model_t * RESTRICT model, const frameblend_t * RESTRICT frameblend, const skeleton_t *skeleton, float * RESTRICT vertex3f, float * RESTRICT normal3f, float * RESTRICT svector3f, float * RESTRICT tvector3f)
403 int i, numblends, blendnum;
404 int numverts = model->surfmesh.num_vertices;
406 VectorClear(translate);
408 // blend the frame translates to avoid redundantly doing so on each vertex
409 // (a bit of a brain twister but it works)
410 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
412 if (model->surfmesh.data_morphmd2framesize6f)
413 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6 + 3, translate);
415 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.num_morphmdlframetranslate, translate);
416 if (frameblend[blendnum].lerp > 0)
417 numblends = blendnum + 1;
419 // special case for the first blend because it avoids some adds and the need to memset the arrays first
420 for (blendnum = 0;blendnum < numblends;blendnum++)
422 const trivertx_t *verts = model->surfmesh.data_morphmdlvertex + numverts * frameblend[blendnum].subframe;
426 if (model->surfmesh.data_morphmd2framesize6f)
427 VectorScale(model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6, frameblend[blendnum].lerp, scale);
429 VectorScale(model->surfmesh.num_morphmdlframescale, frameblend[blendnum].lerp, scale);
432 for (i = 0;i < numverts;i++)
434 vertex3f[i * 3 + 0] = translate[0] + verts[i].v[0] * scale[0];
435 vertex3f[i * 3 + 1] = translate[1] + verts[i].v[1] * scale[1];
436 vertex3f[i * 3 + 2] = translate[2] + verts[i].v[2] * scale[2];
441 for (i = 0;i < numverts;i++)
443 vertex3f[i * 3 + 0] += verts[i].v[0] * scale[0];
444 vertex3f[i * 3 + 1] += verts[i].v[1] * scale[1];
445 vertex3f[i * 3 + 2] += verts[i].v[2] * scale[2];
449 // the vertex normals in mdl models are an index into a table of
450 // 162 unique values, this very crude quantization reduces the
451 // vertex normal to only one byte, which saves a lot of space but
452 // also makes lighting pretty coarse
455 float lerp = frameblend[blendnum].lerp;
458 for (i = 0;i < numverts;i++)
460 const float *vn = m_bytenormals[verts[i].lightnormalindex];
461 VectorScale(vn, lerp, normal3f + i*3);
466 for (i = 0;i < numverts;i++)
468 const float *vn = m_bytenormals[verts[i].lightnormalindex];
469 VectorMA(normal3f + i*3, lerp, vn, normal3f + i*3);
475 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
476 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
479 for (i = 0;i < numverts;i++, texvecvert++)
481 VectorScale(texvecvert->svec, f, svector3f + i*3);
482 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
487 for (i = 0;i < numverts;i++, texvecvert++)
489 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
490 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
497 int Mod_Alias_GetTagMatrix(const dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, int tagindex, matrix4x4_t *outmatrix)
500 matrix4x4_t parentbonematrix;
501 matrix4x4_t tempbonematrix;
502 matrix4x4_t bonematrix;
503 matrix4x4_t blendmatrix;
510 *outmatrix = identitymatrix;
511 if (skeleton && skeleton->relativetransforms)
513 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
515 *outmatrix = skeleton->relativetransforms[tagindex];
516 while ((tagindex = model->data_bones[tagindex].parent) >= 0)
519 Matrix4x4_Concat(outmatrix, &skeleton->relativetransforms[tagindex], &temp);
522 else if (model->num_bones)
524 if (tagindex < 0 || tagindex >= model->num_bones)
526 Matrix4x4_Clear(&blendmatrix);
527 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
529 lerp = frameblend[blendindex].lerp;
530 Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
531 parenttagindex = tagindex;
532 while ((parenttagindex = model->data_bones[parenttagindex].parent) >= 0)
534 Matrix4x4_FromBonePose6s(&parentbonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + parenttagindex));
535 tempbonematrix = bonematrix;
536 Matrix4x4_Concat(&bonematrix, &parentbonematrix, &tempbonematrix);
538 Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
540 *outmatrix = blendmatrix;
542 else if (model->num_tags)
544 if (tagindex < 0 || tagindex >= model->num_tags)
546 for (k = 0;k < 12;k++)
548 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
550 lerp = frameblend[blendindex].lerp;
551 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
552 for (k = 0;k < 12;k++)
553 blendtag[k] += input[k] * lerp;
555 Matrix4x4_FromArray12FloatGL(outmatrix, blendtag);
558 if(!mod_alias_supporttagscale.integer)
559 Matrix4x4_Normalize3(outmatrix, outmatrix);
564 int Mod_Alias_GetExtendedTagInfoForIndex(const dp_model_t *model, unsigned int skin, const frameblend_t *frameblend, const skeleton_t *skeleton, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
569 matrix4x4_t bonematrix;
570 matrix4x4_t blendmatrix;
574 if (skeleton && skeleton->relativetransforms)
576 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
578 *parentindex = skeleton->model->data_bones[tagindex].parent;
579 *tagname = skeleton->model->data_bones[tagindex].name;
580 *tag_localmatrix = skeleton->relativetransforms[tagindex];
583 else if (model->num_bones)
585 if (tagindex < 0 || tagindex >= model->num_bones)
587 *parentindex = model->data_bones[tagindex].parent;
588 *tagname = model->data_bones[tagindex].name;
589 Matrix4x4_Clear(&blendmatrix);
590 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
592 lerp = frameblend[blendindex].lerp;
593 Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
594 Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
596 *tag_localmatrix = blendmatrix;
599 else if (model->num_tags)
601 if (tagindex < 0 || tagindex >= model->num_tags)
604 *tagname = model->data_tags[tagindex].name;
605 for (k = 0;k < 12;k++)
607 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
609 lerp = frameblend[blendindex].lerp;
610 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
611 for (k = 0;k < 12;k++)
612 blendtag[k] += input[k] * lerp;
614 Matrix4x4_FromArray12FloatGL(tag_localmatrix, blendtag);
621 int Mod_Alias_GetTagIndexForName(const dp_model_t *model, unsigned int skin, const char *tagname)
624 if(skin >= (unsigned int)model->numskins)
626 if (model->num_bones)
627 for (i = 0;i < model->num_bones;i++)
628 if (!strcasecmp(tagname, model->data_bones[i].name))
631 for (i = 0;i < model->num_tags;i++)
632 if (!strcasecmp(tagname, model->data_tags[i].name))
637 static void Mod_BuildBaseBonePoses(void)
640 matrix4x4_t *basebonepose;
641 float *outinvmatrix = loadmodel->data_baseboneposeinverse;
642 matrix4x4_t bonematrix;
643 matrix4x4_t tempbonematrix;
644 if (!loadmodel->num_bones)
646 basebonepose = (matrix4x4_t *)Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(matrix4x4_t));
647 for (boneindex = 0;boneindex < loadmodel->num_bones;boneindex++)
649 Matrix4x4_FromBonePose6s(&bonematrix, loadmodel->num_posescale, loadmodel->data_poses6s + 6 * boneindex);
650 if (loadmodel->data_bones[boneindex].parent >= 0)
652 tempbonematrix = bonematrix;
653 Matrix4x4_Concat(&bonematrix, basebonepose + loadmodel->data_bones[boneindex].parent, &tempbonematrix);
655 basebonepose[boneindex] = bonematrix;
656 Matrix4x4_Invert_Simple(&tempbonematrix, basebonepose + boneindex);
657 Matrix4x4_ToArray12FloatD3D(&tempbonematrix, outinvmatrix + 12*boneindex);
659 Mem_Free(basebonepose);
662 static void Mod_Alias_CalculateBoundingBox(void)
665 qboolean firstvertex = true;
666 float dist, yawradius, radius;
669 frameblend_t frameblend[MAX_FRAMEBLENDS];
670 memset(frameblend, 0, sizeof(frameblend));
671 frameblend[0].lerp = 1;
672 vertex3f = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
673 VectorClear(loadmodel->normalmins);
674 VectorClear(loadmodel->normalmaxs);
677 for (frameblend[0].subframe = 0;frameblend[0].subframe < loadmodel->num_poses;frameblend[0].subframe++)
679 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, vertex3f, NULL, NULL, NULL);
680 for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
685 VectorCopy(v, loadmodel->normalmins);
686 VectorCopy(v, loadmodel->normalmaxs);
690 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
691 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
692 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
693 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
694 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
695 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
697 dist = v[0] * v[0] + v[1] * v[1];
698 if (yawradius < dist)
707 radius = sqrt(radius);
708 yawradius = sqrt(yawradius);
709 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
710 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
711 loadmodel->yawmins[2] = loadmodel->normalmins[2];
712 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
713 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
714 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
715 loadmodel->radius = radius;
716 loadmodel->radius2 = radius * radius;
719 static void Mod_Alias_MorphMesh_CompileFrames(void)
722 frameblend_t frameblend[MAX_FRAMEBLENDS];
723 unsigned char *datapointer;
724 memset(frameblend, 0, sizeof(frameblend));
725 frameblend[0].lerp = 1;
726 datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
727 loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
728 loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
729 loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
730 loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
731 loadmodel->surfmesh.data_morphtexvecvertex = (texvecvertex_t *)datapointer;datapointer += loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices * sizeof(texvecvertex_t);
732 // 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)
733 for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
735 frameblend[0].subframe = i;
736 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
737 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);
738 // encode the svector and tvector in 3 byte format for permanent storage
739 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
741 VectorScaleCast(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
742 VectorScaleCast(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
747 static void Mod_MDLMD2MD3_TraceLine(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask)
750 float segmentmins[3], segmentmaxs[3];
752 static int maxvertices = 0;
753 static float *vertex3f = NULL;
754 memset(trace, 0, sizeof(*trace));
756 trace->realfraction = 1;
757 trace->hitsupercontentsmask = hitsupercontentsmask;
758 if (maxvertices < model->surfmesh.num_vertices)
762 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
763 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
765 segmentmins[0] = min(start[0], end[0]) - 1;
766 segmentmins[1] = min(start[1], end[1]) - 1;
767 segmentmins[2] = min(start[2], end[2]) - 1;
768 segmentmaxs[0] = max(start[0], end[0]) + 1;
769 segmentmaxs[1] = max(start[1], end[1]) + 1;
770 segmentmaxs[2] = max(start[2], end[2]) + 1;
771 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
772 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
773 Collision_TraceLineTriangleMeshFloat(trace, start, end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs);
776 static int maxvertices = 0;
777 static float *vertex3f = NULL;
779 static void Mod_MDLMD2MD3_TraceBox(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask)
782 vec3_t shiftstart, shiftend;
783 float segmentmins[3], segmentmaxs[3];
785 colboxbrushf_t thisbrush_start, thisbrush_end;
786 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
788 if (VectorCompare(boxmins, boxmaxs))
790 VectorAdd(start, boxmins, shiftstart);
791 VectorAdd(end, boxmins, shiftend);
792 Mod_MDLMD2MD3_TraceLine(model, frameblend, skeleton, trace, shiftstart, shiftend, hitsupercontentsmask);
793 VectorSubtract(trace->endpos, boxmins, trace->endpos);
797 // box trace, performed as brush trace
798 memset(trace, 0, sizeof(*trace));
800 trace->realfraction = 1;
801 trace->hitsupercontentsmask = hitsupercontentsmask;
802 if (maxvertices < model->surfmesh.num_vertices)
806 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
807 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
809 segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
810 segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
811 segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
812 segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
813 segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
814 segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
815 VectorAdd(start, boxmins, boxstartmins);
816 VectorAdd(start, boxmaxs, boxstartmaxs);
817 VectorAdd(end, boxmins, boxendmins);
818 VectorAdd(end, boxmaxs, boxendmaxs);
819 Collision_BrushForBox(&thisbrush_start, boxstartmins, boxstartmaxs, 0, 0, NULL);
820 Collision_BrushForBox(&thisbrush_end, boxendmins, boxendmaxs, 0, 0, NULL);
821 if (maxvertices < model->surfmesh.num_vertices)
825 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
826 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
828 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
829 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
830 Collision_TraceBrushTriangleMeshFloat(trace, &thisbrush_start.brush, &thisbrush_end.brush, 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);
833 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
836 for (i = 0;i < inverts;i++)
838 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
840 j = vertremap[i]; // not onseam
843 j = vertremap[i+inverts]; // onseam
849 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
851 int i, f, pose, groupframes;
853 daliasframetype_t *pframetype;
854 daliasframe_t *pinframe;
855 daliasgroup_t *group;
856 daliasinterval_t *intervals;
859 scene = loadmodel->animscenes;
860 for (f = 0;f < loadmodel->numframes;f++)
862 pframetype = (daliasframetype_t *)datapointer;
863 datapointer += sizeof(daliasframetype_t);
864 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
866 // a single frame is still treated as a group
873 group = (daliasgroup_t *)datapointer;
874 datapointer += sizeof(daliasgroup_t);
875 groupframes = LittleLong (group->numframes);
877 // intervals (time per frame)
878 intervals = (daliasinterval_t *)datapointer;
879 datapointer += sizeof(daliasinterval_t) * groupframes;
881 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
882 if (interval < 0.01f)
884 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
889 // get scene name from first frame
890 pinframe = (daliasframe_t *)datapointer;
892 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
893 scene->firstframe = pose;
894 scene->framecount = groupframes;
895 scene->framerate = 1.0f / interval;
900 for (i = 0;i < groupframes;i++)
902 pinframe = (daliasframe_t *)datapointer;
903 datapointer += sizeof(daliasframe_t);
904 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
905 datapointer += sizeof(trivertx_t) * inverts;
911 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
913 if (cls.state == ca_dedicated)
917 skinframe = R_SkinFrame_LoadMissing();
918 memset(texture, 0, sizeof(*texture));
919 texture->currentframe = texture;
920 //texture->animated = false;
921 texture->numskinframes = 1;
922 texture->skinframerate = 1;
923 texture->skinframes[0] = skinframe;
924 texture->currentskinframe = skinframe;
925 //texture->backgroundnumskinframes = 0;
926 //texture->customblendfunc[0] = 0;
927 //texture->customblendfunc[1] = 0;
928 //texture->surfaceflags = 0;
929 //texture->supercontents = 0;
930 //texture->surfaceparms = 0;
931 //texture->textureflags = 0;
933 texture->basematerialflags = MATERIALFLAG_WALL;
934 if (texture->currentskinframe->hasalpha)
935 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
936 texture->currentmaterialflags = texture->basematerialflags;
937 texture->specularscalemod = 1;
938 texture->specularpowermod = 1;
939 texture->surfaceflags = 0;
940 texture->supercontents = SUPERCONTENTS_SOLID;
941 if (!(texture->basematerialflags & MATERIALFLAG_BLENDED))
942 texture->supercontents |= SUPERCONTENTS_OPAQUE;
945 void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
948 skinfileitem_t *skinfileitem;
951 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
952 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
954 memset(skin, 0, sizeof(*skin));
956 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
958 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
959 if (!strcmp(skinfileitem->name, meshname))
961 Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
967 // don't render unmentioned meshes
968 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
969 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
974 Mod_LoadTextureFromQ3Shader(skin, shadername, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
977 #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);
978 #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);
979 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
981 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
982 float scales, scalet, interval;
986 stvert_t *pinstverts;
987 dtriangle_t *pintriangles;
988 daliasskintype_t *pinskintype;
989 daliasskingroup_t *pinskingroup;
990 daliasskininterval_t *pinskinintervals;
991 daliasframetype_t *pinframetype;
992 daliasgroup_t *pinframegroup;
993 unsigned char *datapointer, *startframes, *startskins;
994 char name[MAX_QPATH];
995 skinframe_t *tempskinframe;
996 animscene_t *tempskinscenes;
997 texture_t *tempaliasskins;
999 int *vertonseam, *vertremap;
1000 skinfile_t *skinfiles;
1002 datapointer = (unsigned char *)buffer;
1003 pinmodel = (mdl_t *)datapointer;
1004 datapointer += sizeof(mdl_t);
1006 version = LittleLong (pinmodel->version);
1007 if (version != ALIAS_VERSION)
1008 Host_Error ("%s has wrong version number (%i should be %i)",
1009 loadmodel->name, version, ALIAS_VERSION);
1011 loadmodel->modeldatatypestring = "MDL";
1013 loadmodel->type = mod_alias;
1014 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1015 loadmodel->DrawSky = NULL;
1016 loadmodel->DrawAddWaterPlanes = NULL;
1017 loadmodel->Draw = R_Q1BSP_Draw;
1018 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1019 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1020 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1021 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1022 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1023 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1024 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1025 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1026 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1027 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1028 loadmodel->PointSuperContents = NULL;
1030 loadmodel->num_surfaces = 1;
1031 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1032 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
1033 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1034 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1035 loadmodel->sortedmodelsurfaces[0] = 0;
1037 loadmodel->numskins = LittleLong(pinmodel->numskins);
1038 BOUNDI(loadmodel->numskins,0,65536);
1039 skinwidth = LittleLong (pinmodel->skinwidth);
1040 BOUNDI(skinwidth,0,65536);
1041 skinheight = LittleLong (pinmodel->skinheight);
1042 BOUNDI(skinheight,0,65536);
1043 numverts = LittleLong(pinmodel->numverts);
1044 BOUNDI(numverts,0,65536);
1045 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
1046 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
1047 loadmodel->numframes = LittleLong(pinmodel->numframes);
1048 BOUNDI(loadmodel->numframes,0,65536);
1049 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
1050 BOUNDI((int)loadmodel->synctype,0,2);
1051 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1052 i = LittleLong (pinmodel->flags);
1053 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1055 for (i = 0;i < 3;i++)
1057 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
1058 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
1061 startskins = datapointer;
1063 for (i = 0;i < loadmodel->numskins;i++)
1065 pinskintype = (daliasskintype_t *)datapointer;
1066 datapointer += sizeof(daliasskintype_t);
1067 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
1071 pinskingroup = (daliasskingroup_t *)datapointer;
1072 datapointer += sizeof(daliasskingroup_t);
1073 groupskins = LittleLong(pinskingroup->numskins);
1074 datapointer += sizeof(daliasskininterval_t) * groupskins;
1077 for (j = 0;j < groupskins;j++)
1079 datapointer += skinwidth * skinheight;
1084 pinstverts = (stvert_t *)datapointer;
1085 datapointer += sizeof(stvert_t) * numverts;
1087 pintriangles = (dtriangle_t *)datapointer;
1088 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
1090 startframes = datapointer;
1091 loadmodel->surfmesh.num_morphframes = 0;
1092 for (i = 0;i < loadmodel->numframes;i++)
1094 pinframetype = (daliasframetype_t *)datapointer;
1095 datapointer += sizeof(daliasframetype_t);
1096 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
1100 pinframegroup = (daliasgroup_t *)datapointer;
1101 datapointer += sizeof(daliasgroup_t);
1102 groupframes = LittleLong(pinframegroup->numframes);
1103 datapointer += sizeof(daliasinterval_t) * groupframes;
1106 for (j = 0;j < groupframes;j++)
1108 datapointer += sizeof(daliasframe_t);
1109 datapointer += sizeof(trivertx_t) * numverts;
1110 loadmodel->surfmesh.num_morphframes++;
1113 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1115 // store texture coordinates into temporary array, they will be stored
1116 // after usage is determined (triangle data)
1117 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
1118 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
1119 vertonseam = vertremap + numverts * 2;
1121 scales = 1.0 / skinwidth;
1122 scalet = 1.0 / skinheight;
1123 for (i = 0;i < numverts;i++)
1125 vertonseam[i] = LittleLong(pinstverts[i].onseam);
1126 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
1127 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
1128 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
1129 vertst[(i+numverts)*2+1] = vertst[i*2+1];
1132 // load triangle data
1133 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1135 // read the triangle elements
1136 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1137 for (j = 0;j < 3;j++)
1138 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1139 // validate (note numverts is used because this is the original data)
1140 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1141 // now butcher the elements according to vertonseam and tri->facesfront
1142 // and then compact the vertex set to remove duplicates
1143 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1144 if (!LittleLong(pintriangles[i].facesfront)) // backface
1145 for (j = 0;j < 3;j++)
1146 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1147 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1149 // (this uses vertremap to count usage to save some memory)
1150 for (i = 0;i < numverts*2;i++)
1152 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1153 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1154 // build remapping table and compact array
1155 loadmodel->surfmesh.num_vertices = 0;
1156 for (i = 0;i < numverts*2;i++)
1160 vertremap[i] = loadmodel->surfmesh.num_vertices;
1161 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1162 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1163 loadmodel->surfmesh.num_vertices++;
1166 vertremap[i] = -1; // not used at all
1168 // remap the elements to the new vertex set
1169 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1170 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1171 // store the texture coordinates
1172 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1173 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1175 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1176 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1179 // generate ushort elements array if possible
1180 if (loadmodel->surfmesh.num_vertices <= 65536)
1181 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1182 if (loadmodel->surfmesh.data_element3s)
1183 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1184 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1187 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1188 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1189 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1190 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1191 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1192 Mod_Alias_CalculateBoundingBox();
1193 Mod_Alias_MorphMesh_CompileFrames();
1196 Mem_Free(vertremap);
1199 skinfiles = Mod_LoadSkinFiles();
1202 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1203 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1204 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1205 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1206 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1207 Mod_FreeSkinFiles(skinfiles);
1208 for (i = 0;i < loadmodel->numskins;i++)
1210 loadmodel->skinscenes[i].firstframe = i;
1211 loadmodel->skinscenes[i].framecount = 1;
1212 loadmodel->skinscenes[i].loop = true;
1213 loadmodel->skinscenes[i].framerate = 10;
1218 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1219 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1220 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1221 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1223 datapointer = startskins;
1224 for (i = 0;i < loadmodel->numskins;i++)
1226 pinskintype = (daliasskintype_t *)datapointer;
1227 datapointer += sizeof(daliasskintype_t);
1229 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1236 pinskingroup = (daliasskingroup_t *)datapointer;
1237 datapointer += sizeof(daliasskingroup_t);
1239 groupskins = LittleLong (pinskingroup->numskins);
1241 pinskinintervals = (daliasskininterval_t *)datapointer;
1242 datapointer += sizeof(daliasskininterval_t) * groupskins;
1244 interval = LittleFloat(pinskinintervals[0].interval);
1245 if (interval < 0.01f)
1247 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1252 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1253 loadmodel->skinscenes[i].firstframe = totalskins;
1254 loadmodel->skinscenes[i].framecount = groupskins;
1255 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1256 loadmodel->skinscenes[i].loop = true;
1258 for (j = 0;j < groupskins;j++)
1261 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1263 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1264 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))
1265 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));
1266 datapointer += skinwidth * skinheight;
1270 // check for skins that don't exist in the model, but do exist as external images
1271 // (this was added because yummyluv kept pestering me about support for it)
1272 // TODO: support shaders here?
1273 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)))
1275 // expand the arrays to make room
1276 tempskinscenes = loadmodel->skinscenes;
1277 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1278 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1279 Mem_Free(tempskinscenes);
1281 tempaliasskins = loadmodel->data_textures;
1282 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1283 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1284 Mem_Free(tempaliasskins);
1286 // store the info about the new skin
1287 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1288 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1289 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1290 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1291 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1292 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1294 //increase skin counts
1295 loadmodel->numskins++;
1298 // fix up the pointers since they are pointing at the old textures array
1299 // FIXME: this is a hack!
1300 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1301 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1305 surface = loadmodel->data_surfaces;
1306 surface->texture = loadmodel->data_textures;
1307 surface->num_firsttriangle = 0;
1308 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1309 surface->num_firstvertex = 0;
1310 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1312 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1314 if (!loadmodel->surfmesh.isanimated)
1316 Mod_MakeCollisionBIH(loadmodel, true);
1317 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1318 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1319 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1320 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1324 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1326 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1327 float iskinwidth, iskinheight;
1328 unsigned char *data;
1329 msurface_t *surface;
1331 unsigned char *base, *datapointer;
1332 md2frame_t *pinframe;
1334 md2triangle_t *intri;
1335 unsigned short *inst;
1336 struct md2verthash_s
1338 struct md2verthash_s *next;
1342 *hash, **md2verthash, *md2verthashdata;
1343 skinfile_t *skinfiles;
1345 pinmodel = (md2_t *)buffer;
1346 base = (unsigned char *)buffer;
1348 version = LittleLong (pinmodel->version);
1349 if (version != MD2ALIAS_VERSION)
1350 Host_Error ("%s has wrong version number (%i should be %i)",
1351 loadmodel->name, version, MD2ALIAS_VERSION);
1353 loadmodel->modeldatatypestring = "MD2";
1355 loadmodel->type = mod_alias;
1356 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1357 loadmodel->DrawSky = NULL;
1358 loadmodel->DrawAddWaterPlanes = NULL;
1359 loadmodel->Draw = R_Q1BSP_Draw;
1360 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1361 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1362 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1363 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1364 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1365 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1366 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1367 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1368 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1369 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1370 loadmodel->PointSuperContents = NULL;
1372 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1373 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1374 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1375 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1376 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1377 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1378 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1379 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1381 end = LittleLong(pinmodel->ofs_end);
1382 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1383 Host_Error ("%s is not a valid model", loadmodel->name);
1384 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1385 Host_Error ("%s is not a valid model", loadmodel->name);
1386 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1387 Host_Error ("%s is not a valid model", loadmodel->name);
1388 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1389 Host_Error ("%s is not a valid model", loadmodel->name);
1390 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1391 Host_Error ("%s is not a valid model", loadmodel->name);
1393 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1394 numxyz = LittleLong(pinmodel->num_xyz);
1395 numst = LittleLong(pinmodel->num_st);
1396 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1397 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1398 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1399 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1400 skinwidth = LittleLong(pinmodel->skinwidth);
1401 skinheight = LittleLong(pinmodel->skinheight);
1402 iskinwidth = 1.0f / skinwidth;
1403 iskinheight = 1.0f / skinheight;
1405 loadmodel->num_surfaces = 1;
1406 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1407 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]));
1408 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1409 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1410 loadmodel->sortedmodelsurfaces[0] = 0;
1411 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1412 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1413 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1414 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1416 loadmodel->synctype = ST_RAND;
1419 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1420 skinfiles = Mod_LoadSkinFiles();
1423 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1424 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1425 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1426 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1427 Mod_FreeSkinFiles(skinfiles);
1429 else if (loadmodel->numskins)
1431 // skins found (most likely not a player model)
1432 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1433 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1434 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1435 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1436 Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
1440 // no skins (most likely a player model)
1441 loadmodel->numskins = 1;
1442 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1443 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1444 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1445 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1448 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1449 for (i = 0;i < loadmodel->numskins;i++)
1451 loadmodel->skinscenes[i].firstframe = i;
1452 loadmodel->skinscenes[i].framecount = 1;
1453 loadmodel->skinscenes[i].loop = true;
1454 loadmodel->skinscenes[i].framerate = 10;
1457 // load the triangles and stvert data
1458 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1459 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1460 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1461 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1462 // swap the triangle list
1463 loadmodel->surfmesh.num_vertices = 0;
1464 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1466 for (j = 0;j < 3;j++)
1468 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1469 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1472 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1477 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1480 hashindex = (xyz * 256 + st) & 65535;
1481 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1482 if (hash->xyz == xyz && hash->st == st)
1486 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1489 hash->next = md2verthash[hashindex];
1490 md2verthash[hashindex] = hash;
1492 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1496 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1497 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));
1498 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1499 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1500 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1503 hash = md2verthashdata + i;
1504 vertremap[i] = hash->xyz;
1505 sts = LittleShort(inst[hash->st*2+0]);
1506 stt = LittleShort(inst[hash->st*2+1]);
1507 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1509 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1513 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1514 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1517 Mem_Free(md2verthash);
1518 Mem_Free(md2verthashdata);
1520 // generate ushort elements array if possible
1521 if (loadmodel->surfmesh.num_vertices <= 65536)
1522 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1523 if (loadmodel->surfmesh.data_element3s)
1524 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1525 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1528 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1529 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1534 pinframe = (md2frame_t *)datapointer;
1535 datapointer += sizeof(md2frame_t);
1536 // store the frame scale/translate into the appropriate array
1537 for (j = 0;j < 3;j++)
1539 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1540 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1542 // convert the vertices
1543 v = (trivertx_t *)datapointer;
1544 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1545 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1546 out[k] = v[vertremap[k]];
1547 datapointer += numxyz * sizeof(trivertx_t);
1549 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1550 loadmodel->animscenes[i].firstframe = i;
1551 loadmodel->animscenes[i].framecount = 1;
1552 loadmodel->animscenes[i].framerate = 10;
1553 loadmodel->animscenes[i].loop = true;
1556 Mem_Free(vertremap);
1558 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1559 Mod_Alias_CalculateBoundingBox();
1560 Mod_Alias_MorphMesh_CompileFrames();
1562 surface = loadmodel->data_surfaces;
1563 surface->texture = loadmodel->data_textures;
1564 surface->num_firsttriangle = 0;
1565 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1566 surface->num_firstvertex = 0;
1567 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1569 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1571 if (!loadmodel->surfmesh.isanimated)
1573 Mod_MakeCollisionBIH(loadmodel, true);
1574 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1575 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1576 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1577 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1581 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1583 int i, j, k, version, meshvertices, meshtriangles;
1584 unsigned char *data;
1585 msurface_t *surface;
1586 md3modelheader_t *pinmodel;
1587 md3frameinfo_t *pinframe;
1590 skinfile_t *skinfiles;
1592 pinmodel = (md3modelheader_t *)buffer;
1594 if (memcmp(pinmodel->identifier, "IDP3", 4))
1595 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1596 version = LittleLong (pinmodel->version);
1597 if (version != MD3VERSION)
1598 Host_Error ("%s has wrong version number (%i should be %i)",
1599 loadmodel->name, version, MD3VERSION);
1601 skinfiles = Mod_LoadSkinFiles();
1602 if (loadmodel->numskins < 1)
1603 loadmodel->numskins = 1;
1605 loadmodel->modeldatatypestring = "MD3";
1607 loadmodel->type = mod_alias;
1608 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1609 loadmodel->DrawSky = NULL;
1610 loadmodel->DrawAddWaterPlanes = NULL;
1611 loadmodel->Draw = R_Q1BSP_Draw;
1612 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1613 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1614 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1615 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1616 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1617 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1618 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1619 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1620 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1621 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1622 loadmodel->PointSuperContents = NULL;
1623 loadmodel->synctype = ST_RAND;
1624 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1625 i = LittleLong (pinmodel->flags);
1626 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1628 // set up some global info about the model
1629 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1630 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1632 // make skinscenes for the skins (no groups)
1633 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1634 for (i = 0;i < loadmodel->numskins;i++)
1636 loadmodel->skinscenes[i].firstframe = i;
1637 loadmodel->skinscenes[i].framecount = 1;
1638 loadmodel->skinscenes[i].loop = true;
1639 loadmodel->skinscenes[i].framerate = 10;
1643 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1644 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1646 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1647 loadmodel->animscenes[i].firstframe = i;
1648 loadmodel->animscenes[i].framecount = 1;
1649 loadmodel->animscenes[i].framerate = 10;
1650 loadmodel->animscenes[i].loop = true;
1654 loadmodel->num_tagframes = loadmodel->numframes;
1655 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1656 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1657 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1659 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1660 for (j = 0;j < 9;j++)
1661 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1662 for (j = 0;j < 3;j++)
1663 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1664 //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);
1670 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)))
1672 if (memcmp(pinmesh->identifier, "IDP3", 4))
1673 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1674 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1675 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1676 meshvertices += LittleLong(pinmesh->num_vertices);
1677 meshtriangles += LittleLong(pinmesh->num_triangles);
1680 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1681 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1682 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1683 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));
1684 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1685 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1686 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1687 loadmodel->surfmesh.num_vertices = meshvertices;
1688 loadmodel->surfmesh.num_triangles = meshtriangles;
1689 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1690 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1691 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1692 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1693 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1694 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1695 if (meshvertices <= 65536)
1696 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1700 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)))
1702 if (memcmp(pinmesh->identifier, "IDP3", 4))
1703 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1704 loadmodel->sortedmodelsurfaces[i] = i;
1705 surface = loadmodel->data_surfaces + i;
1706 surface->texture = loadmodel->data_textures + i;
1707 surface->num_firsttriangle = meshtriangles;
1708 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1709 surface->num_firstvertex = meshvertices;
1710 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1711 meshvertices += surface->num_vertices;
1712 meshtriangles += surface->num_triangles;
1714 for (j = 0;j < surface->num_triangles * 3;j++)
1715 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1716 for (j = 0;j < surface->num_vertices;j++)
1718 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1719 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1721 for (j = 0;j < loadmodel->numframes;j++)
1723 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1724 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1725 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1727 out->origin[0] = LittleShort(in->origin[0]);
1728 out->origin[1] = LittleShort(in->origin[1]);
1729 out->origin[2] = LittleShort(in->origin[2]);
1730 out->pitch = in->pitch;
1735 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1737 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1739 if (loadmodel->surfmesh.data_element3s)
1740 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1741 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1742 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1743 Mod_Alias_MorphMesh_CompileFrames();
1744 Mod_Alias_CalculateBoundingBox();
1745 Mod_FreeSkinFiles(skinfiles);
1746 Mod_MakeSortedSurfaces(loadmodel);
1748 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1749 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1751 if (!loadmodel->surfmesh.isanimated)
1753 Mod_MakeCollisionBIH(loadmodel, true);
1754 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1755 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1756 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1757 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1761 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1763 zymtype1header_t *pinmodel, *pheader;
1764 unsigned char *pbase;
1765 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1766 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose, f, biggestorigin, tempvec[3], modelscale;
1767 zymvertex_t *verts, *vertdata;
1771 skinfile_t *skinfiles;
1772 unsigned char *data;
1773 msurface_t *surface;
1775 pinmodel = (zymtype1header_t *)buffer;
1776 pbase = (unsigned char *)buffer;
1777 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1778 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1779 if (BigLong(pinmodel->type) != 1)
1780 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1782 loadmodel->modeldatatypestring = "ZYM";
1784 loadmodel->type = mod_alias;
1785 loadmodel->synctype = ST_RAND;
1789 pheader->type = BigLong(pinmodel->type);
1790 pheader->filesize = BigLong(pinmodel->filesize);
1791 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1792 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1793 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1794 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1795 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1796 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1797 pheader->radius = BigFloat(pinmodel->radius);
1798 pheader->numverts = BigLong(pinmodel->numverts);
1799 pheader->numtris = BigLong(pinmodel->numtris);
1800 pheader->numshaders = BigLong(pinmodel->numshaders);
1801 pheader->numbones = BigLong(pinmodel->numbones);
1802 pheader->numscenes = BigLong(pinmodel->numscenes);
1803 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1804 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1805 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1806 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1807 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1808 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1809 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1810 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1811 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1812 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1813 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1814 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1815 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1816 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1817 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1818 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1819 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1820 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1822 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1824 Con_Printf("%s has no geometry\n", loadmodel->name);
1827 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1829 Con_Printf("%s has no animations\n", loadmodel->name);
1833 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1834 loadmodel->DrawSky = NULL;
1835 loadmodel->DrawAddWaterPlanes = NULL;
1836 loadmodel->Draw = R_Q1BSP_Draw;
1837 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1838 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1839 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1840 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1841 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1842 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1843 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1844 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1845 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1846 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1847 loadmodel->PointSuperContents = NULL;
1849 loadmodel->numframes = pheader->numscenes;
1850 loadmodel->num_surfaces = pheader->numshaders;
1852 skinfiles = Mod_LoadSkinFiles();
1853 if (loadmodel->numskins < 1)
1854 loadmodel->numskins = 1;
1856 // make skinscenes for the skins (no groups)
1857 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1858 for (i = 0;i < loadmodel->numskins;i++)
1860 loadmodel->skinscenes[i].firstframe = i;
1861 loadmodel->skinscenes[i].framecount = 1;
1862 loadmodel->skinscenes[i].loop = true;
1863 loadmodel->skinscenes[i].framerate = 10;
1867 modelradius = pheader->radius;
1868 for (i = 0;i < 3;i++)
1870 loadmodel->normalmins[i] = pheader->mins[i];
1871 loadmodel->normalmaxs[i] = pheader->maxs[i];
1872 loadmodel->rotatedmins[i] = -modelradius;
1873 loadmodel->rotatedmaxs[i] = modelradius;
1875 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1876 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1877 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1878 if (loadmodel->yawmaxs[0] > modelradius)
1879 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1880 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1881 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1882 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1883 loadmodel->radius = modelradius;
1884 loadmodel->radius2 = modelradius * modelradius;
1886 // go through the lumps, swapping things
1888 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1889 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1890 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1891 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1892 for (i = 0;i < pheader->numscenes;i++)
1894 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1895 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1896 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1897 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1898 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1899 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1900 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1901 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1902 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1903 if (loadmodel->animscenes[i].framerate < 0)
1904 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1908 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1909 loadmodel->num_bones = pheader->numbones;
1910 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1911 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1912 for (i = 0;i < pheader->numbones;i++)
1914 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1915 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1916 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1917 if (loadmodel->data_bones[i].parent >= i)
1918 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1921 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1922 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1923 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1924 for (i = 0;i < pheader->numverts;i++)
1926 vertbonecounts[i] = BigLong(bonecount[i]);
1927 if (vertbonecounts[i] != 1)
1928 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1931 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1933 meshvertices = pheader->numverts;
1934 meshtriangles = pheader->numtris;
1936 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1937 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1938 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1939 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(unsigned short) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]) + loadmodel->num_bones * sizeof(float[12]));
1940 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1941 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1942 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1943 loadmodel->surfmesh.num_vertices = meshvertices;
1944 loadmodel->surfmesh.num_triangles = meshtriangles;
1945 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1946 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1947 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1948 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1949 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1950 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1951 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1952 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1953 loadmodel->surfmesh.num_blends = 0;
1954 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
1955 if (loadmodel->surfmesh.num_vertices <= 65536)
1956 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1957 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
1958 loadmodel->surfmesh.data_blendweights = NULL;
1960 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1961 poses = (float *) (pheader->lump_poses.start + pbase);
1962 // figure out scale of model from root bone, for compatibility with old zmodel versions
1963 tempvec[0] = BigFloat(poses[0]);
1964 tempvec[1] = BigFloat(poses[1]);
1965 tempvec[2] = BigFloat(poses[2]);
1966 modelscale = VectorLength(tempvec);
1968 for (i = 0;i < loadmodel->num_bones * numposes * 12;i++)
1970 f = fabs(BigFloat(poses[i]));
1971 biggestorigin = max(biggestorigin, f);
1973 loadmodel->num_posescale = biggestorigin / 32767.0f;
1974 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
1975 for (i = 0;i < numposes;i++)
1977 const float *frameposes = (float *) (pheader->lump_poses.start + pbase) + 12*i*loadmodel->num_bones;
1978 for (j = 0;j < loadmodel->num_bones;j++)
1981 matrix4x4_t posematrix;
1982 for (k = 0;k < 12;k++)
1983 pose[k] = BigFloat(frameposes[j*12+k]);
1984 //if (j < loadmodel->num_bones)
1985 // Con_Printf("%s: bone %i = %f %f %f %f : %f %f %f %f : %f %f %f %f : scale = %f\n", loadmodel->name, j, pose[0], pose[1], pose[2], pose[3], pose[4], pose[5], pose[6], pose[7], pose[8], pose[9], pose[10], pose[11], VectorLength(pose));
1986 // scale child bones to match the root scale
1987 if (loadmodel->data_bones[j].parent >= 0)
1989 pose[3] *= modelscale;
1990 pose[7] *= modelscale;
1991 pose[11] *= modelscale;
1993 // normalize rotation matrix
1994 VectorNormalize(pose + 0);
1995 VectorNormalize(pose + 4);
1996 VectorNormalize(pose + 8);
1997 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
1998 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
2002 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
2003 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
2004 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
2005 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2006 // (converting from weight-blending skeletal animation to
2007 // deformation-based skeletal animation)
2008 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2009 for (i = 0;i < loadmodel->num_bones;i++)
2012 for (k = 0;k < 12;k++)
2013 m[k] = BigFloat(poses[i*12+k]);
2014 if (loadmodel->data_bones[i].parent >= 0)
2015 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2017 for (k = 0;k < 12;k++)
2018 bonepose[12*i+k] = m[k];
2020 for (j = 0;j < pheader->numverts;j++)
2022 // this format really should have had a per vertexweight weight value...
2023 // but since it does not, the weighting is completely ignored and
2024 // only one weight is allowed per vertex
2025 int boneindex = BigLong(vertdata[j].bonenum);
2026 const float *m = bonepose + 12 * boneindex;
2027 float relativeorigin[3];
2028 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
2029 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
2030 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
2031 // transform the vertex bone weight into the base mesh
2032 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
2033 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
2034 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
2035 // store the weight as the primary weight on this vertex
2036 loadmodel->surfmesh.blends[j] = boneindex;
2039 // normals and tangents are calculated after elements are loaded
2041 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
2042 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
2043 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
2044 for (i = 0;i < pheader->numverts;i++)
2046 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
2047 // flip T coordinate for OpenGL
2048 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
2051 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
2052 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
2053 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
2055 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
2056 //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)
2057 // byteswap, validate, and swap winding order of tris
2058 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
2059 if (pheader->lump_render.length != count)
2060 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
2061 renderlist = (int *) (pheader->lump_render.start + pbase);
2062 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
2064 for (i = 0;i < loadmodel->num_surfaces;i++)
2066 int firstvertex, lastvertex;
2067 if (renderlist >= renderlistend)
2068 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2069 count = BigLong(*renderlist);renderlist++;
2070 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
2071 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2073 loadmodel->sortedmodelsurfaces[i] = i;
2074 surface = loadmodel->data_surfaces + i;
2075 surface->texture = loadmodel->data_textures + i;
2076 surface->num_firsttriangle = meshtriangles;
2077 surface->num_triangles = count;
2078 meshtriangles += surface->num_triangles;
2080 // load the elements
2081 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2082 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
2084 outelements[j*3+2] = BigLong(renderlist[0]);
2085 outelements[j*3+1] = BigLong(renderlist[1]);
2086 outelements[j*3+0] = BigLong(renderlist[2]);
2088 // validate the elements and find the used vertex range
2089 firstvertex = meshvertices;
2091 for (j = 0;j < surface->num_triangles * 3;j++)
2093 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
2094 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
2095 firstvertex = min(firstvertex, outelements[j]);
2096 lastvertex = max(lastvertex, outelements[j]);
2098 surface->num_firstvertex = firstvertex;
2099 surface->num_vertices = lastvertex + 1 - firstvertex;
2101 // since zym models do not have named sections, reuse their shader
2102 // name as the section name
2103 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
2104 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
2106 Mod_FreeSkinFiles(skinfiles);
2107 Mem_Free(vertbonecounts);
2109 Mod_MakeSortedSurfaces(loadmodel);
2111 // compute all the mesh information that was not loaded from the file
2112 if (loadmodel->surfmesh.data_element3s)
2113 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2114 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2115 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2116 Mod_BuildBaseBonePoses();
2117 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2118 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);
2119 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2121 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2123 if (!loadmodel->surfmesh.isanimated)
2125 Mod_MakeCollisionBIH(loadmodel, true);
2126 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2127 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2128 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2129 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2133 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2135 dpmheader_t *pheader;
2139 unsigned char *pbase;
2140 int i, j, k, meshvertices, meshtriangles;
2141 skinfile_t *skinfiles;
2142 unsigned char *data;
2144 float biggestorigin, tempvec[3], modelscale;
2148 pheader = (dpmheader_t *)buffer;
2149 pbase = (unsigned char *)buffer;
2150 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2151 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2152 if (BigLong(pheader->type) != 2)
2153 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2155 loadmodel->modeldatatypestring = "DPM";
2157 loadmodel->type = mod_alias;
2158 loadmodel->synctype = ST_RAND;
2161 pheader->type = BigLong(pheader->type);
2162 pheader->filesize = BigLong(pheader->filesize);
2163 pheader->mins[0] = BigFloat(pheader->mins[0]);
2164 pheader->mins[1] = BigFloat(pheader->mins[1]);
2165 pheader->mins[2] = BigFloat(pheader->mins[2]);
2166 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2167 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2168 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2169 pheader->yawradius = BigFloat(pheader->yawradius);
2170 pheader->allradius = BigFloat(pheader->allradius);
2171 pheader->num_bones = BigLong(pheader->num_bones);
2172 pheader->num_meshs = BigLong(pheader->num_meshs);
2173 pheader->num_frames = BigLong(pheader->num_frames);
2174 pheader->ofs_bones = BigLong(pheader->ofs_bones);
2175 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2176 pheader->ofs_frames = BigLong(pheader->ofs_frames);
2178 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2180 Con_Printf("%s has no geometry\n", loadmodel->name);
2183 if (pheader->num_frames < 1)
2185 Con_Printf("%s has no frames\n", loadmodel->name);
2189 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2190 loadmodel->DrawSky = NULL;
2191 loadmodel->DrawAddWaterPlanes = NULL;
2192 loadmodel->Draw = R_Q1BSP_Draw;
2193 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2194 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2195 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2196 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2197 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2198 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2199 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2200 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2201 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2202 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2203 loadmodel->PointSuperContents = NULL;
2206 for (i = 0;i < 3;i++)
2208 loadmodel->normalmins[i] = pheader->mins[i];
2209 loadmodel->normalmaxs[i] = pheader->maxs[i];
2210 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2211 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2212 loadmodel->rotatedmins[i] = -pheader->allradius;
2213 loadmodel->rotatedmaxs[i] = pheader->allradius;
2215 loadmodel->radius = pheader->allradius;
2216 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2218 // load external .skin files if present
2219 skinfiles = Mod_LoadSkinFiles();
2220 if (loadmodel->numskins < 1)
2221 loadmodel->numskins = 1;
2226 // gather combined statistics from the meshes
2227 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2228 for (i = 0;i < (int)pheader->num_meshs;i++)
2230 int numverts = BigLong(dpmmesh->num_verts);
2231 meshvertices += numverts;
2232 meshtriangles += BigLong(dpmmesh->num_tris);
2236 loadmodel->numframes = pheader->num_frames;
2237 loadmodel->num_bones = pheader->num_bones;
2238 loadmodel->num_poses = loadmodel->numframes;
2239 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2240 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2241 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2242 // do most allocations as one merged chunk
2243 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(unsigned short)) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
2244 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2245 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2246 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2247 loadmodel->surfmesh.num_vertices = meshvertices;
2248 loadmodel->surfmesh.num_triangles = meshtriangles;
2249 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2250 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2251 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2252 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2253 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2254 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2255 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2256 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2257 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2258 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2259 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2260 loadmodel->surfmesh.num_blends = 0;
2261 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2262 if (meshvertices <= 65536)
2263 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2264 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2265 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
2267 for (i = 0;i < loadmodel->numskins;i++)
2269 loadmodel->skinscenes[i].firstframe = i;
2270 loadmodel->skinscenes[i].framecount = 1;
2271 loadmodel->skinscenes[i].loop = true;
2272 loadmodel->skinscenes[i].framerate = 10;
2275 // load the bone info
2276 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2277 for (i = 0;i < loadmodel->num_bones;i++)
2279 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2280 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2281 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2282 if (loadmodel->data_bones[i].parent >= i)
2283 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2287 frames = (dpmframe_t *) (pbase + pheader->ofs_frames);
2288 // figure out scale of model from root bone, for compatibility with old dpmodel versions
2289 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2290 tempvec[0] = BigFloat(poses[0]);
2291 tempvec[1] = BigFloat(poses[1]);
2292 tempvec[2] = BigFloat(poses[2]);
2293 modelscale = VectorLength(tempvec);
2295 for (i = 0;i < loadmodel->numframes;i++)
2297 memcpy(loadmodel->animscenes[i].name, frames[i].name, sizeof(frames[i].name));
2298 loadmodel->animscenes[i].firstframe = i;
2299 loadmodel->animscenes[i].framecount = 1;
2300 loadmodel->animscenes[i].loop = true;
2301 loadmodel->animscenes[i].framerate = 10;
2302 // load the bone poses for this frame
2303 poses = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2304 for (j = 0;j < loadmodel->num_bones*12;j++)
2306 f = fabs(BigFloat(poses[j]));
2307 biggestorigin = max(biggestorigin, f);
2309 // stuff not processed here: mins, maxs, yawradius, allradius
2311 loadmodel->num_posescale = biggestorigin / 32767.0f;
2312 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2313 for (i = 0;i < loadmodel->numframes;i++)
2315 const float *frameposes = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2316 for (j = 0;j < loadmodel->num_bones;j++)
2319 matrix4x4_t posematrix;
2320 for (k = 0;k < 12;k++)
2321 pose[k] = BigFloat(frameposes[j*12+k]);
2322 // scale child bones to match the root scale
2323 if (loadmodel->data_bones[j].parent >= 0)
2325 pose[3] *= modelscale;
2326 pose[7] *= modelscale;
2327 pose[11] *= modelscale;
2329 // normalize rotation matrix
2330 VectorNormalize(pose + 0);
2331 VectorNormalize(pose + 4);
2332 VectorNormalize(pose + 8);
2333 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2334 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
2338 // load the meshes now
2339 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2342 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2343 // (converting from weight-blending skeletal animation to
2344 // deformation-based skeletal animation)
2345 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2346 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2347 for (i = 0;i < loadmodel->num_bones;i++)
2350 for (k = 0;k < 12;k++)
2351 m[k] = BigFloat(poses[i*12+k]);
2352 if (loadmodel->data_bones[i].parent >= 0)
2353 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2355 for (k = 0;k < 12;k++)
2356 bonepose[12*i+k] = m[k];
2358 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2360 const int *inelements;
2362 const float *intexcoord;
2363 msurface_t *surface;
2365 loadmodel->sortedmodelsurfaces[i] = i;
2366 surface = loadmodel->data_surfaces + i;
2367 surface->texture = loadmodel->data_textures + i;
2368 surface->num_firsttriangle = meshtriangles;
2369 surface->num_triangles = BigLong(dpmmesh->num_tris);
2370 surface->num_firstvertex = meshvertices;
2371 surface->num_vertices = BigLong(dpmmesh->num_verts);
2372 meshvertices += surface->num_vertices;
2373 meshtriangles += surface->num_triangles;
2375 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2376 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2377 for (j = 0;j < surface->num_triangles;j++)
2379 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2380 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2381 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2382 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2387 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2388 for (j = 0;j < surface->num_vertices*2;j++)
2389 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2391 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2392 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2394 int weightindex[4] = { 0, 0, 0, 0 };
2395 float weightinfluence[4] = { 0, 0, 0, 0 };
2397 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2398 data += sizeof(dpmvertex_t);
2399 for (k = 0;k < numweights;k++)
2401 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2402 int boneindex = BigLong(vert->bonenum);
2403 const float *m = bonepose + 12 * boneindex;
2404 float influence = BigFloat(vert->influence);
2405 float relativeorigin[3], relativenormal[3];
2406 relativeorigin[0] = BigFloat(vert->origin[0]);
2407 relativeorigin[1] = BigFloat(vert->origin[1]);
2408 relativeorigin[2] = BigFloat(vert->origin[2]);
2409 relativenormal[0] = BigFloat(vert->normal[0]);
2410 relativenormal[1] = BigFloat(vert->normal[1]);
2411 relativenormal[2] = BigFloat(vert->normal[2]);
2412 // blend the vertex bone weights into the base mesh
2413 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2414 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2415 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2416 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2417 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2418 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2421 // store the first (and often only) weight
2422 weightinfluence[0] = influence;
2423 weightindex[0] = boneindex;
2427 // sort the new weight into this vertex's weight table
2428 // (which only accepts up to 4 bones per vertex)
2429 for (l = 0;l < 4;l++)
2431 if (weightinfluence[l] < influence)
2433 // move weaker influence weights out of the way first
2435 for (l2 = 3;l2 > l;l2--)
2437 weightinfluence[l2] = weightinfluence[l2-1];
2438 weightindex[l2] = weightindex[l2-1];
2440 // store the new weight
2441 weightinfluence[l] = influence;
2442 weightindex[l] = boneindex;
2447 data += sizeof(dpmbonevert_t);
2449 loadmodel->surfmesh.blends[j] = Mod_Skeletal_AddBlend(loadmodel, weightindex, weightinfluence);
2452 // since dpm models do not have named sections, reuse their shader name as the section name
2453 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2455 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2457 if (loadmodel->surfmesh.num_blends < meshvertices)
2458 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2460 Mod_FreeSkinFiles(skinfiles);
2461 Mod_MakeSortedSurfaces(loadmodel);
2463 // compute all the mesh information that was not loaded from the file
2464 if (loadmodel->surfmesh.data_element3s)
2465 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2466 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2467 Mod_BuildBaseBonePoses();
2468 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);
2469 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2471 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2473 if (!loadmodel->surfmesh.isanimated)
2475 Mod_MakeCollisionBIH(loadmodel, true);
2476 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2477 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2478 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2479 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2483 // no idea why PSK/PSA files contain weird quaternions but they do...
2484 #define PSKQUATNEGATIONS
2485 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2487 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2488 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2489 fs_offset_t filesize;
2494 pskboneinfo_t *bones;
2495 pskrawweights_t *rawweights;
2496 //pskboneinfo_t *animbones;
2497 pskaniminfo_t *anims;
2498 pskanimkeys_t *animkeys;
2499 void *animfilebuffer, *animbuffer, *animbufferend;
2500 unsigned char *data;
2502 skinfile_t *skinfiles;
2503 char animname[MAX_QPATH];
2505 float biggestorigin;
2507 pchunk = (pskchunk_t *)buffer;
2508 if (strcmp(pchunk->id, "ACTRHEAD"))
2509 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2511 loadmodel->modeldatatypestring = "PSK";
2513 loadmodel->type = mod_alias;
2514 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2515 loadmodel->DrawSky = NULL;
2516 loadmodel->DrawAddWaterPlanes = NULL;
2517 loadmodel->Draw = R_Q1BSP_Draw;
2518 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2519 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2520 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2521 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2522 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2523 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2524 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2525 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2526 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2527 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2528 loadmodel->PointSuperContents = NULL;
2529 loadmodel->synctype = ST_RAND;
2531 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2532 strlcat(animname, ".psa", sizeof(animname));
2533 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2534 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2535 if (animbuffer == NULL)
2536 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2555 while (buffer < bufferend)
2557 pchunk = (pskchunk_t *)buffer;
2558 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2559 version = LittleLong(pchunk->version);
2560 recordsize = LittleLong(pchunk->recordsize);
2561 numrecords = LittleLong(pchunk->numrecords);
2562 if (developer_extra.integer)
2563 Con_DPrintf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2564 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2565 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);
2566 if (!strcmp(pchunk->id, "ACTRHEAD"))
2570 else if (!strcmp(pchunk->id, "PNTS0000"))
2573 if (recordsize != sizeof(*p))
2574 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2575 // byteswap in place and keep the pointer
2576 numpnts = numrecords;
2577 pnts = (pskpnts_t *)buffer;
2578 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2580 p->origin[0] = LittleFloat(p->origin[0]);
2581 p->origin[1] = LittleFloat(p->origin[1]);
2582 p->origin[2] = LittleFloat(p->origin[2]);
2586 else if (!strcmp(pchunk->id, "VTXW0000"))
2589 if (recordsize != sizeof(*p))
2590 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2591 // byteswap in place and keep the pointer
2592 numvtxw = numrecords;
2593 vtxw = (pskvtxw_t *)buffer;
2594 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2596 p->pntsindex = LittleShort(p->pntsindex);
2597 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2598 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2599 if (p->pntsindex >= numpnts)
2601 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2607 else if (!strcmp(pchunk->id, "FACE0000"))
2610 if (recordsize != sizeof(*p))
2611 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2612 // byteswap in place and keep the pointer
2613 numfaces = numrecords;
2614 faces = (pskface_t *)buffer;
2615 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2617 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2618 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2619 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2620 p->group = LittleLong(p->group);
2621 if (p->vtxwindex[0] >= numvtxw)
2623 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2624 p->vtxwindex[0] = 0;
2626 if (p->vtxwindex[1] >= numvtxw)
2628 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2629 p->vtxwindex[1] = 0;
2631 if (p->vtxwindex[2] >= numvtxw)
2633 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2634 p->vtxwindex[2] = 0;
2639 else if (!strcmp(pchunk->id, "MATT0000"))
2642 if (recordsize != sizeof(*p))
2643 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2644 // byteswap in place and keep the pointer
2645 nummatts = numrecords;
2646 matts = (pskmatt_t *)buffer;
2647 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2653 else if (!strcmp(pchunk->id, "REFSKELT"))
2656 if (recordsize != sizeof(*p))
2657 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2658 // byteswap in place and keep the pointer
2659 numbones = numrecords;
2660 bones = (pskboneinfo_t *)buffer;
2661 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2663 p->numchildren = LittleLong(p->numchildren);
2664 p->parent = LittleLong(p->parent);
2665 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2666 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2667 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2668 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2669 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2670 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2671 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2672 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2673 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2674 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2675 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2676 #ifdef PSKQUATNEGATIONS
2679 p->basepose.quat[0] *= -1;
2680 p->basepose.quat[1] *= -1;
2681 p->basepose.quat[2] *= -1;
2685 p->basepose.quat[0] *= 1;
2686 p->basepose.quat[1] *= -1;
2687 p->basepose.quat[2] *= 1;
2690 if (p->parent < 0 || p->parent >= numbones)
2692 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2698 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2701 if (recordsize != sizeof(*p))
2702 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2703 // byteswap in place and keep the pointer
2704 numrawweights = numrecords;
2705 rawweights = (pskrawweights_t *)buffer;
2706 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2708 p->weight = LittleFloat(p->weight);
2709 p->pntsindex = LittleLong(p->pntsindex);
2710 p->boneindex = LittleLong(p->boneindex);
2711 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2713 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2716 if (p->boneindex < 0 || p->boneindex >= numbones)
2718 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2726 while (animbuffer < animbufferend)
2728 pchunk = (pskchunk_t *)animbuffer;
2729 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2730 version = LittleLong(pchunk->version);
2731 recordsize = LittleLong(pchunk->recordsize);
2732 numrecords = LittleLong(pchunk->numrecords);
2733 if (developer_extra.integer)
2734 Con_DPrintf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2735 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2736 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);
2737 if (!strcmp(pchunk->id, "ANIMHEAD"))
2741 else if (!strcmp(pchunk->id, "BONENAMES"))
2744 if (recordsize != sizeof(*p))
2745 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2746 // byteswap in place and keep the pointer
2747 numanimbones = numrecords;
2748 //animbones = (pskboneinfo_t *)animbuffer;
2749 // NOTE: supposedly psa does not need to match the psk model, the
2750 // bones missing from the psa would simply use their base
2751 // positions from the psk, but this is hard for me to implement
2752 // and people can easily make animations that match.
2753 if (numanimbones != numbones)
2754 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2755 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2757 p->numchildren = LittleLong(p->numchildren);
2758 p->parent = LittleLong(p->parent);
2759 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2760 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2761 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2762 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2763 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2764 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2765 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2766 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2767 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2768 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2769 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2770 #ifdef PSKQUATNEGATIONS
2773 p->basepose.quat[0] *= -1;
2774 p->basepose.quat[1] *= -1;
2775 p->basepose.quat[2] *= -1;
2779 p->basepose.quat[0] *= 1;
2780 p->basepose.quat[1] *= -1;
2781 p->basepose.quat[2] *= 1;
2784 if (p->parent < 0 || p->parent >= numanimbones)
2786 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2789 // check that bones are the same as in the base
2790 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2791 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2795 else if (!strcmp(pchunk->id, "ANIMINFO"))
2798 if (recordsize != sizeof(*p))
2799 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2800 // byteswap in place and keep the pointer
2801 numanims = numrecords;
2802 anims = (pskaniminfo_t *)animbuffer;
2803 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2805 p->numbones = LittleLong(p->numbones);
2806 p->playtime = LittleFloat(p->playtime);
2807 p->fps = LittleFloat(p->fps);
2808 p->firstframe = LittleLong(p->firstframe);
2809 p->numframes = LittleLong(p->numframes);
2810 if (p->numbones != numbones)
2811 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2815 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2818 if (recordsize != sizeof(*p))
2819 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2820 numanimkeys = numrecords;
2821 animkeys = (pskanimkeys_t *)animbuffer;
2822 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2824 p->origin[0] = LittleFloat(p->origin[0]);
2825 p->origin[1] = LittleFloat(p->origin[1]);
2826 p->origin[2] = LittleFloat(p->origin[2]);
2827 p->quat[0] = LittleFloat(p->quat[0]);
2828 p->quat[1] = LittleFloat(p->quat[1]);
2829 p->quat[2] = LittleFloat(p->quat[2]);
2830 p->quat[3] = LittleFloat(p->quat[3]);
2831 p->frametime = LittleFloat(p->frametime);
2832 #ifdef PSKQUATNEGATIONS
2833 if (index % numbones)
2848 // TODO: allocate bonepose stuff
2851 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2854 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2855 Host_Error("%s: missing required chunks", loadmodel->name);
2857 loadmodel->numframes = 0;
2858 for (index = 0;index < numanims;index++)
2859 loadmodel->numframes += anims[index].numframes;
2861 if (numanimkeys != numbones * loadmodel->numframes)
2862 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2864 meshvertices = numvtxw;
2865 meshtriangles = numfaces;
2867 // load external .skin files if present
2868 skinfiles = Mod_LoadSkinFiles();
2869 if (loadmodel->numskins < 1)
2870 loadmodel->numskins = 1;
2871 loadmodel->num_bones = numbones;
2872 loadmodel->num_poses = loadmodel->numframes;
2873 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2874 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2875 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2876 loadmodel->surfmesh.num_vertices = meshvertices;
2877 loadmodel->surfmesh.num_triangles = meshtriangles;
2878 // do most allocations as one merged chunk
2879 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(unsigned short) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]) + 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);
2880 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2881 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2882 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2883 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2884 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2885 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2886 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2887 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2888 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2889 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2890 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2891 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2892 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2893 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2894 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2895 loadmodel->surfmesh.num_blends = 0;
2896 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2897 if (loadmodel->surfmesh.num_vertices <= 65536)
2898 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2899 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2900 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(blendweights_t));
2902 for (i = 0;i < loadmodel->numskins;i++)
2904 loadmodel->skinscenes[i].firstframe = i;
2905 loadmodel->skinscenes[i].framecount = 1;
2906 loadmodel->skinscenes[i].loop = true;
2907 loadmodel->skinscenes[i].framerate = 10;
2911 for (index = 0, i = 0;index < nummatts;index++)
2913 // since psk models do not have named sections, reuse their shader name as the section name
2914 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2915 loadmodel->sortedmodelsurfaces[index] = index;
2916 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2917 loadmodel->data_surfaces[index].num_firstvertex = 0;
2918 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2921 // copy over the vertex locations and texcoords
2922 for (index = 0;index < numvtxw;index++)
2924 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2925 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2926 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2927 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2928 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2931 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2932 for (index = 0;index < numfaces;index++)
2933 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2934 for (index = 0, i = 0;index < nummatts;index++)
2936 loadmodel->data_surfaces[index].num_firsttriangle = i;
2937 i += loadmodel->data_surfaces[index].num_triangles;
2938 loadmodel->data_surfaces[index].num_triangles = 0;
2940 for (index = 0;index < numfaces;index++)
2942 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2943 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2944 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2945 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2948 // copy over the bones
2949 for (index = 0;index < numbones;index++)
2951 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2952 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2953 if (loadmodel->data_bones[index].parent >= index)
2954 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2957 // sort the psk point weights into the vertex weight tables
2958 // (which only accept up to 4 bones per vertex)
2959 for (index = 0;index < numvtxw;index++)
2961 int weightindex[4] = { 0, 0, 0, 0 };
2962 float weightinfluence[4] = { 0, 0, 0, 0 };
2964 for (j = 0;j < numrawweights;j++)
2966 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2968 int boneindex = rawweights[j].boneindex;
2969 float influence = rawweights[j].weight;
2970 for (l = 0;l < 4;l++)
2972 if (weightinfluence[l] < influence)
2974 // move lower influence weights out of the way first
2976 for (l2 = 3;l2 > l;l2--)
2978 weightinfluence[l2] = weightinfluence[l2-1];
2979 weightindex[l2] = weightindex[l2-1];
2981 // store the new weight
2982 weightinfluence[l] = influence;
2983 weightindex[l] = boneindex;
2989 loadmodel->surfmesh.blends[index] = Mod_Skeletal_AddBlend(loadmodel, weightindex, weightinfluence);
2991 if (loadmodel->surfmesh.num_blends < loadmodel->surfmesh.num_vertices)
2992 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2994 // set up the animscenes based on the anims
2995 for (index = 0, i = 0;index < numanims;index++)
2997 for (j = 0;j < anims[index].numframes;j++, i++)
2999 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
3000 loadmodel->animscenes[i].firstframe = i;
3001 loadmodel->animscenes[i].framecount = 1;
3002 loadmodel->animscenes[i].loop = true;
3003 loadmodel->animscenes[i].framerate = 10;
3007 // calculate the scaling value for bone origins so they can be compressed to short
3009 for (index = 0;index < numanimkeys;index++)
3011 pskanimkeys_t *k = animkeys + index;
3012 biggestorigin = max(biggestorigin, fabs(k->origin[0]));
3013 biggestorigin = max(biggestorigin, fabs(k->origin[1]));
3014 biggestorigin = max(biggestorigin, fabs(k->origin[2]));
3016 loadmodel->num_posescale = biggestorigin / 32767.0f;
3017 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3019 // load the poses from the animkeys
3020 for (index = 0;index < numanimkeys;index++)
3022 pskanimkeys_t *k = animkeys + index;
3024 Vector4Copy(k->quat, quat);
3026 Vector4Negate(quat, quat);
3027 Vector4Normalize2(quat, quat);
3028 // compress poses to the short[6] format for longterm storage
3029 loadmodel->data_poses6s[index*6+0] = k->origin[0] * loadmodel->num_poseinvscale;
3030 loadmodel->data_poses6s[index*6+1] = k->origin[1] * loadmodel->num_poseinvscale;
3031 loadmodel->data_poses6s[index*6+2] = k->origin[2] * loadmodel->num_poseinvscale;
3032 loadmodel->data_poses6s[index*6+3] = quat[0] * 32767.0f;
3033 loadmodel->data_poses6s[index*6+4] = quat[1] * 32767.0f;
3034 loadmodel->data_poses6s[index*6+5] = quat[2] * 32767.0f;
3036 Mod_FreeSkinFiles(skinfiles);
3037 Mem_Free(animfilebuffer);
3038 Mod_MakeSortedSurfaces(loadmodel);
3040 // compute all the mesh information that was not loaded from the file
3041 // TODO: honor smoothing groups somehow?
3042 if (loadmodel->surfmesh.data_element3s)
3043 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3044 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3045 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
3046 Mod_BuildBaseBonePoses();
3047 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
3048 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);
3049 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3050 Mod_Alias_CalculateBoundingBox();
3052 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
3054 if (!loadmodel->surfmesh.isanimated)
3056 Mod_MakeCollisionBIH(loadmodel, true);
3057 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3058 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3059 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3060 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;