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 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)
68 if (!model->surfmesh.num_vertices)
71 if (!model->num_bones)
73 if (vertex3f) memcpy(vertex3f, model->surfmesh.data_vertex3f, model->surfmesh.num_vertices*sizeof(float[3]));
74 if (normal3f) memcpy(normal3f, model->surfmesh.data_normal3f, model->surfmesh.num_vertices*sizeof(float[3]));
75 if (svector3f) memcpy(svector3f, model->surfmesh.data_svector3f, model->surfmesh.num_vertices*sizeof(float[3]));
76 if (tvector3f) memcpy(tvector3f, model->surfmesh.data_tvector3f, model->surfmesh.num_vertices*sizeof(float[3]));
81 if(r_skeletal_use_sse_defined)
82 if(r_skeletal_use_sse.integer)
84 Mod_Skeletal_AnimateVertices_SSE(model, frameblend, skeleton, vertex3f, normal3f, svector3f, tvector3f);
88 Mod_Skeletal_AnimateVertices_Generic(model, frameblend, skeleton, vertex3f, normal3f, svector3f, tvector3f);
91 void Mod_AliasInit (void)
94 Cvar_RegisterVariable(&r_skeletal_debugbone);
95 Cvar_RegisterVariable(&r_skeletal_debugbonecomponent);
96 Cvar_RegisterVariable(&r_skeletal_debugbonevalue);
97 Cvar_RegisterVariable(&r_skeletal_debugtranslatex);
98 Cvar_RegisterVariable(&r_skeletal_debugtranslatey);
99 Cvar_RegisterVariable(&r_skeletal_debugtranslatez);
100 Cvar_RegisterVariable(&mod_alias_supporttagscale);
101 Cvar_RegisterVariable(&mod_alias_force_animated);
102 for (i = 0;i < 320;i++)
103 mod_md3_sin[i] = sin(i * M_PI * 2.0f / 256.0);
107 Con_Printf("Skeletal animation uses SSE code path\n");
108 r_skeletal_use_sse_defined = true;
109 Cvar_RegisterVariable(&r_skeletal_use_sse);
112 Con_Printf("Skeletal animation uses generic code path (SSE disabled or not detected)\n");
114 Con_Printf("Skeletal animation uses generic code path (SSE not compiled in)\n");
118 static int Mod_Skeletal_AddBlend(dp_model_t *model, const blendweights_t *newweights)
121 blendweights_t *weights;
122 if(!newweights->influence[1])
123 return newweights->index[0];
124 weights = model->surfmesh.data_blendweights;
125 for (i = 0;i < model->surfmesh.num_blends;i++, weights++)
127 if (!memcmp(weights, newweights, sizeof(blendweights_t)))
128 return model->num_bones + i;
130 model->surfmesh.num_blends++;
131 memcpy(weights, newweights, sizeof(blendweights_t));
132 return model->num_bones + i;
135 static int Mod_Skeletal_CompressBlend(dp_model_t *model, const int *newindex, const float *newinfluence)
139 blendweights_t newweights;
143 for (i = 0;i < 4;i++)
144 scale += newinfluence[i];
145 scale = 255.0f / scale;
147 for (i = 0;i < 4;i++)
149 newweights.index[i] = newindex[i];
150 newweights.influence[i] = (unsigned char)(newinfluence[i] * scale);
151 total += newweights.influence[i];
155 for (i = 0;i < 4;i++)
157 if(newweights.influence[i] > 0 && total > 255)
159 newweights.influence[i]--;
166 for (i = 0; i < 4;i++)
168 if(newweights.influence[i] < 255 && total < 255)
170 newweights.influence[i]++;
175 return Mod_Skeletal_AddBlend(model, &newweights);
178 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)
181 int i, numblends, blendnum;
182 int numverts = model->surfmesh.num_vertices;
184 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
186 //VectorMA(translate, model->surfmesh.num_morphmdlframetranslate, frameblend[blendnum].lerp, translate);
187 if (frameblend[blendnum].lerp > 0)
188 numblends = blendnum + 1;
190 // special case for the first blend because it avoids some adds and the need to memset the arrays first
191 for (blendnum = 0;blendnum < numblends;blendnum++)
193 const md3vertex_t *verts = model->surfmesh.data_morphmd3vertex + numverts * frameblend[blendnum].subframe;
196 float scale = frameblend[blendnum].lerp * (1.0f / 64.0f);
199 for (i = 0;i < numverts;i++)
201 vertex3f[i * 3 + 0] = verts[i].origin[0] * scale;
202 vertex3f[i * 3 + 1] = verts[i].origin[1] * scale;
203 vertex3f[i * 3 + 2] = verts[i].origin[2] * scale;
208 for (i = 0;i < numverts;i++)
210 vertex3f[i * 3 + 0] += verts[i].origin[0] * scale;
211 vertex3f[i * 3 + 1] += verts[i].origin[1] * scale;
212 vertex3f[i * 3 + 2] += verts[i].origin[2] * scale;
216 // the yaw and pitch stored in md3 models are 8bit quantized angles
217 // (0-255), and as such a lookup table is very well suited to
218 // decoding them, and since cosine is equivalent to sine with an
219 // extra 45 degree rotation, this uses one lookup table for both
220 // sine and cosine with a +64 bias to get cosine.
223 float lerp = frameblend[blendnum].lerp;
226 for (i = 0;i < numverts;i++)
228 normal3f[i * 3 + 0] = mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
229 normal3f[i * 3 + 1] = mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
230 normal3f[i * 3 + 2] = mod_md3_sin[verts[i].pitch + 64] * lerp;
235 for (i = 0;i < numverts;i++)
237 normal3f[i * 3 + 0] += mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
238 normal3f[i * 3 + 1] += mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
239 normal3f[i * 3 + 2] += mod_md3_sin[verts[i].pitch + 64] * lerp;
245 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
246 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
249 for (i = 0;i < numverts;i++, texvecvert++)
251 VectorScale(texvecvert->svec, f, svector3f + i*3);
252 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
257 for (i = 0;i < numverts;i++, texvecvert++)
259 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
260 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
266 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)
269 int i, numblends, blendnum;
270 int numverts = model->surfmesh.num_vertices;
272 VectorClear(translate);
274 // blend the frame translates to avoid redundantly doing so on each vertex
275 // (a bit of a brain twister but it works)
276 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
278 if (model->surfmesh.data_morphmd2framesize6f)
279 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6 + 3, translate);
281 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.num_morphmdlframetranslate, translate);
282 if (frameblend[blendnum].lerp > 0)
283 numblends = blendnum + 1;
285 // special case for the first blend because it avoids some adds and the need to memset the arrays first
286 for (blendnum = 0;blendnum < numblends;blendnum++)
288 const trivertx_t *verts = model->surfmesh.data_morphmdlvertex + numverts * frameblend[blendnum].subframe;
292 if (model->surfmesh.data_morphmd2framesize6f)
293 VectorScale(model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6, frameblend[blendnum].lerp, scale);
295 VectorScale(model->surfmesh.num_morphmdlframescale, frameblend[blendnum].lerp, scale);
298 for (i = 0;i < numverts;i++)
300 vertex3f[i * 3 + 0] = translate[0] + verts[i].v[0] * scale[0];
301 vertex3f[i * 3 + 1] = translate[1] + verts[i].v[1] * scale[1];
302 vertex3f[i * 3 + 2] = translate[2] + verts[i].v[2] * scale[2];
307 for (i = 0;i < numverts;i++)
309 vertex3f[i * 3 + 0] += verts[i].v[0] * scale[0];
310 vertex3f[i * 3 + 1] += verts[i].v[1] * scale[1];
311 vertex3f[i * 3 + 2] += verts[i].v[2] * scale[2];
315 // the vertex normals in mdl models are an index into a table of
316 // 162 unique values, this very crude quantization reduces the
317 // vertex normal to only one byte, which saves a lot of space but
318 // also makes lighting pretty coarse
321 float lerp = frameblend[blendnum].lerp;
324 for (i = 0;i < numverts;i++)
326 const float *vn = m_bytenormals[verts[i].lightnormalindex];
327 VectorScale(vn, lerp, normal3f + i*3);
332 for (i = 0;i < numverts;i++)
334 const float *vn = m_bytenormals[verts[i].lightnormalindex];
335 VectorMA(normal3f + i*3, lerp, vn, normal3f + i*3);
341 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
342 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
345 for (i = 0;i < numverts;i++, texvecvert++)
347 VectorScale(texvecvert->svec, f, svector3f + i*3);
348 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
353 for (i = 0;i < numverts;i++, texvecvert++)
355 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
356 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
363 int Mod_Alias_GetTagMatrix(const dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, int tagindex, matrix4x4_t *outmatrix)
366 matrix4x4_t parentbonematrix;
367 matrix4x4_t tempbonematrix;
368 matrix4x4_t bonematrix;
369 matrix4x4_t blendmatrix;
376 *outmatrix = identitymatrix;
377 if (skeleton && skeleton->relativetransforms)
379 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
381 *outmatrix = skeleton->relativetransforms[tagindex];
382 while ((tagindex = model->data_bones[tagindex].parent) >= 0)
385 Matrix4x4_Concat(outmatrix, &skeleton->relativetransforms[tagindex], &temp);
388 else if (model->num_bones)
390 if (tagindex < 0 || tagindex >= model->num_bones)
392 Matrix4x4_Clear(&blendmatrix);
393 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
395 lerp = frameblend[blendindex].lerp;
396 Matrix4x4_FromBonePose7s(&bonematrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
397 parenttagindex = tagindex;
398 while ((parenttagindex = model->data_bones[parenttagindex].parent) >= 0)
400 Matrix4x4_FromBonePose7s(&parentbonematrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + parenttagindex));
401 tempbonematrix = bonematrix;
402 Matrix4x4_Concat(&bonematrix, &parentbonematrix, &tempbonematrix);
404 Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
406 *outmatrix = blendmatrix;
408 else if (model->num_tags)
410 if (tagindex < 0 || tagindex >= model->num_tags)
412 for (k = 0;k < 12;k++)
414 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
416 lerp = frameblend[blendindex].lerp;
417 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
418 for (k = 0;k < 12;k++)
419 blendtag[k] += input[k] * lerp;
421 Matrix4x4_FromArray12FloatGL(outmatrix, blendtag);
424 if(!mod_alias_supporttagscale.integer)
425 Matrix4x4_Normalize3(outmatrix, outmatrix);
430 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)
435 matrix4x4_t bonematrix;
436 matrix4x4_t blendmatrix;
440 if (skeleton && skeleton->relativetransforms)
442 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
444 *parentindex = skeleton->model->data_bones[tagindex].parent;
445 *tagname = skeleton->model->data_bones[tagindex].name;
446 *tag_localmatrix = skeleton->relativetransforms[tagindex];
449 else if (model->num_bones)
451 if (tagindex < 0 || tagindex >= model->num_bones)
453 *parentindex = model->data_bones[tagindex].parent;
454 *tagname = model->data_bones[tagindex].name;
455 Matrix4x4_Clear(&blendmatrix);
456 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
458 lerp = frameblend[blendindex].lerp;
459 Matrix4x4_FromBonePose7s(&bonematrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
460 Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
462 *tag_localmatrix = blendmatrix;
465 else if (model->num_tags)
467 if (tagindex < 0 || tagindex >= model->num_tags)
470 *tagname = model->data_tags[tagindex].name;
471 for (k = 0;k < 12;k++)
473 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
475 lerp = frameblend[blendindex].lerp;
476 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
477 for (k = 0;k < 12;k++)
478 blendtag[k] += input[k] * lerp;
480 Matrix4x4_FromArray12FloatGL(tag_localmatrix, blendtag);
487 int Mod_Alias_GetTagIndexForName(const dp_model_t *model, unsigned int skin, const char *tagname)
490 if(skin >= (unsigned int)model->numskins)
492 if (model->num_bones)
493 for (i = 0;i < model->num_bones;i++)
494 if (!strcasecmp(tagname, model->data_bones[i].name))
497 for (i = 0;i < model->num_tags;i++)
498 if (!strcasecmp(tagname, model->data_tags[i].name))
503 static void Mod_BuildBaseBonePoses(void)
506 matrix4x4_t *basebonepose;
507 float *outinvmatrix = loadmodel->data_baseboneposeinverse;
508 matrix4x4_t bonematrix;
509 matrix4x4_t tempbonematrix;
510 if (!loadmodel->num_bones)
512 basebonepose = (matrix4x4_t *)Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(matrix4x4_t));
513 for (boneindex = 0;boneindex < loadmodel->num_bones;boneindex++)
515 Matrix4x4_FromBonePose7s(&bonematrix, loadmodel->num_posescale, loadmodel->data_poses7s + 7 * boneindex);
516 if (loadmodel->data_bones[boneindex].parent >= 0)
518 tempbonematrix = bonematrix;
519 Matrix4x4_Concat(&bonematrix, basebonepose + loadmodel->data_bones[boneindex].parent, &tempbonematrix);
521 basebonepose[boneindex] = bonematrix;
522 Matrix4x4_Invert_Simple(&tempbonematrix, basebonepose + boneindex);
523 Matrix4x4_ToArray12FloatD3D(&tempbonematrix, outinvmatrix + 12*boneindex);
525 Mem_Free(basebonepose);
528 static qboolean Mod_Alias_CalculateBoundingBox(void)
531 qboolean firstvertex = true;
532 float dist, yawradius, radius;
534 qboolean isanimated = false;
535 VectorClear(loadmodel->normalmins);
536 VectorClear(loadmodel->normalmaxs);
539 if (loadmodel->AnimateVertices)
541 float *vertex3f, *refvertex3f;
542 frameblend_t frameblend[MAX_FRAMEBLENDS];
543 memset(frameblend, 0, sizeof(frameblend));
544 frameblend[0].lerp = 1;
545 vertex3f = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]) * 2);
547 for (frameblend[0].subframe = 0;frameblend[0].subframe < loadmodel->num_poses;frameblend[0].subframe++)
549 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, vertex3f, NULL, NULL, NULL);
552 // make a copy of the first frame for comparing all others
553 refvertex3f = vertex3f + loadmodel->surfmesh.num_vertices * 3;
554 memcpy(refvertex3f, vertex3f, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
558 if (!isanimated && memcmp(refvertex3f, vertex3f, loadmodel->surfmesh.num_vertices * sizeof(float[3])))
561 for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
566 VectorCopy(v, loadmodel->normalmins);
567 VectorCopy(v, loadmodel->normalmaxs);
571 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
572 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
573 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
574 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
575 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
576 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
578 dist = v[0] * v[0] + v[1] * v[1];
579 if (yawradius < dist)
591 for (vnum = 0, v = loadmodel->surfmesh.data_vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
596 VectorCopy(v, loadmodel->normalmins);
597 VectorCopy(v, loadmodel->normalmaxs);
601 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
602 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
603 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
604 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
605 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
606 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
608 dist = v[0] * v[0] + v[1] * v[1];
609 if (yawradius < dist)
616 radius = sqrt(radius);
617 yawradius = sqrt(yawradius);
618 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
619 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
620 loadmodel->yawmins[2] = loadmodel->normalmins[2];
621 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
622 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
623 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
624 loadmodel->radius = radius;
625 loadmodel->radius2 = radius * radius;
629 static void Mod_Alias_MorphMesh_CompileFrames(void)
632 frameblend_t frameblend[MAX_FRAMEBLENDS];
633 unsigned char *datapointer;
634 memset(frameblend, 0, sizeof(frameblend));
635 frameblend[0].lerp = 1;
636 datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
637 loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
638 loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
639 loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
640 loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
641 loadmodel->surfmesh.data_morphtexvecvertex = (texvecvertex_t *)datapointer;datapointer += loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices * sizeof(texvecvertex_t);
642 // 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)
643 for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
645 frameblend[0].subframe = i;
646 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
647 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);
648 // encode the svector and tvector in 3 byte format for permanent storage
649 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
651 VectorScaleCast(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
652 VectorScaleCast(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
657 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)
660 float segmentmins[3], segmentmaxs[3];
662 float vertex3fbuf[1024*3];
663 float *vertex3f = vertex3fbuf;
664 memset(trace, 0, sizeof(*trace));
666 trace->realfraction = 1;
667 trace->hitsupercontentsmask = hitsupercontentsmask;
668 if (model->surfmesh.num_vertices > 1024)
669 vertex3f = (float *)Mem_Alloc(tempmempool, model->surfmesh.num_vertices * sizeof(float[3]));
670 segmentmins[0] = min(start[0], end[0]) - 1;
671 segmentmins[1] = min(start[1], end[1]) - 1;
672 segmentmins[2] = min(start[2], end[2]) - 1;
673 segmentmaxs[0] = max(start[0], end[0]) + 1;
674 segmentmaxs[1] = max(start[1], end[1]) + 1;
675 segmentmaxs[2] = max(start[2], end[2]) + 1;
676 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
677 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
678 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);
679 if (vertex3f != vertex3fbuf)
683 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)
686 vec3_t shiftstart, shiftend;
687 float segmentmins[3], segmentmaxs[3];
689 float vertex3fbuf[1024*3];
690 float *vertex3f = vertex3fbuf;
691 colboxbrushf_t thisbrush_start, thisbrush_end;
692 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
694 if (VectorCompare(boxmins, boxmaxs))
696 VectorAdd(start, boxmins, shiftstart);
697 VectorAdd(end, boxmins, shiftend);
698 Mod_MDLMD2MD3_TraceLine(model, frameblend, skeleton, trace, shiftstart, shiftend, hitsupercontentsmask);
699 VectorSubtract(trace->endpos, boxmins, trace->endpos);
703 // box trace, performed as brush trace
704 memset(trace, 0, sizeof(*trace));
706 trace->realfraction = 1;
707 trace->hitsupercontentsmask = hitsupercontentsmask;
708 if (model->surfmesh.num_vertices > 1024)
709 vertex3f = (float *)Mem_Alloc(tempmempool, model->surfmesh.num_vertices * sizeof(float[3]));
710 segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
711 segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
712 segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
713 segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
714 segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
715 segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
716 VectorAdd(start, boxmins, boxstartmins);
717 VectorAdd(start, boxmaxs, boxstartmaxs);
718 VectorAdd(end, boxmins, boxendmins);
719 VectorAdd(end, boxmaxs, boxendmaxs);
720 Collision_BrushForBox(&thisbrush_start, boxstartmins, boxstartmaxs, 0, 0, NULL);
721 Collision_BrushForBox(&thisbrush_end, boxendmins, boxendmaxs, 0, 0, NULL);
722 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
723 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
724 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);
725 if (vertex3f != vertex3fbuf)
729 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
732 for (i = 0;i < inverts;i++)
734 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
736 j = vertremap[i]; // not onseam
739 j = vertremap[i+inverts]; // onseam
745 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
747 int i, f, pose, groupframes;
749 daliasframetype_t *pframetype;
750 daliasframe_t *pinframe;
751 daliasgroup_t *group;
752 daliasinterval_t *intervals;
755 scene = loadmodel->animscenes;
756 for (f = 0;f < loadmodel->numframes;f++)
758 pframetype = (daliasframetype_t *)datapointer;
759 datapointer += sizeof(daliasframetype_t);
760 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
762 // a single frame is still treated as a group
769 group = (daliasgroup_t *)datapointer;
770 datapointer += sizeof(daliasgroup_t);
771 groupframes = LittleLong (group->numframes);
773 // intervals (time per frame)
774 intervals = (daliasinterval_t *)datapointer;
775 datapointer += sizeof(daliasinterval_t) * groupframes;
777 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
778 if (interval < 0.01f)
780 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
785 // get scene name from first frame
786 pinframe = (daliasframe_t *)datapointer;
788 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
789 scene->firstframe = pose;
790 scene->framecount = groupframes;
791 scene->framerate = 1.0f / interval;
796 for (i = 0;i < groupframes;i++)
798 datapointer += sizeof(daliasframe_t);
799 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
800 datapointer += sizeof(trivertx_t) * inverts;
806 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
808 if (cls.state == ca_dedicated)
812 skinframe = R_SkinFrame_LoadMissing();
813 memset(texture, 0, sizeof(*texture));
814 texture->currentframe = texture;
815 //texture->animated = false;
816 texture->numskinframes = 1;
817 texture->skinframerate = 1;
818 texture->skinframes[0] = skinframe;
819 texture->currentskinframe = skinframe;
820 //texture->backgroundnumskinframes = 0;
821 //texture->customblendfunc[0] = 0;
822 //texture->customblendfunc[1] = 0;
823 //texture->surfaceflags = 0;
824 //texture->supercontents = 0;
825 //texture->surfaceparms = 0;
826 //texture->textureflags = 0;
828 texture->basematerialflags = MATERIALFLAG_WALL;
829 if (texture->currentskinframe->hasalpha)
830 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
831 texture->currentmaterialflags = texture->basematerialflags;
832 texture->offsetmapping = OFFSETMAPPING_DEFAULT;
833 texture->offsetscale = 1;
834 texture->offsetbias = 0;
835 texture->specularscalemod = 1;
836 texture->specularpowermod = 1;
837 texture->surfaceflags = 0;
838 texture->supercontents = SUPERCONTENTS_SOLID;
839 if (!(texture->basematerialflags & MATERIALFLAG_BLENDED))
840 texture->supercontents |= SUPERCONTENTS_OPAQUE;
841 texture->transparentsort = TRANSPARENTSORT_DISTANCE;
842 // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
843 // JUST GREP FOR "specularscalemod = 1".
846 void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
849 char stripbuf[MAX_QPATH];
850 skinfileitem_t *skinfileitem;
851 if(developer_extra.integer)
852 Con_DPrintf("Looking up texture for %s (default: %s)\n", meshname, shadername);
855 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
856 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
858 memset(skin, 0, sizeof(*skin));
860 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
862 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
863 if (!strcmp(skinfileitem->name, meshname))
865 Image_StripImageExtension(skinfileitem->replacement, stripbuf, sizeof(stripbuf));
866 if(developer_extra.integer)
867 Con_DPrintf("--> got %s from skin file\n", stripbuf);
868 Mod_LoadTextureFromQ3Shader(skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
874 // don't render unmentioned meshes
875 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
876 if(developer_extra.integer)
877 Con_DPrintf("--> skipping\n");
878 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
884 if(developer_extra.integer)
885 Con_DPrintf("--> using default\n");
886 Image_StripImageExtension(shadername, stripbuf, sizeof(stripbuf));
887 Mod_LoadTextureFromQ3Shader(skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
891 #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);
892 #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);
893 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
895 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
896 float scales, scalet, interval;
900 stvert_t *pinstverts;
901 dtriangle_t *pintriangles;
902 daliasskintype_t *pinskintype;
903 daliasskingroup_t *pinskingroup;
904 daliasskininterval_t *pinskinintervals;
905 daliasframetype_t *pinframetype;
906 daliasgroup_t *pinframegroup;
907 unsigned char *datapointer, *startframes, *startskins;
908 char name[MAX_QPATH];
909 skinframe_t *tempskinframe;
910 animscene_t *tempskinscenes;
911 texture_t *tempaliasskins;
913 int *vertonseam, *vertremap;
914 skinfile_t *skinfiles;
917 datapointer = (unsigned char *)buffer;
918 pinmodel = (mdl_t *)datapointer;
919 datapointer += sizeof(mdl_t);
921 version = LittleLong (pinmodel->version);
922 if (version != ALIAS_VERSION)
923 Host_Error ("%s has wrong version number (%i should be %i)",
924 loadmodel->name, version, ALIAS_VERSION);
926 loadmodel->modeldatatypestring = "MDL";
928 loadmodel->type = mod_alias;
929 loadmodel->DrawSky = NULL;
930 loadmodel->DrawAddWaterPlanes = NULL;
931 loadmodel->Draw = R_Q1BSP_Draw;
932 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
933 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
934 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
935 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
936 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
937 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
938 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
939 loadmodel->DrawLight = R_Q1BSP_DrawLight;
940 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
941 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
942 // FIXME add TraceBrush!
943 loadmodel->PointSuperContents = NULL;
944 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
946 loadmodel->num_surfaces = 1;
947 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
948 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
949 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
950 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
951 loadmodel->sortedmodelsurfaces[0] = 0;
953 loadmodel->numskins = LittleLong(pinmodel->numskins);
954 BOUNDI(loadmodel->numskins,0,65536);
955 skinwidth = LittleLong (pinmodel->skinwidth);
956 BOUNDI(skinwidth,0,65536);
957 skinheight = LittleLong (pinmodel->skinheight);
958 BOUNDI(skinheight,0,65536);
959 numverts = LittleLong(pinmodel->numverts);
960 BOUNDI(numverts,0,65536);
961 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
962 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
963 loadmodel->numframes = LittleLong(pinmodel->numframes);
964 BOUNDI(loadmodel->numframes,0,65536);
965 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
966 BOUNDI((int)loadmodel->synctype,0,2);
967 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
968 i = LittleLong (pinmodel->flags);
969 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
971 for (i = 0;i < 3;i++)
973 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
974 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
977 startskins = datapointer;
979 for (i = 0;i < loadmodel->numskins;i++)
981 pinskintype = (daliasskintype_t *)datapointer;
982 datapointer += sizeof(daliasskintype_t);
983 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
987 pinskingroup = (daliasskingroup_t *)datapointer;
988 datapointer += sizeof(daliasskingroup_t);
989 groupskins = LittleLong(pinskingroup->numskins);
990 datapointer += sizeof(daliasskininterval_t) * groupskins;
993 for (j = 0;j < groupskins;j++)
995 datapointer += skinwidth * skinheight;
1000 pinstverts = (stvert_t *)datapointer;
1001 datapointer += sizeof(stvert_t) * numverts;
1003 pintriangles = (dtriangle_t *)datapointer;
1004 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
1006 startframes = datapointer;
1007 loadmodel->surfmesh.num_morphframes = 0;
1008 for (i = 0;i < loadmodel->numframes;i++)
1010 pinframetype = (daliasframetype_t *)datapointer;
1011 datapointer += sizeof(daliasframetype_t);
1012 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
1016 pinframegroup = (daliasgroup_t *)datapointer;
1017 datapointer += sizeof(daliasgroup_t);
1018 groupframes = LittleLong(pinframegroup->numframes);
1019 datapointer += sizeof(daliasinterval_t) * groupframes;
1022 for (j = 0;j < groupframes;j++)
1024 datapointer += sizeof(daliasframe_t);
1025 datapointer += sizeof(trivertx_t) * numverts;
1026 loadmodel->surfmesh.num_morphframes++;
1029 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1031 // store texture coordinates into temporary array, they will be stored
1032 // after usage is determined (triangle data)
1033 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
1034 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
1035 vertonseam = vertremap + numverts * 2;
1037 scales = 1.0 / skinwidth;
1038 scalet = 1.0 / skinheight;
1039 for (i = 0;i < numverts;i++)
1041 vertonseam[i] = LittleLong(pinstverts[i].onseam);
1042 vertst[i*2+0] = LittleLong(pinstverts[i].s) * scales;
1043 vertst[i*2+1] = LittleLong(pinstverts[i].t) * scalet;
1044 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
1045 vertst[(i+numverts)*2+1] = vertst[i*2+1];
1048 // load triangle data
1049 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1051 // read the triangle elements
1052 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1053 for (j = 0;j < 3;j++)
1054 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1055 // validate (note numverts is used because this is the original data)
1056 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1057 // now butcher the elements according to vertonseam and tri->facesfront
1058 // and then compact the vertex set to remove duplicates
1059 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1060 if (!LittleLong(pintriangles[i].facesfront)) // backface
1061 for (j = 0;j < 3;j++)
1062 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1063 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1065 // (this uses vertremap to count usage to save some memory)
1066 for (i = 0;i < numverts*2;i++)
1068 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1069 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1070 // build remapping table and compact array
1071 loadmodel->surfmesh.num_vertices = 0;
1072 for (i = 0;i < numverts*2;i++)
1076 vertremap[i] = loadmodel->surfmesh.num_vertices;
1077 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1078 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1079 loadmodel->surfmesh.num_vertices++;
1082 vertremap[i] = -1; // not used at all
1084 // remap the elements to the new vertex set
1085 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1086 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1087 // store the texture coordinates
1088 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1089 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1091 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1092 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1095 // generate ushort elements array if possible
1096 if (loadmodel->surfmesh.num_vertices <= 65536)
1097 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1098 if (loadmodel->surfmesh.data_element3s)
1099 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1100 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1103 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1104 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1105 if (r_enableshadowvolumes.integer)
1107 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1109 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1110 if (loadmodel->surfmesh.data_neighbor3i)
1111 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1112 loadmodel->surfmesh.isanimated = Mod_Alias_CalculateBoundingBox();
1113 Mod_Alias_MorphMesh_CompileFrames();
1116 Mem_Free(vertremap);
1119 skinfiles = Mod_LoadSkinFiles();
1122 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1123 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1124 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1125 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1126 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1127 Mod_FreeSkinFiles(skinfiles);
1128 for (i = 0;i < loadmodel->numskins;i++)
1130 loadmodel->skinscenes[i].firstframe = i;
1131 loadmodel->skinscenes[i].framecount = 1;
1132 loadmodel->skinscenes[i].loop = true;
1133 loadmodel->skinscenes[i].framerate = 10;
1138 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1139 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1140 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1141 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1143 datapointer = startskins;
1144 for (i = 0;i < loadmodel->numskins;i++)
1146 pinskintype = (daliasskintype_t *)datapointer;
1147 datapointer += sizeof(daliasskintype_t);
1149 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1156 pinskingroup = (daliasskingroup_t *)datapointer;
1157 datapointer += sizeof(daliasskingroup_t);
1159 groupskins = LittleLong (pinskingroup->numskins);
1161 pinskinintervals = (daliasskininterval_t *)datapointer;
1162 datapointer += sizeof(daliasskininterval_t) * groupskins;
1164 interval = LittleFloat(pinskinintervals[0].interval);
1165 if (interval < 0.01f)
1167 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1172 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1173 loadmodel->skinscenes[i].firstframe = totalskins;
1174 loadmodel->skinscenes[i].framecount = groupskins;
1175 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1176 loadmodel->skinscenes[i].loop = true;
1178 for (j = 0;j < groupskins;j++)
1181 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1183 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1184 if (!Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, name, false, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS))
1185 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, R_SkinFrame_LoadInternalQuake(name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP, true, r_fullbrights.integer, (unsigned char *)datapointer, skinwidth, skinheight));
1186 datapointer += skinwidth * skinheight;
1190 // check for skins that don't exist in the model, but do exist as external images
1191 // (this was added because yummyluv kept pestering me about support for it)
1192 // TODO: support shaders here?
1193 while ((tempskinframe = R_SkinFrame_LoadExternal(va(vabuf, sizeof(vabuf), "%s_%i", loadmodel->name, loadmodel->numskins), (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS, false)))
1195 // expand the arrays to make room
1196 tempskinscenes = loadmodel->skinscenes;
1197 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1198 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1199 Mem_Free(tempskinscenes);
1201 tempaliasskins = loadmodel->data_textures;
1202 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1203 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1204 Mem_Free(tempaliasskins);
1206 // store the info about the new skin
1207 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1208 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1209 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1210 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1211 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1212 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1214 //increase skin counts
1215 loadmodel->numskins++;
1218 // fix up the pointers since they are pointing at the old textures array
1219 // FIXME: this is a hack!
1220 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1221 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1225 surface = loadmodel->data_surfaces;
1226 surface->texture = loadmodel->data_textures;
1227 surface->num_firsttriangle = 0;
1228 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1229 surface->num_firstvertex = 0;
1230 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1232 if(mod_alias_force_animated.string[0])
1233 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
1235 if (!loadmodel->surfmesh.isanimated)
1237 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1238 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1239 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1240 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1241 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1242 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1245 // because shaders can do somewhat unexpected things, check for unusual features now
1246 for (i = 0;i < loadmodel->num_textures;i++)
1248 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
1249 mod->DrawSky = R_Q1BSP_DrawSky;
1250 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
1251 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
1255 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1257 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1258 float iskinwidth, iskinheight;
1259 unsigned char *data;
1260 msurface_t *surface;
1262 unsigned char *base, *datapointer;
1263 md2frame_t *pinframe;
1265 md2triangle_t *intri;
1266 unsigned short *inst;
1267 struct md2verthash_s
1269 struct md2verthash_s *next;
1273 *hash, **md2verthash, *md2verthashdata;
1274 skinfile_t *skinfiles;
1276 pinmodel = (md2_t *)buffer;
1277 base = (unsigned char *)buffer;
1279 version = LittleLong (pinmodel->version);
1280 if (version != MD2ALIAS_VERSION)
1281 Host_Error ("%s has wrong version number (%i should be %i)",
1282 loadmodel->name, version, MD2ALIAS_VERSION);
1284 loadmodel->modeldatatypestring = "MD2";
1286 loadmodel->type = mod_alias;
1287 loadmodel->DrawSky = NULL;
1288 loadmodel->DrawAddWaterPlanes = NULL;
1289 loadmodel->Draw = R_Q1BSP_Draw;
1290 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1291 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1292 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1293 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1294 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1295 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1296 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1297 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1298 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1299 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1300 loadmodel->PointSuperContents = NULL;
1301 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1303 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1304 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1305 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1306 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1307 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1308 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1309 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1310 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1312 end = LittleLong(pinmodel->ofs_end);
1313 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1314 Host_Error ("%s is not a valid model", loadmodel->name);
1315 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1316 Host_Error ("%s is not a valid model", loadmodel->name);
1317 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1318 Host_Error ("%s is not a valid model", loadmodel->name);
1319 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1320 Host_Error ("%s is not a valid model", loadmodel->name);
1321 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1322 Host_Error ("%s is not a valid model", loadmodel->name);
1324 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1325 numxyz = LittleLong(pinmodel->num_xyz);
1326 numst = LittleLong(pinmodel->num_st);
1327 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1328 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1329 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1330 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1331 skinwidth = LittleLong(pinmodel->skinwidth);
1332 skinheight = LittleLong(pinmodel->skinheight);
1333 iskinwidth = 1.0f / skinwidth;
1334 iskinheight = 1.0f / skinheight;
1336 loadmodel->num_surfaces = 1;
1337 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1338 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]) + (r_enableshadowvolumes.integer ? loadmodel->surfmesh.num_triangles * sizeof(int[3]) : 0));
1339 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1340 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1341 loadmodel->sortedmodelsurfaces[0] = 0;
1342 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1343 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1344 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1345 if (r_enableshadowvolumes.integer)
1347 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1350 loadmodel->synctype = ST_RAND;
1353 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1354 skinfiles = Mod_LoadSkinFiles();
1357 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1358 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1359 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1360 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1361 Mod_FreeSkinFiles(skinfiles);
1363 else if (loadmodel->numskins)
1365 // skins found (most likely not a player model)
1366 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1367 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1368 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1369 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1370 Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
1374 // no skins (most likely a player model)
1375 loadmodel->numskins = 1;
1376 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1377 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1378 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1379 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1382 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1383 for (i = 0;i < loadmodel->numskins;i++)
1385 loadmodel->skinscenes[i].firstframe = i;
1386 loadmodel->skinscenes[i].framecount = 1;
1387 loadmodel->skinscenes[i].loop = true;
1388 loadmodel->skinscenes[i].framerate = 10;
1391 // load the triangles and stvert data
1392 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1393 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1394 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1395 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1396 // swap the triangle list
1397 loadmodel->surfmesh.num_vertices = 0;
1398 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1400 for (j = 0;j < 3;j++)
1402 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1403 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1406 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1411 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1414 hashindex = (xyz * 256 + st) & 65535;
1415 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1416 if (hash->xyz == xyz && hash->st == st)
1420 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1423 hash->next = md2verthash[hashindex];
1424 md2verthash[hashindex] = hash;
1426 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1430 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1431 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));
1432 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1433 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1434 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1437 hash = md2verthashdata + i;
1438 vertremap[i] = hash->xyz;
1439 sts = LittleShort(inst[hash->st*2+0]);
1440 stt = LittleShort(inst[hash->st*2+1]);
1441 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1443 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1447 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1448 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1451 Mem_Free(md2verthash);
1452 Mem_Free(md2verthashdata);
1454 // generate ushort elements array if possible
1455 if (loadmodel->surfmesh.num_vertices <= 65536)
1456 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1457 if (loadmodel->surfmesh.data_element3s)
1458 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1459 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1462 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1463 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1468 pinframe = (md2frame_t *)datapointer;
1469 datapointer += sizeof(md2frame_t);
1470 // store the frame scale/translate into the appropriate array
1471 for (j = 0;j < 3;j++)
1473 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1474 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1476 // convert the vertices
1477 v = (trivertx_t *)datapointer;
1478 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1479 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1480 out[k] = v[vertremap[k]];
1481 datapointer += numxyz * sizeof(trivertx_t);
1483 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1484 loadmodel->animscenes[i].firstframe = i;
1485 loadmodel->animscenes[i].framecount = 1;
1486 loadmodel->animscenes[i].framerate = 10;
1487 loadmodel->animscenes[i].loop = true;
1490 Mem_Free(vertremap);
1492 if (loadmodel->surfmesh.data_neighbor3i)
1493 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1494 loadmodel->surfmesh.isanimated = Mod_Alias_CalculateBoundingBox();
1495 Mod_Alias_MorphMesh_CompileFrames();
1496 if(mod_alias_force_animated.string[0])
1497 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
1499 surface = loadmodel->data_surfaces;
1500 surface->texture = loadmodel->data_textures;
1501 surface->num_firsttriangle = 0;
1502 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1503 surface->num_firstvertex = 0;
1504 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1506 if (!loadmodel->surfmesh.isanimated)
1508 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1509 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1510 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1511 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1512 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1513 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1516 // because shaders can do somewhat unexpected things, check for unusual features now
1517 for (i = 0;i < loadmodel->num_textures;i++)
1519 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
1520 mod->DrawSky = R_Q1BSP_DrawSky;
1521 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
1522 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
1526 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1528 int i, j, k, version, meshvertices, meshtriangles;
1529 unsigned char *data;
1530 msurface_t *surface;
1531 md3modelheader_t *pinmodel;
1532 md3frameinfo_t *pinframe;
1535 skinfile_t *skinfiles;
1537 pinmodel = (md3modelheader_t *)buffer;
1539 if (memcmp(pinmodel->identifier, "IDP3", 4))
1540 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1541 version = LittleLong (pinmodel->version);
1542 if (version != MD3VERSION)
1543 Host_Error ("%s has wrong version number (%i should be %i)",
1544 loadmodel->name, version, MD3VERSION);
1546 skinfiles = Mod_LoadSkinFiles();
1547 if (loadmodel->numskins < 1)
1548 loadmodel->numskins = 1;
1550 loadmodel->modeldatatypestring = "MD3";
1552 loadmodel->type = mod_alias;
1553 loadmodel->DrawSky = NULL;
1554 loadmodel->DrawAddWaterPlanes = NULL;
1555 loadmodel->Draw = R_Q1BSP_Draw;
1556 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1557 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1558 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1559 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1560 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1561 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1562 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1563 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1564 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1565 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1566 loadmodel->PointSuperContents = NULL;
1567 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1568 loadmodel->synctype = ST_RAND;
1569 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1570 i = LittleLong (pinmodel->flags);
1571 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1573 // set up some global info about the model
1574 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1575 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1577 // make skinscenes for the skins (no groups)
1578 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1579 for (i = 0;i < loadmodel->numskins;i++)
1581 loadmodel->skinscenes[i].firstframe = i;
1582 loadmodel->skinscenes[i].framecount = 1;
1583 loadmodel->skinscenes[i].loop = true;
1584 loadmodel->skinscenes[i].framerate = 10;
1588 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1589 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1591 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1592 loadmodel->animscenes[i].firstframe = i;
1593 loadmodel->animscenes[i].framecount = 1;
1594 loadmodel->animscenes[i].framerate = 10;
1595 loadmodel->animscenes[i].loop = true;
1599 loadmodel->num_tagframes = loadmodel->numframes;
1600 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1601 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1602 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1604 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1605 for (j = 0;j < 9;j++)
1606 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1607 for (j = 0;j < 3;j++)
1608 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1609 //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);
1615 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)))
1617 if (memcmp(pinmesh->identifier, "IDP3", 4))
1618 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1619 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1620 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1621 meshvertices += LittleLong(pinmesh->num_vertices);
1622 meshtriangles += LittleLong(pinmesh->num_triangles);
1625 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1626 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1627 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1628 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]) + (r_enableshadowvolumes.integer ? meshtriangles * sizeof(int[3]) : 0) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshvertices * sizeof(float[2]) + meshvertices * loadmodel->numframes * sizeof(md3vertex_t));
1629 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1630 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1631 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1632 loadmodel->surfmesh.num_vertices = meshvertices;
1633 loadmodel->surfmesh.num_triangles = meshtriangles;
1634 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1635 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1636 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1637 if (r_enableshadowvolumes.integer)
1639 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1641 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1642 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1643 if (meshvertices <= 65536)
1645 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1650 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)))
1652 if (memcmp(pinmesh->identifier, "IDP3", 4))
1653 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1654 loadmodel->sortedmodelsurfaces[i] = i;
1655 surface = loadmodel->data_surfaces + i;
1656 surface->texture = loadmodel->data_textures + i;
1657 surface->num_firsttriangle = meshtriangles;
1658 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1659 surface->num_firstvertex = meshvertices;
1660 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1661 meshvertices += surface->num_vertices;
1662 meshtriangles += surface->num_triangles;
1664 for (j = 0;j < surface->num_triangles * 3;j++)
1665 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1666 for (j = 0;j < surface->num_vertices;j++)
1668 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1669 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1671 for (j = 0;j < loadmodel->numframes;j++)
1673 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1674 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1675 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1677 out->origin[0] = LittleShort(in->origin[0]);
1678 out->origin[1] = LittleShort(in->origin[1]);
1679 out->origin[2] = LittleShort(in->origin[2]);
1680 out->pitch = in->pitch;
1685 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1687 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1689 if (loadmodel->surfmesh.data_element3s)
1690 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1691 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1692 if (loadmodel->surfmesh.data_neighbor3i)
1693 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1694 Mod_Alias_MorphMesh_CompileFrames();
1695 loadmodel->surfmesh.isanimated = Mod_Alias_CalculateBoundingBox();
1696 Mod_FreeSkinFiles(skinfiles);
1697 Mod_MakeSortedSurfaces(loadmodel);
1698 if(mod_alias_force_animated.string[0])
1699 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
1701 if (!loadmodel->surfmesh.isanimated)
1703 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1704 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1705 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1706 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1707 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1708 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1711 // because shaders can do somewhat unexpected things, check for unusual features now
1712 for (i = 0;i < loadmodel->num_textures;i++)
1714 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
1715 mod->DrawSky = R_Q1BSP_DrawSky;
1716 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
1717 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
1721 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1723 zymtype1header_t *pinmodel, *pheader;
1724 unsigned char *pbase;
1725 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1726 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose, f, biggestorigin, tempvec[3], modelscale;
1727 zymvertex_t *verts, *vertdata;
1731 skinfile_t *skinfiles;
1732 unsigned char *data;
1733 msurface_t *surface;
1735 pinmodel = (zymtype1header_t *)buffer;
1736 pbase = (unsigned char *)buffer;
1737 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1738 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1739 if (BigLong(pinmodel->type) != 1)
1740 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1742 loadmodel->modeldatatypestring = "ZYM";
1744 loadmodel->type = mod_alias;
1745 loadmodel->synctype = ST_RAND;
1749 pheader->type = BigLong(pinmodel->type);
1750 pheader->filesize = BigLong(pinmodel->filesize);
1751 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1752 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1753 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1754 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1755 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1756 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1757 pheader->radius = BigFloat(pinmodel->radius);
1758 pheader->numverts = BigLong(pinmodel->numverts);
1759 pheader->numtris = BigLong(pinmodel->numtris);
1760 pheader->numshaders = BigLong(pinmodel->numshaders);
1761 pheader->numbones = BigLong(pinmodel->numbones);
1762 pheader->numscenes = BigLong(pinmodel->numscenes);
1763 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1764 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1765 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1766 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1767 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1768 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1769 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1770 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1771 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1772 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1773 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1774 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1775 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1776 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1777 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1778 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1779 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1780 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1782 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1784 Con_Printf("%s has no geometry\n", loadmodel->name);
1787 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1789 Con_Printf("%s has no animations\n", loadmodel->name);
1793 loadmodel->DrawSky = NULL;
1794 loadmodel->DrawAddWaterPlanes = NULL;
1795 loadmodel->Draw = R_Q1BSP_Draw;
1796 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1797 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1798 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1799 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1800 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1801 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1802 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1803 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1804 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1805 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1806 loadmodel->PointSuperContents = NULL;
1807 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1809 loadmodel->numframes = pheader->numscenes;
1810 loadmodel->num_surfaces = pheader->numshaders;
1812 skinfiles = Mod_LoadSkinFiles();
1813 if (loadmodel->numskins < 1)
1814 loadmodel->numskins = 1;
1816 // make skinscenes for the skins (no groups)
1817 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1818 for (i = 0;i < loadmodel->numskins;i++)
1820 loadmodel->skinscenes[i].firstframe = i;
1821 loadmodel->skinscenes[i].framecount = 1;
1822 loadmodel->skinscenes[i].loop = true;
1823 loadmodel->skinscenes[i].framerate = 10;
1827 // LordHavoc: actually we blow this away later with Mod_Alias_CalculateBoundingBox()
1828 modelradius = pheader->radius;
1829 for (i = 0;i < 3;i++)
1831 loadmodel->normalmins[i] = pheader->mins[i];
1832 loadmodel->normalmaxs[i] = pheader->maxs[i];
1833 loadmodel->rotatedmins[i] = -modelradius;
1834 loadmodel->rotatedmaxs[i] = modelradius;
1836 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1837 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1838 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1839 if (loadmodel->yawmaxs[0] > modelradius)
1840 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1841 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1842 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1843 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1844 loadmodel->radius = modelradius;
1845 loadmodel->radius2 = modelradius * modelradius;
1847 // go through the lumps, swapping things
1849 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1850 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1851 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1852 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1853 for (i = 0;i < pheader->numscenes;i++)
1855 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1856 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1857 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1858 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1859 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1860 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1861 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1862 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1863 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1864 if (loadmodel->animscenes[i].framerate < 0)
1865 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1869 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1870 loadmodel->num_bones = pheader->numbones;
1871 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1872 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1873 for (i = 0;i < pheader->numbones;i++)
1875 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1876 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1877 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1878 if (loadmodel->data_bones[i].parent >= i)
1879 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1882 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1883 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1884 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1885 for (i = 0;i < pheader->numverts;i++)
1887 vertbonecounts[i] = BigLong(bonecount[i]);
1888 if (vertbonecounts[i] != 1)
1889 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1892 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1894 meshvertices = pheader->numverts;
1895 meshtriangles = pheader->numtris;
1897 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1898 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1899 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1900 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]) + (r_enableshadowvolumes.integer ? meshtriangles * sizeof(int[3]) : 0) + (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]));
1901 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1902 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1903 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1904 loadmodel->surfmesh.num_vertices = meshvertices;
1905 loadmodel->surfmesh.num_triangles = meshtriangles;
1906 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1907 if (r_enableshadowvolumes.integer)
1909 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1911 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1912 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1913 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1914 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1915 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1916 loadmodel->surfmesh.data_skeletalindex4ub = (unsigned char *)data;data += meshvertices * sizeof(unsigned char[4]);
1917 loadmodel->surfmesh.data_skeletalweight4ub = (unsigned char *)data;data += meshvertices * sizeof(unsigned char[4]);
1918 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1919 loadmodel->surfmesh.num_blends = 0;
1920 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
1921 if (loadmodel->surfmesh.num_vertices <= 65536)
1923 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1925 loadmodel->data_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
1926 loadmodel->surfmesh.data_blendweights = NULL;
1928 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1929 poses = (float *) (pheader->lump_poses.start + pbase);
1930 // figure out scale of model from root bone, for compatibility with old zmodel versions
1931 tempvec[0] = BigFloat(poses[0]);
1932 tempvec[1] = BigFloat(poses[1]);
1933 tempvec[2] = BigFloat(poses[2]);
1934 modelscale = VectorLength(tempvec);
1936 for (i = 0;i < loadmodel->num_bones * numposes * 12;i++)
1938 f = fabs(BigFloat(poses[i]));
1939 biggestorigin = max(biggestorigin, f);
1941 loadmodel->num_posescale = biggestorigin / 32767.0f;
1942 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
1943 for (i = 0;i < numposes;i++)
1945 const float *frameposes = (float *) (pheader->lump_poses.start + pbase) + 12*i*loadmodel->num_bones;
1946 for (j = 0;j < loadmodel->num_bones;j++)
1949 matrix4x4_t posematrix;
1950 for (k = 0;k < 12;k++)
1951 pose[k] = BigFloat(frameposes[j*12+k]);
1952 //if (j < loadmodel->num_bones)
1953 // 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));
1954 // scale child bones to match the root scale
1955 if (loadmodel->data_bones[j].parent >= 0)
1957 pose[3] *= modelscale;
1958 pose[7] *= modelscale;
1959 pose[11] *= modelscale;
1961 // normalize rotation matrix
1962 VectorNormalize(pose + 0);
1963 VectorNormalize(pose + 4);
1964 VectorNormalize(pose + 8);
1965 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
1966 Matrix4x4_ToBonePose7s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses7s + 7*(i*loadmodel->num_bones+j));
1970 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1971 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1972 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1973 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1974 // (converting from weight-blending skeletal animation to
1975 // deformation-based skeletal animation)
1976 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1977 for (i = 0;i < loadmodel->num_bones;i++)
1980 for (k = 0;k < 12;k++)
1981 m[k] = BigFloat(poses[i*12+k]);
1982 if (loadmodel->data_bones[i].parent >= 0)
1983 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1985 for (k = 0;k < 12;k++)
1986 bonepose[12*i+k] = m[k];
1988 for (j = 0;j < pheader->numverts;j++)
1990 // this format really should have had a per vertexweight weight value...
1991 // but since it does not, the weighting is completely ignored and
1992 // only one weight is allowed per vertex
1993 int boneindex = BigLong(vertdata[j].bonenum);
1994 const float *m = bonepose + 12 * boneindex;
1995 float relativeorigin[3];
1996 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1997 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1998 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1999 // transform the vertex bone weight into the base mesh
2000 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
2001 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
2002 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
2003 // store the weight as the primary weight on this vertex
2004 loadmodel->surfmesh.blends[j] = boneindex;
2005 loadmodel->surfmesh.data_skeletalindex4ub[j*4 ] = boneindex;
2006 loadmodel->surfmesh.data_skeletalindex4ub[j*4+1] = 0;
2007 loadmodel->surfmesh.data_skeletalindex4ub[j*4+2] = 0;
2008 loadmodel->surfmesh.data_skeletalindex4ub[j*4+3] = 0;
2009 loadmodel->surfmesh.data_skeletalweight4ub[j*4 ] = 255;
2010 loadmodel->surfmesh.data_skeletalweight4ub[j*4+1] = 0;
2011 loadmodel->surfmesh.data_skeletalweight4ub[j*4+2] = 0;
2012 loadmodel->surfmesh.data_skeletalweight4ub[j*4+3] = 0;
2015 // normals and tangents are calculated after elements are loaded
2017 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
2018 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
2019 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
2020 for (i = 0;i < pheader->numverts;i++)
2022 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
2023 // flip T coordinate for OpenGL
2024 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
2027 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
2028 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
2029 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
2031 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
2032 //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)
2033 // byteswap, validate, and swap winding order of tris
2034 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
2035 if (pheader->lump_render.length != count)
2036 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
2037 renderlist = (int *) (pheader->lump_render.start + pbase);
2038 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
2040 for (i = 0;i < loadmodel->num_surfaces;i++)
2042 int firstvertex, lastvertex;
2043 if (renderlist >= renderlistend)
2044 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2045 count = BigLong(*renderlist);renderlist++;
2046 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
2047 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2049 loadmodel->sortedmodelsurfaces[i] = i;
2050 surface = loadmodel->data_surfaces + i;
2051 surface->texture = loadmodel->data_textures + i;
2052 surface->num_firsttriangle = meshtriangles;
2053 surface->num_triangles = count;
2054 meshtriangles += surface->num_triangles;
2056 // load the elements
2057 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2058 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
2060 outelements[j*3+2] = BigLong(renderlist[0]);
2061 outelements[j*3+1] = BigLong(renderlist[1]);
2062 outelements[j*3+0] = BigLong(renderlist[2]);
2064 // validate the elements and find the used vertex range
2065 firstvertex = meshvertices;
2067 for (j = 0;j < surface->num_triangles * 3;j++)
2069 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
2070 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
2071 firstvertex = min(firstvertex, outelements[j]);
2072 lastvertex = max(lastvertex, outelements[j]);
2074 surface->num_firstvertex = firstvertex;
2075 surface->num_vertices = lastvertex + 1 - firstvertex;
2077 // since zym models do not have named sections, reuse their shader
2078 // name as the section name
2079 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
2080 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
2082 Mod_FreeSkinFiles(skinfiles);
2083 Mem_Free(vertbonecounts);
2085 Mod_MakeSortedSurfaces(loadmodel);
2087 // compute all the mesh information that was not loaded from the file
2088 if (loadmodel->surfmesh.data_element3s)
2089 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2090 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2091 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2092 Mod_BuildBaseBonePoses();
2093 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);
2094 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);
2095 if (loadmodel->surfmesh.data_neighbor3i)
2096 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2097 loadmodel->surfmesh.isanimated = Mod_Alias_CalculateBoundingBox();
2098 if(mod_alias_force_animated.string[0])
2099 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
2101 if (!loadmodel->surfmesh.isanimated)
2103 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2104 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2105 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2106 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2107 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2108 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2111 // because shaders can do somewhat unexpected things, check for unusual features now
2112 for (i = 0;i < loadmodel->num_textures;i++)
2114 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
2115 mod->DrawSky = R_Q1BSP_DrawSky;
2116 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
2117 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
2121 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2123 dpmheader_t *pheader;
2127 unsigned char *pbase;
2128 int i, j, k, meshvertices, meshtriangles;
2129 skinfile_t *skinfiles;
2130 unsigned char *data;
2132 float biggestorigin, tempvec[3], modelscale;
2136 pheader = (dpmheader_t *)buffer;
2137 pbase = (unsigned char *)buffer;
2138 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2139 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2140 if (BigLong(pheader->type) != 2)
2141 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2143 loadmodel->modeldatatypestring = "DPM";
2145 loadmodel->type = mod_alias;
2146 loadmodel->synctype = ST_RAND;
2149 pheader->type = BigLong(pheader->type);
2150 pheader->filesize = BigLong(pheader->filesize);
2151 pheader->mins[0] = BigFloat(pheader->mins[0]);
2152 pheader->mins[1] = BigFloat(pheader->mins[1]);
2153 pheader->mins[2] = BigFloat(pheader->mins[2]);
2154 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2155 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2156 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2157 pheader->yawradius = BigFloat(pheader->yawradius);
2158 pheader->allradius = BigFloat(pheader->allradius);
2159 pheader->num_bones = BigLong(pheader->num_bones);
2160 pheader->num_meshs = BigLong(pheader->num_meshs);
2161 pheader->num_frames = BigLong(pheader->num_frames);
2162 pheader->ofs_bones = BigLong(pheader->ofs_bones);
2163 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2164 pheader->ofs_frames = BigLong(pheader->ofs_frames);
2166 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2168 Con_Printf("%s has no geometry\n", loadmodel->name);
2171 if (pheader->num_frames < 1)
2173 Con_Printf("%s has no frames\n", loadmodel->name);
2177 loadmodel->DrawSky = NULL;
2178 loadmodel->DrawAddWaterPlanes = NULL;
2179 loadmodel->Draw = R_Q1BSP_Draw;
2180 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2181 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2182 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2183 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2184 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2185 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2186 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2187 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2188 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2189 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2190 loadmodel->PointSuperContents = NULL;
2191 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2194 // LordHavoc: actually we blow this away later with Mod_Alias_CalculateBoundingBox()
2195 for (i = 0;i < 3;i++)
2197 loadmodel->normalmins[i] = pheader->mins[i];
2198 loadmodel->normalmaxs[i] = pheader->maxs[i];
2199 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2200 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2201 loadmodel->rotatedmins[i] = -pheader->allradius;
2202 loadmodel->rotatedmaxs[i] = pheader->allradius;
2204 loadmodel->radius = pheader->allradius;
2205 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2207 // load external .skin files if present
2208 skinfiles = Mod_LoadSkinFiles();
2209 if (loadmodel->numskins < 1)
2210 loadmodel->numskins = 1;
2215 // gather combined statistics from the meshes
2216 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2217 for (i = 0;i < (int)pheader->num_meshs;i++)
2219 int numverts = BigLong(dpmmesh->num_verts);
2220 meshvertices += numverts;
2221 meshtriangles += BigLong(dpmmesh->num_tris);
2225 loadmodel->numframes = pheader->num_frames;
2226 loadmodel->num_bones = pheader->num_bones;
2227 loadmodel->num_poses = loadmodel->numframes;
2228 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2229 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2230 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2231 // do most allocations as one merged chunk
2232 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) + (r_enableshadowvolumes.integer ? meshtriangles * sizeof(int[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));
2233 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2234 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2235 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2236 loadmodel->surfmesh.num_vertices = meshvertices;
2237 loadmodel->surfmesh.num_triangles = meshtriangles;
2238 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2239 if (r_enableshadowvolumes.integer)
2241 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2243 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2244 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2245 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2246 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2247 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2248 loadmodel->surfmesh.data_skeletalindex4ub = (unsigned char *)data;data += meshvertices * sizeof(unsigned char[4]);
2249 loadmodel->surfmesh.data_skeletalweight4ub = (unsigned char *)data;data += meshvertices * sizeof(unsigned char[4]);
2250 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2251 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2252 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2253 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2254 loadmodel->surfmesh.num_blends = 0;
2255 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2256 if (meshvertices <= 65536)
2258 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2260 loadmodel->data_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
2261 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
2263 for (i = 0;i < loadmodel->numskins;i++)
2265 loadmodel->skinscenes[i].firstframe = i;
2266 loadmodel->skinscenes[i].framecount = 1;
2267 loadmodel->skinscenes[i].loop = true;
2268 loadmodel->skinscenes[i].framerate = 10;
2271 // load the bone info
2272 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2273 for (i = 0;i < loadmodel->num_bones;i++)
2275 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2276 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2277 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2278 if (loadmodel->data_bones[i].parent >= i)
2279 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2283 frames = (dpmframe_t *) (pbase + pheader->ofs_frames);
2284 // figure out scale of model from root bone, for compatibility with old dpmodel versions
2285 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2286 tempvec[0] = BigFloat(poses[0]);
2287 tempvec[1] = BigFloat(poses[1]);
2288 tempvec[2] = BigFloat(poses[2]);
2289 modelscale = VectorLength(tempvec);
2291 for (i = 0;i < loadmodel->numframes;i++)
2293 memcpy(loadmodel->animscenes[i].name, frames[i].name, sizeof(frames[i].name));
2294 loadmodel->animscenes[i].firstframe = i;
2295 loadmodel->animscenes[i].framecount = 1;
2296 loadmodel->animscenes[i].loop = true;
2297 loadmodel->animscenes[i].framerate = 10;
2298 // load the bone poses for this frame
2299 poses = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2300 for (j = 0;j < loadmodel->num_bones*12;j++)
2302 f = fabs(BigFloat(poses[j]));
2303 biggestorigin = max(biggestorigin, f);
2305 // stuff not processed here: mins, maxs, yawradius, allradius
2307 loadmodel->num_posescale = biggestorigin / 32767.0f;
2308 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2309 for (i = 0;i < loadmodel->numframes;i++)
2311 const float *frameposes = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2312 for (j = 0;j < loadmodel->num_bones;j++)
2315 matrix4x4_t posematrix;
2316 for (k = 0;k < 12;k++)
2317 pose[k] = BigFloat(frameposes[j*12+k]);
2318 // scale child bones to match the root scale
2319 if (loadmodel->data_bones[j].parent >= 0)
2321 pose[3] *= modelscale;
2322 pose[7] *= modelscale;
2323 pose[11] *= modelscale;
2325 // normalize rotation matrix
2326 VectorNormalize(pose + 0);
2327 VectorNormalize(pose + 4);
2328 VectorNormalize(pose + 8);
2329 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2330 Matrix4x4_ToBonePose7s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses7s + 7*(i*loadmodel->num_bones+j));
2334 // load the meshes now
2335 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2338 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2339 // (converting from weight-blending skeletal animation to
2340 // deformation-based skeletal animation)
2341 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2342 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2343 for (i = 0;i < loadmodel->num_bones;i++)
2346 for (k = 0;k < 12;k++)
2347 m[k] = BigFloat(poses[i*12+k]);
2348 if (loadmodel->data_bones[i].parent >= 0)
2349 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2351 for (k = 0;k < 12;k++)
2352 bonepose[12*i+k] = m[k];
2354 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2356 const int *inelements;
2358 const float *intexcoord;
2359 msurface_t *surface;
2361 loadmodel->sortedmodelsurfaces[i] = i;
2362 surface = loadmodel->data_surfaces + i;
2363 surface->texture = loadmodel->data_textures + i;
2364 surface->num_firsttriangle = meshtriangles;
2365 surface->num_triangles = BigLong(dpmmesh->num_tris);
2366 surface->num_firstvertex = meshvertices;
2367 surface->num_vertices = BigLong(dpmmesh->num_verts);
2368 meshvertices += surface->num_vertices;
2369 meshtriangles += surface->num_triangles;
2371 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2372 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2373 for (j = 0;j < surface->num_triangles;j++)
2375 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2376 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2377 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2378 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2383 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2384 for (j = 0;j < surface->num_vertices*2;j++)
2385 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2387 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2388 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2390 int weightindex[4] = { 0, 0, 0, 0 };
2391 float weightinfluence[4] = { 0, 0, 0, 0 };
2393 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2394 data += sizeof(dpmvertex_t);
2395 for (k = 0;k < numweights;k++)
2397 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2398 int boneindex = BigLong(vert->bonenum);
2399 const float *m = bonepose + 12 * boneindex;
2400 float influence = BigFloat(vert->influence);
2401 float relativeorigin[3], relativenormal[3];
2402 relativeorigin[0] = BigFloat(vert->origin[0]);
2403 relativeorigin[1] = BigFloat(vert->origin[1]);
2404 relativeorigin[2] = BigFloat(vert->origin[2]);
2405 relativenormal[0] = BigFloat(vert->normal[0]);
2406 relativenormal[1] = BigFloat(vert->normal[1]);
2407 relativenormal[2] = BigFloat(vert->normal[2]);
2408 // blend the vertex bone weights into the base mesh
2409 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2410 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2411 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2412 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2413 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2414 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2417 // store the first (and often only) weight
2418 weightinfluence[0] = influence;
2419 weightindex[0] = boneindex;
2423 // sort the new weight into this vertex's weight table
2424 // (which only accepts up to 4 bones per vertex)
2425 for (l = 0;l < 4;l++)
2427 if (weightinfluence[l] < influence)
2429 // move weaker influence weights out of the way first
2431 for (l2 = 3;l2 > l;l2--)
2433 weightinfluence[l2] = weightinfluence[l2-1];
2434 weightindex[l2] = weightindex[l2-1];
2436 // store the new weight
2437 weightinfluence[l] = influence;
2438 weightindex[l] = boneindex;
2443 data += sizeof(dpmbonevert_t);
2445 loadmodel->surfmesh.blends[j] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
2446 loadmodel->surfmesh.data_skeletalindex4ub[j*4 ] = weightindex[0];
2447 loadmodel->surfmesh.data_skeletalindex4ub[j*4+1] = weightindex[1];
2448 loadmodel->surfmesh.data_skeletalindex4ub[j*4+2] = weightindex[2];
2449 loadmodel->surfmesh.data_skeletalindex4ub[j*4+3] = weightindex[3];
2450 loadmodel->surfmesh.data_skeletalweight4ub[j*4 ] = (unsigned char)(weightinfluence[0]*255.0f);
2451 loadmodel->surfmesh.data_skeletalweight4ub[j*4+1] = (unsigned char)(weightinfluence[1]*255.0f);
2452 loadmodel->surfmesh.data_skeletalweight4ub[j*4+2] = (unsigned char)(weightinfluence[2]*255.0f);
2453 loadmodel->surfmesh.data_skeletalweight4ub[j*4+3] = (unsigned char)(weightinfluence[3]*255.0f);
2456 // since dpm models do not have named sections, reuse their shader name as the section name
2457 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2459 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2461 if (loadmodel->surfmesh.num_blends < meshvertices)
2462 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2464 Mod_FreeSkinFiles(skinfiles);
2465 Mod_MakeSortedSurfaces(loadmodel);
2467 // compute all the mesh information that was not loaded from the file
2468 if (loadmodel->surfmesh.data_element3s)
2469 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2470 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2471 Mod_BuildBaseBonePoses();
2472 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);
2473 if (loadmodel->surfmesh.data_neighbor3i)
2474 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2475 loadmodel->surfmesh.isanimated = Mod_Alias_CalculateBoundingBox();
2476 if(mod_alias_force_animated.string[0])
2477 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
2479 if (!loadmodel->surfmesh.isanimated)
2481 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2482 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2483 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2484 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2485 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2486 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2489 // because shaders can do somewhat unexpected things, check for unusual features now
2490 for (i = 0;i < loadmodel->num_textures;i++)
2492 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
2493 mod->DrawSky = R_Q1BSP_DrawSky;
2494 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
2495 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
2499 // no idea why PSK/PSA files contain weird quaternions but they do...
2500 #define PSKQUATNEGATIONS
2501 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2503 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2504 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2505 fs_offset_t filesize;
2510 pskboneinfo_t *bones;
2511 pskrawweights_t *rawweights;
2512 //pskboneinfo_t *animbones;
2513 pskaniminfo_t *anims;
2514 pskanimkeys_t *animkeys;
2515 void *animfilebuffer, *animbuffer, *animbufferend;
2516 unsigned char *data;
2518 skinfile_t *skinfiles;
2519 char animname[MAX_QPATH];
2521 float biggestorigin;
2523 pchunk = (pskchunk_t *)buffer;
2524 if (strcmp(pchunk->id, "ACTRHEAD"))
2525 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2527 loadmodel->modeldatatypestring = "PSK";
2529 loadmodel->type = mod_alias;
2530 loadmodel->DrawSky = NULL;
2531 loadmodel->DrawAddWaterPlanes = NULL;
2532 loadmodel->Draw = R_Q1BSP_Draw;
2533 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2534 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2535 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2536 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2537 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2538 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2539 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2540 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2541 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2542 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2543 loadmodel->PointSuperContents = NULL;
2544 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2545 loadmodel->synctype = ST_RAND;
2547 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2548 strlcat(animname, ".psa", sizeof(animname));
2549 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2550 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2552 animbufferend = animbuffer;
2571 while (buffer < bufferend)
2573 pchunk = (pskchunk_t *)buffer;
2574 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2575 version = LittleLong(pchunk->version);
2576 recordsize = LittleLong(pchunk->recordsize);
2577 numrecords = LittleLong(pchunk->numrecords);
2578 if (developer_extra.integer)
2579 Con_DPrintf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2580 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2581 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);
2582 if (!strcmp(pchunk->id, "ACTRHEAD"))
2586 else if (!strcmp(pchunk->id, "PNTS0000"))
2589 if (recordsize != sizeof(*p))
2590 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2591 // byteswap in place and keep the pointer
2592 numpnts = numrecords;
2593 pnts = (pskpnts_t *)buffer;
2594 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2596 p->origin[0] = LittleFloat(p->origin[0]);
2597 p->origin[1] = LittleFloat(p->origin[1]);
2598 p->origin[2] = LittleFloat(p->origin[2]);
2602 else if (!strcmp(pchunk->id, "VTXW0000"))
2605 if (recordsize != sizeof(*p))
2606 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2607 // byteswap in place and keep the pointer
2608 numvtxw = numrecords;
2609 vtxw = (pskvtxw_t *)buffer;
2610 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2612 p->pntsindex = LittleShort(p->pntsindex);
2613 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2614 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2615 if (p->pntsindex >= numpnts)
2617 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2623 else if (!strcmp(pchunk->id, "FACE0000"))
2626 if (recordsize != sizeof(*p))
2627 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2628 // byteswap in place and keep the pointer
2629 numfaces = numrecords;
2630 faces = (pskface_t *)buffer;
2631 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2633 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2634 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2635 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2636 p->group = LittleLong(p->group);
2637 if (p->vtxwindex[0] >= numvtxw)
2639 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2640 p->vtxwindex[0] = 0;
2642 if (p->vtxwindex[1] >= numvtxw)
2644 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2645 p->vtxwindex[1] = 0;
2647 if (p->vtxwindex[2] >= numvtxw)
2649 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2650 p->vtxwindex[2] = 0;
2655 else if (!strcmp(pchunk->id, "MATT0000"))
2658 if (recordsize != sizeof(*p))
2659 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2660 // byteswap in place and keep the pointer
2661 nummatts = numrecords;
2662 matts = (pskmatt_t *)buffer;
2663 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2669 else if (!strcmp(pchunk->id, "REFSKELT"))
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 numbones = numrecords;
2676 bones = (pskboneinfo_t *)buffer;
2677 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2679 p->numchildren = LittleLong(p->numchildren);
2680 p->parent = LittleLong(p->parent);
2681 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2682 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2683 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2684 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2685 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2686 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2687 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2688 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2689 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2690 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2691 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2692 #ifdef PSKQUATNEGATIONS
2695 p->basepose.quat[0] *= -1;
2696 p->basepose.quat[1] *= -1;
2697 p->basepose.quat[2] *= -1;
2701 p->basepose.quat[0] *= 1;
2702 p->basepose.quat[1] *= -1;
2703 p->basepose.quat[2] *= 1;
2706 if (p->parent < 0 || p->parent >= numbones)
2708 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2714 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2717 if (recordsize != sizeof(*p))
2718 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2719 // byteswap in place and keep the pointer
2720 numrawweights = numrecords;
2721 rawweights = (pskrawweights_t *)buffer;
2722 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2724 p->weight = LittleFloat(p->weight);
2725 p->pntsindex = LittleLong(p->pntsindex);
2726 p->boneindex = LittleLong(p->boneindex);
2727 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2729 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2732 if (p->boneindex < 0 || p->boneindex >= numbones)
2734 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2742 while (animbuffer < animbufferend)
2744 pchunk = (pskchunk_t *)animbuffer;
2745 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2746 version = LittleLong(pchunk->version);
2747 recordsize = LittleLong(pchunk->recordsize);
2748 numrecords = LittleLong(pchunk->numrecords);
2749 if (developer_extra.integer)
2750 Con_DPrintf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2751 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2752 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);
2753 if (!strcmp(pchunk->id, "ANIMHEAD"))
2757 else if (!strcmp(pchunk->id, "BONENAMES"))
2760 if (recordsize != sizeof(*p))
2761 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2762 // byteswap in place and keep the pointer
2763 numanimbones = numrecords;
2764 //animbones = (pskboneinfo_t *)animbuffer;
2765 // NOTE: supposedly psa does not need to match the psk model, the
2766 // bones missing from the psa would simply use their base
2767 // positions from the psk, but this is hard for me to implement
2768 // and people can easily make animations that match.
2769 if (numanimbones != numbones)
2770 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2771 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2773 p->numchildren = LittleLong(p->numchildren);
2774 p->parent = LittleLong(p->parent);
2775 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2776 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2777 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2778 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2779 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2780 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2781 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2782 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2783 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2784 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2785 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2786 #ifdef PSKQUATNEGATIONS
2789 p->basepose.quat[0] *= -1;
2790 p->basepose.quat[1] *= -1;
2791 p->basepose.quat[2] *= -1;
2795 p->basepose.quat[0] *= 1;
2796 p->basepose.quat[1] *= -1;
2797 p->basepose.quat[2] *= 1;
2800 if (p->parent < 0 || p->parent >= numanimbones)
2802 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2805 // check that bones are the same as in the base
2806 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2807 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2811 else if (!strcmp(pchunk->id, "ANIMINFO"))
2814 if (recordsize != sizeof(*p))
2815 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2816 // byteswap in place and keep the pointer
2817 numanims = numrecords;
2818 anims = (pskaniminfo_t *)animbuffer;
2819 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2821 p->numbones = LittleLong(p->numbones);
2822 p->playtime = LittleFloat(p->playtime);
2823 p->fps = LittleFloat(p->fps);
2824 p->firstframe = LittleLong(p->firstframe);
2825 p->numframes = LittleLong(p->numframes);
2826 if (p->numbones != numbones)
2827 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2831 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2834 if (recordsize != sizeof(*p))
2835 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2836 numanimkeys = numrecords;
2837 animkeys = (pskanimkeys_t *)animbuffer;
2838 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2840 p->origin[0] = LittleFloat(p->origin[0]);
2841 p->origin[1] = LittleFloat(p->origin[1]);
2842 p->origin[2] = LittleFloat(p->origin[2]);
2843 p->quat[0] = LittleFloat(p->quat[0]);
2844 p->quat[1] = LittleFloat(p->quat[1]);
2845 p->quat[2] = LittleFloat(p->quat[2]);
2846 p->quat[3] = LittleFloat(p->quat[3]);
2847 p->frametime = LittleFloat(p->frametime);
2848 #ifdef PSKQUATNEGATIONS
2849 if (index % numbones)
2864 // TODO: allocate bonepose stuff
2867 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2870 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights)
2871 Host_Error("%s: missing required chunks", loadmodel->name);
2875 loadmodel->numframes = 0;
2876 for (index = 0;index < numanims;index++)
2877 loadmodel->numframes += anims[index].numframes;
2878 if (numanimkeys != numbones * loadmodel->numframes)
2879 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2882 loadmodel->numframes = loadmodel->num_poses = 1;
2884 meshvertices = numvtxw;
2885 meshtriangles = numfaces;
2887 // load external .skin files if present
2888 skinfiles = Mod_LoadSkinFiles();
2889 if (loadmodel->numskins < 1)
2890 loadmodel->numskins = 1;
2891 loadmodel->num_bones = numbones;
2892 loadmodel->num_poses = loadmodel->numframes;
2893 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2894 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2895 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2896 loadmodel->surfmesh.num_vertices = meshvertices;
2897 loadmodel->surfmesh.num_triangles = meshtriangles;
2898 // do most allocations as one merged chunk
2899 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]) + (r_enableshadowvolumes.integer ? loadmodel->surfmesh.num_triangles * sizeof(int[3]) : 0) + 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);
2900 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2901 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2902 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2903 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2904 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2905 if (r_enableshadowvolumes.integer)
2907 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2909 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2910 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2911 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2912 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2913 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2914 loadmodel->surfmesh.data_skeletalindex4ub = (unsigned char *)data;data += loadmodel->surfmesh.num_vertices * sizeof(unsigned char[4]);
2915 loadmodel->surfmesh.data_skeletalweight4ub = (unsigned char *)data;data += loadmodel->surfmesh.num_vertices * sizeof(unsigned char[4]);
2916 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2917 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2918 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2919 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2920 loadmodel->surfmesh.num_blends = 0;
2921 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2922 if (loadmodel->surfmesh.num_vertices <= 65536)
2924 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2926 loadmodel->data_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
2927 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(blendweights_t));
2929 for (i = 0;i < loadmodel->numskins;i++)
2931 loadmodel->skinscenes[i].firstframe = i;
2932 loadmodel->skinscenes[i].framecount = 1;
2933 loadmodel->skinscenes[i].loop = true;
2934 loadmodel->skinscenes[i].framerate = 10;
2938 for (index = 0, i = 0;index < nummatts;index++)
2940 // since psk models do not have named sections, reuse their shader name as the section name
2941 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2942 loadmodel->sortedmodelsurfaces[index] = index;
2943 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2944 loadmodel->data_surfaces[index].num_firstvertex = 0;
2945 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2948 // copy over the vertex locations and texcoords
2949 for (index = 0;index < numvtxw;index++)
2951 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2952 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2953 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2954 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2955 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2958 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2959 for (index = 0;index < numfaces;index++)
2960 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2961 for (index = 0, i = 0;index < nummatts;index++)
2963 loadmodel->data_surfaces[index].num_firsttriangle = i;
2964 i += loadmodel->data_surfaces[index].num_triangles;
2965 loadmodel->data_surfaces[index].num_triangles = 0;
2967 for (index = 0;index < numfaces;index++)
2969 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2970 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2971 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2972 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2975 // copy over the bones
2976 for (index = 0;index < numbones;index++)
2978 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2979 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2980 if (loadmodel->data_bones[index].parent >= index)
2981 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2984 // convert the basepose data
2985 if (loadmodel->num_bones)
2988 matrix4x4_t *basebonepose;
2989 float *outinvmatrix = loadmodel->data_baseboneposeinverse;
2990 matrix4x4_t bonematrix;
2991 matrix4x4_t tempbonematrix;
2992 basebonepose = (matrix4x4_t *)Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(matrix4x4_t));
2993 for (boneindex = 0;boneindex < loadmodel->num_bones;boneindex++)
2995 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]);
2996 if (loadmodel->data_bones[boneindex].parent >= 0)
2998 tempbonematrix = bonematrix;
2999 Matrix4x4_Concat(&bonematrix, basebonepose + loadmodel->data_bones[boneindex].parent, &tempbonematrix);
3001 basebonepose[boneindex] = bonematrix;
3002 Matrix4x4_Invert_Simple(&tempbonematrix, basebonepose + boneindex);
3003 Matrix4x4_ToArray12FloatD3D(&tempbonematrix, outinvmatrix + 12*boneindex);
3005 Mem_Free(basebonepose);
3008 // sort the psk point weights into the vertex weight tables
3009 // (which only accept up to 4 bones per vertex)
3010 for (index = 0;index < numvtxw;index++)
3012 int weightindex[4] = { 0, 0, 0, 0 };
3013 float weightinfluence[4] = { 0, 0, 0, 0 };
3015 for (j = 0;j < numrawweights;j++)
3017 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
3019 int boneindex = rawweights[j].boneindex;
3020 float influence = rawweights[j].weight;
3021 for (l = 0;l < 4;l++)
3023 if (weightinfluence[l] < influence)
3025 // move lower influence weights out of the way first
3027 for (l2 = 3;l2 > l;l2--)
3029 weightinfluence[l2] = weightinfluence[l2-1];
3030 weightindex[l2] = weightindex[l2-1];
3032 // store the new weight
3033 weightinfluence[l] = influence;
3034 weightindex[l] = boneindex;
3040 loadmodel->surfmesh.blends[index] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
3041 loadmodel->surfmesh.data_skeletalindex4ub[index*4 ] = weightindex[0];
3042 loadmodel->surfmesh.data_skeletalindex4ub[index*4+1] = weightindex[1];
3043 loadmodel->surfmesh.data_skeletalindex4ub[index*4+2] = weightindex[2];
3044 loadmodel->surfmesh.data_skeletalindex4ub[index*4+3] = weightindex[3];
3045 loadmodel->surfmesh.data_skeletalweight4ub[index*4 ] = (unsigned char)(weightinfluence[0]*255.0f);
3046 loadmodel->surfmesh.data_skeletalweight4ub[index*4+1] = (unsigned char)(weightinfluence[1]*255.0f);
3047 loadmodel->surfmesh.data_skeletalweight4ub[index*4+2] = (unsigned char)(weightinfluence[2]*255.0f);
3048 loadmodel->surfmesh.data_skeletalweight4ub[index*4+3] = (unsigned char)(weightinfluence[3]*255.0f);
3050 if (loadmodel->surfmesh.num_blends < loadmodel->surfmesh.num_vertices)
3051 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
3053 // set up the animscenes based on the anims
3056 for (index = 0, i = 0;index < numanims;index++)
3058 for (j = 0;j < anims[index].numframes;j++, i++)
3060 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
3061 loadmodel->animscenes[i].firstframe = i;
3062 loadmodel->animscenes[i].framecount = 1;
3063 loadmodel->animscenes[i].loop = true;
3064 loadmodel->animscenes[i].framerate = anims[index].fps;
3067 // calculate the scaling value for bone origins so they can be compressed to short
3069 for (index = 0;index < numanimkeys;index++)
3071 pskanimkeys_t *k = animkeys + index;
3072 biggestorigin = max(biggestorigin, fabs(k->origin[0]));
3073 biggestorigin = max(biggestorigin, fabs(k->origin[1]));
3074 biggestorigin = max(biggestorigin, fabs(k->origin[2]));
3076 loadmodel->num_posescale = biggestorigin / 32767.0f;
3077 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3079 // load the poses from the animkeys
3080 for (index = 0;index < numanimkeys;index++)
3082 pskanimkeys_t *k = animkeys + index;
3084 Vector4Copy(k->quat, quat);
3086 Vector4Negate(quat, quat);
3087 Vector4Normalize2(quat, quat);
3088 // compress poses to the short[7] format for longterm storage
3089 loadmodel->data_poses7s[index*7+0] = k->origin[0] * loadmodel->num_poseinvscale;
3090 loadmodel->data_poses7s[index*7+1] = k->origin[1] * loadmodel->num_poseinvscale;
3091 loadmodel->data_poses7s[index*7+2] = k->origin[2] * loadmodel->num_poseinvscale;
3092 loadmodel->data_poses7s[index*7+3] = quat[0] * 32767.0f;
3093 loadmodel->data_poses7s[index*7+4] = quat[1] * 32767.0f;
3094 loadmodel->data_poses7s[index*7+5] = quat[2] * 32767.0f;
3095 loadmodel->data_poses7s[index*7+6] = quat[3] * 32767.0f;
3100 strlcpy(loadmodel->animscenes[0].name, "base", sizeof(loadmodel->animscenes[0].name));
3101 loadmodel->animscenes[0].firstframe = 0;
3102 loadmodel->animscenes[0].framecount = 1;
3103 loadmodel->animscenes[0].loop = true;
3104 loadmodel->animscenes[0].framerate = 10;
3106 // calculate the scaling value for bone origins so they can be compressed to short
3108 for (index = 0;index < numbones;index++)
3110 pskboneinfo_t *p = bones + index;
3111 biggestorigin = max(biggestorigin, fabs(p->basepose.origin[0]));
3112 biggestorigin = max(biggestorigin, fabs(p->basepose.origin[1]));
3113 biggestorigin = max(biggestorigin, fabs(p->basepose.origin[2]));
3115 loadmodel->num_posescale = biggestorigin / 32767.0f;
3116 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3118 // load the basepose as a frame
3119 for (index = 0;index < numbones;index++)
3121 pskboneinfo_t *p = bones + index;
3123 Vector4Copy(p->basepose.quat, quat);
3125 Vector4Negate(quat, quat);
3126 Vector4Normalize2(quat, quat);
3127 // compress poses to the short[7] format for longterm storage
3128 loadmodel->data_poses7s[index*7+0] = p->basepose.origin[0] * loadmodel->num_poseinvscale;
3129 loadmodel->data_poses7s[index*7+1] = p->basepose.origin[1] * loadmodel->num_poseinvscale;
3130 loadmodel->data_poses7s[index*7+2] = p->basepose.origin[2] * loadmodel->num_poseinvscale;
3131 loadmodel->data_poses7s[index*7+3] = quat[0] * 32767.0f;
3132 loadmodel->data_poses7s[index*7+4] = quat[1] * 32767.0f;
3133 loadmodel->data_poses7s[index*7+5] = quat[2] * 32767.0f;
3134 loadmodel->data_poses7s[index*7+6] = quat[3] * 32767.0f;
3138 Mod_FreeSkinFiles(skinfiles);
3140 Mem_Free(animfilebuffer);
3141 Mod_MakeSortedSurfaces(loadmodel);
3143 // compute all the mesh information that was not loaded from the file
3144 // TODO: honor smoothing groups somehow?
3145 if (loadmodel->surfmesh.data_element3s)
3146 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3147 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3148 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
3149 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);
3150 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);
3151 if (loadmodel->surfmesh.data_neighbor3i)
3152 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3153 loadmodel->surfmesh.isanimated = Mod_Alias_CalculateBoundingBox();
3154 if(mod_alias_force_animated.string[0])
3155 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
3157 if (!loadmodel->surfmesh.isanimated)
3159 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3160 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3161 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3162 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3163 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3164 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
3167 // because shaders can do somewhat unexpected things, check for unusual features now
3168 for (i = 0;i < loadmodel->num_textures;i++)
3170 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
3171 mod->DrawSky = R_Q1BSP_DrawSky;
3172 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
3173 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
3177 void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
3179 unsigned char *data;
3181 const unsigned char *pbase, *pend;
3183 skinfile_t *skinfiles;
3184 int i, j, k, meshvertices, meshtriangles;
3185 float biggestorigin;
3186 const unsigned int *inelements;
3188 const int *inneighbors;
3190 float *outvertex, *outnormal, *outtexcoord, *outsvector, *outtvector, *outcolor;
3191 // this pointers into the file data are read only through Little* functions so they can be unaligned memory
3192 const float *vnormal = NULL;
3193 const float *vposition = NULL;
3194 const float *vtangent = NULL;
3195 const float *vtexcoord = NULL;
3196 const float *vcolor4f = NULL;
3197 const unsigned char *vblendindexes = NULL;
3198 const unsigned char *vblendweights = NULL;
3199 const unsigned char *vcolor4ub = NULL;
3200 const unsigned short *framedata = NULL;
3201 // temporary memory allocations (because the data in the file may be misaligned)
3202 iqmanim_t *anims = NULL;
3203 iqmbounds_t *bounds = NULL;
3204 iqmjoint1_t *joint1 = NULL;
3205 iqmjoint_t *joint = NULL;
3206 iqmmesh_t *meshes = NULL;
3207 iqmpose1_t *pose1 = NULL;
3208 iqmpose_t *pose = NULL;
3209 iqmvertexarray_t *vas = NULL;
3211 pbase = (unsigned char *)buffer;
3212 pend = (unsigned char *)bufferend;
3214 if (pbase + sizeof(iqmheader_t) > pend)
3215 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model %d", loadmodel->name, (int)(pend - pbase));
3217 // copy struct (otherwise it may be misaligned)
3218 // LordHavoc: okay it's definitely not misaligned here, but for consistency...
3219 memcpy(&header, pbase, sizeof(iqmheader_t));
3221 if (memcmp(header.id, "INTERQUAKEMODEL", 16))
3222 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model", loadmodel->name);
3223 if (LittleLong(header.version) != 1 && LittleLong(header.version) != 2)
3224 Host_Error ("Mod_INTERQUAKEMODEL_Load: only version 1 and 2 models are currently supported (name = %s)", loadmodel->name);
3226 loadmodel->modeldatatypestring = "IQM";
3228 loadmodel->type = mod_alias;
3229 loadmodel->synctype = ST_RAND;
3232 header.version = LittleLong(header.version);
3233 header.filesize = LittleLong(header.filesize);
3234 header.flags = LittleLong(header.flags);
3235 header.num_text = LittleLong(header.num_text);
3236 header.ofs_text = LittleLong(header.ofs_text);
3237 header.num_meshes = LittleLong(header.num_meshes);
3238 header.ofs_meshes = LittleLong(header.ofs_meshes);
3239 header.num_vertexarrays = LittleLong(header.num_vertexarrays);
3240 header.num_vertexes = LittleLong(header.num_vertexes);
3241 header.ofs_vertexarrays = LittleLong(header.ofs_vertexarrays);
3242 header.num_triangles = LittleLong(header.num_triangles);
3243 header.ofs_triangles = LittleLong(header.ofs_triangles);
3244 header.ofs_neighbors = LittleLong(header.ofs_neighbors);
3245 header.num_joints = LittleLong(header.num_joints);
3246 header.ofs_joints = LittleLong(header.ofs_joints);
3247 header.num_poses = LittleLong(header.num_poses);
3248 header.ofs_poses = LittleLong(header.ofs_poses);
3249 header.num_anims = LittleLong(header.num_anims);
3250 header.ofs_anims = LittleLong(header.ofs_anims);
3251 header.num_frames = LittleLong(header.num_frames);
3252 header.num_framechannels = LittleLong(header.num_framechannels);
3253 header.ofs_frames = LittleLong(header.ofs_frames);
3254 header.ofs_bounds = LittleLong(header.ofs_bounds);
3255 header.num_comment = LittleLong(header.num_comment);
3256 header.ofs_comment = LittleLong(header.ofs_comment);
3257 header.num_extensions = LittleLong(header.num_extensions);
3258 header.ofs_extensions = LittleLong(header.ofs_extensions);
3260 if (header.version == 1)
3262 if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint1_t) > pend ||
3263 pbase + header.ofs_poses + header.num_poses*sizeof(iqmpose1_t) > pend)
3265 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3271 if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint_t) > pend ||
3272 pbase + header.ofs_poses + header.num_poses*sizeof(iqmpose_t) > pend)
3274 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3278 if (pbase + header.ofs_text + header.num_text > pend ||
3279 pbase + header.ofs_meshes + header.num_meshes*sizeof(iqmmesh_t) > pend ||
3280 pbase + header.ofs_vertexarrays + header.num_vertexarrays*sizeof(iqmvertexarray_t) > pend ||
3281 pbase + header.ofs_triangles + header.num_triangles*sizeof(int[3]) > pend ||
3282 (header.ofs_neighbors && pbase + header.ofs_neighbors + header.num_triangles*sizeof(int[3]) > pend) ||
3283 pbase + header.ofs_anims + header.num_anims*sizeof(iqmanim_t) > pend ||
3284 pbase + header.ofs_frames + header.num_frames*header.num_framechannels*sizeof(unsigned short) > pend ||
3285 (header.ofs_bounds && pbase + header.ofs_bounds + header.num_frames*sizeof(iqmbounds_t) > pend) ||
3286 pbase + header.ofs_comment + header.num_comment > pend)
3288 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3292 // copy structs to make them aligned in memory (otherwise we crash on Sparc and PowerPC and others)
3293 if (header.num_vertexarrays)
3294 vas = (iqmvertexarray_t *)(pbase + header.ofs_vertexarrays);
3295 if (header.num_anims)
3296 anims = (iqmanim_t *)(pbase + header.ofs_anims);
3297 if (header.ofs_bounds)
3298 bounds = (iqmbounds_t *)(pbase + header.ofs_bounds);
3299 if (header.num_meshes)
3300 meshes = (iqmmesh_t *)(pbase + header.ofs_meshes);
3302 for (i = 0;i < (int)header.num_vertexarrays;i++)
3304 iqmvertexarray_t va;
3306 va.type = LittleLong(vas[i].type);
3307 va.flags = LittleLong(vas[i].flags);
3308 va.format = LittleLong(vas[i].format);
3309 va.size = LittleLong(vas[i].size);
3310 va.offset = LittleLong(vas[i].offset);
3311 vsize = header.num_vertexes*va.size;
3314 case IQM_FLOAT: vsize *= sizeof(float); break;
3315 case IQM_UBYTE: vsize *= sizeof(unsigned char); break;
3318 if (pbase + va.offset + vsize > pend)
3320 // no need to copy the vertex data for alignment because LittleLong/LittleShort will be invoked on reading them, and the destination is aligned
3324 if (va.format == IQM_FLOAT && va.size == 3)
3325 vposition = (const float *)(pbase + va.offset);
3328 if (va.format == IQM_FLOAT && va.size == 2)
3329 vtexcoord = (const float *)(pbase + va.offset);
3332 if (va.format == IQM_FLOAT && va.size == 3)
3333 vnormal = (const float *)(pbase + va.offset);
3336 if (va.format == IQM_FLOAT && va.size == 4)
3337 vtangent = (const float *)(pbase + va.offset);
3339 case IQM_BLENDINDEXES:
3340 if (va.format == IQM_UBYTE && va.size == 4)
3341 vblendindexes = (const unsigned char *)(pbase + va.offset);
3343 case IQM_BLENDWEIGHTS:
3344 if (va.format == IQM_UBYTE && va.size == 4)
3345 vblendweights = (const unsigned char *)(pbase + va.offset);
3348 if (va.format == IQM_FLOAT && va.size == 4)
3349 vcolor4f = (const float *)(pbase + va.offset);
3350 if (va.format == IQM_UBYTE && va.size == 4)
3351 vcolor4ub = (const unsigned char *)(pbase + va.offset);
3355 if (header.num_vertexes > 0 && (!vposition || !vtexcoord || ((header.num_frames > 0 || header.num_anims > 0) && (!vblendindexes || !vblendweights))))
3357 Con_Printf("%s is missing vertex array data\n", loadmodel->name);
3361 text = header.num_text && header.ofs_text ? (const char *)(pbase + header.ofs_text) : "";
3363 loadmodel->DrawSky = NULL;
3364 loadmodel->DrawAddWaterPlanes = NULL;
3365 loadmodel->Draw = R_Q1BSP_Draw;
3366 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
3367 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
3368 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
3369 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
3370 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
3371 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
3372 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
3373 loadmodel->DrawLight = R_Q1BSP_DrawLight;
3374 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
3375 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
3376 loadmodel->PointSuperContents = NULL;
3377 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
3379 // load external .skin files if present
3380 skinfiles = Mod_LoadSkinFiles();
3381 if (loadmodel->numskins < 1)
3382 loadmodel->numskins = 1;
3384 loadmodel->numframes = max(header.num_anims, 1);
3385 loadmodel->num_bones = header.num_joints;
3386 loadmodel->num_poses = max(header.num_frames, 1);
3387 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = header.num_meshes;
3388 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3389 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3391 meshvertices = header.num_vertexes;
3392 meshtriangles = header.num_triangles;
3394 // do most allocations as one merged chunk
3395 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) + (r_enableshadowvolumes.integer ? meshtriangles * sizeof(int[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));
3396 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
3397 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
3398 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
3399 loadmodel->surfmesh.num_vertices = meshvertices;
3400 loadmodel->surfmesh.num_triangles = meshtriangles;
3401 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3402 if (r_enableshadowvolumes.integer)
3404 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3406 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
3407 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3408 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3409 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
3410 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
3411 if (vcolor4f || vcolor4ub)
3413 loadmodel->surfmesh.data_lightmapcolor4f = (float *)data;data += meshvertices * sizeof(float[4]);
3415 if (vblendindexes && vblendweights)
3417 loadmodel->surfmesh.data_skeletalindex4ub = (unsigned char *)data;data += meshvertices * sizeof(unsigned char[4]);
3418 loadmodel->surfmesh.data_skeletalweight4ub = (unsigned char *)data;data += meshvertices * sizeof(unsigned char[4]);
3420 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
3421 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
3422 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
3423 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
3424 if (vblendindexes && vblendweights)
3426 loadmodel->surfmesh.num_blends = 0;
3427 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
3429 if (meshvertices <= 65536)
3431 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
3433 loadmodel->data_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
3434 if (vblendindexes && vblendweights)
3435 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
3437 for (i = 0;i < loadmodel->numskins;i++)
3439 loadmodel->skinscenes[i].firstframe = i;
3440 loadmodel->skinscenes[i].framecount = 1;
3441 loadmodel->skinscenes[i].loop = true;
3442 loadmodel->skinscenes[i].framerate = 10;
3445 // load the bone info
3446 if (header.version == 1)
3448 iqmjoint1_t *injoint1 = (iqmjoint1_t *)(pbase + header.ofs_joints);
3449 if (loadmodel->num_bones)
3450 joint1 = (iqmjoint1_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(iqmjoint1_t));
3451 for (i = 0;i < loadmodel->num_bones;i++)
3453 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3454 joint1[i].name = LittleLong(injoint1[i].name);
3455 joint1[i].parent = LittleLong(injoint1[i].parent);
3456 for (j = 0;j < 3;j++)
3458 joint1[i].origin[j] = LittleFloat(injoint1[i].origin[j]);
3459 joint1[i].rotation[j] = LittleFloat(injoint1[i].rotation[j]);
3460 joint1[i].scale[j] = LittleFloat(injoint1[i].scale[j]);
3462 strlcpy(loadmodel->data_bones[i].name, &text[joint1[i].name], sizeof(loadmodel->data_bones[i].name));
3463 loadmodel->data_bones[i].parent = joint1[i].parent;
3464 if (loadmodel->data_bones[i].parent >= i)
3465 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3466 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]);
3467 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3468 if (loadmodel->data_bones[i].parent >= 0)
3470 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3471 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3472 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3474 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3479 iqmjoint_t *injoint = (iqmjoint_t *)(pbase + header.ofs_joints);
3480 if (header.num_joints)
3481 joint = (iqmjoint_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(iqmjoint_t));
3482 for (i = 0;i < loadmodel->num_bones;i++)
3484 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3485 joint[i].name = LittleLong(injoint[i].name);
3486 joint[i].parent = LittleLong(injoint[i].parent);
3487 for (j = 0;j < 3;j++)
3489 joint[i].origin[j] = LittleFloat(injoint[i].origin[j]);
3490 joint[i].rotation[j] = LittleFloat(injoint[i].rotation[j]);
3491 joint[i].scale[j] = LittleFloat(injoint[i].scale[j]);
3493 joint[i].rotation[3] = LittleFloat(injoint[i].rotation[3]);
3494 strlcpy(loadmodel->data_bones[i].name, &text[joint[i].name], sizeof(loadmodel->data_bones[i].name));
3495 loadmodel->data_bones[i].parent = joint[i].parent;
3496 if (loadmodel->data_bones[i].parent >= i)
3497 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3498 if (joint[i].rotation[3] > 0)
3499 Vector4Negate(joint[i].rotation, joint[i].rotation);
3500 Vector4Normalize2(joint[i].rotation, joint[i].rotation);
3501 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]);
3502 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3503 if (loadmodel->data_bones[i].parent >= 0)
3505 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3506 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3507 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3509 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3513 // set up the animscenes based on the anims
3514 for (i = 0;i < (int)header.num_anims;i++)
3517 anim.name = LittleLong(anims[i].name);
3518 anim.first_frame = LittleLong(anims[i].first_frame);
3519 anim.num_frames = LittleLong(anims[i].num_frames);
3520 anim.framerate = LittleFloat(anims[i].framerate);
3521 anim.flags = LittleLong(anims[i].flags);
3522 strlcpy(loadmodel->animscenes[i].name, &text[anim.name], sizeof(loadmodel->animscenes[i].name));
3523 loadmodel->animscenes[i].firstframe = anim.first_frame;
3524 loadmodel->animscenes[i].framecount = anim.num_frames;
3525 loadmodel->animscenes[i].loop = ((anim.flags & IQM_LOOP) != 0);
3526 loadmodel->animscenes[i].framerate = anim.framerate;
3528 if (header.num_anims <= 0)
3530 strlcpy(loadmodel->animscenes[0].name, "static", sizeof(loadmodel->animscenes[0].name));
3531 loadmodel->animscenes[0].firstframe = 0;
3532 loadmodel->animscenes[0].framecount = 1;
3533 loadmodel->animscenes[0].loop = true;
3534 loadmodel->animscenes[0].framerate = 10;
3537 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
3538 if(mod_alias_force_animated.string[0])
3539 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
3542 if (header.version == 1)
3544 iqmpose1_t *inpose1 = (iqmpose1_t *)(pbase + header.ofs_poses);
3545 if (header.num_poses)
3546 pose1 = (iqmpose1_t *)Mem_Alloc(loadmodel->mempool, header.num_poses * sizeof(iqmpose1_t));
3547 for (i = 0;i < (int)header.num_poses;i++)
3550 pose1[i].parent = LittleLong(inpose1[i].parent);
3551 pose1[i].channelmask = LittleLong(inpose1[i].channelmask);
3552 for (j = 0;j < 9;j++)
3554 pose1[i].channeloffset[j] = LittleFloat(inpose1[i].channeloffset[j]);
3555 pose1[i].channelscale[j] = LittleFloat(inpose1[i].channelscale[j]);
3557 f = fabs(pose1[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3558 f = fabs(pose1[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3559 f = fabs(pose1[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3560 f = fabs(pose1[i].channeloffset[0] + 0xFFFF*pose1[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3561 f = fabs(pose1[i].channeloffset[1] + 0xFFFF*pose1[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3562 f = fabs(pose1[i].channeloffset[2] + 0xFFFF*pose1[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3564 if (header.num_frames <= 0)
3566 for (i = 0;i < loadmodel->num_bones;i++)
3569 f = fabs(joint1[i].origin[0]); biggestorigin = max(biggestorigin, f);
3570 f = fabs(joint1[i].origin[1]); biggestorigin = max(biggestorigin, f);
3571 f = fabs(joint1[i].origin[2]); biggestorigin = max(biggestorigin, f);
3577 iqmpose_t *inpose = (iqmpose_t *)(pbase + header.ofs_poses);
3578 if (header.num_poses)
3579 pose = (iqmpose_t *)Mem_Alloc(loadmodel->mempool, header.num_poses * sizeof(iqmpose_t));
3580 for (i = 0;i < (int)header.num_poses;i++)
3583 pose[i].parent = LittleLong(inpose[i].parent);
3584 pose[i].channelmask = LittleLong(inpose[i].channelmask);
3585 for (j = 0;j < 10;j++)
3587 pose[i].channeloffset[j] = LittleFloat(inpose[i].channeloffset[j]);
3588 pose[i].channelscale[j] = LittleFloat(inpose[i].channelscale[j]);
3590 f = fabs(pose[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3591 f = fabs(pose[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3592 f = fabs(pose[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3593 f = fabs(pose[i].channeloffset[0] + 0xFFFF*pose[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3594 f = fabs(pose[i].channeloffset[1] + 0xFFFF*pose[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3595 f = fabs(pose[i].channeloffset[2] + 0xFFFF*pose[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(joint[i].origin[0]); biggestorigin = max(biggestorigin, f);
3603 f = fabs(joint[i].origin[1]); biggestorigin = max(biggestorigin, f);
3604 f = fabs(joint[i].origin[2]); biggestorigin = max(biggestorigin, f);
3608 loadmodel->num_posescale = biggestorigin / 32767.0f;
3609 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3611 // load the pose data
3612 // this unaligned memory access is safe (LittleShort reads as bytes)
3613 framedata = (const unsigned short *)(pbase + header.ofs_frames);
3614 if (header.version == 1)
3616 for (i = 0, k = 0;i < (int)header.num_frames;i++)
3618 for (j = 0;j < (int)header.num_poses;j++, k++)
3620 float qx, qy, qz, qw;
3621 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));
3622 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));
3623 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));
3624 qx = pose1[j].channeloffset[3] + (pose1[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[3] : 0);
3625 qy = pose1[j].channeloffset[4] + (pose1[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[4] : 0);
3626 qz = pose1[j].channeloffset[5] + (pose1[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[5] : 0);
3627 qw = 1.0f - (qx*qx + qy*qy + qz*qz);
3628 qw = qw > 0.0f ? -sqrt(qw) : 0.0f;
3629 loadmodel->data_poses7s[k*7 + 3] = 32767.0f * qx;
3630 loadmodel->data_poses7s[k*7 + 4] = 32767.0f * qy;
3631 loadmodel->data_poses7s[k*7 + 5] = 32767.0f * qz;
3632 loadmodel->data_poses7s[k*7 + 6] = 32767.0f * qw;
3633 // skip scale data for now
3634 if(pose1[j].channelmask&64) framedata++;
3635 if(pose1[j].channelmask&128) framedata++;
3636 if(pose1[j].channelmask&256) framedata++;
3639 if (header.num_frames <= 0)
3641 for (i = 0;i < loadmodel->num_bones;i++)
3643 float qx, qy, qz, qw;
3644 loadmodel->data_poses7s[i*7 + 0] = loadmodel->num_poseinvscale * joint1[i].origin[0];
3645 loadmodel->data_poses7s[i*7 + 1] = loadmodel->num_poseinvscale * joint1[i].origin[1];
3646 loadmodel->data_poses7s[i*7 + 2] = loadmodel->num_poseinvscale * joint1[i].origin[2];
3647 qx = joint1[i].rotation[0];
3648 qy = joint1[i].rotation[1];
3649 qz = joint1[i].rotation[2];
3650 qw = 1.0f - (qx*qx + qy*qy + qz*qz);
3651 qw = qw > 0.0f ? -sqrt(qw) : 0.0f;
3652 loadmodel->data_poses7s[i*7 + 3] = 32767.0f * qx;
3653 loadmodel->data_poses7s[i*7 + 4] = 32767.0f * qy;
3654 loadmodel->data_poses7s[i*7 + 5] = 32767.0f * qz;
3655 loadmodel->data_poses7s[i*7 + 6] = 32767.0f * qw;
3661 for (i = 0, k = 0;i < (int)header.num_frames;i++)
3663 for (j = 0;j < (int)header.num_poses;j++, k++)
3666 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));
3667 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));
3668 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));
3669 rot[0] = pose[j].channeloffset[3] + (pose[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[3] : 0);
3670 rot[1] = pose[j].channeloffset[4] + (pose[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[4] : 0);
3671 rot[2] = pose[j].channeloffset[5] + (pose[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[5] : 0);
3672 rot[3] = pose[j].channeloffset[6] + (pose[j].channelmask&64 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[6] : 0);
3674 Vector4Negate(rot, rot);
3675 Vector4Normalize2(rot, rot);
3676 loadmodel->data_poses7s[k*7 + 3] = 32767.0f * rot[0];
3677 loadmodel->data_poses7s[k*7 + 4] = 32767.0f * rot[1];
3678 loadmodel->data_poses7s[k*7 + 5] = 32767.0f * rot[2];
3679 loadmodel->data_poses7s[k*7 + 6] = 32767.0f * rot[3];
3680 // skip scale data for now
3681 if(pose[j].channelmask&128) framedata++;
3682 if(pose[j].channelmask&256) framedata++;
3683 if(pose[j].channelmask&512) framedata++;
3686 if (header.num_frames <= 0)
3688 for (i = 0;i < loadmodel->num_bones;i++)
3690 loadmodel->data_poses7s[i*7 + 0] = loadmodel->num_poseinvscale * joint[i].origin[0];
3691 loadmodel->data_poses7s[i*7 + 1] = loadmodel->num_poseinvscale * joint[i].origin[1];
3692 loadmodel->data_poses7s[i*7 + 2] = loadmodel->num_poseinvscale * joint[i].origin[2];
3693 loadmodel->data_poses7s[i*7 + 3] = 32767.0f * joint[i].rotation[0];
3694 loadmodel->data_poses7s[i*7 + 4] = 32767.0f * joint[i].rotation[1];
3695 loadmodel->data_poses7s[i*7 + 5] = 32767.0f * joint[i].rotation[2];
3696 loadmodel->data_poses7s[i*7 + 6] = 32767.0f * joint[i].rotation[3];
3701 // load bounding box data
3702 if (header.ofs_bounds)
3704 float xyradius = 0, radius = 0;
3705 VectorClear(loadmodel->normalmins);
3706 VectorClear(loadmodel->normalmaxs);
3707 for (i = 0; i < (int)header.num_frames;i++)
3710 bound.mins[0] = LittleFloat(bounds[i].mins[0]);
3711 bound.mins[1] = LittleFloat(bounds[i].mins[1]);
3712 bound.mins[2] = LittleFloat(bounds[i].mins[2]);
3713 bound.maxs[0] = LittleFloat(bounds[i].maxs[0]);
3714 bound.maxs[1] = LittleFloat(bounds[i].maxs[1]);
3715 bound.maxs[2] = LittleFloat(bounds[i].maxs[2]);
3716 bound.xyradius = LittleFloat(bounds[i].xyradius);
3717 bound.radius = LittleFloat(bounds[i].radius);
3720 VectorCopy(bound.mins, loadmodel->normalmins);
3721 VectorCopy(bound.maxs, loadmodel->normalmaxs);
3725 if (loadmodel->normalmins[0] > bound.mins[0]) loadmodel->normalmins[0] = bound.mins[0];
3726 if (loadmodel->normalmins[1] > bound.mins[1]) loadmodel->normalmins[1] = bound.mins[1];
3727 if (loadmodel->normalmins[2] > bound.mins[2]) loadmodel->normalmins[2] = bound.mins[2];
3728 if (loadmodel->normalmaxs[0] < bound.maxs[0]) loadmodel->normalmaxs[0] = bound.maxs[0];
3729 if (loadmodel->normalmaxs[1] < bound.maxs[1]) loadmodel->normalmaxs[1] = bound.maxs[1];
3730 if (loadmodel->normalmaxs[2] < bound.maxs[2]) loadmodel->normalmaxs[2] = bound.maxs[2];
3732 if (bound.xyradius > xyradius)
3733 xyradius = bound.xyradius;
3734 if (bound.radius > radius)
3735 radius = bound.radius;
3737 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -xyradius;
3738 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = xyradius;
3739 loadmodel->yawmins[2] = loadmodel->normalmins[2];
3740 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
3741 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
3742 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
3743 loadmodel->radius = radius;
3744 loadmodel->radius2 = radius * radius;
3747 // load triangle data
3748 // this unaligned memory access is safe (LittleLong reads as bytes)
3749 inelements = (const unsigned int *)(pbase + header.ofs_triangles);
3750 outelements = loadmodel->surfmesh.data_element3i;
3751 for (i = 0;i < (int)header.num_triangles;i++)
3753 outelements[0] = LittleLong(inelements[0]);
3754 outelements[1] = LittleLong(inelements[1]);
3755 outelements[2] = LittleLong(inelements[2]);
3759 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, header.num_vertexes, __FILE__, __LINE__);
3761 if (header.ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
3763 // this unaligned memory access is safe (LittleLong reads as bytes)
3764 inneighbors = (const int *)(pbase + header.ofs_neighbors);
3765 outneighbors = loadmodel->surfmesh.data_neighbor3i;
3766 for (i = 0;i < (int)header.num_triangles;i++)
3768 outneighbors[0] = LittleLong(inneighbors[0]);
3769 outneighbors[1] = LittleLong(inneighbors[1]);
3770 outneighbors[2] = LittleLong(inneighbors[2]);
3777 // this unaligned memory access is safe (LittleFloat reads as bytes)
3778 outvertex = loadmodel->surfmesh.data_vertex3f;
3779 for (i = 0;i < (int)header.num_vertexes;i++)
3781 outvertex[0] = LittleFloat(vposition[0]);
3782 outvertex[1] = LittleFloat(vposition[1]);
3783 outvertex[2] = LittleFloat(vposition[2]);
3788 outtexcoord = loadmodel->surfmesh.data_texcoordtexture2f;
3789 // this unaligned memory access is safe (LittleFloat reads as bytes)
3790 for (i = 0;i < (int)header.num_vertexes;i++)
3792 outtexcoord[0] = LittleFloat(vtexcoord[0]);
3793 outtexcoord[1] = LittleFloat(vtexcoord[1]);
3798 // this unaligned memory access is safe (LittleFloat reads as bytes)
3801 outnormal = loadmodel->surfmesh.data_normal3f;
3802 for (i = 0;i < (int)header.num_vertexes;i++)
3804 outnormal[0] = LittleFloat(vnormal[0]);
3805 outnormal[1] = LittleFloat(vnormal[1]);
3806 outnormal[2] = LittleFloat(vnormal[2]);
3812 // this unaligned memory access is safe (LittleFloat reads as bytes)
3813 if(vnormal && vtangent)
3815 outnormal = loadmodel->surfmesh.data_normal3f;
3816 outsvector = loadmodel->surfmesh.data_svector3f;
3817 outtvector = loadmodel->surfmesh.data_tvector3f;
3818 for (i = 0;i < (int)header.num_vertexes;i++)
3820 outsvector[0] = LittleFloat(vtangent[0]);
3821 outsvector[1] = LittleFloat(vtangent[1]);
3822 outsvector[2] = LittleFloat(vtangent[2]);
3823 if(LittleFloat(vtangent[3]) < 0)
3824 CrossProduct(outsvector, outnormal, outtvector);
3826 CrossProduct(outnormal, outsvector, outtvector);
3834 // this unaligned memory access is safe (all bytes)
3835 if (vblendindexes && vblendweights)
3837 for (i = 0; i < (int)header.num_vertexes;i++)
3839 blendweights_t weights;
3840 memcpy(weights.index, vblendindexes + i*4, 4);
3841 memcpy(weights.influence, vblendweights + i*4, 4);
3842 loadmodel->surfmesh.blends[i] = Mod_Skeletal_AddBlend(loadmodel, &weights);
3843 loadmodel->surfmesh.data_skeletalindex4ub[i*4 ] = weights.index[0];
3844 loadmodel->surfmesh.data_skeletalindex4ub[i*4+1] = weights.index[1];
3845 loadmodel->surfmesh.data_skeletalindex4ub[i*4+2] = weights.index[2];
3846 loadmodel->surfmesh.data_skeletalindex4ub[i*4+3] = weights.index[3];
3847 loadmodel->surfmesh.data_skeletalweight4ub[i*4 ] = weights.influence[0];
3848 loadmodel->surfmesh.data_skeletalweight4ub[i*4+1] = weights.influence[1];
3849 loadmodel->surfmesh.data_skeletalweight4ub[i*4+2] = weights.influence[2];
3850 loadmodel->surfmesh.data_skeletalweight4ub[i*4+3] = weights.influence[3];
3856 outcolor = loadmodel->surfmesh.data_lightmapcolor4f;
3857 // this unaligned memory access is safe (LittleFloat reads as bytes)
3858 for (i = 0;i < (int)header.num_vertexes;i++)
3860 outcolor[0] = LittleFloat(vcolor4f[0]);
3861 outcolor[1] = LittleFloat(vcolor4f[1]);
3862 outcolor[2] = LittleFloat(vcolor4f[2]);
3863 outcolor[3] = LittleFloat(vcolor4f[3]);
3870 outcolor = loadmodel->surfmesh.data_lightmapcolor4f;
3871 // this unaligned memory access is safe (all bytes)
3872 for (i = 0;i < (int)header.num_vertexes;i++)
3874 outcolor[0] = vcolor4ub[0] * (1.0f / 255.0f);
3875 outcolor[1] = vcolor4ub[1] * (1.0f / 255.0f);
3876 outcolor[2] = vcolor4ub[2] * (1.0f / 255.0f);
3877 outcolor[3] = vcolor4ub[3] * (1.0f / 255.0f);
3884 for (i = 0;i < (int)header.num_meshes;i++)
3887 msurface_t *surface;
3889 mesh.name = LittleLong(meshes[i].name);
3890 mesh.material = LittleLong(meshes[i].material);
3891 mesh.first_vertex = LittleLong(meshes[i].first_vertex);
3892 mesh.num_vertexes = LittleLong(meshes[i].num_vertexes);
3893 mesh.first_triangle = LittleLong(meshes[i].first_triangle);
3894 mesh.num_triangles = LittleLong(meshes[i].num_triangles);
3896 loadmodel->sortedmodelsurfaces[i] = i;
3897 surface = loadmodel->data_surfaces + i;
3898 surface->texture = loadmodel->data_textures + i;
3899 surface->num_firsttriangle = mesh.first_triangle;
3900 surface->num_triangles = mesh.num_triangles;
3901 surface->num_firstvertex = mesh.first_vertex;
3902 surface->num_vertices = mesh.num_vertexes;
3904 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, &text[mesh.name], &text[mesh.material]);
3907 Mod_FreeSkinFiles(skinfiles);
3908 Mod_MakeSortedSurfaces(loadmodel);
3910 // compute all the mesh information that was not loaded from the file
3911 if (loadmodel->surfmesh.data_element3s)
3912 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3913 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3915 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);
3916 if (!vnormal || !vtangent)
3917 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);
3918 if (!header.ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
3919 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3920 if (!header.ofs_bounds)
3921 Mod_Alias_CalculateBoundingBox();
3923 if (!loadmodel->surfmesh.isanimated && loadmodel->surfmesh.num_triangles >= 1)
3925 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3926 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3927 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3928 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3929 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3930 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
3933 if (joint ) Mem_Free(joint );joint = NULL;
3934 if (joint1 ) Mem_Free(joint1 );joint1 = NULL;
3935 if (pose ) Mem_Free(pose );pose = NULL;
3936 if (pose1 ) Mem_Free(pose1 );pose1 = NULL;
3938 // because shaders can do somewhat unexpected things, check for unusual features now
3939 for (i = 0;i < loadmodel->num_textures;i++)
3941 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
3942 mod->DrawSky = R_Q1BSP_DrawSky;
3943 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
3944 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;