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.
24 #include "mod_skeletal_animatevertices_generic.h"
26 #include "mod_skeletal_animatevertices_sse.h"
30 static qboolean r_skeletal_use_sse_defined = false;
31 cvar_t r_skeletal_use_sse = {0, "r_skeletal_use_sse", "1", "use SSE for skeletal model animation"};
33 cvar_t r_skeletal_debugbone = {0, "r_skeletal_debugbone", "-1", "development cvar for testing skeletal model code"};
34 cvar_t r_skeletal_debugbonecomponent = {0, "r_skeletal_debugbonecomponent", "3", "development cvar for testing skeletal model code"};
35 cvar_t r_skeletal_debugbonevalue = {0, "r_skeletal_debugbonevalue", "100", "development cvar for testing skeletal model code"};
36 cvar_t r_skeletal_debugtranslatex = {0, "r_skeletal_debugtranslatex", "1", "development cvar for testing skeletal model code"};
37 cvar_t r_skeletal_debugtranslatey = {0, "r_skeletal_debugtranslatey", "1", "development cvar for testing skeletal model code"};
38 cvar_t r_skeletal_debugtranslatez = {0, "r_skeletal_debugtranslatez", "1", "development cvar for testing skeletal model code"};
39 cvar_t mod_alias_supporttagscale = {0, "mod_alias_supporttagscale", "1", "support scaling factors in bone/tag attachment matrices as supported by MD3"};
40 cvar_t mod_alias_force_animated = {0, "mod_alias_force_animated", "", "if set to an non-empty string, overrides the is-animated flag of any alias models (for benchmarking)"};
42 float mod_md3_sin[320];
44 static size_t Mod_Skeletal_AnimateVertices_maxbonepose = 0;
45 static void *Mod_Skeletal_AnimateVertices_bonepose = NULL;
46 void Mod_Skeletal_FreeBuffers(void)
48 if(Mod_Skeletal_AnimateVertices_bonepose)
49 Mem_Free(Mod_Skeletal_AnimateVertices_bonepose);
50 Mod_Skeletal_AnimateVertices_maxbonepose = 0;
51 Mod_Skeletal_AnimateVertices_bonepose = NULL;
53 void *Mod_Skeletal_AnimateVertices_AllocBuffers(size_t nbytes)
55 if(Mod_Skeletal_AnimateVertices_maxbonepose < nbytes)
57 if(Mod_Skeletal_AnimateVertices_bonepose)
58 Mem_Free(Mod_Skeletal_AnimateVertices_bonepose);
59 Mod_Skeletal_AnimateVertices_bonepose = Z_Malloc(nbytes);
60 Mod_Skeletal_AnimateVertices_maxbonepose = nbytes;
62 return Mod_Skeletal_AnimateVertices_bonepose;
65 void Mod_Skeletal_BuildTransforms(const dp_model_t * RESTRICT model, const frameblend_t * RESTRICT frameblend, const skeleton_t *skeleton, float * RESTRICT bonepose, float * RESTRICT boneposerelative)
71 bonepose = (float * RESTRICT) Mod_Skeletal_AnimateVertices_AllocBuffers(sizeof(float[12]) * model->num_bones);
73 if (skeleton && !skeleton->relativetransforms)
76 // interpolate matrices
79 for (i = 0;i < model->num_bones;i++)
81 Matrix4x4_ToArray12FloatD3D(&skeleton->relativetransforms[i], m);
82 if (model->data_bones[i].parent >= 0)
83 R_ConcatTransforms(bonepose + model->data_bones[i].parent * 12, m, bonepose + i * 12);
85 memcpy(bonepose + i * 12, m, sizeof(m));
87 // create a relative deformation matrix to describe displacement
88 // from the base mesh, which is used by the actual weighting
89 R_ConcatTransforms(bonepose + i * 12, model->data_baseboneposeinverse + i * 12, boneposerelative + i * 12);
94 for (i = 0;i < model->num_bones;i++)
96 // blend by transform each quaternion/translation into a dual-quaternion first, then blending
97 const short * RESTRICT firstpose7s = model->data_poses7s + 7 * (frameblend[0].subframe * model->num_bones + i);
98 float firstlerp = frameblend[0].lerp,
99 firsttx = firstpose7s[0], firstty = firstpose7s[1], firsttz = firstpose7s[2],
100 rx = firstpose7s[3] * firstlerp,
101 ry = firstpose7s[4] * firstlerp,
102 rz = firstpose7s[5] * firstlerp,
103 rw = firstpose7s[6] * firstlerp,
104 dx = firsttx*rw + firstty*rz - firsttz*ry,
105 dy = -firsttx*rz + firstty*rw + firsttz*rx,
106 dz = firsttx*ry - firstty*rx + firsttz*rw,
107 dw = -firsttx*rx - firstty*ry - firsttz*rz,
108 scale, sx, sy, sz, sw;
109 for (blends = 1;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++)
111 const short * RESTRICT blendpose7s = model->data_poses7s + 7 * (frameblend[blends].subframe * model->num_bones + i);
112 float blendlerp = frameblend[blends].lerp,
113 blendtx = blendpose7s[0], blendty = blendpose7s[1], blendtz = blendpose7s[2],
114 qx = blendpose7s[3], qy = blendpose7s[4], qz = blendpose7s[5], qw = blendpose7s[6];
115 if(rx*qx + ry*qy + rz*qz + rw*qw < 0) blendlerp = -blendlerp;
124 dx += blendtx*qw + blendty*qz - blendtz*qy;
125 dy += -blendtx*qz + blendty*qw + blendtz*qx;
126 dz += blendtx*qy - blendty*qx + blendtz*qw;
127 dw += -blendtx*qx - blendty*qy - blendtz*qz;
129 // generate a matrix from the dual-quaternion, implicitly normalizing it in the process
130 scale = 1.0f / (rx*rx + ry*ry + rz*rz + rw*rw);
135 m[0] = sw*rw + sx*rx - sy*ry - sz*rz;
136 m[1] = 2*(sx*ry - sw*rz);
137 m[2] = 2*(sx*rz + sw*ry);
138 m[3] = model->num_posescale*(dx*sw - dy*sz + dz*sy - dw*sx);
139 m[4] = 2*(sx*ry + sw*rz);
140 m[5] = sw*rw + sy*ry - sx*rx - sz*rz;
141 m[6] = 2*(sy*rz - sw*rx);
142 m[7] = model->num_posescale*(dx*sz + dy*sw - dz*sx - dw*sy);
143 m[8] = 2*(sx*rz - sw*ry);
144 m[9] = 2*(sy*rz + sw*rx);
145 m[10] = sw*rw + sz*rz - sx*rx - sy*ry;
146 m[11] = model->num_posescale*(dy*sx + dz*sw - dx*sy - dw*sz);
147 if (i == r_skeletal_debugbone.integer)
148 m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
149 m[3] *= r_skeletal_debugtranslatex.value;
150 m[7] *= r_skeletal_debugtranslatey.value;
151 m[11] *= r_skeletal_debugtranslatez.value;
152 if (model->data_bones[i].parent >= 0)
153 R_ConcatTransforms(bonepose + model->data_bones[i].parent * 12, m, bonepose + i * 12);
155 memcpy(bonepose + i * 12, m, sizeof(m));
156 // create a relative deformation matrix to describe displacement
157 // from the base mesh, which is used by the actual weighting
158 R_ConcatTransforms(bonepose + i * 12, model->data_baseboneposeinverse + i * 12, boneposerelative + i * 12);
163 static 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)
166 if (!model->surfmesh.num_vertices)
169 if (!model->num_bones)
171 if (vertex3f) memcpy(vertex3f, model->surfmesh.data_vertex3f, model->surfmesh.num_vertices*sizeof(float[3]));
172 if (normal3f) memcpy(normal3f, model->surfmesh.data_normal3f, model->surfmesh.num_vertices*sizeof(float[3]));
173 if (svector3f) memcpy(svector3f, model->surfmesh.data_svector3f, model->surfmesh.num_vertices*sizeof(float[3]));
174 if (tvector3f) memcpy(tvector3f, model->surfmesh.data_tvector3f, model->surfmesh.num_vertices*sizeof(float[3]));
179 if(r_skeletal_use_sse_defined)
180 if(r_skeletal_use_sse.integer)
182 Mod_Skeletal_AnimateVertices_SSE(model, frameblend, skeleton, vertex3f, normal3f, svector3f, tvector3f);
186 Mod_Skeletal_AnimateVertices_Generic(model, frameblend, skeleton, vertex3f, normal3f, svector3f, tvector3f);
189 void Mod_AliasInit (void)
192 Cvar_RegisterVariable(&r_skeletal_debugbone);
193 Cvar_RegisterVariable(&r_skeletal_debugbonecomponent);
194 Cvar_RegisterVariable(&r_skeletal_debugbonevalue);
195 Cvar_RegisterVariable(&r_skeletal_debugtranslatex);
196 Cvar_RegisterVariable(&r_skeletal_debugtranslatey);
197 Cvar_RegisterVariable(&r_skeletal_debugtranslatez);
198 Cvar_RegisterVariable(&mod_alias_supporttagscale);
199 Cvar_RegisterVariable(&mod_alias_force_animated);
200 for (i = 0;i < 320;i++)
201 mod_md3_sin[i] = sin(i * M_PI * 2.0f / 256.0);
205 Con_Printf("Skeletal animation uses SSE code path\n");
206 r_skeletal_use_sse_defined = true;
207 Cvar_RegisterVariable(&r_skeletal_use_sse);
210 Con_Printf("Skeletal animation uses generic code path (SSE disabled or not detected)\n");
212 Con_Printf("Skeletal animation uses generic code path (SSE not compiled in)\n");
216 static int Mod_Skeletal_AddBlend(dp_model_t *model, const blendweights_t *newweights)
219 blendweights_t *weights;
220 if(!newweights->influence[1])
221 return newweights->index[0];
222 weights = model->surfmesh.data_blendweights;
223 for (i = 0;i < model->surfmesh.num_blends;i++, weights++)
225 if (!memcmp(weights, newweights, sizeof(blendweights_t)))
226 return model->num_bones + i;
228 model->surfmesh.num_blends++;
229 memcpy(weights, newweights, sizeof(blendweights_t));
230 return model->num_bones + i;
233 static int Mod_Skeletal_CompressBlend(dp_model_t *model, const int *newindex, const float *newinfluence)
237 blendweights_t newweights;
241 for (i = 0;i < 4;i++)
242 scale += newinfluence[i];
243 scale = 255.0f / scale;
245 for (i = 0;i < 4;i++)
247 newweights.index[i] = newindex[i];
248 newweights.influence[i] = (unsigned char)(newinfluence[i] * scale);
249 total += newweights.influence[i];
253 for (i = 0;i < 4;i++)
255 if(newweights.influence[i] > 0 && total > 255)
257 newweights.influence[i]--;
264 for (i = 0; i < 4;i++)
266 if(newweights.influence[i] < 255 && total < 255)
268 newweights.influence[i]++;
273 return Mod_Skeletal_AddBlend(model, &newweights);
276 static 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)
279 int i, numblends, blendnum;
280 int numverts = model->surfmesh.num_vertices;
282 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
284 //VectorMA(translate, model->surfmesh.num_morphmdlframetranslate, frameblend[blendnum].lerp, translate);
285 if (frameblend[blendnum].lerp > 0)
286 numblends = blendnum + 1;
288 // special case for the first blend because it avoids some adds and the need to memset the arrays first
289 for (blendnum = 0;blendnum < numblends;blendnum++)
291 const md3vertex_t *verts = model->surfmesh.data_morphmd3vertex + numverts * frameblend[blendnum].subframe;
294 float scale = frameblend[blendnum].lerp * (1.0f / 64.0f);
297 for (i = 0;i < numverts;i++)
299 vertex3f[i * 3 + 0] = verts[i].origin[0] * scale;
300 vertex3f[i * 3 + 1] = verts[i].origin[1] * scale;
301 vertex3f[i * 3 + 2] = verts[i].origin[2] * scale;
306 for (i = 0;i < numverts;i++)
308 vertex3f[i * 3 + 0] += verts[i].origin[0] * scale;
309 vertex3f[i * 3 + 1] += verts[i].origin[1] * scale;
310 vertex3f[i * 3 + 2] += verts[i].origin[2] * scale;
314 // the yaw and pitch stored in md3 models are 8bit quantized angles
315 // (0-255), and as such a lookup table is very well suited to
316 // decoding them, and since cosine is equivalent to sine with an
317 // extra 45 degree rotation, this uses one lookup table for both
318 // sine and cosine with a +64 bias to get cosine.
321 float lerp = frameblend[blendnum].lerp;
324 for (i = 0;i < numverts;i++)
326 normal3f[i * 3 + 0] = mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
327 normal3f[i * 3 + 1] = mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
328 normal3f[i * 3 + 2] = mod_md3_sin[verts[i].pitch + 64] * lerp;
333 for (i = 0;i < numverts;i++)
335 normal3f[i * 3 + 0] += mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
336 normal3f[i * 3 + 1] += mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
337 normal3f[i * 3 + 2] += mod_md3_sin[verts[i].pitch + 64] * lerp;
343 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
344 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
347 for (i = 0;i < numverts;i++, texvecvert++)
349 VectorScale(texvecvert->svec, f, svector3f + i*3);
350 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
355 for (i = 0;i < numverts;i++, texvecvert++)
357 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
358 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
364 static 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)
367 int i, numblends, blendnum;
368 int numverts = model->surfmesh.num_vertices;
370 VectorClear(translate);
372 // blend the frame translates to avoid redundantly doing so on each vertex
373 // (a bit of a brain twister but it works)
374 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
376 if (model->surfmesh.data_morphmd2framesize6f)
377 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6 + 3, translate);
379 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.num_morphmdlframetranslate, translate);
380 if (frameblend[blendnum].lerp > 0)
381 numblends = blendnum + 1;
383 // special case for the first blend because it avoids some adds and the need to memset the arrays first
384 for (blendnum = 0;blendnum < numblends;blendnum++)
386 const trivertx_t *verts = model->surfmesh.data_morphmdlvertex + numverts * frameblend[blendnum].subframe;
390 if (model->surfmesh.data_morphmd2framesize6f)
391 VectorScale(model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6, frameblend[blendnum].lerp, scale);
393 VectorScale(model->surfmesh.num_morphmdlframescale, frameblend[blendnum].lerp, scale);
396 for (i = 0;i < numverts;i++)
398 vertex3f[i * 3 + 0] = translate[0] + verts[i].v[0] * scale[0];
399 vertex3f[i * 3 + 1] = translate[1] + verts[i].v[1] * scale[1];
400 vertex3f[i * 3 + 2] = translate[2] + verts[i].v[2] * scale[2];
405 for (i = 0;i < numverts;i++)
407 vertex3f[i * 3 + 0] += verts[i].v[0] * scale[0];
408 vertex3f[i * 3 + 1] += verts[i].v[1] * scale[1];
409 vertex3f[i * 3 + 2] += verts[i].v[2] * scale[2];
413 // the vertex normals in mdl models are an index into a table of
414 // 162 unique values, this very crude quantization reduces the
415 // vertex normal to only one byte, which saves a lot of space but
416 // also makes lighting pretty coarse
419 float lerp = frameblend[blendnum].lerp;
422 for (i = 0;i < numverts;i++)
424 const float *vn = m_bytenormals[verts[i].lightnormalindex];
425 VectorScale(vn, lerp, normal3f + i*3);
430 for (i = 0;i < numverts;i++)
432 const float *vn = m_bytenormals[verts[i].lightnormalindex];
433 VectorMA(normal3f + i*3, lerp, vn, normal3f + i*3);
439 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
440 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
443 for (i = 0;i < numverts;i++, texvecvert++)
445 VectorScale(texvecvert->svec, f, svector3f + i*3);
446 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
451 for (i = 0;i < numverts;i++, texvecvert++)
453 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
454 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
461 int Mod_Alias_GetTagMatrix(const dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, int tagindex, matrix4x4_t *outmatrix)
464 matrix4x4_t parentbonematrix;
465 matrix4x4_t tempbonematrix;
466 matrix4x4_t bonematrix;
467 matrix4x4_t blendmatrix;
474 *outmatrix = identitymatrix;
475 if (skeleton && skeleton->relativetransforms)
477 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
479 *outmatrix = skeleton->relativetransforms[tagindex];
480 while ((tagindex = model->data_bones[tagindex].parent) >= 0)
483 Matrix4x4_Concat(outmatrix, &skeleton->relativetransforms[tagindex], &temp);
486 else if (model->num_bones)
488 if (tagindex < 0 || tagindex >= model->num_bones)
490 Matrix4x4_Clear(&blendmatrix);
491 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
493 lerp = frameblend[blendindex].lerp;
494 Matrix4x4_FromBonePose7s(&bonematrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
495 parenttagindex = tagindex;
496 while ((parenttagindex = model->data_bones[parenttagindex].parent) >= 0)
498 Matrix4x4_FromBonePose7s(&parentbonematrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + parenttagindex));
499 tempbonematrix = bonematrix;
500 Matrix4x4_Concat(&bonematrix, &parentbonematrix, &tempbonematrix);
502 Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
504 *outmatrix = blendmatrix;
506 else if (model->num_tags)
508 if (tagindex < 0 || tagindex >= model->num_tags)
510 for (k = 0;k < 12;k++)
512 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
514 lerp = frameblend[blendindex].lerp;
515 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
516 for (k = 0;k < 12;k++)
517 blendtag[k] += input[k] * lerp;
519 Matrix4x4_FromArray12FloatGL(outmatrix, blendtag);
522 if(!mod_alias_supporttagscale.integer)
523 Matrix4x4_Normalize3(outmatrix, outmatrix);
528 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)
533 matrix4x4_t bonematrix;
534 matrix4x4_t blendmatrix;
538 if (skeleton && skeleton->relativetransforms)
540 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
542 *parentindex = skeleton->model->data_bones[tagindex].parent;
543 *tagname = skeleton->model->data_bones[tagindex].name;
544 *tag_localmatrix = skeleton->relativetransforms[tagindex];
547 else if (model->num_bones)
549 if (tagindex < 0 || tagindex >= model->num_bones)
551 *parentindex = model->data_bones[tagindex].parent;
552 *tagname = model->data_bones[tagindex].name;
553 Matrix4x4_Clear(&blendmatrix);
554 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
556 lerp = frameblend[blendindex].lerp;
557 Matrix4x4_FromBonePose7s(&bonematrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
558 Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
560 *tag_localmatrix = blendmatrix;
563 else if (model->num_tags)
565 if (tagindex < 0 || tagindex >= model->num_tags)
568 *tagname = model->data_tags[tagindex].name;
569 for (k = 0;k < 12;k++)
571 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
573 lerp = frameblend[blendindex].lerp;
574 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
575 for (k = 0;k < 12;k++)
576 blendtag[k] += input[k] * lerp;
578 Matrix4x4_FromArray12FloatGL(tag_localmatrix, blendtag);
585 int Mod_Alias_GetTagIndexForName(const dp_model_t *model, unsigned int skin, const char *tagname)
588 if(skin >= (unsigned int)model->numskins)
590 if (model->num_bones)
591 for (i = 0;i < model->num_bones;i++)
592 if (!strcasecmp(tagname, model->data_bones[i].name))
595 for (i = 0;i < model->num_tags;i++)
596 if (!strcasecmp(tagname, model->data_tags[i].name))
601 static void Mod_BuildBaseBonePoses(void)
604 matrix4x4_t *basebonepose;
605 float *outinvmatrix = loadmodel->data_baseboneposeinverse;
606 matrix4x4_t bonematrix;
607 matrix4x4_t tempbonematrix;
608 if (!loadmodel->num_bones)
610 basebonepose = (matrix4x4_t *)Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(matrix4x4_t));
611 for (boneindex = 0;boneindex < loadmodel->num_bones;boneindex++)
613 Matrix4x4_FromBonePose7s(&bonematrix, loadmodel->num_posescale, loadmodel->data_poses7s + 7 * boneindex);
614 if (loadmodel->data_bones[boneindex].parent >= 0)
616 tempbonematrix = bonematrix;
617 Matrix4x4_Concat(&bonematrix, basebonepose + loadmodel->data_bones[boneindex].parent, &tempbonematrix);
619 basebonepose[boneindex] = bonematrix;
620 Matrix4x4_Invert_Simple(&tempbonematrix, basebonepose + boneindex);
621 Matrix4x4_ToArray12FloatD3D(&tempbonematrix, outinvmatrix + 12*boneindex);
623 Mem_Free(basebonepose);
626 static qboolean Mod_Alias_CalculateBoundingBox(void)
629 qboolean firstvertex = true;
630 float dist, yawradius, radius;
632 qboolean isanimated = false;
633 VectorClear(loadmodel->normalmins);
634 VectorClear(loadmodel->normalmaxs);
637 if (loadmodel->AnimateVertices)
639 float *vertex3f, *refvertex3f;
640 frameblend_t frameblend[MAX_FRAMEBLENDS];
641 memset(frameblend, 0, sizeof(frameblend));
642 frameblend[0].lerp = 1;
643 vertex3f = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]) * 2);
645 for (frameblend[0].subframe = 0;frameblend[0].subframe < loadmodel->num_poses;frameblend[0].subframe++)
647 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, vertex3f, NULL, NULL, NULL);
650 // make a copy of the first frame for comparing all others
651 refvertex3f = vertex3f + loadmodel->surfmesh.num_vertices * 3;
652 memcpy(refvertex3f, vertex3f, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
656 if (!isanimated && memcmp(refvertex3f, vertex3f, loadmodel->surfmesh.num_vertices * sizeof(float[3])))
659 for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
664 VectorCopy(v, loadmodel->normalmins);
665 VectorCopy(v, loadmodel->normalmaxs);
669 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
670 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
671 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
672 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
673 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
674 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
676 dist = v[0] * v[0] + v[1] * v[1];
677 if (yawradius < dist)
689 for (vnum = 0, v = loadmodel->surfmesh.data_vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
694 VectorCopy(v, loadmodel->normalmins);
695 VectorCopy(v, loadmodel->normalmaxs);
699 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
700 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
701 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
702 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
703 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
704 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
706 dist = v[0] * v[0] + v[1] * v[1];
707 if (yawradius < dist)
714 radius = sqrt(radius);
715 yawradius = sqrt(yawradius);
716 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
717 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
718 loadmodel->yawmins[2] = loadmodel->normalmins[2];
719 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
720 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
721 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
722 loadmodel->radius = radius;
723 loadmodel->radius2 = radius * radius;
727 static void Mod_Alias_MorphMesh_CompileFrames(void)
730 frameblend_t frameblend[MAX_FRAMEBLENDS];
731 unsigned char *datapointer;
732 memset(frameblend, 0, sizeof(frameblend));
733 frameblend[0].lerp = 1;
734 datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
735 loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
736 loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
737 loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
738 loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
739 loadmodel->surfmesh.data_morphtexvecvertex = (texvecvertex_t *)datapointer;datapointer += loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices * sizeof(texvecvertex_t);
740 // 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)
741 for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
743 frameblend[0].subframe = i;
744 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
745 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);
746 // encode the svector and tvector in 3 byte format for permanent storage
747 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
749 VectorScaleCast(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
750 VectorScaleCast(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
755 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, int skipsupercontentsmask, int skipmaterialflagsmask)
758 float segmentmins[3], segmentmaxs[3];
760 float vertex3fbuf[1024 * 3];
761 float *vertex3f = vertex3fbuf;
762 float *freevertex3f = NULL;
763 // for static cases we can just call CollisionBIH which is much faster
764 if ((frameblend == NULL || (frameblend[0].subframe == 0 && frameblend[1].lerp == 0)) && (skeleton == NULL || skeleton->relativetransforms == NULL))
766 Mod_CollisionBIH_TraceLine(model, frameblend, skeleton, trace, start, end, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
769 memset(trace, 0, sizeof(*trace));
771 trace->hitsupercontentsmask = hitsupercontentsmask;
772 trace->skipsupercontentsmask = skipsupercontentsmask;
773 trace->skipmaterialflagsmask = skipmaterialflagsmask;
774 segmentmins[0] = min(start[0], end[0]) - 1;
775 segmentmins[1] = min(start[1], end[1]) - 1;
776 segmentmins[2] = min(start[2], end[2]) - 1;
777 segmentmaxs[0] = max(start[0], end[0]) + 1;
778 segmentmaxs[1] = max(start[1], end[1]) + 1;
779 segmentmaxs[2] = max(start[2], end[2]) + 1;
780 if (frameblend == NULL || frameblend[0].subframe != 0 || frameblend[0].lerp != 0 || skeleton != NULL)
782 if (model->surfmesh.num_vertices > 1024)
783 vertex3f = freevertex3f = (float *)Mem_Alloc(tempmempool, model->surfmesh.num_vertices * sizeof(float[3]));
784 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
787 vertex3f = model->surfmesh.data_vertex3f;
788 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
789 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);
791 Mem_Free(freevertex3f);
794 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, int skipsupercontentsmask, int skipmaterialflagsmask)
797 vec3_t shiftstart, shiftend;
798 float segmentmins[3], segmentmaxs[3];
800 float vertex3fbuf[1024*3];
801 float *vertex3f = vertex3fbuf;
802 colboxbrushf_t thisbrush_start, thisbrush_end;
803 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
805 if (VectorCompare(boxmins, boxmaxs))
807 VectorAdd(start, boxmins, shiftstart);
808 VectorAdd(end, boxmins, shiftend);
809 Mod_MDLMD2MD3_TraceLine(model, frameblend, skeleton, trace, shiftstart, shiftend, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
810 VectorSubtract(trace->endpos, boxmins, trace->endpos);
814 // for static cases we can just call CollisionBIH which is much faster
815 if ((frameblend == NULL || (frameblend[0].subframe == 0 && frameblend[1].lerp == 0)) && (skeleton == NULL || skeleton->relativetransforms == NULL))
817 Mod_CollisionBIH_TraceBox(model, frameblend, skeleton, trace, start, boxmins, boxmaxs, end, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
821 // box trace, performed as brush trace
822 memset(trace, 0, sizeof(*trace));
824 trace->hitsupercontentsmask = hitsupercontentsmask;
825 trace->skipsupercontentsmask = skipsupercontentsmask;
826 trace->skipmaterialflagsmask = skipmaterialflagsmask;
827 if (model->surfmesh.num_vertices > 1024)
828 vertex3f = (float *)Mem_Alloc(tempmempool, model->surfmesh.num_vertices * sizeof(float[3]));
829 segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
830 segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
831 segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
832 segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
833 segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
834 segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
835 VectorAdd(start, boxmins, boxstartmins);
836 VectorAdd(start, boxmaxs, boxstartmaxs);
837 VectorAdd(end, boxmins, boxendmins);
838 VectorAdd(end, boxmaxs, boxendmaxs);
839 Collision_BrushForBox(&thisbrush_start, boxstartmins, boxstartmaxs, 0, 0, NULL);
840 Collision_BrushForBox(&thisbrush_end, boxendmins, boxendmaxs, 0, 0, NULL);
841 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
842 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
843 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);
844 if (vertex3f != vertex3fbuf)
848 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
851 for (i = 0;i < inverts;i++)
853 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
855 j = vertremap[i]; // not onseam
858 j = vertremap[i+inverts]; // onseam
864 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
866 int i, f, pose, groupframes;
868 daliasframetype_t *pframetype;
869 daliasframe_t *pinframe;
870 daliasgroup_t *group;
871 daliasinterval_t *intervals;
874 scene = loadmodel->animscenes;
875 for (f = 0;f < loadmodel->numframes;f++)
877 pframetype = (daliasframetype_t *)datapointer;
878 datapointer += sizeof(daliasframetype_t);
879 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
881 // a single frame is still treated as a group
888 group = (daliasgroup_t *)datapointer;
889 datapointer += sizeof(daliasgroup_t);
890 groupframes = LittleLong (group->numframes);
892 // intervals (time per frame)
893 intervals = (daliasinterval_t *)datapointer;
894 datapointer += sizeof(daliasinterval_t) * groupframes;
896 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
897 if (interval < 0.01f)
899 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
904 // get scene name from first frame
905 pinframe = (daliasframe_t *)datapointer;
907 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
908 scene->firstframe = pose;
909 scene->framecount = groupframes;
910 scene->framerate = 1.0f / interval;
915 for (i = 0;i < groupframes;i++)
917 datapointer += sizeof(daliasframe_t);
918 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
919 datapointer += sizeof(trivertx_t) * inverts;
925 void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
928 char stripbuf[MAX_QPATH];
929 skinfileitem_t *skinfileitem;
930 if(developer_extra.integer)
931 Con_DPrintf("Looking up texture for %s (default: %s)\n", meshname, shadername);
934 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
935 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
937 memset(skin, 0, sizeof(*skin));
939 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
941 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
942 if (!strcmp(skinfileitem->name, meshname))
944 Image_StripImageExtension(skinfileitem->replacement, stripbuf, sizeof(stripbuf));
945 if(developer_extra.integer)
946 Con_DPrintf("--> got %s from skin file\n", stripbuf);
947 Mod_LoadTextureFromQ3Shader(loadmodel->mempool, loadmodel->name, skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS, MATERIALFLAG_WALL);
953 // don't render unmentioned meshes
954 Mod_LoadCustomMaterial(loadmodel->mempool, skin, meshname, SUPERCONTENTS_SOLID, MATERIALFLAG_WALL, R_SkinFrame_LoadMissing());
955 if(developer_extra.integer)
956 Con_DPrintf("--> skipping\n");
957 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
963 if(developer_extra.integer)
964 Con_DPrintf("--> using default\n");
965 Image_StripImageExtension(shadername, stripbuf, sizeof(stripbuf));
966 Mod_LoadTextureFromQ3Shader(loadmodel->mempool, loadmodel->name, skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS, MATERIALFLAG_WALL);
970 #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);
971 #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);
972 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
974 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
975 float scales, scalet, interval;
979 stvert_t *pinstverts;
980 dtriangle_t *pintriangles;
981 daliasskintype_t *pinskintype;
982 daliasskingroup_t *pinskingroup;
983 daliasskininterval_t *pinskinintervals;
984 daliasframetype_t *pinframetype;
985 daliasgroup_t *pinframegroup;
986 unsigned char *datapointer, *startframes, *startskins;
987 char name[MAX_QPATH];
988 skinframe_t *tempskinframe;
989 animscene_t *tempskinscenes;
990 texture_t *tempaliasskins;
992 int *vertonseam, *vertremap;
993 skinfile_t *skinfiles;
995 datapointer = (unsigned char *)buffer;
996 pinmodel = (mdl_t *)datapointer;
997 datapointer += sizeof(mdl_t);
999 version = LittleLong (pinmodel->version);
1000 if (version != ALIAS_VERSION)
1001 Host_Error ("%s has wrong version number (%i should be %i)",
1002 loadmodel->name, version, ALIAS_VERSION);
1004 loadmodel->modeldatatypestring = "MDL";
1006 loadmodel->type = mod_alias;
1007 loadmodel->DrawSky = NULL;
1008 loadmodel->DrawAddWaterPlanes = NULL;
1009 loadmodel->Draw = R_Q1BSP_Draw;
1010 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1011 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1012 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1013 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1014 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1015 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1016 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1017 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1018 // FIXME add TraceBrush!
1019 loadmodel->PointSuperContents = NULL;
1020 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1022 loadmodel->num_surfaces = 1;
1023 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1024 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
1025 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1026 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1027 loadmodel->sortedmodelsurfaces[0] = 0;
1029 loadmodel->numskins = LittleLong(pinmodel->numskins);
1030 BOUNDI(loadmodel->numskins,0,65536);
1031 skinwidth = LittleLong (pinmodel->skinwidth);
1032 BOUNDI(skinwidth,0,65536);
1033 skinheight = LittleLong (pinmodel->skinheight);
1034 BOUNDI(skinheight,0,65536);
1035 numverts = LittleLong(pinmodel->numverts);
1036 BOUNDI(numverts,0,65536);
1037 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
1038 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
1039 loadmodel->numframes = LittleLong(pinmodel->numframes);
1040 BOUNDI(loadmodel->numframes,0,65536);
1041 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
1042 BOUNDI((int)loadmodel->synctype,0,2);
1043 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1044 i = LittleLong (pinmodel->flags);
1045 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1047 for (i = 0;i < 3;i++)
1049 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
1050 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
1053 startskins = datapointer;
1055 for (i = 0;i < loadmodel->numskins;i++)
1057 pinskintype = (daliasskintype_t *)datapointer;
1058 datapointer += sizeof(daliasskintype_t);
1059 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
1063 pinskingroup = (daliasskingroup_t *)datapointer;
1064 datapointer += sizeof(daliasskingroup_t);
1065 groupskins = LittleLong(pinskingroup->numskins);
1066 datapointer += sizeof(daliasskininterval_t) * groupskins;
1069 for (j = 0;j < groupskins;j++)
1071 datapointer += skinwidth * skinheight;
1076 pinstverts = (stvert_t *)datapointer;
1077 datapointer += sizeof(stvert_t) * numverts;
1079 pintriangles = (dtriangle_t *)datapointer;
1080 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
1082 startframes = datapointer;
1083 loadmodel->surfmesh.num_morphframes = 0;
1084 for (i = 0;i < loadmodel->numframes;i++)
1086 pinframetype = (daliasframetype_t *)datapointer;
1087 datapointer += sizeof(daliasframetype_t);
1088 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
1092 pinframegroup = (daliasgroup_t *)datapointer;
1093 datapointer += sizeof(daliasgroup_t);
1094 groupframes = LittleLong(pinframegroup->numframes);
1095 datapointer += sizeof(daliasinterval_t) * groupframes;
1098 for (j = 0;j < groupframes;j++)
1100 datapointer += sizeof(daliasframe_t);
1101 datapointer += sizeof(trivertx_t) * numverts;
1102 loadmodel->surfmesh.num_morphframes++;
1105 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1107 // store texture coordinates into temporary array, they will be stored
1108 // after usage is determined (triangle data)
1109 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
1110 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
1111 vertonseam = vertremap + numverts * 2;
1113 scales = 1.0 / skinwidth;
1114 scalet = 1.0 / skinheight;
1115 for (i = 0;i < numverts;i++)
1117 vertonseam[i] = LittleLong(pinstverts[i].onseam);
1118 vertst[i*2+0] = LittleLong(pinstverts[i].s) * scales;
1119 vertst[i*2+1] = LittleLong(pinstverts[i].t) * scalet;
1120 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
1121 vertst[(i+numverts)*2+1] = vertst[i*2+1];
1124 // load triangle data
1125 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1127 // read the triangle elements
1128 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1129 for (j = 0;j < 3;j++)
1130 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1131 // validate (note numverts is used because this is the original data)
1132 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_element3s, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1133 // now butcher the elements according to vertonseam and tri->facesfront
1134 // and then compact the vertex set to remove duplicates
1135 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1136 if (!LittleLong(pintriangles[i].facesfront)) // backface
1137 for (j = 0;j < 3;j++)
1138 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1139 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1141 // (this uses vertremap to count usage to save some memory)
1142 for (i = 0;i < numverts*2;i++)
1144 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1145 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1146 // build remapping table and compact array
1147 loadmodel->surfmesh.num_vertices = 0;
1148 for (i = 0;i < numverts*2;i++)
1152 vertremap[i] = loadmodel->surfmesh.num_vertices;
1153 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1154 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1155 loadmodel->surfmesh.num_vertices++;
1158 vertremap[i] = -1; // not used at all
1160 // remap the elements to the new vertex set
1161 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1162 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1163 // store the texture coordinates
1164 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1165 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1167 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1168 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1171 // generate ushort elements array if possible
1172 if (loadmodel->surfmesh.num_vertices <= 65536)
1173 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1174 if (loadmodel->surfmesh.data_element3s)
1175 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1176 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1179 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1180 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1181 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1182 loadmodel->surfmesh.isanimated = Mod_Alias_CalculateBoundingBox();
1183 Mod_Alias_MorphMesh_CompileFrames();
1186 Mem_Free(vertremap);
1189 skinfiles = Mod_LoadSkinFiles();
1192 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1193 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1194 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1195 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1196 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1197 Mod_FreeSkinFiles(skinfiles);
1198 for (i = 0;i < loadmodel->numskins;i++)
1200 loadmodel->skinscenes[i].firstframe = i;
1201 loadmodel->skinscenes[i].framecount = 1;
1202 loadmodel->skinscenes[i].loop = true;
1203 loadmodel->skinscenes[i].framerate = 10;
1208 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1209 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1210 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1211 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1213 datapointer = startskins;
1214 for (i = 0;i < loadmodel->numskins;i++)
1216 pinskintype = (daliasskintype_t *)datapointer;
1217 datapointer += sizeof(daliasskintype_t);
1219 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1226 pinskingroup = (daliasskingroup_t *)datapointer;
1227 datapointer += sizeof(daliasskingroup_t);
1229 groupskins = LittleLong (pinskingroup->numskins);
1231 pinskinintervals = (daliasskininterval_t *)datapointer;
1232 datapointer += sizeof(daliasskininterval_t) * groupskins;
1234 interval = LittleFloat(pinskinintervals[0].interval);
1235 if (interval < 0.01f)
1237 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1242 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1243 loadmodel->skinscenes[i].firstframe = totalskins;
1244 loadmodel->skinscenes[i].framecount = groupskins;
1245 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1246 loadmodel->skinscenes[i].loop = true;
1248 for (j = 0;j < groupskins;j++)
1251 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1253 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1254 if (!Mod_LoadTextureFromQ3Shader(loadmodel->mempool, loadmodel->name, loadmodel->data_textures + totalskins * loadmodel->num_surfaces, name, false, false, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS, MATERIALFLAG_WALL))
1255 Mod_LoadCustomMaterial(loadmodel->mempool, loadmodel->data_textures + totalskins * loadmodel->num_surfaces, name, SUPERCONTENTS_SOLID, MATERIALFLAG_WALL, R_SkinFrame_LoadInternalQuake(name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP, true, r_fullbrights.integer, (unsigned char *)datapointer, skinwidth, skinheight));
1256 datapointer += skinwidth * skinheight;
1260 // check for skins that don't exist in the model, but do exist as external images
1261 // (this was added because yummyluv kept pestering me about support for it)
1262 // TODO: support shaders here?
1265 dpsnprintf(name, sizeof(name), "%s_%i", loadmodel->name, loadmodel->numskins);
1266 tempskinframe = R_SkinFrame_LoadExternal(name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS, false, false);
1269 // expand the arrays to make room
1270 tempskinscenes = loadmodel->skinscenes;
1271 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1272 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1273 Mem_Free(tempskinscenes);
1275 tempaliasskins = loadmodel->data_textures;
1276 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1277 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1278 Mem_Free(tempaliasskins);
1280 // store the info about the new skin
1281 Mod_LoadCustomMaterial(loadmodel->mempool, loadmodel->data_textures + totalskins * loadmodel->num_surfaces, name, SUPERCONTENTS_SOLID, MATERIALFLAG_WALL, tempskinframe);
1282 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1283 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1284 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1285 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1286 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1288 //increase skin counts
1289 loadmodel->num_textures++;
1290 loadmodel->numskins++;
1293 // fix up the pointers since they are pointing at the old textures array
1294 // FIXME: this is a hack!
1295 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1296 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1300 surface = loadmodel->data_surfaces;
1301 surface->texture = loadmodel->data_textures;
1302 surface->num_firsttriangle = 0;
1303 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1304 surface->num_firstvertex = 0;
1305 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1307 if(mod_alias_force_animated.string[0])
1308 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
1310 // Always make a BIH for the first frame, we can use it where possible.
1311 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1312 if (!loadmodel->surfmesh.isanimated)
1314 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1315 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1316 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1317 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1318 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1321 // because shaders can do somewhat unexpected things, check for unusual features now
1322 for (i = 0;i < loadmodel->num_textures;i++)
1324 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
1325 mod->DrawSky = R_Q1BSP_DrawSky;
1326 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
1327 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
1331 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1333 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1334 float iskinwidth, iskinheight;
1335 unsigned char *data;
1336 msurface_t *surface;
1338 unsigned char *base, *datapointer;
1339 md2frame_t *pinframe;
1341 md2triangle_t *intri;
1342 unsigned short *inst;
1343 struct md2verthash_s
1345 struct md2verthash_s *next;
1349 *hash, **md2verthash, *md2verthashdata;
1350 skinfile_t *skinfiles;
1352 pinmodel = (md2_t *)buffer;
1353 base = (unsigned char *)buffer;
1355 version = LittleLong (pinmodel->version);
1356 if (version != MD2ALIAS_VERSION)
1357 Host_Error ("%s has wrong version number (%i should be %i)",
1358 loadmodel->name, version, MD2ALIAS_VERSION);
1360 loadmodel->modeldatatypestring = "MD2";
1362 loadmodel->type = mod_alias;
1363 loadmodel->DrawSky = NULL;
1364 loadmodel->DrawAddWaterPlanes = NULL;
1365 loadmodel->Draw = R_Q1BSP_Draw;
1366 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1367 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1368 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1369 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1370 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1371 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1372 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1373 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1374 loadmodel->PointSuperContents = NULL;
1375 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1377 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1378 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1379 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1380 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1381 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1382 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1383 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1384 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1386 end = LittleLong(pinmodel->ofs_end);
1387 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1388 Host_Error ("%s is not a valid model", loadmodel->name);
1389 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1390 Host_Error ("%s is not a valid model", loadmodel->name);
1391 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1392 Host_Error ("%s is not a valid model", loadmodel->name);
1393 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1394 Host_Error ("%s is not a valid model", loadmodel->name);
1395 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1396 Host_Error ("%s is not a valid model", loadmodel->name);
1398 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1399 numxyz = LittleLong(pinmodel->num_xyz);
1400 numst = LittleLong(pinmodel->num_st);
1401 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1402 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1403 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1404 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1405 skinwidth = LittleLong(pinmodel->skinwidth);
1406 skinheight = LittleLong(pinmodel->skinheight);
1407 iskinwidth = 1.0f / skinwidth;
1408 iskinheight = 1.0f / skinheight;
1410 loadmodel->num_surfaces = 1;
1411 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1412 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]));
1413 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1414 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1415 loadmodel->sortedmodelsurfaces[0] = 0;
1416 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1417 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1418 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1420 loadmodel->synctype = ST_RAND;
1423 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1424 skinfiles = Mod_LoadSkinFiles();
1427 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1428 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1429 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1430 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1431 Mod_FreeSkinFiles(skinfiles);
1433 else if (loadmodel->numskins)
1435 // skins found (most likely not a player model)
1436 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1437 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1438 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1439 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1440 Mod_LoadTextureFromQ3Shader(loadmodel->mempool, loadmodel->name, loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS, MATERIALFLAG_WALL);
1444 // no skins (most likely a player model)
1445 loadmodel->numskins = 1;
1446 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1447 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1448 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1449 Mod_LoadCustomMaterial(loadmodel->mempool, loadmodel->data_textures, loadmodel->name, SUPERCONTENTS_SOLID, MATERIALFLAG_WALL, R_SkinFrame_LoadMissing());
1452 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1453 for (i = 0;i < loadmodel->numskins;i++)
1455 loadmodel->skinscenes[i].firstframe = i;
1456 loadmodel->skinscenes[i].framecount = 1;
1457 loadmodel->skinscenes[i].loop = true;
1458 loadmodel->skinscenes[i].framerate = 10;
1461 // load the triangles and stvert data
1462 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1463 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1464 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1465 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1466 // swap the triangle list
1467 loadmodel->surfmesh.num_vertices = 0;
1468 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1470 for (j = 0;j < 3;j++)
1472 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1473 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1476 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1481 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1484 hashindex = (xyz * 256 + st) & 65535;
1485 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1486 if (hash->xyz == xyz && hash->st == st)
1490 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1493 hash->next = md2verthash[hashindex];
1494 md2verthash[hashindex] = hash;
1496 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1500 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1501 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));
1502 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1503 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1504 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1507 hash = md2verthashdata + i;
1508 vertremap[i] = hash->xyz;
1509 sts = LittleShort(inst[hash->st*2+0]);
1510 stt = LittleShort(inst[hash->st*2+1]);
1511 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1513 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1517 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1518 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1521 Mem_Free(md2verthash);
1522 Mem_Free(md2verthashdata);
1524 // generate ushort elements array if possible
1525 if (loadmodel->surfmesh.num_vertices <= 65536)
1526 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1527 if (loadmodel->surfmesh.data_element3s)
1528 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1529 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1532 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1533 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1538 pinframe = (md2frame_t *)datapointer;
1539 datapointer += sizeof(md2frame_t);
1540 // store the frame scale/translate into the appropriate array
1541 for (j = 0;j < 3;j++)
1543 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1544 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1546 // convert the vertices
1547 v = (trivertx_t *)datapointer;
1548 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1549 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1550 out[k] = v[vertremap[k]];
1551 datapointer += numxyz * sizeof(trivertx_t);
1553 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1554 loadmodel->animscenes[i].firstframe = i;
1555 loadmodel->animscenes[i].framecount = 1;
1556 loadmodel->animscenes[i].framerate = 10;
1557 loadmodel->animscenes[i].loop = true;
1560 Mem_Free(vertremap);
1562 loadmodel->surfmesh.isanimated = Mod_Alias_CalculateBoundingBox();
1563 Mod_Alias_MorphMesh_CompileFrames();
1564 if(mod_alias_force_animated.string[0])
1565 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
1567 surface = loadmodel->data_surfaces;
1568 surface->texture = loadmodel->data_textures;
1569 surface->num_firsttriangle = 0;
1570 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1571 surface->num_firstvertex = 0;
1572 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1574 // Always make a BIH for the first frame, we can use it where possible.
1575 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1576 if (!loadmodel->surfmesh.isanimated)
1578 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1579 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1580 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1581 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1582 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1585 // because shaders can do somewhat unexpected things, check for unusual features now
1586 for (i = 0;i < loadmodel->num_textures;i++)
1588 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
1589 mod->DrawSky = R_Q1BSP_DrawSky;
1590 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
1591 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
1595 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1597 int i, j, k, version, meshvertices, meshtriangles;
1598 unsigned char *data;
1599 msurface_t *surface;
1600 md3modelheader_t *pinmodel;
1601 md3frameinfo_t *pinframe;
1604 skinfile_t *skinfiles;
1606 pinmodel = (md3modelheader_t *)buffer;
1608 if (memcmp(pinmodel->identifier, "IDP3", 4))
1609 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1610 version = LittleLong (pinmodel->version);
1611 if (version != MD3VERSION)
1612 Host_Error ("%s has wrong version number (%i should be %i)",
1613 loadmodel->name, version, MD3VERSION);
1615 skinfiles = Mod_LoadSkinFiles();
1616 if (loadmodel->numskins < 1)
1617 loadmodel->numskins = 1;
1619 loadmodel->modeldatatypestring = "MD3";
1621 loadmodel->type = mod_alias;
1622 loadmodel->DrawSky = NULL;
1623 loadmodel->DrawAddWaterPlanes = NULL;
1624 loadmodel->Draw = R_Q1BSP_Draw;
1625 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1626 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1627 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1628 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1629 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1630 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1631 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1632 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1633 loadmodel->PointSuperContents = NULL;
1634 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1635 loadmodel->synctype = ST_RAND;
1636 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1637 i = LittleLong (pinmodel->flags);
1638 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1640 // set up some global info about the model
1641 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1642 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1644 // make skinscenes for the skins (no groups)
1645 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1646 for (i = 0;i < loadmodel->numskins;i++)
1648 loadmodel->skinscenes[i].firstframe = i;
1649 loadmodel->skinscenes[i].framecount = 1;
1650 loadmodel->skinscenes[i].loop = true;
1651 loadmodel->skinscenes[i].framerate = 10;
1655 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1656 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1658 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1659 loadmodel->animscenes[i].firstframe = i;
1660 loadmodel->animscenes[i].framecount = 1;
1661 loadmodel->animscenes[i].framerate = 10;
1662 loadmodel->animscenes[i].loop = true;
1666 loadmodel->num_tagframes = loadmodel->numframes;
1667 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1668 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1669 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1671 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1672 for (j = 0;j < 9;j++)
1673 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1674 for (j = 0;j < 3;j++)
1675 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1676 //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);
1682 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)))
1684 if (memcmp(pinmesh->identifier, "IDP3", 4))
1685 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1686 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1687 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1688 meshvertices += LittleLong(pinmesh->num_vertices);
1689 meshtriangles += LittleLong(pinmesh->num_triangles);
1692 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1693 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1694 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1695 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) + meshvertices * sizeof(float[2]) + meshvertices * loadmodel->numframes * sizeof(md3vertex_t));
1696 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1697 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1698 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1699 loadmodel->surfmesh.num_vertices = meshvertices;
1700 loadmodel->surfmesh.num_triangles = meshtriangles;
1701 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1702 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1703 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1704 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1705 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1706 if (meshvertices <= 65536)
1708 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1713 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)))
1715 if (memcmp(pinmesh->identifier, "IDP3", 4))
1716 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1717 loadmodel->sortedmodelsurfaces[i] = i;
1718 surface = loadmodel->data_surfaces + i;
1719 surface->texture = loadmodel->data_textures + i;
1720 surface->num_firsttriangle = meshtriangles;
1721 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1722 surface->num_firstvertex = meshvertices;
1723 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1724 meshvertices += surface->num_vertices;
1725 meshtriangles += surface->num_triangles;
1727 for (j = 0;j < surface->num_triangles * 3;j++)
1728 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1729 for (j = 0;j < surface->num_vertices;j++)
1731 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1732 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1734 for (j = 0;j < loadmodel->numframes;j++)
1736 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1737 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1738 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1740 out->origin[0] = LittleShort(in->origin[0]);
1741 out->origin[1] = LittleShort(in->origin[1]);
1742 out->origin[2] = LittleShort(in->origin[2]);
1743 out->pitch = in->pitch;
1748 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1750 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, loadmodel->surfmesh.data_element3s + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1752 if (loadmodel->surfmesh.data_element3s)
1753 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1754 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1755 Mod_Alias_MorphMesh_CompileFrames();
1756 loadmodel->surfmesh.isanimated = Mod_Alias_CalculateBoundingBox();
1757 Mod_FreeSkinFiles(skinfiles);
1758 Mod_MakeSortedSurfaces(loadmodel);
1759 if(mod_alias_force_animated.string[0])
1760 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
1762 // Always make a BIH for the first frame, we can use it where possible.
1763 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1764 if (!loadmodel->surfmesh.isanimated)
1766 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1767 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1768 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1769 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1770 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1773 // because shaders can do somewhat unexpected things, check for unusual features now
1774 for (i = 0;i < loadmodel->num_textures;i++)
1776 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
1777 mod->DrawSky = R_Q1BSP_DrawSky;
1778 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
1779 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
1783 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1785 zymtype1header_t *pinmodel, *pheader;
1786 unsigned char *pbase;
1787 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1788 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose, f, biggestorigin, tempvec[3], modelscale;
1789 zymvertex_t *verts, *vertdata;
1793 skinfile_t *skinfiles;
1794 unsigned char *data;
1795 msurface_t *surface;
1797 pinmodel = (zymtype1header_t *)buffer;
1798 pbase = (unsigned char *)buffer;
1799 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1800 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1801 if (BigLong(pinmodel->type) != 1)
1802 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1804 loadmodel->modeldatatypestring = "ZYM";
1806 loadmodel->type = mod_alias;
1807 loadmodel->synctype = ST_RAND;
1811 pheader->type = BigLong(pinmodel->type);
1812 pheader->filesize = BigLong(pinmodel->filesize);
1813 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1814 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1815 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1816 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1817 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1818 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1819 pheader->radius = BigFloat(pinmodel->radius);
1820 pheader->numverts = BigLong(pinmodel->numverts);
1821 pheader->numtris = BigLong(pinmodel->numtris);
1822 pheader->numshaders = BigLong(pinmodel->numshaders);
1823 pheader->numbones = BigLong(pinmodel->numbones);
1824 pheader->numscenes = BigLong(pinmodel->numscenes);
1825 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1826 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1827 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1828 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1829 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1830 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1831 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1832 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1833 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1834 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1835 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1836 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1837 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1838 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1839 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1840 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1841 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1842 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1844 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1846 Con_Printf("%s has no geometry\n", loadmodel->name);
1849 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1851 Con_Printf("%s has no animations\n", loadmodel->name);
1855 loadmodel->DrawSky = NULL;
1856 loadmodel->DrawAddWaterPlanes = NULL;
1857 loadmodel->Draw = R_Q1BSP_Draw;
1858 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1859 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1860 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1861 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1862 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1863 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1864 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1865 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1866 loadmodel->PointSuperContents = NULL;
1867 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1869 loadmodel->numframes = pheader->numscenes;
1870 loadmodel->num_surfaces = pheader->numshaders;
1872 skinfiles = Mod_LoadSkinFiles();
1873 if (loadmodel->numskins < 1)
1874 loadmodel->numskins = 1;
1876 // make skinscenes for the skins (no groups)
1877 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1878 for (i = 0;i < loadmodel->numskins;i++)
1880 loadmodel->skinscenes[i].firstframe = i;
1881 loadmodel->skinscenes[i].framecount = 1;
1882 loadmodel->skinscenes[i].loop = true;
1883 loadmodel->skinscenes[i].framerate = 10;
1887 // LordHavoc: actually we blow this away later with Mod_Alias_CalculateBoundingBox()
1888 modelradius = pheader->radius;
1889 for (i = 0;i < 3;i++)
1891 loadmodel->normalmins[i] = pheader->mins[i];
1892 loadmodel->normalmaxs[i] = pheader->maxs[i];
1893 loadmodel->rotatedmins[i] = -modelradius;
1894 loadmodel->rotatedmaxs[i] = modelradius;
1896 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1897 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1898 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1899 if (loadmodel->yawmaxs[0] > modelradius)
1900 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1901 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1902 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1903 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1904 loadmodel->radius = modelradius;
1905 loadmodel->radius2 = modelradius * modelradius;
1907 // go through the lumps, swapping things
1909 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1910 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1911 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1912 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1913 for (i = 0;i < pheader->numscenes;i++)
1915 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1916 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1917 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1918 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1919 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1920 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1921 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1922 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1923 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1924 if (loadmodel->animscenes[i].framerate < 0)
1925 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1929 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1930 loadmodel->num_bones = pheader->numbones;
1931 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1932 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1933 for (i = 0;i < pheader->numbones;i++)
1935 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1936 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1937 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1938 if (loadmodel->data_bones[i].parent >= i)
1939 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1942 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1943 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1944 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1945 for (i = 0;i < pheader->numverts;i++)
1947 vertbonecounts[i] = BigLong(bonecount[i]);
1948 if (vertbonecounts[i] != 1)
1949 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1952 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1954 meshvertices = pheader->numverts;
1955 meshtriangles = pheader->numtris;
1957 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1958 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1959 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1960 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) + meshvertices * (sizeof(float[14]) + sizeof(unsigned short) + sizeof(unsigned char[2][4])) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]) + loadmodel->num_bones * sizeof(float[12]));
1961 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1962 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1963 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1964 loadmodel->surfmesh.num_vertices = meshvertices;
1965 loadmodel->surfmesh.num_triangles = meshtriangles;
1966 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1967 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1968 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1969 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1970 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1971 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1972 loadmodel->surfmesh.data_skeletalindex4ub = (unsigned char *)data;data += meshvertices * sizeof(unsigned char[4]);
1973 loadmodel->surfmesh.data_skeletalweight4ub = (unsigned char *)data;data += meshvertices * sizeof(unsigned char[4]);
1974 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1975 loadmodel->surfmesh.num_blends = 0;
1976 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
1977 if (loadmodel->surfmesh.num_vertices <= 65536)
1979 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1981 loadmodel->data_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
1982 loadmodel->surfmesh.data_blendweights = NULL;
1984 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1985 poses = (float *) (pheader->lump_poses.start + pbase);
1986 // figure out scale of model from root bone, for compatibility with old zmodel versions
1987 tempvec[0] = BigFloat(poses[0]);
1988 tempvec[1] = BigFloat(poses[1]);
1989 tempvec[2] = BigFloat(poses[2]);
1990 modelscale = VectorLength(tempvec);
1992 for (i = 0;i < loadmodel->num_bones * numposes * 12;i++)
1994 f = fabs(BigFloat(poses[i]));
1995 biggestorigin = max(biggestorigin, f);
1997 loadmodel->num_posescale = biggestorigin / 32767.0f;
1998 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
1999 for (i = 0;i < numposes;i++)
2001 const float *frameposes = (float *) (pheader->lump_poses.start + pbase) + 12*i*loadmodel->num_bones;
2002 for (j = 0;j < loadmodel->num_bones;j++)
2005 matrix4x4_t posematrix;
2006 for (k = 0;k < 12;k++)
2007 pose[k] = BigFloat(frameposes[j*12+k]);
2008 //if (j < loadmodel->num_bones)
2009 // 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));
2010 // scale child bones to match the root scale
2011 if (loadmodel->data_bones[j].parent >= 0)
2013 pose[3] *= modelscale;
2014 pose[7] *= modelscale;
2015 pose[11] *= modelscale;
2017 // normalize rotation matrix
2018 VectorNormalize(pose + 0);
2019 VectorNormalize(pose + 4);
2020 VectorNormalize(pose + 8);
2021 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2022 Matrix4x4_ToBonePose7s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses7s + 7*(i*loadmodel->num_bones+j));
2026 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
2027 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
2028 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
2029 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2030 // (converting from weight-blending skeletal animation to
2031 // deformation-based skeletal animation)
2032 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2033 for (i = 0;i < loadmodel->num_bones;i++)
2036 for (k = 0;k < 12;k++)
2037 m[k] = BigFloat(poses[i*12+k]);
2038 if (loadmodel->data_bones[i].parent >= 0)
2039 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2041 for (k = 0;k < 12;k++)
2042 bonepose[12*i+k] = m[k];
2044 for (j = 0;j < pheader->numverts;j++)
2046 // this format really should have had a per vertexweight weight value...
2047 // but since it does not, the weighting is completely ignored and
2048 // only one weight is allowed per vertex
2049 int boneindex = BigLong(vertdata[j].bonenum);
2050 const float *m = bonepose + 12 * boneindex;
2051 float relativeorigin[3];
2052 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
2053 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
2054 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
2055 // transform the vertex bone weight into the base mesh
2056 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
2057 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
2058 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
2059 // store the weight as the primary weight on this vertex
2060 loadmodel->surfmesh.blends[j] = boneindex;
2061 loadmodel->surfmesh.data_skeletalindex4ub[j*4 ] = boneindex;
2062 loadmodel->surfmesh.data_skeletalindex4ub[j*4+1] = 0;
2063 loadmodel->surfmesh.data_skeletalindex4ub[j*4+2] = 0;
2064 loadmodel->surfmesh.data_skeletalindex4ub[j*4+3] = 0;
2065 loadmodel->surfmesh.data_skeletalweight4ub[j*4 ] = 255;
2066 loadmodel->surfmesh.data_skeletalweight4ub[j*4+1] = 0;
2067 loadmodel->surfmesh.data_skeletalweight4ub[j*4+2] = 0;
2068 loadmodel->surfmesh.data_skeletalweight4ub[j*4+3] = 0;
2071 // normals and tangents are calculated after elements are loaded
2073 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
2074 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
2075 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
2076 for (i = 0;i < pheader->numverts;i++)
2078 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
2079 // flip T coordinate for OpenGL
2080 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
2083 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
2084 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
2085 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
2087 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
2088 //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)
2089 // byteswap, validate, and swap winding order of tris
2090 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
2091 if (pheader->lump_render.length != count)
2092 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
2093 renderlist = (int *) (pheader->lump_render.start + pbase);
2094 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
2096 for (i = 0;i < loadmodel->num_surfaces;i++)
2098 int firstvertex, lastvertex;
2099 if (renderlist >= renderlistend)
2100 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2101 count = BigLong(*renderlist);renderlist++;
2102 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
2103 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2105 loadmodel->sortedmodelsurfaces[i] = i;
2106 surface = loadmodel->data_surfaces + i;
2107 surface->texture = loadmodel->data_textures + i;
2108 surface->num_firsttriangle = meshtriangles;
2109 surface->num_triangles = count;
2110 meshtriangles += surface->num_triangles;
2112 // load the elements
2113 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2114 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
2116 outelements[j*3+2] = BigLong(renderlist[0]);
2117 outelements[j*3+1] = BigLong(renderlist[1]);
2118 outelements[j*3+0] = BigLong(renderlist[2]);
2120 // validate the elements and find the used vertex range
2121 firstvertex = meshvertices;
2123 for (j = 0;j < surface->num_triangles * 3;j++)
2125 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
2126 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
2127 firstvertex = min(firstvertex, outelements[j]);
2128 lastvertex = max(lastvertex, outelements[j]);
2130 surface->num_firstvertex = firstvertex;
2131 surface->num_vertices = lastvertex + 1 - firstvertex;
2133 // since zym models do not have named sections, reuse their shader
2134 // name as the section name
2135 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
2136 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
2138 Mod_FreeSkinFiles(skinfiles);
2139 Mem_Free(vertbonecounts);
2141 Mod_MakeSortedSurfaces(loadmodel);
2143 // compute all the mesh information that was not loaded from the file
2144 if (loadmodel->surfmesh.data_element3s)
2145 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2146 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2147 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_element3s, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2148 Mod_BuildBaseBonePoses();
2149 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, r_smoothnormals_areaweighting.integer != 0);
2150 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);
2151 loadmodel->surfmesh.isanimated = Mod_Alias_CalculateBoundingBox();
2152 if(mod_alias_force_animated.string[0])
2153 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
2155 // Always make a BIH for the first frame, we can use it where possible.
2156 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2157 if (!loadmodel->surfmesh.isanimated)
2159 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2160 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2161 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2162 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2163 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2166 // because shaders can do somewhat unexpected things, check for unusual features now
2167 for (i = 0;i < loadmodel->num_textures;i++)
2169 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
2170 mod->DrawSky = R_Q1BSP_DrawSky;
2171 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
2172 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
2176 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2178 dpmheader_t *pheader;
2182 unsigned char *pbase;
2183 int i, j, k, meshvertices, meshtriangles;
2184 skinfile_t *skinfiles;
2185 unsigned char *data;
2187 float biggestorigin, tempvec[3], modelscale;
2191 pheader = (dpmheader_t *)buffer;
2192 pbase = (unsigned char *)buffer;
2193 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2194 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2195 if (BigLong(pheader->type) != 2)
2196 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2198 loadmodel->modeldatatypestring = "DPM";
2200 loadmodel->type = mod_alias;
2201 loadmodel->synctype = ST_RAND;
2204 pheader->type = BigLong(pheader->type);
2205 pheader->filesize = BigLong(pheader->filesize);
2206 pheader->mins[0] = BigFloat(pheader->mins[0]);
2207 pheader->mins[1] = BigFloat(pheader->mins[1]);
2208 pheader->mins[2] = BigFloat(pheader->mins[2]);
2209 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2210 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2211 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2212 pheader->yawradius = BigFloat(pheader->yawradius);
2213 pheader->allradius = BigFloat(pheader->allradius);
2214 pheader->num_bones = BigLong(pheader->num_bones);
2215 pheader->num_meshs = BigLong(pheader->num_meshs);
2216 pheader->num_frames = BigLong(pheader->num_frames);
2217 pheader->ofs_bones = BigLong(pheader->ofs_bones);
2218 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2219 pheader->ofs_frames = BigLong(pheader->ofs_frames);
2221 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2223 Con_Printf("%s has no geometry\n", loadmodel->name);
2226 if (pheader->num_frames < 1)
2228 Con_Printf("%s has no frames\n", loadmodel->name);
2232 loadmodel->DrawSky = NULL;
2233 loadmodel->DrawAddWaterPlanes = NULL;
2234 loadmodel->Draw = R_Q1BSP_Draw;
2235 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2236 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2237 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2238 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2239 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2240 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2241 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2242 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2243 loadmodel->PointSuperContents = NULL;
2244 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2247 // LordHavoc: actually we blow this away later with Mod_Alias_CalculateBoundingBox()
2248 for (i = 0;i < 3;i++)
2250 loadmodel->normalmins[i] = pheader->mins[i];
2251 loadmodel->normalmaxs[i] = pheader->maxs[i];
2252 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2253 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2254 loadmodel->rotatedmins[i] = -pheader->allradius;
2255 loadmodel->rotatedmaxs[i] = pheader->allradius;
2257 loadmodel->radius = pheader->allradius;
2258 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2260 // load external .skin files if present
2261 skinfiles = Mod_LoadSkinFiles();
2262 if (loadmodel->numskins < 1)
2263 loadmodel->numskins = 1;
2268 // gather combined statistics from the meshes
2269 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2270 for (i = 0;i < (int)pheader->num_meshs;i++)
2272 int numverts = BigLong(dpmmesh->num_verts);
2273 meshvertices += numverts;
2274 meshtriangles += BigLong(dpmmesh->num_tris);
2278 loadmodel->numframes = pheader->num_frames;
2279 loadmodel->num_bones = pheader->num_bones;
2280 loadmodel->num_poses = loadmodel->numframes;
2281 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2282 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2283 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2284 // do most allocations as one merged chunk
2285 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) + meshvertices * (sizeof(float[14]) + sizeof(unsigned short) + sizeof(unsigned char[2][4])) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
2286 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2287 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2288 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2289 loadmodel->surfmesh.num_vertices = meshvertices;
2290 loadmodel->surfmesh.num_triangles = meshtriangles;
2291 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2292 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2293 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2294 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2295 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2296 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2297 loadmodel->surfmesh.data_skeletalindex4ub = (unsigned char *)data;data += meshvertices * sizeof(unsigned char[4]);
2298 loadmodel->surfmesh.data_skeletalweight4ub = (unsigned char *)data;data += meshvertices * sizeof(unsigned char[4]);
2299 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2300 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2301 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2302 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2303 loadmodel->surfmesh.num_blends = 0;
2304 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2305 if (meshvertices <= 65536)
2307 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2309 loadmodel->data_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
2310 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
2312 for (i = 0;i < loadmodel->numskins;i++)
2314 loadmodel->skinscenes[i].firstframe = i;
2315 loadmodel->skinscenes[i].framecount = 1;
2316 loadmodel->skinscenes[i].loop = true;
2317 loadmodel->skinscenes[i].framerate = 10;
2320 // load the bone info
2321 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2322 for (i = 0;i < loadmodel->num_bones;i++)
2324 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2325 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2326 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2327 if (loadmodel->data_bones[i].parent >= i)
2328 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2332 frames = (dpmframe_t *) (pbase + pheader->ofs_frames);
2333 // figure out scale of model from root bone, for compatibility with old dpmodel versions
2334 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2335 tempvec[0] = BigFloat(poses[0]);
2336 tempvec[1] = BigFloat(poses[1]);
2337 tempvec[2] = BigFloat(poses[2]);
2338 modelscale = VectorLength(tempvec);
2340 for (i = 0;i < loadmodel->numframes;i++)
2342 memcpy(loadmodel->animscenes[i].name, frames[i].name, sizeof(frames[i].name));
2343 loadmodel->animscenes[i].firstframe = i;
2344 loadmodel->animscenes[i].framecount = 1;
2345 loadmodel->animscenes[i].loop = true;
2346 loadmodel->animscenes[i].framerate = 10;
2347 // load the bone poses for this frame
2348 poses = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2349 for (j = 0;j < loadmodel->num_bones*12;j++)
2351 f = fabs(BigFloat(poses[j]));
2352 biggestorigin = max(biggestorigin, f);
2354 // stuff not processed here: mins, maxs, yawradius, allradius
2356 loadmodel->num_posescale = biggestorigin / 32767.0f;
2357 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2358 for (i = 0;i < loadmodel->numframes;i++)
2360 const float *frameposes = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2361 for (j = 0;j < loadmodel->num_bones;j++)
2364 matrix4x4_t posematrix;
2365 for (k = 0;k < 12;k++)
2366 pose[k] = BigFloat(frameposes[j*12+k]);
2367 // scale child bones to match the root scale
2368 if (loadmodel->data_bones[j].parent >= 0)
2370 pose[3] *= modelscale;
2371 pose[7] *= modelscale;
2372 pose[11] *= modelscale;
2374 // normalize rotation matrix
2375 VectorNormalize(pose + 0);
2376 VectorNormalize(pose + 4);
2377 VectorNormalize(pose + 8);
2378 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2379 Matrix4x4_ToBonePose7s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses7s + 7*(i*loadmodel->num_bones+j));
2383 // load the meshes now
2384 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2387 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2388 // (converting from weight-blending skeletal animation to
2389 // deformation-based skeletal animation)
2390 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2391 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2392 for (i = 0;i < loadmodel->num_bones;i++)
2395 for (k = 0;k < 12;k++)
2396 m[k] = BigFloat(poses[i*12+k]);
2397 if (loadmodel->data_bones[i].parent >= 0)
2398 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2400 for (k = 0;k < 12;k++)
2401 bonepose[12*i+k] = m[k];
2403 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2405 const int *inelements;
2407 const float *intexcoord;
2408 msurface_t *surface;
2410 loadmodel->sortedmodelsurfaces[i] = i;
2411 surface = loadmodel->data_surfaces + i;
2412 surface->texture = loadmodel->data_textures + i;
2413 surface->num_firsttriangle = meshtriangles;
2414 surface->num_triangles = BigLong(dpmmesh->num_tris);
2415 surface->num_firstvertex = meshvertices;
2416 surface->num_vertices = BigLong(dpmmesh->num_verts);
2417 meshvertices += surface->num_vertices;
2418 meshtriangles += surface->num_triangles;
2420 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2421 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2422 for (j = 0;j < surface->num_triangles;j++)
2424 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2425 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2426 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2427 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2432 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2433 for (j = 0;j < surface->num_vertices*2;j++)
2434 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2436 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2437 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2439 int weightindex[4] = { 0, 0, 0, 0 };
2440 float weightinfluence[4] = { 0, 0, 0, 0 };
2442 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2443 data += sizeof(dpmvertex_t);
2444 for (k = 0;k < numweights;k++)
2446 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2447 int boneindex = BigLong(vert->bonenum);
2448 const float *m = bonepose + 12 * boneindex;
2449 float influence = BigFloat(vert->influence);
2450 float relativeorigin[3], relativenormal[3];
2451 relativeorigin[0] = BigFloat(vert->origin[0]);
2452 relativeorigin[1] = BigFloat(vert->origin[1]);
2453 relativeorigin[2] = BigFloat(vert->origin[2]);
2454 relativenormal[0] = BigFloat(vert->normal[0]);
2455 relativenormal[1] = BigFloat(vert->normal[1]);
2456 relativenormal[2] = BigFloat(vert->normal[2]);
2457 // blend the vertex bone weights into the base mesh
2458 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2459 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2460 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2461 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2462 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2463 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2466 // store the first (and often only) weight
2467 weightinfluence[0] = influence;
2468 weightindex[0] = boneindex;
2472 // sort the new weight into this vertex's weight table
2473 // (which only accepts up to 4 bones per vertex)
2474 for (l = 0;l < 4;l++)
2476 if (weightinfluence[l] < influence)
2478 // move weaker influence weights out of the way first
2480 for (l2 = 3;l2 > l;l2--)
2482 weightinfluence[l2] = weightinfluence[l2-1];
2483 weightindex[l2] = weightindex[l2-1];
2485 // store the new weight
2486 weightinfluence[l] = influence;
2487 weightindex[l] = boneindex;
2492 data += sizeof(dpmbonevert_t);
2494 loadmodel->surfmesh.blends[j] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
2495 loadmodel->surfmesh.data_skeletalindex4ub[j*4 ] = weightindex[0];
2496 loadmodel->surfmesh.data_skeletalindex4ub[j*4+1] = weightindex[1];
2497 loadmodel->surfmesh.data_skeletalindex4ub[j*4+2] = weightindex[2];
2498 loadmodel->surfmesh.data_skeletalindex4ub[j*4+3] = weightindex[3];
2499 loadmodel->surfmesh.data_skeletalweight4ub[j*4 ] = (unsigned char)(weightinfluence[0]*255.0f);
2500 loadmodel->surfmesh.data_skeletalweight4ub[j*4+1] = (unsigned char)(weightinfluence[1]*255.0f);
2501 loadmodel->surfmesh.data_skeletalweight4ub[j*4+2] = (unsigned char)(weightinfluence[2]*255.0f);
2502 loadmodel->surfmesh.data_skeletalweight4ub[j*4+3] = (unsigned char)(weightinfluence[3]*255.0f);
2505 // since dpm models do not have named sections, reuse their shader name as the section name
2506 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2508 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, loadmodel->surfmesh.data_element3s + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2510 if (loadmodel->surfmesh.num_blends < meshvertices)
2511 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2513 Mod_FreeSkinFiles(skinfiles);
2514 Mod_MakeSortedSurfaces(loadmodel);
2516 // compute all the mesh information that was not loaded from the file
2517 if (loadmodel->surfmesh.data_element3s)
2518 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2519 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2520 Mod_BuildBaseBonePoses();
2521 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);
2522 loadmodel->surfmesh.isanimated = Mod_Alias_CalculateBoundingBox();
2523 if(mod_alias_force_animated.string[0])
2524 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
2526 // Always make a BIH for the first frame, we can use it where possible.
2527 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2528 if (!loadmodel->surfmesh.isanimated)
2530 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2531 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2532 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2533 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2534 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2537 // because shaders can do somewhat unexpected things, check for unusual features now
2538 for (i = 0;i < loadmodel->num_textures;i++)
2540 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
2541 mod->DrawSky = R_Q1BSP_DrawSky;
2542 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
2543 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
2547 // no idea why PSK/PSA files contain weird quaternions but they do...
2548 #define PSKQUATNEGATIONS
2549 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2551 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2552 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2553 fs_offset_t filesize;
2558 pskboneinfo_t *bones;
2559 pskrawweights_t *rawweights;
2560 //pskboneinfo_t *animbones;
2561 pskaniminfo_t *anims;
2562 pskanimkeys_t *animkeys;
2563 void *animfilebuffer, *animbuffer, *animbufferend;
2564 unsigned char *data;
2566 skinfile_t *skinfiles;
2567 char animname[MAX_QPATH];
2569 float biggestorigin;
2571 pchunk = (pskchunk_t *)buffer;
2572 if (strcmp(pchunk->id, "ACTRHEAD"))
2573 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2575 loadmodel->modeldatatypestring = "PSK";
2577 loadmodel->type = mod_alias;
2578 loadmodel->DrawSky = NULL;
2579 loadmodel->DrawAddWaterPlanes = NULL;
2580 loadmodel->Draw = R_Q1BSP_Draw;
2581 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2582 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2583 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2584 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2585 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2586 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2587 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2588 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2589 loadmodel->PointSuperContents = NULL;
2590 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2591 loadmodel->synctype = ST_RAND;
2593 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2594 strlcat(animname, ".psa", sizeof(animname));
2595 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2596 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2598 animbufferend = animbuffer;
2617 while (buffer < bufferend)
2619 pchunk = (pskchunk_t *)buffer;
2620 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2621 version = LittleLong(pchunk->version);
2622 recordsize = LittleLong(pchunk->recordsize);
2623 numrecords = LittleLong(pchunk->numrecords);
2624 if (developer_extra.integer)
2625 Con_DPrintf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2626 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2627 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);
2628 if (!strcmp(pchunk->id, "ACTRHEAD"))
2632 else if (!strcmp(pchunk->id, "PNTS0000"))
2635 if (recordsize != sizeof(*p))
2636 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2637 // byteswap in place and keep the pointer
2638 numpnts = numrecords;
2639 pnts = (pskpnts_t *)buffer;
2640 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2642 p->origin[0] = LittleFloat(p->origin[0]);
2643 p->origin[1] = LittleFloat(p->origin[1]);
2644 p->origin[2] = LittleFloat(p->origin[2]);
2648 else if (!strcmp(pchunk->id, "VTXW0000"))
2651 if (recordsize != sizeof(*p))
2652 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2653 // byteswap in place and keep the pointer
2654 numvtxw = numrecords;
2655 vtxw = (pskvtxw_t *)buffer;
2656 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2658 p->pntsindex = LittleShort(p->pntsindex);
2659 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2660 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2661 if (p->pntsindex >= numpnts)
2663 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2669 else if (!strcmp(pchunk->id, "FACE0000"))
2672 if (recordsize != sizeof(*p))
2673 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2674 // byteswap in place and keep the pointer
2675 numfaces = numrecords;
2676 faces = (pskface_t *)buffer;
2677 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2679 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2680 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2681 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2682 p->group = LittleLong(p->group);
2683 if (p->vtxwindex[0] >= numvtxw)
2685 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2686 p->vtxwindex[0] = 0;
2688 if (p->vtxwindex[1] >= numvtxw)
2690 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2691 p->vtxwindex[1] = 0;
2693 if (p->vtxwindex[2] >= numvtxw)
2695 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2696 p->vtxwindex[2] = 0;
2701 else if (!strcmp(pchunk->id, "MATT0000"))
2704 if (recordsize != sizeof(*p))
2705 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2706 // byteswap in place and keep the pointer
2707 nummatts = numrecords;
2708 matts = (pskmatt_t *)buffer;
2709 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2715 else if (!strcmp(pchunk->id, "REFSKELT"))
2718 if (recordsize != sizeof(*p))
2719 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2720 // byteswap in place and keep the pointer
2721 numbones = numrecords;
2722 bones = (pskboneinfo_t *)buffer;
2723 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2725 p->numchildren = LittleLong(p->numchildren);
2726 p->parent = LittleLong(p->parent);
2727 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2728 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2729 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2730 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2731 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2732 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2733 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2734 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2735 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2736 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2737 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2738 #ifdef PSKQUATNEGATIONS
2741 p->basepose.quat[0] *= -1;
2742 p->basepose.quat[1] *= -1;
2743 p->basepose.quat[2] *= -1;
2747 p->basepose.quat[0] *= 1;
2748 p->basepose.quat[1] *= -1;
2749 p->basepose.quat[2] *= 1;
2752 if (p->parent < 0 || p->parent >= numbones)
2754 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2760 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2763 if (recordsize != sizeof(*p))
2764 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2765 // byteswap in place and keep the pointer
2766 numrawweights = numrecords;
2767 rawweights = (pskrawweights_t *)buffer;
2768 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2770 p->weight = LittleFloat(p->weight);
2771 p->pntsindex = LittleLong(p->pntsindex);
2772 p->boneindex = LittleLong(p->boneindex);
2773 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2775 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2778 if (p->boneindex < 0 || p->boneindex >= numbones)
2780 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2788 while (animbuffer < animbufferend)
2790 pchunk = (pskchunk_t *)animbuffer;
2791 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2792 version = LittleLong(pchunk->version);
2793 recordsize = LittleLong(pchunk->recordsize);
2794 numrecords = LittleLong(pchunk->numrecords);
2795 if (developer_extra.integer)
2796 Con_DPrintf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2797 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2798 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);
2799 if (!strcmp(pchunk->id, "ANIMHEAD"))
2803 else if (!strcmp(pchunk->id, "BONENAMES"))
2806 if (recordsize != sizeof(*p))
2807 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2808 // byteswap in place and keep the pointer
2809 numanimbones = numrecords;
2810 //animbones = (pskboneinfo_t *)animbuffer;
2811 // NOTE: supposedly psa does not need to match the psk model, the
2812 // bones missing from the psa would simply use their base
2813 // positions from the psk, but this is hard for me to implement
2814 // and people can easily make animations that match.
2815 if (numanimbones != numbones)
2816 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2817 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2819 p->numchildren = LittleLong(p->numchildren);
2820 p->parent = LittleLong(p->parent);
2821 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2822 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2823 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2824 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2825 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2826 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2827 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2828 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2829 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2830 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2831 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2832 #ifdef PSKQUATNEGATIONS
2835 p->basepose.quat[0] *= -1;
2836 p->basepose.quat[1] *= -1;
2837 p->basepose.quat[2] *= -1;
2841 p->basepose.quat[0] *= 1;
2842 p->basepose.quat[1] *= -1;
2843 p->basepose.quat[2] *= 1;
2846 if (p->parent < 0 || p->parent >= numanimbones)
2848 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2851 // check that bones are the same as in the base
2852 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2853 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2857 else if (!strcmp(pchunk->id, "ANIMINFO"))
2860 if (recordsize != sizeof(*p))
2861 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2862 // byteswap in place and keep the pointer
2863 numanims = numrecords;
2864 anims = (pskaniminfo_t *)animbuffer;
2865 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2867 p->numbones = LittleLong(p->numbones);
2868 p->playtime = LittleFloat(p->playtime);
2869 p->fps = LittleFloat(p->fps);
2870 p->firstframe = LittleLong(p->firstframe);
2871 p->numframes = LittleLong(p->numframes);
2872 if (p->numbones != numbones)
2873 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2877 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2880 if (recordsize != sizeof(*p))
2881 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2882 numanimkeys = numrecords;
2883 animkeys = (pskanimkeys_t *)animbuffer;
2884 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2886 p->origin[0] = LittleFloat(p->origin[0]);
2887 p->origin[1] = LittleFloat(p->origin[1]);
2888 p->origin[2] = LittleFloat(p->origin[2]);
2889 p->quat[0] = LittleFloat(p->quat[0]);
2890 p->quat[1] = LittleFloat(p->quat[1]);
2891 p->quat[2] = LittleFloat(p->quat[2]);
2892 p->quat[3] = LittleFloat(p->quat[3]);
2893 p->frametime = LittleFloat(p->frametime);
2894 #ifdef PSKQUATNEGATIONS
2895 if (index % numbones)
2910 // TODO: allocate bonepose stuff
2913 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2916 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights)
2917 Host_Error("%s: missing required chunks", loadmodel->name);
2921 loadmodel->numframes = 0;
2922 for (index = 0;index < numanims;index++)
2923 loadmodel->numframes += anims[index].numframes;
2924 if (numanimkeys != numbones * loadmodel->numframes)
2925 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2928 loadmodel->numframes = loadmodel->num_poses = 1;
2930 meshvertices = numvtxw;
2931 meshtriangles = numfaces;
2933 // load external .skin files if present
2934 skinfiles = Mod_LoadSkinFiles();
2935 if (loadmodel->numskins < 1)
2936 loadmodel->numskins = 1;
2937 loadmodel->num_bones = numbones;
2938 loadmodel->num_poses = loadmodel->numframes;
2939 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2940 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2941 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2942 loadmodel->surfmesh.num_vertices = meshvertices;
2943 loadmodel->surfmesh.num_triangles = meshtriangles;
2944 // do most allocations as one merged chunk
2945 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_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 char[4]) + loadmodel->surfmesh.num_vertices * sizeof(unsigned char[4]) + loadmodel->surfmesh.num_vertices * sizeof(unsigned short) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]) + 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);
2946 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2947 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2948 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2949 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2950 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2951 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2952 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2953 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2954 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2955 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2956 loadmodel->surfmesh.data_skeletalindex4ub = (unsigned char *)data;data += loadmodel->surfmesh.num_vertices * sizeof(unsigned char[4]);
2957 loadmodel->surfmesh.data_skeletalweight4ub = (unsigned char *)data;data += loadmodel->surfmesh.num_vertices * sizeof(unsigned char[4]);
2958 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2959 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2960 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2961 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2962 loadmodel->surfmesh.num_blends = 0;
2963 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2964 if (loadmodel->surfmesh.num_vertices <= 65536)
2966 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2968 loadmodel->data_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
2969 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(blendweights_t));
2971 for (i = 0;i < loadmodel->numskins;i++)
2973 loadmodel->skinscenes[i].firstframe = i;
2974 loadmodel->skinscenes[i].framecount = 1;
2975 loadmodel->skinscenes[i].loop = true;
2976 loadmodel->skinscenes[i].framerate = 10;
2980 for (index = 0, i = 0;index < nummatts;index++)
2982 // since psk models do not have named sections, reuse their shader name as the section name
2983 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2984 loadmodel->sortedmodelsurfaces[index] = index;
2985 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2986 loadmodel->data_surfaces[index].num_firstvertex = 0;
2987 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2990 // copy over the vertex locations and texcoords
2991 for (index = 0;index < numvtxw;index++)
2993 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2994 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2995 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2996 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2997 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
3000 // loading the faces is complicated because we need to sort them into surfaces by mattindex
3001 for (index = 0;index < numfaces;index++)
3002 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
3003 for (index = 0, i = 0;index < nummatts;index++)
3005 loadmodel->data_surfaces[index].num_firsttriangle = i;
3006 i += loadmodel->data_surfaces[index].num_triangles;
3007 loadmodel->data_surfaces[index].num_triangles = 0;
3009 for (index = 0;index < numfaces;index++)
3011 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
3012 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
3013 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
3014 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
3017 // copy over the bones
3018 for (index = 0;index < numbones;index++)
3020 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
3021 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
3022 if (loadmodel->data_bones[index].parent >= index)
3023 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
3026 // convert the basepose data
3027 if (loadmodel->num_bones)
3030 matrix4x4_t *basebonepose;
3031 float *outinvmatrix = loadmodel->data_baseboneposeinverse;
3032 matrix4x4_t bonematrix;
3033 matrix4x4_t tempbonematrix;
3034 basebonepose = (matrix4x4_t *)Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(matrix4x4_t));
3035 for (boneindex = 0;boneindex < loadmodel->num_bones;boneindex++)
3037 Matrix4x4_FromOriginQuat(&bonematrix, bones[boneindex].basepose.origin[0], bones[boneindex].basepose.origin[1], bones[boneindex].basepose.origin[2], bones[boneindex].basepose.quat[0], bones[boneindex].basepose.quat[1], bones[boneindex].basepose.quat[2], bones[boneindex].basepose.quat[3]);
3038 if (loadmodel->data_bones[boneindex].parent >= 0)
3040 tempbonematrix = bonematrix;
3041 Matrix4x4_Concat(&bonematrix, basebonepose + loadmodel->data_bones[boneindex].parent, &tempbonematrix);
3043 basebonepose[boneindex] = bonematrix;
3044 Matrix4x4_Invert_Simple(&tempbonematrix, basebonepose + boneindex);
3045 Matrix4x4_ToArray12FloatD3D(&tempbonematrix, outinvmatrix + 12*boneindex);
3047 Mem_Free(basebonepose);
3050 // sort the psk point weights into the vertex weight tables
3051 // (which only accept up to 4 bones per vertex)
3052 for (index = 0;index < numvtxw;index++)
3054 int weightindex[4] = { 0, 0, 0, 0 };
3055 float weightinfluence[4] = { 0, 0, 0, 0 };
3057 for (j = 0;j < numrawweights;j++)
3059 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
3061 int boneindex = rawweights[j].boneindex;
3062 float influence = rawweights[j].weight;
3063 for (l = 0;l < 4;l++)
3065 if (weightinfluence[l] < influence)
3067 // move lower influence weights out of the way first
3069 for (l2 = 3;l2 > l;l2--)
3071 weightinfluence[l2] = weightinfluence[l2-1];
3072 weightindex[l2] = weightindex[l2-1];
3074 // store the new weight
3075 weightinfluence[l] = influence;
3076 weightindex[l] = boneindex;
3082 loadmodel->surfmesh.blends[index] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
3083 loadmodel->surfmesh.data_skeletalindex4ub[index*4 ] = weightindex[0];
3084 loadmodel->surfmesh.data_skeletalindex4ub[index*4+1] = weightindex[1];
3085 loadmodel->surfmesh.data_skeletalindex4ub[index*4+2] = weightindex[2];
3086 loadmodel->surfmesh.data_skeletalindex4ub[index*4+3] = weightindex[3];
3087 loadmodel->surfmesh.data_skeletalweight4ub[index*4 ] = (unsigned char)(weightinfluence[0]*255.0f);
3088 loadmodel->surfmesh.data_skeletalweight4ub[index*4+1] = (unsigned char)(weightinfluence[1]*255.0f);
3089 loadmodel->surfmesh.data_skeletalweight4ub[index*4+2] = (unsigned char)(weightinfluence[2]*255.0f);
3090 loadmodel->surfmesh.data_skeletalweight4ub[index*4+3] = (unsigned char)(weightinfluence[3]*255.0f);
3092 if (loadmodel->surfmesh.num_blends < loadmodel->surfmesh.num_vertices)
3093 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
3095 // set up the animscenes based on the anims
3098 for (index = 0, i = 0;index < numanims;index++)
3100 for (j = 0;j < anims[index].numframes;j++, i++)
3102 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
3103 loadmodel->animscenes[i].firstframe = i;
3104 loadmodel->animscenes[i].framecount = 1;
3105 loadmodel->animscenes[i].loop = true;
3106 loadmodel->animscenes[i].framerate = anims[index].fps;
3109 // calculate the scaling value for bone origins so they can be compressed to short
3111 for (index = 0;index < numanimkeys;index++)
3113 pskanimkeys_t *k = animkeys + index;
3114 biggestorigin = max(biggestorigin, fabs(k->origin[0]));
3115 biggestorigin = max(biggestorigin, fabs(k->origin[1]));
3116 biggestorigin = max(biggestorigin, fabs(k->origin[2]));
3118 loadmodel->num_posescale = biggestorigin / 32767.0f;
3119 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3121 // load the poses from the animkeys
3122 for (index = 0;index < numanimkeys;index++)
3124 pskanimkeys_t *k = animkeys + index;
3126 Vector4Copy(k->quat, quat);
3128 Vector4Negate(quat, quat);
3129 Vector4Normalize2(quat, quat);
3130 // compress poses to the short[7] format for longterm storage
3131 loadmodel->data_poses7s[index*7+0] = k->origin[0] * loadmodel->num_poseinvscale;
3132 loadmodel->data_poses7s[index*7+1] = k->origin[1] * loadmodel->num_poseinvscale;
3133 loadmodel->data_poses7s[index*7+2] = k->origin[2] * loadmodel->num_poseinvscale;
3134 loadmodel->data_poses7s[index*7+3] = quat[0] * 32767.0f;
3135 loadmodel->data_poses7s[index*7+4] = quat[1] * 32767.0f;
3136 loadmodel->data_poses7s[index*7+5] = quat[2] * 32767.0f;
3137 loadmodel->data_poses7s[index*7+6] = quat[3] * 32767.0f;
3142 strlcpy(loadmodel->animscenes[0].name, "base", sizeof(loadmodel->animscenes[0].name));
3143 loadmodel->animscenes[0].firstframe = 0;
3144 loadmodel->animscenes[0].framecount = 1;
3145 loadmodel->animscenes[0].loop = true;
3146 loadmodel->animscenes[0].framerate = 10;
3148 // calculate the scaling value for bone origins so they can be compressed to short
3150 for (index = 0;index < numbones;index++)
3152 pskboneinfo_t *p = bones + index;
3153 biggestorigin = max(biggestorigin, fabs(p->basepose.origin[0]));
3154 biggestorigin = max(biggestorigin, fabs(p->basepose.origin[1]));
3155 biggestorigin = max(biggestorigin, fabs(p->basepose.origin[2]));
3157 loadmodel->num_posescale = biggestorigin / 32767.0f;
3158 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3160 // load the basepose as a frame
3161 for (index = 0;index < numbones;index++)
3163 pskboneinfo_t *p = bones + index;
3165 Vector4Copy(p->basepose.quat, quat);
3167 Vector4Negate(quat, quat);
3168 Vector4Normalize2(quat, quat);
3169 // compress poses to the short[7] format for longterm storage
3170 loadmodel->data_poses7s[index*7+0] = p->basepose.origin[0] * loadmodel->num_poseinvscale;
3171 loadmodel->data_poses7s[index*7+1] = p->basepose.origin[1] * loadmodel->num_poseinvscale;
3172 loadmodel->data_poses7s[index*7+2] = p->basepose.origin[2] * loadmodel->num_poseinvscale;
3173 loadmodel->data_poses7s[index*7+3] = quat[0] * 32767.0f;
3174 loadmodel->data_poses7s[index*7+4] = quat[1] * 32767.0f;
3175 loadmodel->data_poses7s[index*7+5] = quat[2] * 32767.0f;
3176 loadmodel->data_poses7s[index*7+6] = quat[3] * 32767.0f;
3180 Mod_FreeSkinFiles(skinfiles);
3182 Mem_Free(animfilebuffer);
3183 Mod_MakeSortedSurfaces(loadmodel);
3185 // compute all the mesh information that was not loaded from the file
3186 // TODO: honor smoothing groups somehow?
3187 if (loadmodel->surfmesh.data_element3s)
3188 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3189 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3190 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_element3s, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
3191 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, r_smoothnormals_areaweighting.integer != 0);
3192 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);
3193 loadmodel->surfmesh.isanimated = Mod_Alias_CalculateBoundingBox();
3194 if(mod_alias_force_animated.string[0])
3195 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
3197 // Always make a BIH for the first frame, we can use it where possible.
3198 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3199 if (!loadmodel->surfmesh.isanimated)
3201 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3202 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3203 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3204 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3205 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
3208 // because shaders can do somewhat unexpected things, check for unusual features now
3209 for (i = 0;i < loadmodel->num_textures;i++)
3211 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
3212 mod->DrawSky = R_Q1BSP_DrawSky;
3213 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
3214 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
3218 void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
3220 unsigned char *data;
3222 const unsigned char *pbase, *pend;
3224 skinfile_t *skinfiles;
3225 int i, j, k, meshvertices, meshtriangles;
3226 float biggestorigin;
3227 const unsigned int *inelements;
3229 float *outvertex, *outnormal, *outtexcoord, *outsvector, *outtvector, *outcolor;
3230 // this pointers into the file data are read only through Little* functions so they can be unaligned memory
3231 const float *vnormal = NULL;
3232 const float *vposition = NULL;
3233 const float *vtangent = NULL;
3234 const float *vtexcoord = NULL;
3235 const float *vcolor4f = NULL;
3236 const unsigned char *vblendindexes = NULL;
3237 const unsigned char *vblendweights = NULL;
3238 const unsigned char *vcolor4ub = NULL;
3239 const unsigned short *framedata = NULL;
3240 // temporary memory allocations (because the data in the file may be misaligned)
3241 iqmanim_t *anims = NULL;
3242 iqmbounds_t *bounds = NULL;
3243 iqmjoint1_t *joint1 = NULL;
3244 iqmjoint_t *joint = NULL;
3245 iqmmesh_t *meshes = NULL;
3246 iqmpose1_t *pose1 = NULL;
3247 iqmpose_t *pose = NULL;
3248 iqmvertexarray_t *vas = NULL;
3250 pbase = (unsigned char *)buffer;
3251 pend = (unsigned char *)bufferend;
3253 if (pbase + sizeof(iqmheader_t) > pend)
3254 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model %d", loadmodel->name, (int)(pend - pbase));
3256 // copy struct (otherwise it may be misaligned)
3257 // LordHavoc: okay it's definitely not misaligned here, but for consistency...
3258 memcpy(&header, pbase, sizeof(iqmheader_t));
3260 if (memcmp(header.id, "INTERQUAKEMODEL", 16))
3261 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model", loadmodel->name);
3262 if (LittleLong(header.version) != 1 && LittleLong(header.version) != 2)
3263 Host_Error ("Mod_INTERQUAKEMODEL_Load: only version 1 and 2 models are currently supported (name = %s)", loadmodel->name);
3265 loadmodel->modeldatatypestring = "IQM";
3267 loadmodel->type = mod_alias;
3268 loadmodel->synctype = ST_RAND;
3271 header.version = LittleLong(header.version);
3272 header.filesize = LittleLong(header.filesize);
3273 header.flags = LittleLong(header.flags);
3274 header.num_text = LittleLong(header.num_text);
3275 header.ofs_text = LittleLong(header.ofs_text);
3276 header.num_meshes = LittleLong(header.num_meshes);
3277 header.ofs_meshes = LittleLong(header.ofs_meshes);
3278 header.num_vertexarrays = LittleLong(header.num_vertexarrays);
3279 header.num_vertexes = LittleLong(header.num_vertexes);
3280 header.ofs_vertexarrays = LittleLong(header.ofs_vertexarrays);
3281 header.num_triangles = LittleLong(header.num_triangles);
3282 header.ofs_triangles = LittleLong(header.ofs_triangles);
3283 header.ofs_neighbors = LittleLong(header.ofs_neighbors);
3284 header.num_joints = LittleLong(header.num_joints);
3285 header.ofs_joints = LittleLong(header.ofs_joints);
3286 header.num_poses = LittleLong(header.num_poses);
3287 header.ofs_poses = LittleLong(header.ofs_poses);
3288 header.num_anims = LittleLong(header.num_anims);
3289 header.ofs_anims = LittleLong(header.ofs_anims);
3290 header.num_frames = LittleLong(header.num_frames);
3291 header.num_framechannels = LittleLong(header.num_framechannels);
3292 header.ofs_frames = LittleLong(header.ofs_frames);
3293 header.ofs_bounds = LittleLong(header.ofs_bounds);
3294 header.num_comment = LittleLong(header.num_comment);
3295 header.ofs_comment = LittleLong(header.ofs_comment);
3296 header.num_extensions = LittleLong(header.num_extensions);
3297 header.ofs_extensions = LittleLong(header.ofs_extensions);
3299 if (header.version == 1)
3301 if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint1_t) > pend ||
3302 pbase + header.ofs_poses + header.num_poses*sizeof(iqmpose1_t) > pend)
3304 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3310 if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint_t) > pend ||
3311 pbase + header.ofs_poses + header.num_poses*sizeof(iqmpose_t) > pend)
3313 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3317 if (pbase + header.ofs_text + header.num_text > pend ||
3318 pbase + header.ofs_meshes + header.num_meshes*sizeof(iqmmesh_t) > pend ||
3319 pbase + header.ofs_vertexarrays + header.num_vertexarrays*sizeof(iqmvertexarray_t) > pend ||
3320 pbase + header.ofs_triangles + header.num_triangles*sizeof(int[3]) > pend ||
3321 (header.ofs_neighbors && pbase + header.ofs_neighbors + header.num_triangles*sizeof(int[3]) > pend) ||
3322 pbase + header.ofs_anims + header.num_anims*sizeof(iqmanim_t) > pend ||
3323 pbase + header.ofs_frames + header.num_frames*header.num_framechannels*sizeof(unsigned short) > pend ||
3324 (header.ofs_bounds && pbase + header.ofs_bounds + header.num_frames*sizeof(iqmbounds_t) > pend) ||
3325 pbase + header.ofs_comment + header.num_comment > pend)
3327 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3331 // copy structs to make them aligned in memory (otherwise we crash on Sparc and PowerPC and others)
3332 if (header.num_vertexarrays)
3333 vas = (iqmvertexarray_t *)(pbase + header.ofs_vertexarrays);
3334 if (header.num_anims)
3335 anims = (iqmanim_t *)(pbase + header.ofs_anims);
3336 if (header.ofs_bounds)
3337 bounds = (iqmbounds_t *)(pbase + header.ofs_bounds);
3338 if (header.num_meshes)
3339 meshes = (iqmmesh_t *)(pbase + header.ofs_meshes);
3341 for (i = 0;i < (int)header.num_vertexarrays;i++)
3343 iqmvertexarray_t va;
3345 va.type = LittleLong(vas[i].type);
3346 va.flags = LittleLong(vas[i].flags);
3347 va.format = LittleLong(vas[i].format);
3348 va.size = LittleLong(vas[i].size);
3349 va.offset = LittleLong(vas[i].offset);
3350 vsize = header.num_vertexes*va.size;
3353 case IQM_FLOAT: vsize *= sizeof(float); break;
3354 case IQM_UBYTE: vsize *= sizeof(unsigned char); break;
3357 if (pbase + va.offset + vsize > pend)
3359 // no need to copy the vertex data for alignment because LittleLong/LittleShort will be invoked on reading them, and the destination is aligned
3363 if (va.format == IQM_FLOAT && va.size == 3)
3364 vposition = (const float *)(pbase + va.offset);
3367 if (va.format == IQM_FLOAT && va.size == 2)
3368 vtexcoord = (const float *)(pbase + va.offset);
3371 if (va.format == IQM_FLOAT && va.size == 3)
3372 vnormal = (const float *)(pbase + va.offset);
3375 if (va.format == IQM_FLOAT && va.size == 4)
3376 vtangent = (const float *)(pbase + va.offset);
3378 case IQM_BLENDINDEXES:
3379 if (va.format == IQM_UBYTE && va.size == 4)
3380 vblendindexes = (const unsigned char *)(pbase + va.offset);
3382 case IQM_BLENDWEIGHTS:
3383 if (va.format == IQM_UBYTE && va.size == 4)
3384 vblendweights = (const unsigned char *)(pbase + va.offset);
3387 if (va.format == IQM_FLOAT && va.size == 4)
3388 vcolor4f = (const float *)(pbase + va.offset);
3389 if (va.format == IQM_UBYTE && va.size == 4)
3390 vcolor4ub = (const unsigned char *)(pbase + va.offset);
3394 if (header.num_vertexes > 0 && (!vposition || !vtexcoord || ((header.num_frames > 0 || header.num_anims > 0) && (!vblendindexes || !vblendweights))))
3396 Con_Printf("%s is missing vertex array data\n", loadmodel->name);
3400 text = header.num_text && header.ofs_text ? (const char *)(pbase + header.ofs_text) : "";
3402 loadmodel->DrawSky = NULL;
3403 loadmodel->DrawAddWaterPlanes = NULL;
3404 loadmodel->Draw = R_Q1BSP_Draw;
3405 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
3406 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
3407 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
3408 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
3409 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
3410 loadmodel->DrawLight = R_Q1BSP_DrawLight;
3411 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
3412 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
3413 loadmodel->PointSuperContents = NULL;
3414 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
3416 // load external .skin files if present
3417 skinfiles = Mod_LoadSkinFiles();
3418 if (loadmodel->numskins < 1)
3419 loadmodel->numskins = 1;
3421 loadmodel->numframes = max(header.num_anims, 1);
3422 loadmodel->num_bones = header.num_joints;
3423 loadmodel->num_poses = max(header.num_frames, 1);
3424 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = header.num_meshes;
3425 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3426 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3428 meshvertices = header.num_vertexes;
3429 meshtriangles = header.num_triangles;
3431 // do most allocations as one merged chunk
3432 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) + meshvertices * (sizeof(float[14]) + (vcolor4f || vcolor4ub ? sizeof(float[4]) : 0)) + (vblendindexes && vblendweights ? meshvertices * (sizeof(unsigned short) + sizeof(unsigned char[2][4])) : 0) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
3433 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
3434 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
3435 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
3436 loadmodel->surfmesh.num_vertices = meshvertices;
3437 loadmodel->surfmesh.num_triangles = meshtriangles;
3438 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3439 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
3440 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3441 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3442 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
3443 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
3444 if (vcolor4f || vcolor4ub)
3446 loadmodel->surfmesh.data_lightmapcolor4f = (float *)data;data += meshvertices * sizeof(float[4]);
3448 if (vblendindexes && vblendweights)
3450 loadmodel->surfmesh.data_skeletalindex4ub = (unsigned char *)data;data += meshvertices * sizeof(unsigned char[4]);
3451 loadmodel->surfmesh.data_skeletalweight4ub = (unsigned char *)data;data += meshvertices * sizeof(unsigned char[4]);
3453 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
3454 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
3455 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
3456 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
3457 if (vblendindexes && vblendweights)
3459 loadmodel->surfmesh.num_blends = 0;
3460 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
3462 if (meshvertices <= 65536)
3464 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
3466 loadmodel->data_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
3467 if (vblendindexes && vblendweights)
3468 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
3470 for (i = 0;i < loadmodel->numskins;i++)
3472 loadmodel->skinscenes[i].firstframe = i;
3473 loadmodel->skinscenes[i].framecount = 1;
3474 loadmodel->skinscenes[i].loop = true;
3475 loadmodel->skinscenes[i].framerate = 10;
3478 // load the bone info
3479 if (header.version == 1)
3481 iqmjoint1_t *injoint1 = (iqmjoint1_t *)(pbase + header.ofs_joints);
3482 if (loadmodel->num_bones)
3483 joint1 = (iqmjoint1_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(iqmjoint1_t));
3484 for (i = 0;i < loadmodel->num_bones;i++)
3486 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3487 joint1[i].name = LittleLong(injoint1[i].name);
3488 joint1[i].parent = LittleLong(injoint1[i].parent);
3489 for (j = 0;j < 3;j++)
3491 joint1[i].origin[j] = LittleFloat(injoint1[i].origin[j]);
3492 joint1[i].rotation[j] = LittleFloat(injoint1[i].rotation[j]);
3493 joint1[i].scale[j] = LittleFloat(injoint1[i].scale[j]);
3495 strlcpy(loadmodel->data_bones[i].name, &text[joint1[i].name], sizeof(loadmodel->data_bones[i].name));
3496 loadmodel->data_bones[i].parent = joint1[i].parent;
3497 if (loadmodel->data_bones[i].parent >= i)
3498 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3499 Matrix4x4_FromDoom3Joint(&relbase, joint1[i].origin[0], joint1[i].origin[1], joint1[i].origin[2], joint1[i].rotation[0], joint1[i].rotation[1], joint1[i].rotation[2]);
3500 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3501 if (loadmodel->data_bones[i].parent >= 0)
3503 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3504 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3505 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3507 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3512 iqmjoint_t *injoint = (iqmjoint_t *)(pbase + header.ofs_joints);
3513 if (header.num_joints)
3514 joint = (iqmjoint_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(iqmjoint_t));
3515 for (i = 0;i < loadmodel->num_bones;i++)
3517 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3518 joint[i].name = LittleLong(injoint[i].name);
3519 joint[i].parent = LittleLong(injoint[i].parent);
3520 for (j = 0;j < 3;j++)
3522 joint[i].origin[j] = LittleFloat(injoint[i].origin[j]);
3523 joint[i].rotation[j] = LittleFloat(injoint[i].rotation[j]);
3524 joint[i].scale[j] = LittleFloat(injoint[i].scale[j]);
3526 joint[i].rotation[3] = LittleFloat(injoint[i].rotation[3]);
3527 strlcpy(loadmodel->data_bones[i].name, &text[joint[i].name], sizeof(loadmodel->data_bones[i].name));
3528 loadmodel->data_bones[i].parent = joint[i].parent;
3529 if (loadmodel->data_bones[i].parent >= i)
3530 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3531 if (joint[i].rotation[3] > 0)
3532 Vector4Negate(joint[i].rotation, joint[i].rotation);
3533 Vector4Normalize2(joint[i].rotation, joint[i].rotation);
3534 Matrix4x4_FromDoom3Joint(&relbase, joint[i].origin[0], joint[i].origin[1], joint[i].origin[2], joint[i].rotation[0], joint[i].rotation[1], joint[i].rotation[2]);
3535 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3536 if (loadmodel->data_bones[i].parent >= 0)
3538 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3539 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3540 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3542 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3546 // set up the animscenes based on the anims
3547 for (i = 0;i < (int)header.num_anims;i++)
3550 anim.name = LittleLong(anims[i].name);
3551 anim.first_frame = LittleLong(anims[i].first_frame);
3552 anim.num_frames = LittleLong(anims[i].num_frames);
3553 anim.framerate = LittleFloat(anims[i].framerate);
3554 anim.flags = LittleLong(anims[i].flags);
3555 strlcpy(loadmodel->animscenes[i].name, &text[anim.name], sizeof(loadmodel->animscenes[i].name));
3556 loadmodel->animscenes[i].firstframe = anim.first_frame;
3557 loadmodel->animscenes[i].framecount = anim.num_frames;
3558 loadmodel->animscenes[i].loop = ((anim.flags & IQM_LOOP) != 0);
3559 loadmodel->animscenes[i].framerate = anim.framerate;
3561 if (header.num_anims <= 0)
3563 strlcpy(loadmodel->animscenes[0].name, "static", sizeof(loadmodel->animscenes[0].name));
3564 loadmodel->animscenes[0].firstframe = 0;
3565 loadmodel->animscenes[0].framecount = 1;
3566 loadmodel->animscenes[0].loop = true;
3567 loadmodel->animscenes[0].framerate = 10;
3570 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
3571 if(mod_alias_force_animated.string[0])
3572 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
3575 if (header.version == 1)
3577 iqmpose1_t *inpose1 = (iqmpose1_t *)(pbase + header.ofs_poses);
3578 if (header.num_poses)
3579 pose1 = (iqmpose1_t *)Mem_Alloc(loadmodel->mempool, header.num_poses * sizeof(iqmpose1_t));
3580 for (i = 0;i < (int)header.num_poses;i++)
3583 pose1[i].parent = LittleLong(inpose1[i].parent);
3584 pose1[i].channelmask = LittleLong(inpose1[i].channelmask);
3585 for (j = 0;j < 9;j++)
3587 pose1[i].channeloffset[j] = LittleFloat(inpose1[i].channeloffset[j]);
3588 pose1[i].channelscale[j] = LittleFloat(inpose1[i].channelscale[j]);
3590 f = fabs(pose1[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3591 f = fabs(pose1[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3592 f = fabs(pose1[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3593 f = fabs(pose1[i].channeloffset[0] + 0xFFFF*pose1[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3594 f = fabs(pose1[i].channeloffset[1] + 0xFFFF*pose1[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3595 f = fabs(pose1[i].channeloffset[2] + 0xFFFF*pose1[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3597 if (header.num_frames <= 0)
3599 for (i = 0;i < loadmodel->num_bones;i++)
3602 f = fabs(joint1[i].origin[0]); biggestorigin = max(biggestorigin, f);
3603 f = fabs(joint1[i].origin[1]); biggestorigin = max(biggestorigin, f);
3604 f = fabs(joint1[i].origin[2]); biggestorigin = max(biggestorigin, f);
3610 iqmpose_t *inpose = (iqmpose_t *)(pbase + header.ofs_poses);
3611 if (header.num_poses)
3612 pose = (iqmpose_t *)Mem_Alloc(loadmodel->mempool, header.num_poses * sizeof(iqmpose_t));
3613 for (i = 0;i < (int)header.num_poses;i++)
3616 pose[i].parent = LittleLong(inpose[i].parent);
3617 pose[i].channelmask = LittleLong(inpose[i].channelmask);
3618 for (j = 0;j < 10;j++)
3620 pose[i].channeloffset[j] = LittleFloat(inpose[i].channeloffset[j]);
3621 pose[i].channelscale[j] = LittleFloat(inpose[i].channelscale[j]);
3623 f = fabs(pose[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3624 f = fabs(pose[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3625 f = fabs(pose[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3626 f = fabs(pose[i].channeloffset[0] + 0xFFFF*pose[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3627 f = fabs(pose[i].channeloffset[1] + 0xFFFF*pose[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3628 f = fabs(pose[i].channeloffset[2] + 0xFFFF*pose[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3630 if (header.num_frames <= 0)
3632 for (i = 0;i < loadmodel->num_bones;i++)
3635 f = fabs(joint[i].origin[0]); biggestorigin = max(biggestorigin, f);
3636 f = fabs(joint[i].origin[1]); biggestorigin = max(biggestorigin, f);
3637 f = fabs(joint[i].origin[2]); biggestorigin = max(biggestorigin, f);
3641 loadmodel->num_posescale = biggestorigin / 32767.0f;
3642 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3644 // load the pose data
3645 // this unaligned memory access is safe (LittleShort reads as bytes)
3646 framedata = (const unsigned short *)(pbase + header.ofs_frames);
3647 if (header.version == 1)
3649 for (i = 0, k = 0;i < (int)header.num_frames;i++)
3651 for (j = 0;j < (int)header.num_poses;j++, k++)
3653 float qx, qy, qz, qw;
3654 loadmodel->data_poses7s[k*7 + 0] = loadmodel->num_poseinvscale * (pose1[j].channeloffset[0] + (pose1[j].channelmask&1 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[0] : 0));
3655 loadmodel->data_poses7s[k*7 + 1] = loadmodel->num_poseinvscale * (pose1[j].channeloffset[1] + (pose1[j].channelmask&2 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[1] : 0));
3656 loadmodel->data_poses7s[k*7 + 2] = loadmodel->num_poseinvscale * (pose1[j].channeloffset[2] + (pose1[j].channelmask&4 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[2] : 0));
3657 qx = pose1[j].channeloffset[3] + (pose1[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[3] : 0);
3658 qy = pose1[j].channeloffset[4] + (pose1[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[4] : 0);
3659 qz = pose1[j].channeloffset[5] + (pose1[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[5] : 0);
3660 qw = 1.0f - (qx*qx + qy*qy + qz*qz);
3661 qw = qw > 0.0f ? -sqrt(qw) : 0.0f;
3662 loadmodel->data_poses7s[k*7 + 3] = 32767.0f * qx;
3663 loadmodel->data_poses7s[k*7 + 4] = 32767.0f * qy;
3664 loadmodel->data_poses7s[k*7 + 5] = 32767.0f * qz;
3665 loadmodel->data_poses7s[k*7 + 6] = 32767.0f * qw;
3666 // skip scale data for now
3667 if(pose1[j].channelmask&64) framedata++;
3668 if(pose1[j].channelmask&128) framedata++;
3669 if(pose1[j].channelmask&256) framedata++;
3672 if (header.num_frames <= 0)
3674 for (i = 0;i < loadmodel->num_bones;i++)
3676 float qx, qy, qz, qw;
3677 loadmodel->data_poses7s[i*7 + 0] = loadmodel->num_poseinvscale * joint1[i].origin[0];
3678 loadmodel->data_poses7s[i*7 + 1] = loadmodel->num_poseinvscale * joint1[i].origin[1];
3679 loadmodel->data_poses7s[i*7 + 2] = loadmodel->num_poseinvscale * joint1[i].origin[2];
3680 qx = joint1[i].rotation[0];
3681 qy = joint1[i].rotation[1];
3682 qz = joint1[i].rotation[2];
3683 qw = 1.0f - (qx*qx + qy*qy + qz*qz);
3684 qw = qw > 0.0f ? -sqrt(qw) : 0.0f;
3685 loadmodel->data_poses7s[i*7 + 3] = 32767.0f * qx;
3686 loadmodel->data_poses7s[i*7 + 4] = 32767.0f * qy;
3687 loadmodel->data_poses7s[i*7 + 5] = 32767.0f * qz;
3688 loadmodel->data_poses7s[i*7 + 6] = 32767.0f * qw;
3694 for (i = 0, k = 0;i < (int)header.num_frames;i++)
3696 for (j = 0;j < (int)header.num_poses;j++, k++)
3699 loadmodel->data_poses7s[k*7 + 0] = loadmodel->num_poseinvscale * (pose[j].channeloffset[0] + (pose[j].channelmask&1 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[0] : 0));
3700 loadmodel->data_poses7s[k*7 + 1] = loadmodel->num_poseinvscale * (pose[j].channeloffset[1] + (pose[j].channelmask&2 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[1] : 0));
3701 loadmodel->data_poses7s[k*7 + 2] = loadmodel->num_poseinvscale * (pose[j].channeloffset[2] + (pose[j].channelmask&4 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[2] : 0));
3702 rot[0] = pose[j].channeloffset[3] + (pose[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[3] : 0);
3703 rot[1] = pose[j].channeloffset[4] + (pose[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[4] : 0);
3704 rot[2] = pose[j].channeloffset[5] + (pose[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[5] : 0);
3705 rot[3] = pose[j].channeloffset[6] + (pose[j].channelmask&64 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[6] : 0);
3707 Vector4Negate(rot, rot);
3708 Vector4Normalize2(rot, rot);
3709 loadmodel->data_poses7s[k*7 + 3] = 32767.0f * rot[0];
3710 loadmodel->data_poses7s[k*7 + 4] = 32767.0f * rot[1];
3711 loadmodel->data_poses7s[k*7 + 5] = 32767.0f * rot[2];
3712 loadmodel->data_poses7s[k*7 + 6] = 32767.0f * rot[3];
3713 // skip scale data for now
3714 if(pose[j].channelmask&128) framedata++;
3715 if(pose[j].channelmask&256) framedata++;
3716 if(pose[j].channelmask&512) framedata++;
3719 if (header.num_frames <= 0)
3721 for (i = 0;i < loadmodel->num_bones;i++)
3723 loadmodel->data_poses7s[i*7 + 0] = loadmodel->num_poseinvscale * joint[i].origin[0];
3724 loadmodel->data_poses7s[i*7 + 1] = loadmodel->num_poseinvscale * joint[i].origin[1];
3725 loadmodel->data_poses7s[i*7 + 2] = loadmodel->num_poseinvscale * joint[i].origin[2];
3726 loadmodel->data_poses7s[i*7 + 3] = 32767.0f * joint[i].rotation[0];
3727 loadmodel->data_poses7s[i*7 + 4] = 32767.0f * joint[i].rotation[1];
3728 loadmodel->data_poses7s[i*7 + 5] = 32767.0f * joint[i].rotation[2];
3729 loadmodel->data_poses7s[i*7 + 6] = 32767.0f * joint[i].rotation[3];
3734 // load bounding box data
3735 if (header.ofs_bounds)
3737 float xyradius = 0, radius = 0;
3738 VectorClear(loadmodel->normalmins);
3739 VectorClear(loadmodel->normalmaxs);
3740 for (i = 0; i < (int)header.num_frames;i++)
3743 bound.mins[0] = LittleFloat(bounds[i].mins[0]);
3744 bound.mins[1] = LittleFloat(bounds[i].mins[1]);
3745 bound.mins[2] = LittleFloat(bounds[i].mins[2]);
3746 bound.maxs[0] = LittleFloat(bounds[i].maxs[0]);
3747 bound.maxs[1] = LittleFloat(bounds[i].maxs[1]);
3748 bound.maxs[2] = LittleFloat(bounds[i].maxs[2]);
3749 bound.xyradius = LittleFloat(bounds[i].xyradius);
3750 bound.radius = LittleFloat(bounds[i].radius);
3753 VectorCopy(bound.mins, loadmodel->normalmins);
3754 VectorCopy(bound.maxs, loadmodel->normalmaxs);
3758 if (loadmodel->normalmins[0] > bound.mins[0]) loadmodel->normalmins[0] = bound.mins[0];
3759 if (loadmodel->normalmins[1] > bound.mins[1]) loadmodel->normalmins[1] = bound.mins[1];
3760 if (loadmodel->normalmins[2] > bound.mins[2]) loadmodel->normalmins[2] = bound.mins[2];
3761 if (loadmodel->normalmaxs[0] < bound.maxs[0]) loadmodel->normalmaxs[0] = bound.maxs[0];
3762 if (loadmodel->normalmaxs[1] < bound.maxs[1]) loadmodel->normalmaxs[1] = bound.maxs[1];
3763 if (loadmodel->normalmaxs[2] < bound.maxs[2]) loadmodel->normalmaxs[2] = bound.maxs[2];
3765 if (bound.xyradius > xyradius)
3766 xyradius = bound.xyradius;
3767 if (bound.radius > radius)
3768 radius = bound.radius;
3770 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -xyradius;
3771 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = xyradius;
3772 loadmodel->yawmins[2] = loadmodel->normalmins[2];
3773 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
3774 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
3775 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
3776 loadmodel->radius = radius;
3777 loadmodel->radius2 = radius * radius;
3780 // load triangle data
3781 // this unaligned memory access is safe (LittleLong reads as bytes)
3782 inelements = (const unsigned int *)(pbase + header.ofs_triangles);
3783 outelements = loadmodel->surfmesh.data_element3i;
3784 for (i = 0;i < (int)header.num_triangles;i++)
3786 outelements[0] = LittleLong(inelements[0]);
3787 outelements[1] = LittleLong(inelements[1]);
3788 outelements[2] = LittleLong(inelements[2]);
3792 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_element3s, loadmodel->surfmesh.num_triangles, 0, header.num_vertexes, __FILE__, __LINE__);
3795 // this unaligned memory access is safe (LittleFloat reads as bytes)
3796 outvertex = loadmodel->surfmesh.data_vertex3f;
3797 for (i = 0;i < (int)header.num_vertexes;i++)
3799 outvertex[0] = LittleFloat(vposition[0]);
3800 outvertex[1] = LittleFloat(vposition[1]);
3801 outvertex[2] = LittleFloat(vposition[2]);
3806 outtexcoord = loadmodel->surfmesh.data_texcoordtexture2f;
3807 // this unaligned memory access is safe (LittleFloat reads as bytes)
3808 for (i = 0;i < (int)header.num_vertexes;i++)
3810 outtexcoord[0] = LittleFloat(vtexcoord[0]);
3811 outtexcoord[1] = LittleFloat(vtexcoord[1]);
3816 // this unaligned memory access is safe (LittleFloat reads as bytes)
3819 outnormal = loadmodel->surfmesh.data_normal3f;
3820 for (i = 0;i < (int)header.num_vertexes;i++)
3822 outnormal[0] = LittleFloat(vnormal[0]);
3823 outnormal[1] = LittleFloat(vnormal[1]);
3824 outnormal[2] = LittleFloat(vnormal[2]);
3830 // this unaligned memory access is safe (LittleFloat reads as bytes)
3831 if(vnormal && vtangent)
3833 outnormal = loadmodel->surfmesh.data_normal3f;
3834 outsvector = loadmodel->surfmesh.data_svector3f;
3835 outtvector = loadmodel->surfmesh.data_tvector3f;
3836 for (i = 0;i < (int)header.num_vertexes;i++)
3838 outsvector[0] = LittleFloat(vtangent[0]);
3839 outsvector[1] = LittleFloat(vtangent[1]);
3840 outsvector[2] = LittleFloat(vtangent[2]);
3841 if(LittleFloat(vtangent[3]) < 0)
3842 CrossProduct(outsvector, outnormal, outtvector);
3844 CrossProduct(outnormal, outsvector, outtvector);
3852 // this unaligned memory access is safe (all bytes)
3853 if (vblendindexes && vblendweights)
3855 for (i = 0; i < (int)header.num_vertexes;i++)
3857 blendweights_t weights;
3858 memcpy(weights.index, vblendindexes + i*4, 4);
3859 memcpy(weights.influence, vblendweights + i*4, 4);
3860 loadmodel->surfmesh.blends[i] = Mod_Skeletal_AddBlend(loadmodel, &weights);
3861 loadmodel->surfmesh.data_skeletalindex4ub[i*4 ] = weights.index[0];
3862 loadmodel->surfmesh.data_skeletalindex4ub[i*4+1] = weights.index[1];
3863 loadmodel->surfmesh.data_skeletalindex4ub[i*4+2] = weights.index[2];
3864 loadmodel->surfmesh.data_skeletalindex4ub[i*4+3] = weights.index[3];
3865 loadmodel->surfmesh.data_skeletalweight4ub[i*4 ] = weights.influence[0];
3866 loadmodel->surfmesh.data_skeletalweight4ub[i*4+1] = weights.influence[1];
3867 loadmodel->surfmesh.data_skeletalweight4ub[i*4+2] = weights.influence[2];
3868 loadmodel->surfmesh.data_skeletalweight4ub[i*4+3] = weights.influence[3];
3874 outcolor = loadmodel->surfmesh.data_lightmapcolor4f;
3875 // this unaligned memory access is safe (LittleFloat reads as bytes)
3876 for (i = 0;i < (int)header.num_vertexes;i++)
3878 outcolor[0] = LittleFloat(vcolor4f[0]);
3879 outcolor[1] = LittleFloat(vcolor4f[1]);
3880 outcolor[2] = LittleFloat(vcolor4f[2]);
3881 outcolor[3] = LittleFloat(vcolor4f[3]);
3888 outcolor = loadmodel->surfmesh.data_lightmapcolor4f;
3889 // this unaligned memory access is safe (all bytes)
3890 for (i = 0;i < (int)header.num_vertexes;i++)
3892 outcolor[0] = vcolor4ub[0] * (1.0f / 255.0f);
3893 outcolor[1] = vcolor4ub[1] * (1.0f / 255.0f);
3894 outcolor[2] = vcolor4ub[2] * (1.0f / 255.0f);
3895 outcolor[3] = vcolor4ub[3] * (1.0f / 255.0f);
3902 for (i = 0;i < (int)header.num_meshes;i++)
3905 msurface_t *surface;
3907 mesh.name = LittleLong(meshes[i].name);
3908 mesh.material = LittleLong(meshes[i].material);
3909 mesh.first_vertex = LittleLong(meshes[i].first_vertex);
3910 mesh.num_vertexes = LittleLong(meshes[i].num_vertexes);
3911 mesh.first_triangle = LittleLong(meshes[i].first_triangle);
3912 mesh.num_triangles = LittleLong(meshes[i].num_triangles);
3914 loadmodel->sortedmodelsurfaces[i] = i;
3915 surface = loadmodel->data_surfaces + i;
3916 surface->texture = loadmodel->data_textures + i;
3917 surface->num_firsttriangle = mesh.first_triangle;
3918 surface->num_triangles = mesh.num_triangles;
3919 surface->num_firstvertex = mesh.first_vertex;
3920 surface->num_vertices = mesh.num_vertexes;
3922 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, &text[mesh.name], &text[mesh.material]);
3925 Mod_FreeSkinFiles(skinfiles);
3926 Mod_MakeSortedSurfaces(loadmodel);
3928 // compute all the mesh information that was not loaded from the file
3929 if (loadmodel->surfmesh.data_element3s)
3930 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3931 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3933 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, r_smoothnormals_areaweighting.integer != 0);
3934 if (!vnormal || !vtangent)
3935 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);
3936 if (!header.ofs_bounds)
3937 Mod_Alias_CalculateBoundingBox();
3939 // Always make a BIH for the first frame, we can use it where possible.
3940 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3941 if (!loadmodel->surfmesh.isanimated)
3943 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3944 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3945 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3946 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3947 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
3950 if (joint ) Mem_Free(joint );joint = NULL;
3951 if (joint1 ) Mem_Free(joint1 );joint1 = NULL;
3952 if (pose ) Mem_Free(pose );pose = NULL;
3953 if (pose1 ) Mem_Free(pose1 );pose1 = NULL;
3955 // because shaders can do somewhat unexpected things, check for unusual features now
3956 for (i = 0;i < loadmodel->num_textures;i++)
3958 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
3959 mod->DrawSky = R_Q1BSP_DrawSky;
3960 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
3961 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;