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 void Mod_Alias_CalculateBoundingBox(void)
531 qboolean firstvertex = true;
532 float dist, yawradius, radius;
534 VectorClear(loadmodel->normalmins);
535 VectorClear(loadmodel->normalmaxs);
538 if (loadmodel->AnimateVertices)
541 frameblend_t frameblend[MAX_FRAMEBLENDS];
542 memset(frameblend, 0, sizeof(frameblend));
543 frameblend[0].lerp = 1;
544 vertex3f = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
545 for (frameblend[0].subframe = 0;frameblend[0].subframe < loadmodel->num_poses;frameblend[0].subframe++)
547 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, vertex3f, NULL, NULL, NULL);
548 for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
553 VectorCopy(v, loadmodel->normalmins);
554 VectorCopy(v, loadmodel->normalmaxs);
558 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
559 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
560 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
561 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
562 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
563 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
565 dist = v[0] * v[0] + v[1] * v[1];
566 if (yawradius < dist)
578 for (vnum = 0, v = loadmodel->surfmesh.data_vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
583 VectorCopy(v, loadmodel->normalmins);
584 VectorCopy(v, loadmodel->normalmaxs);
588 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
589 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
590 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
591 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
592 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
593 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
595 dist = v[0] * v[0] + v[1] * v[1];
596 if (yawradius < dist)
603 radius = sqrt(radius);
604 yawradius = sqrt(yawradius);
605 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
606 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
607 loadmodel->yawmins[2] = loadmodel->normalmins[2];
608 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
609 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
610 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
611 loadmodel->radius = radius;
612 loadmodel->radius2 = radius * radius;
615 static void Mod_Alias_MorphMesh_CompileFrames(void)
618 frameblend_t frameblend[MAX_FRAMEBLENDS];
619 unsigned char *datapointer;
620 memset(frameblend, 0, sizeof(frameblend));
621 frameblend[0].lerp = 1;
622 datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
623 loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
624 loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
625 loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
626 loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
627 loadmodel->surfmesh.data_morphtexvecvertex = (texvecvertex_t *)datapointer;datapointer += loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices * sizeof(texvecvertex_t);
628 // 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)
629 for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
631 frameblend[0].subframe = i;
632 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
633 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);
634 // encode the svector and tvector in 3 byte format for permanent storage
635 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
637 VectorScaleCast(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
638 VectorScaleCast(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
643 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)
646 float segmentmins[3], segmentmaxs[3];
648 float vertex3fbuf[1024*3];
649 float *vertex3f = vertex3fbuf;
650 memset(trace, 0, sizeof(*trace));
652 trace->realfraction = 1;
653 trace->hitsupercontentsmask = hitsupercontentsmask;
654 if (model->surfmesh.num_vertices > 1024)
655 vertex3f = (float *)Mem_Alloc(tempmempool, model->surfmesh.num_vertices * sizeof(float[3]));
656 segmentmins[0] = min(start[0], end[0]) - 1;
657 segmentmins[1] = min(start[1], end[1]) - 1;
658 segmentmins[2] = min(start[2], end[2]) - 1;
659 segmentmaxs[0] = max(start[0], end[0]) + 1;
660 segmentmaxs[1] = max(start[1], end[1]) + 1;
661 segmentmaxs[2] = max(start[2], end[2]) + 1;
662 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
663 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
664 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);
665 if (vertex3f != vertex3fbuf)
669 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)
672 vec3_t shiftstart, shiftend;
673 float segmentmins[3], segmentmaxs[3];
675 float vertex3fbuf[1024*3];
676 float *vertex3f = vertex3fbuf;
677 colboxbrushf_t thisbrush_start, thisbrush_end;
678 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
680 if (VectorCompare(boxmins, boxmaxs))
682 VectorAdd(start, boxmins, shiftstart);
683 VectorAdd(end, boxmins, shiftend);
684 Mod_MDLMD2MD3_TraceLine(model, frameblend, skeleton, trace, shiftstart, shiftend, hitsupercontentsmask);
685 VectorSubtract(trace->endpos, boxmins, trace->endpos);
689 // box trace, performed as brush trace
690 memset(trace, 0, sizeof(*trace));
692 trace->realfraction = 1;
693 trace->hitsupercontentsmask = hitsupercontentsmask;
694 if (model->surfmesh.num_vertices > 1024)
695 vertex3f = (float *)Mem_Alloc(tempmempool, model->surfmesh.num_vertices * sizeof(float[3]));
696 segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
697 segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
698 segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
699 segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
700 segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
701 segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
702 VectorAdd(start, boxmins, boxstartmins);
703 VectorAdd(start, boxmaxs, boxstartmaxs);
704 VectorAdd(end, boxmins, boxendmins);
705 VectorAdd(end, boxmaxs, boxendmaxs);
706 Collision_BrushForBox(&thisbrush_start, boxstartmins, boxstartmaxs, 0, 0, NULL);
707 Collision_BrushForBox(&thisbrush_end, boxendmins, boxendmaxs, 0, 0, NULL);
708 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
709 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
710 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);
711 if (vertex3f != vertex3fbuf)
715 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
718 for (i = 0;i < inverts;i++)
720 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
722 j = vertremap[i]; // not onseam
725 j = vertremap[i+inverts]; // onseam
731 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
733 int i, f, pose, groupframes;
735 daliasframetype_t *pframetype;
736 daliasframe_t *pinframe;
737 daliasgroup_t *group;
738 daliasinterval_t *intervals;
741 scene = loadmodel->animscenes;
742 for (f = 0;f < loadmodel->numframes;f++)
744 pframetype = (daliasframetype_t *)datapointer;
745 datapointer += sizeof(daliasframetype_t);
746 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
748 // a single frame is still treated as a group
755 group = (daliasgroup_t *)datapointer;
756 datapointer += sizeof(daliasgroup_t);
757 groupframes = LittleLong (group->numframes);
759 // intervals (time per frame)
760 intervals = (daliasinterval_t *)datapointer;
761 datapointer += sizeof(daliasinterval_t) * groupframes;
763 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
764 if (interval < 0.01f)
766 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
771 // get scene name from first frame
772 pinframe = (daliasframe_t *)datapointer;
774 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
775 scene->firstframe = pose;
776 scene->framecount = groupframes;
777 scene->framerate = 1.0f / interval;
782 for (i = 0;i < groupframes;i++)
784 pinframe = (daliasframe_t *)datapointer;
785 datapointer += sizeof(daliasframe_t);
786 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
787 datapointer += sizeof(trivertx_t) * inverts;
793 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
795 if (cls.state == ca_dedicated)
799 skinframe = R_SkinFrame_LoadMissing();
800 memset(texture, 0, sizeof(*texture));
801 texture->currentframe = texture;
802 //texture->animated = false;
803 texture->numskinframes = 1;
804 texture->skinframerate = 1;
805 texture->skinframes[0] = skinframe;
806 texture->currentskinframe = skinframe;
807 //texture->backgroundnumskinframes = 0;
808 //texture->customblendfunc[0] = 0;
809 //texture->customblendfunc[1] = 0;
810 //texture->surfaceflags = 0;
811 //texture->supercontents = 0;
812 //texture->surfaceparms = 0;
813 //texture->textureflags = 0;
815 texture->basematerialflags = MATERIALFLAG_WALL;
816 if (texture->currentskinframe->hasalpha)
817 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
818 texture->currentmaterialflags = texture->basematerialflags;
819 texture->offsetmapping = OFFSETMAPPING_DEFAULT;
820 texture->offsetscale = 1;
821 texture->offsetbias = 0;
822 texture->specularscalemod = 1;
823 texture->specularpowermod = 1;
824 texture->surfaceflags = 0;
825 texture->supercontents = SUPERCONTENTS_SOLID;
826 if (!(texture->basematerialflags & MATERIALFLAG_BLENDED))
827 texture->supercontents |= SUPERCONTENTS_OPAQUE;
830 void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
833 char stripbuf[MAX_QPATH];
834 skinfileitem_t *skinfileitem;
835 if(developer_extra.integer)
836 Con_DPrintf("Looking up texture for %s (default: %s)\n", meshname, shadername);
839 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
840 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
842 memset(skin, 0, sizeof(*skin));
844 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
846 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
847 if (!strcmp(skinfileitem->name, meshname))
849 Image_StripImageExtension(skinfileitem->replacement, stripbuf, sizeof(stripbuf));
850 if(developer_extra.integer)
851 Con_DPrintf("--> got %s from skin file\n", stripbuf);
852 Mod_LoadTextureFromQ3Shader(skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
858 // don't render unmentioned meshes
859 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
860 if(developer_extra.integer)
861 Con_DPrintf("--> skipping\n");
862 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
868 if(developer_extra.integer)
869 Con_DPrintf("--> using default\n");
870 Image_StripImageExtension(shadername, stripbuf, sizeof(stripbuf));
871 Mod_LoadTextureFromQ3Shader(skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
875 #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);
876 #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);
877 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
879 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
880 float scales, scalet, interval;
884 stvert_t *pinstverts;
885 dtriangle_t *pintriangles;
886 daliasskintype_t *pinskintype;
887 daliasskingroup_t *pinskingroup;
888 daliasskininterval_t *pinskinintervals;
889 daliasframetype_t *pinframetype;
890 daliasgroup_t *pinframegroup;
891 unsigned char *datapointer, *startframes, *startskins;
892 char name[MAX_QPATH];
893 skinframe_t *tempskinframe;
894 animscene_t *tempskinscenes;
895 texture_t *tempaliasskins;
897 int *vertonseam, *vertremap;
898 skinfile_t *skinfiles;
901 datapointer = (unsigned char *)buffer;
902 pinmodel = (mdl_t *)datapointer;
903 datapointer += sizeof(mdl_t);
905 version = LittleLong (pinmodel->version);
906 if (version != ALIAS_VERSION)
907 Host_Error ("%s has wrong version number (%i should be %i)",
908 loadmodel->name, version, ALIAS_VERSION);
910 loadmodel->modeldatatypestring = "MDL";
912 loadmodel->type = mod_alias;
913 loadmodel->DrawSky = NULL;
914 loadmodel->DrawAddWaterPlanes = NULL;
915 loadmodel->Draw = R_Q1BSP_Draw;
916 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
917 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
918 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
919 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
920 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
921 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
922 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
923 loadmodel->DrawLight = R_Q1BSP_DrawLight;
924 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
925 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
926 // FIXME add TraceBrush!
927 loadmodel->PointSuperContents = NULL;
929 loadmodel->num_surfaces = 1;
930 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
931 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
932 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
933 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
934 loadmodel->sortedmodelsurfaces[0] = 0;
936 loadmodel->numskins = LittleLong(pinmodel->numskins);
937 BOUNDI(loadmodel->numskins,0,65536);
938 skinwidth = LittleLong (pinmodel->skinwidth);
939 BOUNDI(skinwidth,0,65536);
940 skinheight = LittleLong (pinmodel->skinheight);
941 BOUNDI(skinheight,0,65536);
942 numverts = LittleLong(pinmodel->numverts);
943 BOUNDI(numverts,0,65536);
944 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
945 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
946 loadmodel->numframes = LittleLong(pinmodel->numframes);
947 BOUNDI(loadmodel->numframes,0,65536);
948 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
949 BOUNDI((int)loadmodel->synctype,0,2);
950 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
951 i = LittleLong (pinmodel->flags);
952 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
954 for (i = 0;i < 3;i++)
956 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
957 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
960 startskins = datapointer;
962 for (i = 0;i < loadmodel->numskins;i++)
964 pinskintype = (daliasskintype_t *)datapointer;
965 datapointer += sizeof(daliasskintype_t);
966 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
970 pinskingroup = (daliasskingroup_t *)datapointer;
971 datapointer += sizeof(daliasskingroup_t);
972 groupskins = LittleLong(pinskingroup->numskins);
973 datapointer += sizeof(daliasskininterval_t) * groupskins;
976 for (j = 0;j < groupskins;j++)
978 datapointer += skinwidth * skinheight;
983 pinstverts = (stvert_t *)datapointer;
984 datapointer += sizeof(stvert_t) * numverts;
986 pintriangles = (dtriangle_t *)datapointer;
987 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
989 startframes = datapointer;
990 loadmodel->surfmesh.num_morphframes = 0;
991 for (i = 0;i < loadmodel->numframes;i++)
993 pinframetype = (daliasframetype_t *)datapointer;
994 datapointer += sizeof(daliasframetype_t);
995 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
999 pinframegroup = (daliasgroup_t *)datapointer;
1000 datapointer += sizeof(daliasgroup_t);
1001 groupframes = LittleLong(pinframegroup->numframes);
1002 datapointer += sizeof(daliasinterval_t) * groupframes;
1005 for (j = 0;j < groupframes;j++)
1007 datapointer += sizeof(daliasframe_t);
1008 datapointer += sizeof(trivertx_t) * numverts;
1009 loadmodel->surfmesh.num_morphframes++;
1012 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1014 // store texture coordinates into temporary array, they will be stored
1015 // after usage is determined (triangle data)
1016 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
1017 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
1018 vertonseam = vertremap + numverts * 2;
1020 scales = 1.0 / skinwidth;
1021 scalet = 1.0 / skinheight;
1022 for (i = 0;i < numverts;i++)
1024 vertonseam[i] = LittleLong(pinstverts[i].onseam);
1025 vertst[i*2+0] = LittleLong(pinstverts[i].s) * scales;
1026 vertst[i*2+1] = LittleLong(pinstverts[i].t) * scalet;
1027 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
1028 vertst[(i+numverts)*2+1] = vertst[i*2+1];
1031 // load triangle data
1032 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1034 // read the triangle elements
1035 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1036 for (j = 0;j < 3;j++)
1037 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1038 // validate (note numverts is used because this is the original data)
1039 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1040 // now butcher the elements according to vertonseam and tri->facesfront
1041 // and then compact the vertex set to remove duplicates
1042 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1043 if (!LittleLong(pintriangles[i].facesfront)) // backface
1044 for (j = 0;j < 3;j++)
1045 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1046 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1048 // (this uses vertremap to count usage to save some memory)
1049 for (i = 0;i < numverts*2;i++)
1051 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1052 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1053 // build remapping table and compact array
1054 loadmodel->surfmesh.num_vertices = 0;
1055 for (i = 0;i < numverts*2;i++)
1059 vertremap[i] = loadmodel->surfmesh.num_vertices;
1060 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1061 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1062 loadmodel->surfmesh.num_vertices++;
1065 vertremap[i] = -1; // not used at all
1067 // remap the elements to the new vertex set
1068 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1069 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1070 // store the texture coordinates
1071 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1072 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1074 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1075 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1078 // generate ushort elements array if possible
1079 if (loadmodel->surfmesh.num_vertices <= 65536)
1080 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1081 if (loadmodel->surfmesh.data_element3s)
1082 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1083 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1086 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1087 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1088 if (r_enableshadowvolumes.integer)
1090 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1092 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1093 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices; // needed during loading, may be cleared by code later in this function
1094 if (loadmodel->surfmesh.data_neighbor3i)
1095 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1096 Mod_Alias_CalculateBoundingBox();
1097 Mod_Alias_MorphMesh_CompileFrames();
1100 Mem_Free(vertremap);
1103 skinfiles = Mod_LoadSkinFiles();
1106 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1107 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1108 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1109 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1110 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1111 Mod_FreeSkinFiles(skinfiles);
1112 for (i = 0;i < loadmodel->numskins;i++)
1114 loadmodel->skinscenes[i].firstframe = i;
1115 loadmodel->skinscenes[i].framecount = 1;
1116 loadmodel->skinscenes[i].loop = true;
1117 loadmodel->skinscenes[i].framerate = 10;
1122 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1123 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1124 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1125 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1127 datapointer = startskins;
1128 for (i = 0;i < loadmodel->numskins;i++)
1130 pinskintype = (daliasskintype_t *)datapointer;
1131 datapointer += sizeof(daliasskintype_t);
1133 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1140 pinskingroup = (daliasskingroup_t *)datapointer;
1141 datapointer += sizeof(daliasskingroup_t);
1143 groupskins = LittleLong (pinskingroup->numskins);
1145 pinskinintervals = (daliasskininterval_t *)datapointer;
1146 datapointer += sizeof(daliasskininterval_t) * groupskins;
1148 interval = LittleFloat(pinskinintervals[0].interval);
1149 if (interval < 0.01f)
1151 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1156 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1157 loadmodel->skinscenes[i].firstframe = totalskins;
1158 loadmodel->skinscenes[i].framecount = groupskins;
1159 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1160 loadmodel->skinscenes[i].loop = true;
1162 for (j = 0;j < groupskins;j++)
1165 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1167 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1168 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))
1169 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));
1170 datapointer += skinwidth * skinheight;
1174 // check for skins that don't exist in the model, but do exist as external images
1175 // (this was added because yummyluv kept pestering me about support for it)
1176 // TODO: support shaders here?
1177 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)))
1179 // expand the arrays to make room
1180 tempskinscenes = loadmodel->skinscenes;
1181 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1182 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1183 Mem_Free(tempskinscenes);
1185 tempaliasskins = loadmodel->data_textures;
1186 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1187 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1188 Mem_Free(tempaliasskins);
1190 // store the info about the new skin
1191 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1192 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1193 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1194 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1195 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1196 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1198 //increase skin counts
1199 loadmodel->numskins++;
1202 // fix up the pointers since they are pointing at the old textures array
1203 // FIXME: this is a hack!
1204 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1205 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1209 surface = loadmodel->data_surfaces;
1210 surface->texture = loadmodel->data_textures;
1211 surface->num_firsttriangle = 0;
1212 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1213 surface->num_firstvertex = 0;
1214 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1216 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1217 if(mod_alias_force_animated.string[0])
1218 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer;
1219 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_MDL_AnimateVertices : NULL;
1221 if (!loadmodel->surfmesh.isanimated)
1223 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1224 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1225 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1226 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1227 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1228 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1231 // because shaders can do somewhat unexpected things, check for unusual features now
1232 for (i = 0;i < loadmodel->num_textures;i++)
1234 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
1235 mod->DrawSky = R_Q1BSP_DrawSky;
1236 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
1237 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
1241 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1243 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1244 float iskinwidth, iskinheight;
1245 unsigned char *data;
1246 msurface_t *surface;
1248 unsigned char *base, *datapointer;
1249 md2frame_t *pinframe;
1251 md2triangle_t *intri;
1252 unsigned short *inst;
1253 struct md2verthash_s
1255 struct md2verthash_s *next;
1259 *hash, **md2verthash, *md2verthashdata;
1260 skinfile_t *skinfiles;
1262 pinmodel = (md2_t *)buffer;
1263 base = (unsigned char *)buffer;
1265 version = LittleLong (pinmodel->version);
1266 if (version != MD2ALIAS_VERSION)
1267 Host_Error ("%s has wrong version number (%i should be %i)",
1268 loadmodel->name, version, MD2ALIAS_VERSION);
1270 loadmodel->modeldatatypestring = "MD2";
1272 loadmodel->type = mod_alias;
1273 loadmodel->DrawSky = NULL;
1274 loadmodel->DrawAddWaterPlanes = NULL;
1275 loadmodel->Draw = R_Q1BSP_Draw;
1276 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1277 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1278 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1279 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1280 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1281 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1282 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1283 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1284 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1285 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1286 loadmodel->PointSuperContents = NULL;
1288 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1289 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1290 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1291 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1292 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1293 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1294 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1295 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1297 end = LittleLong(pinmodel->ofs_end);
1298 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1299 Host_Error ("%s is not a valid model", loadmodel->name);
1300 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1301 Host_Error ("%s is not a valid model", loadmodel->name);
1302 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1303 Host_Error ("%s is not a valid model", loadmodel->name);
1304 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1305 Host_Error ("%s is not a valid model", loadmodel->name);
1306 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1307 Host_Error ("%s is not a valid model", loadmodel->name);
1309 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1310 numxyz = LittleLong(pinmodel->num_xyz);
1311 numst = LittleLong(pinmodel->num_st);
1312 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1313 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1314 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1315 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1316 skinwidth = LittleLong(pinmodel->skinwidth);
1317 skinheight = LittleLong(pinmodel->skinheight);
1318 iskinwidth = 1.0f / skinwidth;
1319 iskinheight = 1.0f / skinheight;
1321 loadmodel->num_surfaces = 1;
1322 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1323 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));
1324 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1325 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1326 loadmodel->sortedmodelsurfaces[0] = 0;
1327 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1328 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1329 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1330 if (r_enableshadowvolumes.integer)
1332 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1335 loadmodel->synctype = ST_RAND;
1338 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1339 skinfiles = Mod_LoadSkinFiles();
1342 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1343 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1344 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1345 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1346 Mod_FreeSkinFiles(skinfiles);
1348 else if (loadmodel->numskins)
1350 // skins found (most likely not a player model)
1351 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1352 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1353 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1354 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1355 Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
1359 // no skins (most likely a player model)
1360 loadmodel->numskins = 1;
1361 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1362 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1363 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1364 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1367 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1368 for (i = 0;i < loadmodel->numskins;i++)
1370 loadmodel->skinscenes[i].firstframe = i;
1371 loadmodel->skinscenes[i].framecount = 1;
1372 loadmodel->skinscenes[i].loop = true;
1373 loadmodel->skinscenes[i].framerate = 10;
1376 // load the triangles and stvert data
1377 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1378 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1379 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1380 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1381 // swap the triangle list
1382 loadmodel->surfmesh.num_vertices = 0;
1383 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1385 for (j = 0;j < 3;j++)
1387 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1388 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1391 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1396 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1399 hashindex = (xyz * 256 + st) & 65535;
1400 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1401 if (hash->xyz == xyz && hash->st == st)
1405 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1408 hash->next = md2verthash[hashindex];
1409 md2verthash[hashindex] = hash;
1411 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1415 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1416 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));
1417 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1418 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1419 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1422 hash = md2verthashdata + i;
1423 vertremap[i] = hash->xyz;
1424 sts = LittleShort(inst[hash->st*2+0]);
1425 stt = LittleShort(inst[hash->st*2+1]);
1426 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1428 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1432 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1433 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1436 Mem_Free(md2verthash);
1437 Mem_Free(md2verthashdata);
1439 // generate ushort elements array if possible
1440 if (loadmodel->surfmesh.num_vertices <= 65536)
1441 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1442 if (loadmodel->surfmesh.data_element3s)
1443 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1444 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1447 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1448 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1453 pinframe = (md2frame_t *)datapointer;
1454 datapointer += sizeof(md2frame_t);
1455 // store the frame scale/translate into the appropriate array
1456 for (j = 0;j < 3;j++)
1458 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1459 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1461 // convert the vertices
1462 v = (trivertx_t *)datapointer;
1463 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1464 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1465 out[k] = v[vertremap[k]];
1466 datapointer += numxyz * sizeof(trivertx_t);
1468 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1469 loadmodel->animscenes[i].firstframe = i;
1470 loadmodel->animscenes[i].framecount = 1;
1471 loadmodel->animscenes[i].framerate = 10;
1472 loadmodel->animscenes[i].loop = true;
1475 Mem_Free(vertremap);
1477 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1478 if(mod_alias_force_animated.string[0])
1479 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer;
1480 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices; // needed during loading, may be cleared by code later in this function
1481 if (loadmodel->surfmesh.data_neighbor3i)
1482 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1483 Mod_Alias_CalculateBoundingBox();
1484 Mod_Alias_MorphMesh_CompileFrames();
1485 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_MDL_AnimateVertices : NULL;
1487 surface = loadmodel->data_surfaces;
1488 surface->texture = loadmodel->data_textures;
1489 surface->num_firsttriangle = 0;
1490 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1491 surface->num_firstvertex = 0;
1492 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1494 if (!loadmodel->surfmesh.isanimated)
1496 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1497 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1498 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1499 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1500 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1501 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1504 // because shaders can do somewhat unexpected things, check for unusual features now
1505 for (i = 0;i < loadmodel->num_textures;i++)
1507 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
1508 mod->DrawSky = R_Q1BSP_DrawSky;
1509 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
1510 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
1514 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1516 int i, j, k, version, meshvertices, meshtriangles;
1517 unsigned char *data;
1518 msurface_t *surface;
1519 md3modelheader_t *pinmodel;
1520 md3frameinfo_t *pinframe;
1523 skinfile_t *skinfiles;
1525 pinmodel = (md3modelheader_t *)buffer;
1527 if (memcmp(pinmodel->identifier, "IDP3", 4))
1528 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1529 version = LittleLong (pinmodel->version);
1530 if (version != MD3VERSION)
1531 Host_Error ("%s has wrong version number (%i should be %i)",
1532 loadmodel->name, version, MD3VERSION);
1534 skinfiles = Mod_LoadSkinFiles();
1535 if (loadmodel->numskins < 1)
1536 loadmodel->numskins = 1;
1538 loadmodel->modeldatatypestring = "MD3";
1540 loadmodel->type = mod_alias;
1541 loadmodel->DrawSky = NULL;
1542 loadmodel->DrawAddWaterPlanes = NULL;
1543 loadmodel->Draw = R_Q1BSP_Draw;
1544 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1545 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1546 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1547 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1548 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1549 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1550 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1551 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1552 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1553 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1554 loadmodel->PointSuperContents = NULL;
1555 loadmodel->synctype = ST_RAND;
1556 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1557 i = LittleLong (pinmodel->flags);
1558 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1560 // set up some global info about the model
1561 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1562 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1564 // make skinscenes for the skins (no groups)
1565 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1566 for (i = 0;i < loadmodel->numskins;i++)
1568 loadmodel->skinscenes[i].firstframe = i;
1569 loadmodel->skinscenes[i].framecount = 1;
1570 loadmodel->skinscenes[i].loop = true;
1571 loadmodel->skinscenes[i].framerate = 10;
1575 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1576 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1578 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1579 loadmodel->animscenes[i].firstframe = i;
1580 loadmodel->animscenes[i].framecount = 1;
1581 loadmodel->animscenes[i].framerate = 10;
1582 loadmodel->animscenes[i].loop = true;
1586 loadmodel->num_tagframes = loadmodel->numframes;
1587 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1588 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1589 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1591 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1592 for (j = 0;j < 9;j++)
1593 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1594 for (j = 0;j < 3;j++)
1595 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1596 //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);
1602 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)))
1604 if (memcmp(pinmesh->identifier, "IDP3", 4))
1605 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1606 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1607 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1608 meshvertices += LittleLong(pinmesh->num_vertices);
1609 meshtriangles += LittleLong(pinmesh->num_triangles);
1612 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1613 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1614 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1615 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));
1616 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1617 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1618 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1619 loadmodel->surfmesh.num_vertices = meshvertices;
1620 loadmodel->surfmesh.num_triangles = meshtriangles;
1621 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1622 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1623 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1624 if (r_enableshadowvolumes.integer)
1626 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1628 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1629 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1630 if (meshvertices <= 65536)
1632 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1637 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)))
1639 if (memcmp(pinmesh->identifier, "IDP3", 4))
1640 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1641 loadmodel->sortedmodelsurfaces[i] = i;
1642 surface = loadmodel->data_surfaces + i;
1643 surface->texture = loadmodel->data_textures + i;
1644 surface->num_firsttriangle = meshtriangles;
1645 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1646 surface->num_firstvertex = meshvertices;
1647 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1648 meshvertices += surface->num_vertices;
1649 meshtriangles += surface->num_triangles;
1651 for (j = 0;j < surface->num_triangles * 3;j++)
1652 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1653 for (j = 0;j < surface->num_vertices;j++)
1655 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1656 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1658 for (j = 0;j < loadmodel->numframes;j++)
1660 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1661 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1662 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1664 out->origin[0] = LittleShort(in->origin[0]);
1665 out->origin[1] = LittleShort(in->origin[1]);
1666 out->origin[2] = LittleShort(in->origin[2]);
1667 out->pitch = in->pitch;
1672 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1674 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1676 if (loadmodel->surfmesh.data_element3s)
1677 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1678 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1679 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1680 if(mod_alias_force_animated.string[0])
1681 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer;
1682 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices; // needed during loading, may be cleared by code later in this function
1683 if (loadmodel->surfmesh.data_neighbor3i)
1684 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1685 Mod_Alias_MorphMesh_CompileFrames();
1686 Mod_Alias_CalculateBoundingBox();
1687 Mod_FreeSkinFiles(skinfiles);
1688 Mod_MakeSortedSurfaces(loadmodel);
1689 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_MD3_AnimateVertices : NULL;
1691 if (!loadmodel->surfmesh.isanimated)
1693 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1694 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1695 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1696 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1697 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1698 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1701 // because shaders can do somewhat unexpected things, check for unusual features now
1702 for (i = 0;i < loadmodel->num_textures;i++)
1704 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
1705 mod->DrawSky = R_Q1BSP_DrawSky;
1706 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
1707 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
1711 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1713 zymtype1header_t *pinmodel, *pheader;
1714 unsigned char *pbase;
1715 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1716 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose, f, biggestorigin, tempvec[3], modelscale;
1717 zymvertex_t *verts, *vertdata;
1721 skinfile_t *skinfiles;
1722 unsigned char *data;
1723 msurface_t *surface;
1725 pinmodel = (zymtype1header_t *)buffer;
1726 pbase = (unsigned char *)buffer;
1727 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1728 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1729 if (BigLong(pinmodel->type) != 1)
1730 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1732 loadmodel->modeldatatypestring = "ZYM";
1734 loadmodel->type = mod_alias;
1735 loadmodel->synctype = ST_RAND;
1739 pheader->type = BigLong(pinmodel->type);
1740 pheader->filesize = BigLong(pinmodel->filesize);
1741 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1742 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1743 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1744 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1745 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1746 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1747 pheader->radius = BigFloat(pinmodel->radius);
1748 pheader->numverts = BigLong(pinmodel->numverts);
1749 pheader->numtris = BigLong(pinmodel->numtris);
1750 pheader->numshaders = BigLong(pinmodel->numshaders);
1751 pheader->numbones = BigLong(pinmodel->numbones);
1752 pheader->numscenes = BigLong(pinmodel->numscenes);
1753 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1754 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1755 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1756 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1757 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1758 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1759 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1760 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1761 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1762 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1763 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1764 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1765 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1766 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1767 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1768 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1769 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1770 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1772 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1774 Con_Printf("%s has no geometry\n", loadmodel->name);
1777 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1779 Con_Printf("%s has no animations\n", loadmodel->name);
1783 loadmodel->DrawSky = NULL;
1784 loadmodel->DrawAddWaterPlanes = NULL;
1785 loadmodel->Draw = R_Q1BSP_Draw;
1786 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1787 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1788 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1789 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1790 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1791 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1792 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1793 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1794 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1795 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1796 loadmodel->PointSuperContents = NULL;
1798 loadmodel->numframes = pheader->numscenes;
1799 loadmodel->num_surfaces = pheader->numshaders;
1801 skinfiles = Mod_LoadSkinFiles();
1802 if (loadmodel->numskins < 1)
1803 loadmodel->numskins = 1;
1805 // make skinscenes for the skins (no groups)
1806 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1807 for (i = 0;i < loadmodel->numskins;i++)
1809 loadmodel->skinscenes[i].firstframe = i;
1810 loadmodel->skinscenes[i].framecount = 1;
1811 loadmodel->skinscenes[i].loop = true;
1812 loadmodel->skinscenes[i].framerate = 10;
1816 modelradius = pheader->radius;
1817 for (i = 0;i < 3;i++)
1819 loadmodel->normalmins[i] = pheader->mins[i];
1820 loadmodel->normalmaxs[i] = pheader->maxs[i];
1821 loadmodel->rotatedmins[i] = -modelradius;
1822 loadmodel->rotatedmaxs[i] = modelradius;
1824 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1825 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1826 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1827 if (loadmodel->yawmaxs[0] > modelradius)
1828 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1829 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1830 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1831 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1832 loadmodel->radius = modelradius;
1833 loadmodel->radius2 = modelradius * modelradius;
1835 // go through the lumps, swapping things
1837 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1838 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1839 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1840 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1841 for (i = 0;i < pheader->numscenes;i++)
1843 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1844 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1845 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1846 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1847 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1848 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1849 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1850 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1851 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1852 if (loadmodel->animscenes[i].framerate < 0)
1853 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1857 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1858 loadmodel->num_bones = pheader->numbones;
1859 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1860 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1861 for (i = 0;i < pheader->numbones;i++)
1863 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1864 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1865 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1866 if (loadmodel->data_bones[i].parent >= i)
1867 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1870 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1871 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1872 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1873 for (i = 0;i < pheader->numverts;i++)
1875 vertbonecounts[i] = BigLong(bonecount[i]);
1876 if (vertbonecounts[i] != 1)
1877 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1880 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1882 meshvertices = pheader->numverts;
1883 meshtriangles = pheader->numtris;
1885 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1886 if(mod_alias_force_animated.string[0])
1887 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer;
1888 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
1889 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1890 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1891 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1892 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]) + meshvertices * sizeof(unsigned short) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]) + loadmodel->num_bones * sizeof(float[12]));
1893 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1894 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1895 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1896 loadmodel->surfmesh.num_vertices = meshvertices;
1897 loadmodel->surfmesh.num_triangles = meshtriangles;
1898 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1899 if (r_enableshadowvolumes.integer)
1901 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1903 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1904 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1905 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1906 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1907 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1908 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1909 loadmodel->surfmesh.num_blends = 0;
1910 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
1911 if (loadmodel->surfmesh.num_vertices <= 65536)
1913 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1915 loadmodel->data_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
1916 loadmodel->surfmesh.data_blendweights = NULL;
1918 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1919 poses = (float *) (pheader->lump_poses.start + pbase);
1920 // figure out scale of model from root bone, for compatibility with old zmodel versions
1921 tempvec[0] = BigFloat(poses[0]);
1922 tempvec[1] = BigFloat(poses[1]);
1923 tempvec[2] = BigFloat(poses[2]);
1924 modelscale = VectorLength(tempvec);
1926 for (i = 0;i < loadmodel->num_bones * numposes * 12;i++)
1928 f = fabs(BigFloat(poses[i]));
1929 biggestorigin = max(biggestorigin, f);
1931 loadmodel->num_posescale = biggestorigin / 32767.0f;
1932 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
1933 for (i = 0;i < numposes;i++)
1935 const float *frameposes = (float *) (pheader->lump_poses.start + pbase) + 12*i*loadmodel->num_bones;
1936 for (j = 0;j < loadmodel->num_bones;j++)
1939 matrix4x4_t posematrix;
1940 for (k = 0;k < 12;k++)
1941 pose[k] = BigFloat(frameposes[j*12+k]);
1942 //if (j < loadmodel->num_bones)
1943 // 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));
1944 // scale child bones to match the root scale
1945 if (loadmodel->data_bones[j].parent >= 0)
1947 pose[3] *= modelscale;
1948 pose[7] *= modelscale;
1949 pose[11] *= modelscale;
1951 // normalize rotation matrix
1952 VectorNormalize(pose + 0);
1953 VectorNormalize(pose + 4);
1954 VectorNormalize(pose + 8);
1955 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
1956 Matrix4x4_ToBonePose7s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses7s + 7*(i*loadmodel->num_bones+j));
1960 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1961 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1962 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1963 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1964 // (converting from weight-blending skeletal animation to
1965 // deformation-based skeletal animation)
1966 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1967 for (i = 0;i < loadmodel->num_bones;i++)
1970 for (k = 0;k < 12;k++)
1971 m[k] = BigFloat(poses[i*12+k]);
1972 if (loadmodel->data_bones[i].parent >= 0)
1973 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1975 for (k = 0;k < 12;k++)
1976 bonepose[12*i+k] = m[k];
1978 for (j = 0;j < pheader->numverts;j++)
1980 // this format really should have had a per vertexweight weight value...
1981 // but since it does not, the weighting is completely ignored and
1982 // only one weight is allowed per vertex
1983 int boneindex = BigLong(vertdata[j].bonenum);
1984 const float *m = bonepose + 12 * boneindex;
1985 float relativeorigin[3];
1986 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1987 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1988 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1989 // transform the vertex bone weight into the base mesh
1990 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1991 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1992 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1993 // store the weight as the primary weight on this vertex
1994 loadmodel->surfmesh.blends[j] = boneindex;
1997 // normals and tangents are calculated after elements are loaded
1999 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
2000 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
2001 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
2002 for (i = 0;i < pheader->numverts;i++)
2004 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
2005 // flip T coordinate for OpenGL
2006 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
2009 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
2010 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
2011 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
2013 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
2014 //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)
2015 // byteswap, validate, and swap winding order of tris
2016 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
2017 if (pheader->lump_render.length != count)
2018 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
2019 renderlist = (int *) (pheader->lump_render.start + pbase);
2020 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
2022 for (i = 0;i < loadmodel->num_surfaces;i++)
2024 int firstvertex, lastvertex;
2025 if (renderlist >= renderlistend)
2026 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2027 count = BigLong(*renderlist);renderlist++;
2028 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
2029 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2031 loadmodel->sortedmodelsurfaces[i] = i;
2032 surface = loadmodel->data_surfaces + i;
2033 surface->texture = loadmodel->data_textures + i;
2034 surface->num_firsttriangle = meshtriangles;
2035 surface->num_triangles = count;
2036 meshtriangles += surface->num_triangles;
2038 // load the elements
2039 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2040 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
2042 outelements[j*3+2] = BigLong(renderlist[0]);
2043 outelements[j*3+1] = BigLong(renderlist[1]);
2044 outelements[j*3+0] = BigLong(renderlist[2]);
2046 // validate the elements and find the used vertex range
2047 firstvertex = meshvertices;
2049 for (j = 0;j < surface->num_triangles * 3;j++)
2051 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
2052 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
2053 firstvertex = min(firstvertex, outelements[j]);
2054 lastvertex = max(lastvertex, outelements[j]);
2056 surface->num_firstvertex = firstvertex;
2057 surface->num_vertices = lastvertex + 1 - firstvertex;
2059 // since zym models do not have named sections, reuse their shader
2060 // name as the section name
2061 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
2062 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
2064 Mod_FreeSkinFiles(skinfiles);
2065 Mem_Free(vertbonecounts);
2067 Mod_MakeSortedSurfaces(loadmodel);
2069 // compute all the mesh information that was not loaded from the file
2070 if (loadmodel->surfmesh.data_element3s)
2071 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2072 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2073 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2074 Mod_BuildBaseBonePoses();
2075 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);
2076 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);
2077 if (loadmodel->surfmesh.data_neighbor3i)
2078 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2080 if (!loadmodel->surfmesh.isanimated)
2082 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2083 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2084 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2085 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2086 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2087 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2090 // because shaders can do somewhat unexpected things, check for unusual features now
2091 for (i = 0;i < loadmodel->num_textures;i++)
2093 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
2094 mod->DrawSky = R_Q1BSP_DrawSky;
2095 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
2096 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
2100 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2102 dpmheader_t *pheader;
2106 unsigned char *pbase;
2107 int i, j, k, meshvertices, meshtriangles;
2108 skinfile_t *skinfiles;
2109 unsigned char *data;
2111 float biggestorigin, tempvec[3], modelscale;
2115 pheader = (dpmheader_t *)buffer;
2116 pbase = (unsigned char *)buffer;
2117 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2118 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2119 if (BigLong(pheader->type) != 2)
2120 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2122 loadmodel->modeldatatypestring = "DPM";
2124 loadmodel->type = mod_alias;
2125 loadmodel->synctype = ST_RAND;
2128 pheader->type = BigLong(pheader->type);
2129 pheader->filesize = BigLong(pheader->filesize);
2130 pheader->mins[0] = BigFloat(pheader->mins[0]);
2131 pheader->mins[1] = BigFloat(pheader->mins[1]);
2132 pheader->mins[2] = BigFloat(pheader->mins[2]);
2133 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2134 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2135 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2136 pheader->yawradius = BigFloat(pheader->yawradius);
2137 pheader->allradius = BigFloat(pheader->allradius);
2138 pheader->num_bones = BigLong(pheader->num_bones);
2139 pheader->num_meshs = BigLong(pheader->num_meshs);
2140 pheader->num_frames = BigLong(pheader->num_frames);
2141 pheader->ofs_bones = BigLong(pheader->ofs_bones);
2142 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2143 pheader->ofs_frames = BigLong(pheader->ofs_frames);
2145 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2147 Con_Printf("%s has no geometry\n", loadmodel->name);
2150 if (pheader->num_frames < 1)
2152 Con_Printf("%s has no frames\n", loadmodel->name);
2156 loadmodel->DrawSky = NULL;
2157 loadmodel->DrawAddWaterPlanes = NULL;
2158 loadmodel->Draw = R_Q1BSP_Draw;
2159 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2160 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2161 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2162 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2163 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2164 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2165 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2166 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2167 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2168 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2169 loadmodel->PointSuperContents = NULL;
2172 for (i = 0;i < 3;i++)
2174 loadmodel->normalmins[i] = pheader->mins[i];
2175 loadmodel->normalmaxs[i] = pheader->maxs[i];
2176 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2177 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2178 loadmodel->rotatedmins[i] = -pheader->allradius;
2179 loadmodel->rotatedmaxs[i] = pheader->allradius;
2181 loadmodel->radius = pheader->allradius;
2182 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2184 // load external .skin files if present
2185 skinfiles = Mod_LoadSkinFiles();
2186 if (loadmodel->numskins < 1)
2187 loadmodel->numskins = 1;
2192 // gather combined statistics from the meshes
2193 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2194 for (i = 0;i < (int)pheader->num_meshs;i++)
2196 int numverts = BigLong(dpmmesh->num_verts);
2197 meshvertices += numverts;
2198 meshtriangles += BigLong(dpmmesh->num_tris);
2202 loadmodel->numframes = pheader->num_frames;
2203 loadmodel->num_bones = pheader->num_bones;
2204 loadmodel->num_poses = loadmodel->numframes;
2205 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2206 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2207 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2208 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
2209 if(mod_alias_force_animated.string[0])
2210 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer;
2211 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
2212 // do most allocations as one merged chunk
2213 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)) + 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));
2214 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2215 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2216 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2217 loadmodel->surfmesh.num_vertices = meshvertices;
2218 loadmodel->surfmesh.num_triangles = meshtriangles;
2219 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2220 if (r_enableshadowvolumes.integer)
2222 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2224 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2225 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2226 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2227 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2228 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2229 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2230 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2231 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2232 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2233 loadmodel->surfmesh.num_blends = 0;
2234 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2235 if (meshvertices <= 65536)
2237 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2239 loadmodel->data_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
2240 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
2242 for (i = 0;i < loadmodel->numskins;i++)
2244 loadmodel->skinscenes[i].firstframe = i;
2245 loadmodel->skinscenes[i].framecount = 1;
2246 loadmodel->skinscenes[i].loop = true;
2247 loadmodel->skinscenes[i].framerate = 10;
2250 // load the bone info
2251 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2252 for (i = 0;i < loadmodel->num_bones;i++)
2254 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2255 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2256 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2257 if (loadmodel->data_bones[i].parent >= i)
2258 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2262 frames = (dpmframe_t *) (pbase + pheader->ofs_frames);
2263 // figure out scale of model from root bone, for compatibility with old dpmodel versions
2264 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2265 tempvec[0] = BigFloat(poses[0]);
2266 tempvec[1] = BigFloat(poses[1]);
2267 tempvec[2] = BigFloat(poses[2]);
2268 modelscale = VectorLength(tempvec);
2270 for (i = 0;i < loadmodel->numframes;i++)
2272 memcpy(loadmodel->animscenes[i].name, frames[i].name, sizeof(frames[i].name));
2273 loadmodel->animscenes[i].firstframe = i;
2274 loadmodel->animscenes[i].framecount = 1;
2275 loadmodel->animscenes[i].loop = true;
2276 loadmodel->animscenes[i].framerate = 10;
2277 // load the bone poses for this frame
2278 poses = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2279 for (j = 0;j < loadmodel->num_bones*12;j++)
2281 f = fabs(BigFloat(poses[j]));
2282 biggestorigin = max(biggestorigin, f);
2284 // stuff not processed here: mins, maxs, yawradius, allradius
2286 loadmodel->num_posescale = biggestorigin / 32767.0f;
2287 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2288 for (i = 0;i < loadmodel->numframes;i++)
2290 const float *frameposes = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2291 for (j = 0;j < loadmodel->num_bones;j++)
2294 matrix4x4_t posematrix;
2295 for (k = 0;k < 12;k++)
2296 pose[k] = BigFloat(frameposes[j*12+k]);
2297 // scale child bones to match the root scale
2298 if (loadmodel->data_bones[j].parent >= 0)
2300 pose[3] *= modelscale;
2301 pose[7] *= modelscale;
2302 pose[11] *= modelscale;
2304 // normalize rotation matrix
2305 VectorNormalize(pose + 0);
2306 VectorNormalize(pose + 4);
2307 VectorNormalize(pose + 8);
2308 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2309 Matrix4x4_ToBonePose7s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses7s + 7*(i*loadmodel->num_bones+j));
2313 // load the meshes now
2314 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2317 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2318 // (converting from weight-blending skeletal animation to
2319 // deformation-based skeletal animation)
2320 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2321 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2322 for (i = 0;i < loadmodel->num_bones;i++)
2325 for (k = 0;k < 12;k++)
2326 m[k] = BigFloat(poses[i*12+k]);
2327 if (loadmodel->data_bones[i].parent >= 0)
2328 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2330 for (k = 0;k < 12;k++)
2331 bonepose[12*i+k] = m[k];
2333 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2335 const int *inelements;
2337 const float *intexcoord;
2338 msurface_t *surface;
2340 loadmodel->sortedmodelsurfaces[i] = i;
2341 surface = loadmodel->data_surfaces + i;
2342 surface->texture = loadmodel->data_textures + i;
2343 surface->num_firsttriangle = meshtriangles;
2344 surface->num_triangles = BigLong(dpmmesh->num_tris);
2345 surface->num_firstvertex = meshvertices;
2346 surface->num_vertices = BigLong(dpmmesh->num_verts);
2347 meshvertices += surface->num_vertices;
2348 meshtriangles += surface->num_triangles;
2350 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2351 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2352 for (j = 0;j < surface->num_triangles;j++)
2354 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2355 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2356 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2357 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2362 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2363 for (j = 0;j < surface->num_vertices*2;j++)
2364 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2366 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2367 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2369 int weightindex[4] = { 0, 0, 0, 0 };
2370 float weightinfluence[4] = { 0, 0, 0, 0 };
2372 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2373 data += sizeof(dpmvertex_t);
2374 for (k = 0;k < numweights;k++)
2376 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2377 int boneindex = BigLong(vert->bonenum);
2378 const float *m = bonepose + 12 * boneindex;
2379 float influence = BigFloat(vert->influence);
2380 float relativeorigin[3], relativenormal[3];
2381 relativeorigin[0] = BigFloat(vert->origin[0]);
2382 relativeorigin[1] = BigFloat(vert->origin[1]);
2383 relativeorigin[2] = BigFloat(vert->origin[2]);
2384 relativenormal[0] = BigFloat(vert->normal[0]);
2385 relativenormal[1] = BigFloat(vert->normal[1]);
2386 relativenormal[2] = BigFloat(vert->normal[2]);
2387 // blend the vertex bone weights into the base mesh
2388 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2389 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2390 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2391 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2392 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2393 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2396 // store the first (and often only) weight
2397 weightinfluence[0] = influence;
2398 weightindex[0] = boneindex;
2402 // sort the new weight into this vertex's weight table
2403 // (which only accepts up to 4 bones per vertex)
2404 for (l = 0;l < 4;l++)
2406 if (weightinfluence[l] < influence)
2408 // move weaker influence weights out of the way first
2410 for (l2 = 3;l2 > l;l2--)
2412 weightinfluence[l2] = weightinfluence[l2-1];
2413 weightindex[l2] = weightindex[l2-1];
2415 // store the new weight
2416 weightinfluence[l] = influence;
2417 weightindex[l] = boneindex;
2422 data += sizeof(dpmbonevert_t);
2424 loadmodel->surfmesh.blends[j] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
2427 // since dpm models do not have named sections, reuse their shader name as the section name
2428 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2430 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2432 if (loadmodel->surfmesh.num_blends < meshvertices)
2433 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2435 Mod_FreeSkinFiles(skinfiles);
2436 Mod_MakeSortedSurfaces(loadmodel);
2438 // compute all the mesh information that was not loaded from the file
2439 if (loadmodel->surfmesh.data_element3s)
2440 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2441 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2442 Mod_BuildBaseBonePoses();
2443 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);
2444 if (loadmodel->surfmesh.data_neighbor3i)
2445 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2447 if (!loadmodel->surfmesh.isanimated)
2449 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2450 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2451 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2452 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2453 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2454 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2457 // because shaders can do somewhat unexpected things, check for unusual features now
2458 for (i = 0;i < loadmodel->num_textures;i++)
2460 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
2461 mod->DrawSky = R_Q1BSP_DrawSky;
2462 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
2463 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
2467 // no idea why PSK/PSA files contain weird quaternions but they do...
2468 #define PSKQUATNEGATIONS
2469 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2471 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2472 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2473 fs_offset_t filesize;
2478 pskboneinfo_t *bones;
2479 pskrawweights_t *rawweights;
2480 //pskboneinfo_t *animbones;
2481 pskaniminfo_t *anims;
2482 pskanimkeys_t *animkeys;
2483 void *animfilebuffer, *animbuffer, *animbufferend;
2484 unsigned char *data;
2486 skinfile_t *skinfiles;
2487 char animname[MAX_QPATH];
2489 float biggestorigin;
2491 pchunk = (pskchunk_t *)buffer;
2492 if (strcmp(pchunk->id, "ACTRHEAD"))
2493 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2495 loadmodel->modeldatatypestring = "PSK";
2497 loadmodel->type = mod_alias;
2498 loadmodel->DrawSky = NULL;
2499 loadmodel->DrawAddWaterPlanes = NULL;
2500 loadmodel->Draw = R_Q1BSP_Draw;
2501 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2502 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2503 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2504 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2505 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2506 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2507 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2508 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2509 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2510 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2511 loadmodel->PointSuperContents = NULL;
2512 loadmodel->synctype = ST_RAND;
2514 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2515 strlcat(animname, ".psa", sizeof(animname));
2516 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2517 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2519 animbufferend = animbuffer;
2538 while (buffer < bufferend)
2540 pchunk = (pskchunk_t *)buffer;
2541 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2542 version = LittleLong(pchunk->version);
2543 recordsize = LittleLong(pchunk->recordsize);
2544 numrecords = LittleLong(pchunk->numrecords);
2545 if (developer_extra.integer)
2546 Con_DPrintf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2547 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2548 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);
2549 if (!strcmp(pchunk->id, "ACTRHEAD"))
2553 else if (!strcmp(pchunk->id, "PNTS0000"))
2556 if (recordsize != sizeof(*p))
2557 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2558 // byteswap in place and keep the pointer
2559 numpnts = numrecords;
2560 pnts = (pskpnts_t *)buffer;
2561 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2563 p->origin[0] = LittleFloat(p->origin[0]);
2564 p->origin[1] = LittleFloat(p->origin[1]);
2565 p->origin[2] = LittleFloat(p->origin[2]);
2569 else if (!strcmp(pchunk->id, "VTXW0000"))
2572 if (recordsize != sizeof(*p))
2573 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2574 // byteswap in place and keep the pointer
2575 numvtxw = numrecords;
2576 vtxw = (pskvtxw_t *)buffer;
2577 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2579 p->pntsindex = LittleShort(p->pntsindex);
2580 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2581 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2582 if (p->pntsindex >= numpnts)
2584 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2590 else if (!strcmp(pchunk->id, "FACE0000"))
2593 if (recordsize != sizeof(*p))
2594 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2595 // byteswap in place and keep the pointer
2596 numfaces = numrecords;
2597 faces = (pskface_t *)buffer;
2598 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2600 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2601 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2602 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2603 p->group = LittleLong(p->group);
2604 if (p->vtxwindex[0] >= numvtxw)
2606 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2607 p->vtxwindex[0] = 0;
2609 if (p->vtxwindex[1] >= numvtxw)
2611 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2612 p->vtxwindex[1] = 0;
2614 if (p->vtxwindex[2] >= numvtxw)
2616 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2617 p->vtxwindex[2] = 0;
2622 else if (!strcmp(pchunk->id, "MATT0000"))
2625 if (recordsize != sizeof(*p))
2626 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2627 // byteswap in place and keep the pointer
2628 nummatts = numrecords;
2629 matts = (pskmatt_t *)buffer;
2630 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2636 else if (!strcmp(pchunk->id, "REFSKELT"))
2639 if (recordsize != sizeof(*p))
2640 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2641 // byteswap in place and keep the pointer
2642 numbones = numrecords;
2643 bones = (pskboneinfo_t *)buffer;
2644 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2646 p->numchildren = LittleLong(p->numchildren);
2647 p->parent = LittleLong(p->parent);
2648 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2649 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2650 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2651 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2652 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2653 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2654 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2655 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2656 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2657 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2658 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2659 #ifdef PSKQUATNEGATIONS
2662 p->basepose.quat[0] *= -1;
2663 p->basepose.quat[1] *= -1;
2664 p->basepose.quat[2] *= -1;
2668 p->basepose.quat[0] *= 1;
2669 p->basepose.quat[1] *= -1;
2670 p->basepose.quat[2] *= 1;
2673 if (p->parent < 0 || p->parent >= numbones)
2675 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2681 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2684 if (recordsize != sizeof(*p))
2685 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2686 // byteswap in place and keep the pointer
2687 numrawweights = numrecords;
2688 rawweights = (pskrawweights_t *)buffer;
2689 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2691 p->weight = LittleFloat(p->weight);
2692 p->pntsindex = LittleLong(p->pntsindex);
2693 p->boneindex = LittleLong(p->boneindex);
2694 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2696 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2699 if (p->boneindex < 0 || p->boneindex >= numbones)
2701 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2709 while (animbuffer < animbufferend)
2711 pchunk = (pskchunk_t *)animbuffer;
2712 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2713 version = LittleLong(pchunk->version);
2714 recordsize = LittleLong(pchunk->recordsize);
2715 numrecords = LittleLong(pchunk->numrecords);
2716 if (developer_extra.integer)
2717 Con_DPrintf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2718 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2719 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);
2720 if (!strcmp(pchunk->id, "ANIMHEAD"))
2724 else if (!strcmp(pchunk->id, "BONENAMES"))
2727 if (recordsize != sizeof(*p))
2728 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2729 // byteswap in place and keep the pointer
2730 numanimbones = numrecords;
2731 //animbones = (pskboneinfo_t *)animbuffer;
2732 // NOTE: supposedly psa does not need to match the psk model, the
2733 // bones missing from the psa would simply use their base
2734 // positions from the psk, but this is hard for me to implement
2735 // and people can easily make animations that match.
2736 if (numanimbones != numbones)
2737 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2738 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2740 p->numchildren = LittleLong(p->numchildren);
2741 p->parent = LittleLong(p->parent);
2742 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2743 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2744 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2745 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2746 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2747 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2748 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2749 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2750 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2751 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2752 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2753 #ifdef PSKQUATNEGATIONS
2756 p->basepose.quat[0] *= -1;
2757 p->basepose.quat[1] *= -1;
2758 p->basepose.quat[2] *= -1;
2762 p->basepose.quat[0] *= 1;
2763 p->basepose.quat[1] *= -1;
2764 p->basepose.quat[2] *= 1;
2767 if (p->parent < 0 || p->parent >= numanimbones)
2769 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2772 // check that bones are the same as in the base
2773 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2774 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2778 else if (!strcmp(pchunk->id, "ANIMINFO"))
2781 if (recordsize != sizeof(*p))
2782 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2783 // byteswap in place and keep the pointer
2784 numanims = numrecords;
2785 anims = (pskaniminfo_t *)animbuffer;
2786 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2788 p->numbones = LittleLong(p->numbones);
2789 p->playtime = LittleFloat(p->playtime);
2790 p->fps = LittleFloat(p->fps);
2791 p->firstframe = LittleLong(p->firstframe);
2792 p->numframes = LittleLong(p->numframes);
2793 if (p->numbones != numbones)
2794 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2798 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2801 if (recordsize != sizeof(*p))
2802 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2803 numanimkeys = numrecords;
2804 animkeys = (pskanimkeys_t *)animbuffer;
2805 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2807 p->origin[0] = LittleFloat(p->origin[0]);
2808 p->origin[1] = LittleFloat(p->origin[1]);
2809 p->origin[2] = LittleFloat(p->origin[2]);
2810 p->quat[0] = LittleFloat(p->quat[0]);
2811 p->quat[1] = LittleFloat(p->quat[1]);
2812 p->quat[2] = LittleFloat(p->quat[2]);
2813 p->quat[3] = LittleFloat(p->quat[3]);
2814 p->frametime = LittleFloat(p->frametime);
2815 #ifdef PSKQUATNEGATIONS
2816 if (index % numbones)
2831 // TODO: allocate bonepose stuff
2834 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2837 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights)
2838 Host_Error("%s: missing required chunks", loadmodel->name);
2842 loadmodel->numframes = 0;
2843 for (index = 0;index < numanims;index++)
2844 loadmodel->numframes += anims[index].numframes;
2845 if (numanimkeys != numbones * loadmodel->numframes)
2846 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2849 loadmodel->numframes = loadmodel->num_poses = 1;
2851 meshvertices = numvtxw;
2852 meshtriangles = numfaces;
2854 // load external .skin files if present
2855 skinfiles = Mod_LoadSkinFiles();
2856 if (loadmodel->numskins < 1)
2857 loadmodel->numskins = 1;
2858 loadmodel->num_bones = numbones;
2859 loadmodel->num_poses = loadmodel->numframes;
2860 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2861 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2862 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2863 loadmodel->surfmesh.num_vertices = meshvertices;
2864 loadmodel->surfmesh.num_triangles = meshtriangles;
2865 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
2866 if(mod_alias_force_animated.string[0])
2867 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer;
2868 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
2869 // do most allocations as one merged chunk
2870 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 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);
2871 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2872 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2873 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2874 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2875 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2876 if (r_enableshadowvolumes.integer)
2878 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2880 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2881 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2882 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2883 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2884 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2885 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2886 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2887 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2888 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2889 loadmodel->surfmesh.num_blends = 0;
2890 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2891 if (loadmodel->surfmesh.num_vertices <= 65536)
2893 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2895 loadmodel->data_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
2896 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(blendweights_t));
2898 for (i = 0;i < loadmodel->numskins;i++)
2900 loadmodel->skinscenes[i].firstframe = i;
2901 loadmodel->skinscenes[i].framecount = 1;
2902 loadmodel->skinscenes[i].loop = true;
2903 loadmodel->skinscenes[i].framerate = 10;
2907 for (index = 0, i = 0;index < nummatts;index++)
2909 // since psk models do not have named sections, reuse their shader name as the section name
2910 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2911 loadmodel->sortedmodelsurfaces[index] = index;
2912 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2913 loadmodel->data_surfaces[index].num_firstvertex = 0;
2914 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2917 // copy over the vertex locations and texcoords
2918 for (index = 0;index < numvtxw;index++)
2920 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2921 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2922 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2923 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2924 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2927 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2928 for (index = 0;index < numfaces;index++)
2929 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2930 for (index = 0, i = 0;index < nummatts;index++)
2932 loadmodel->data_surfaces[index].num_firsttriangle = i;
2933 i += loadmodel->data_surfaces[index].num_triangles;
2934 loadmodel->data_surfaces[index].num_triangles = 0;
2936 for (index = 0;index < numfaces;index++)
2938 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2939 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2940 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2941 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2944 // copy over the bones
2945 for (index = 0;index < numbones;index++)
2947 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2948 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2949 if (loadmodel->data_bones[index].parent >= index)
2950 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2953 // convert the basepose data
2954 if (loadmodel->num_bones)
2957 matrix4x4_t *basebonepose;
2958 float *outinvmatrix = loadmodel->data_baseboneposeinverse;
2959 matrix4x4_t bonematrix;
2960 matrix4x4_t tempbonematrix;
2961 basebonepose = (matrix4x4_t *)Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(matrix4x4_t));
2962 for (boneindex = 0;boneindex < loadmodel->num_bones;boneindex++)
2964 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]);
2965 if (loadmodel->data_bones[boneindex].parent >= 0)
2967 tempbonematrix = bonematrix;
2968 Matrix4x4_Concat(&bonematrix, basebonepose + loadmodel->data_bones[boneindex].parent, &tempbonematrix);
2970 basebonepose[boneindex] = bonematrix;
2971 Matrix4x4_Invert_Simple(&tempbonematrix, basebonepose + boneindex);
2972 Matrix4x4_ToArray12FloatD3D(&tempbonematrix, outinvmatrix + 12*boneindex);
2974 Mem_Free(basebonepose);
2977 // sort the psk point weights into the vertex weight tables
2978 // (which only accept up to 4 bones per vertex)
2979 for (index = 0;index < numvtxw;index++)
2981 int weightindex[4] = { 0, 0, 0, 0 };
2982 float weightinfluence[4] = { 0, 0, 0, 0 };
2984 for (j = 0;j < numrawweights;j++)
2986 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2988 int boneindex = rawweights[j].boneindex;
2989 float influence = rawweights[j].weight;
2990 for (l = 0;l < 4;l++)
2992 if (weightinfluence[l] < influence)
2994 // move lower influence weights out of the way first
2996 for (l2 = 3;l2 > l;l2--)
2998 weightinfluence[l2] = weightinfluence[l2-1];
2999 weightindex[l2] = weightindex[l2-1];
3001 // store the new weight
3002 weightinfluence[l] = influence;
3003 weightindex[l] = boneindex;
3009 loadmodel->surfmesh.blends[index] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
3011 if (loadmodel->surfmesh.num_blends < loadmodel->surfmesh.num_vertices)
3012 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
3014 // set up the animscenes based on the anims
3017 for (index = 0, i = 0;index < numanims;index++)
3019 for (j = 0;j < anims[index].numframes;j++, i++)
3021 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
3022 loadmodel->animscenes[i].firstframe = i;
3023 loadmodel->animscenes[i].framecount = 1;
3024 loadmodel->animscenes[i].loop = true;
3025 loadmodel->animscenes[i].framerate = anims[index].fps;
3028 // calculate the scaling value for bone origins so they can be compressed to short
3030 for (index = 0;index < numanimkeys;index++)
3032 pskanimkeys_t *k = animkeys + index;
3033 biggestorigin = max(biggestorigin, fabs(k->origin[0]));
3034 biggestorigin = max(biggestorigin, fabs(k->origin[1]));
3035 biggestorigin = max(biggestorigin, fabs(k->origin[2]));
3037 loadmodel->num_posescale = biggestorigin / 32767.0f;
3038 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3040 // load the poses from the animkeys
3041 for (index = 0;index < numanimkeys;index++)
3043 pskanimkeys_t *k = animkeys + index;
3045 Vector4Copy(k->quat, quat);
3047 Vector4Negate(quat, quat);
3048 Vector4Normalize2(quat, quat);
3049 // compress poses to the short[7] format for longterm storage
3050 loadmodel->data_poses7s[index*7+0] = k->origin[0] * loadmodel->num_poseinvscale;
3051 loadmodel->data_poses7s[index*7+1] = k->origin[1] * loadmodel->num_poseinvscale;
3052 loadmodel->data_poses7s[index*7+2] = k->origin[2] * loadmodel->num_poseinvscale;
3053 loadmodel->data_poses7s[index*7+3] = quat[0] * 32767.0f;
3054 loadmodel->data_poses7s[index*7+4] = quat[1] * 32767.0f;
3055 loadmodel->data_poses7s[index*7+5] = quat[2] * 32767.0f;
3056 loadmodel->data_poses7s[index*7+6] = quat[3] * 32767.0f;
3061 strlcpy(loadmodel->animscenes[0].name, "base", sizeof(loadmodel->animscenes[0].name));
3062 loadmodel->animscenes[0].firstframe = 0;
3063 loadmodel->animscenes[0].framecount = 1;
3064 loadmodel->animscenes[0].loop = true;
3065 loadmodel->animscenes[0].framerate = 10;
3067 // calculate the scaling value for bone origins so they can be compressed to short
3069 for (index = 0;index < numbones;index++)
3071 pskboneinfo_t *p = bones + index;
3072 biggestorigin = max(biggestorigin, fabs(p->basepose.origin[0]));
3073 biggestorigin = max(biggestorigin, fabs(p->basepose.origin[1]));
3074 biggestorigin = max(biggestorigin, fabs(p->basepose.origin[2]));
3076 loadmodel->num_posescale = biggestorigin / 32767.0f;
3077 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3079 // load the basepose as a frame
3080 for (index = 0;index < numbones;index++)
3082 pskboneinfo_t *p = bones + index;
3084 Vector4Copy(p->basepose.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] = p->basepose.origin[0] * loadmodel->num_poseinvscale;
3090 loadmodel->data_poses7s[index*7+1] = p->basepose.origin[1] * loadmodel->num_poseinvscale;
3091 loadmodel->data_poses7s[index*7+2] = p->basepose.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;
3099 Mod_FreeSkinFiles(skinfiles);
3101 Mem_Free(animfilebuffer);
3102 Mod_MakeSortedSurfaces(loadmodel);
3104 // compute all the mesh information that was not loaded from the file
3105 // TODO: honor smoothing groups somehow?
3106 if (loadmodel->surfmesh.data_element3s)
3107 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3108 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3109 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
3110 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);
3111 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);
3112 if (loadmodel->surfmesh.data_neighbor3i)
3113 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3114 Mod_Alias_CalculateBoundingBox();
3116 if (!loadmodel->surfmesh.isanimated)
3118 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3119 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3120 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3121 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3122 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3123 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
3126 // because shaders can do somewhat unexpected things, check for unusual features now
3127 for (i = 0;i < loadmodel->num_textures;i++)
3129 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
3130 mod->DrawSky = R_Q1BSP_DrawSky;
3131 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
3132 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
3136 void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
3138 unsigned char *data;
3140 const unsigned char *pbase, *pend;
3142 skinfile_t *skinfiles;
3143 int i, j, k, meshvertices, meshtriangles;
3144 float biggestorigin;
3145 const unsigned int *inelements;
3147 const int *inneighbors;
3149 float *outvertex, *outnormal, *outtexcoord, *outsvector, *outtvector, *outcolor;
3150 // this pointers into the file data are read only through Little* functions so they can be unaligned memory
3151 const float *vnormal = NULL;
3152 const float *vposition = NULL;
3153 const float *vtangent = NULL;
3154 const float *vtexcoord = NULL;
3155 const float *vcolor4f = NULL;
3156 const unsigned char *vblendindexes = NULL;
3157 const unsigned char *vblendweights = NULL;
3158 const unsigned char *vcolor4ub = NULL;
3159 const unsigned short *framedata = NULL;
3160 // temporary memory allocations (because the data in the file may be misaligned)
3161 iqmanim_t *anims = NULL;
3162 iqmbounds_t *bounds = NULL;
3163 iqmjoint1_t *joint1 = NULL;
3164 iqmjoint_t *joint = NULL;
3165 iqmmesh_t *meshes = NULL;
3166 iqmpose1_t *pose1 = NULL;
3167 iqmpose_t *pose = NULL;
3168 iqmvertexarray_t *vas = NULL;
3170 pbase = (unsigned char *)buffer;
3171 pend = (unsigned char *)bufferend;
3173 if (pbase + sizeof(iqmheader_t) > pend)
3174 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model %d", loadmodel->name, (int)(pend - pbase));
3176 // copy struct (otherwise it may be misaligned)
3177 // LordHavoc: okay it's definitely not misaligned here, but for consistency...
3178 memcpy(&header, pbase, sizeof(iqmheader_t));
3180 if (memcmp(header.id, "INTERQUAKEMODEL", 16))
3181 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model", loadmodel->name);
3182 if (LittleLong(header.version) != 1 && LittleLong(header.version) != 2)
3183 Host_Error ("Mod_INTERQUAKEMODEL_Load: only version 1 and 2 models are currently supported (name = %s)", loadmodel->name);
3185 loadmodel->modeldatatypestring = "IQM";
3187 loadmodel->type = mod_alias;
3188 loadmodel->synctype = ST_RAND;
3191 header.version = LittleLong(header.version);
3192 header.filesize = LittleLong(header.filesize);
3193 header.flags = LittleLong(header.flags);
3194 header.num_text = LittleLong(header.num_text);
3195 header.ofs_text = LittleLong(header.ofs_text);
3196 header.num_meshes = LittleLong(header.num_meshes);
3197 header.ofs_meshes = LittleLong(header.ofs_meshes);
3198 header.num_vertexarrays = LittleLong(header.num_vertexarrays);
3199 header.num_vertexes = LittleLong(header.num_vertexes);
3200 header.ofs_vertexarrays = LittleLong(header.ofs_vertexarrays);
3201 header.num_triangles = LittleLong(header.num_triangles);
3202 header.ofs_triangles = LittleLong(header.ofs_triangles);
3203 header.ofs_neighbors = LittleLong(header.ofs_neighbors);
3204 header.num_joints = LittleLong(header.num_joints);
3205 header.ofs_joints = LittleLong(header.ofs_joints);
3206 header.num_poses = LittleLong(header.num_poses);
3207 header.ofs_poses = LittleLong(header.ofs_poses);
3208 header.num_anims = LittleLong(header.num_anims);
3209 header.ofs_anims = LittleLong(header.ofs_anims);
3210 header.num_frames = LittleLong(header.num_frames);
3211 header.num_framechannels = LittleLong(header.num_framechannels);
3212 header.ofs_frames = LittleLong(header.ofs_frames);
3213 header.ofs_bounds = LittleLong(header.ofs_bounds);
3214 header.num_comment = LittleLong(header.num_comment);
3215 header.ofs_comment = LittleLong(header.ofs_comment);
3216 header.num_extensions = LittleLong(header.num_extensions);
3217 header.ofs_extensions = LittleLong(header.ofs_extensions);
3219 if (header.version == 1)
3221 if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint1_t) > pend ||
3222 pbase + header.ofs_poses + header.num_poses*sizeof(iqmpose1_t) > pend)
3224 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3230 if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint_t) > pend ||
3231 pbase + header.ofs_poses + header.num_poses*sizeof(iqmpose_t) > pend)
3233 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3237 if (pbase + header.ofs_text + header.num_text > pend ||
3238 pbase + header.ofs_meshes + header.num_meshes*sizeof(iqmmesh_t) > pend ||
3239 pbase + header.ofs_vertexarrays + header.num_vertexarrays*sizeof(iqmvertexarray_t) > pend ||
3240 pbase + header.ofs_triangles + header.num_triangles*sizeof(int[3]) > pend ||
3241 (header.ofs_neighbors && pbase + header.ofs_neighbors + header.num_triangles*sizeof(int[3]) > pend) ||
3242 pbase + header.ofs_anims + header.num_anims*sizeof(iqmanim_t) > pend ||
3243 pbase + header.ofs_frames + header.num_frames*header.num_framechannels*sizeof(unsigned short) > pend ||
3244 (header.ofs_bounds && pbase + header.ofs_bounds + header.num_frames*sizeof(iqmbounds_t) > pend) ||
3245 pbase + header.ofs_comment + header.num_comment > pend)
3247 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3251 // copy structs to make them aligned in memory (otherwise we crash on Sparc and PowerPC and others)
3252 if (header.num_vertexarrays)
3253 vas = (iqmvertexarray_t *)(pbase + header.ofs_vertexarrays);
3254 if (header.num_anims)
3255 anims = (iqmanim_t *)(pbase + header.ofs_anims);
3256 if (header.ofs_bounds)
3257 bounds = (iqmbounds_t *)(pbase + header.ofs_bounds);
3258 if (header.num_meshes)
3259 meshes = (iqmmesh_t *)(pbase + header.ofs_meshes);
3261 for (i = 0;i < (int)header.num_vertexarrays;i++)
3263 iqmvertexarray_t va;
3265 va.type = LittleLong(vas[i].type);
3266 va.flags = LittleLong(vas[i].flags);
3267 va.format = LittleLong(vas[i].format);
3268 va.size = LittleLong(vas[i].size);
3269 va.offset = LittleLong(vas[i].offset);
3270 vsize = header.num_vertexes*va.size;
3273 case IQM_FLOAT: vsize *= sizeof(float); break;
3274 case IQM_UBYTE: vsize *= sizeof(unsigned char); break;
3277 if (pbase + va.offset + vsize > pend)
3279 // no need to copy the vertex data for alignment because LittleLong/LittleShort will be invoked on reading them, and the destination is aligned
3283 if (va.format == IQM_FLOAT && va.size == 3)
3284 vposition = (const float *)(pbase + va.offset);
3287 if (va.format == IQM_FLOAT && va.size == 2)
3288 vtexcoord = (const float *)(pbase + va.offset);
3291 if (va.format == IQM_FLOAT && va.size == 3)
3292 vnormal = (const float *)(pbase + va.offset);
3295 if (va.format == IQM_FLOAT && va.size == 4)
3296 vtangent = (const float *)(pbase + va.offset);
3298 case IQM_BLENDINDEXES:
3299 if (va.format == IQM_UBYTE && va.size == 4)
3300 vblendindexes = (const unsigned char *)(pbase + va.offset);
3302 case IQM_BLENDWEIGHTS:
3303 if (va.format == IQM_UBYTE && va.size == 4)
3304 vblendweights = (const unsigned char *)(pbase + va.offset);
3307 if (va.format == IQM_FLOAT && va.size == 4)
3308 vcolor4f = (const float *)(pbase + va.offset);
3309 if (va.format == IQM_UBYTE && va.size == 4)
3310 vcolor4ub = (const unsigned char *)(pbase + va.offset);
3314 if (header.num_vertexes > 0 && (!vposition || !vtexcoord || ((header.num_frames > 0 || header.num_anims > 0) && (!vblendindexes || !vblendweights))))
3316 Con_Printf("%s is missing vertex array data\n", loadmodel->name);
3320 text = header.num_text && header.ofs_text ? (const char *)(pbase + header.ofs_text) : "";
3322 loadmodel->DrawSky = NULL;
3323 loadmodel->DrawAddWaterPlanes = NULL;
3324 loadmodel->Draw = R_Q1BSP_Draw;
3325 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
3326 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
3327 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
3328 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
3329 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
3330 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
3331 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
3332 loadmodel->DrawLight = R_Q1BSP_DrawLight;
3333 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
3334 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
3335 loadmodel->PointSuperContents = NULL;
3337 // load external .skin files if present
3338 skinfiles = Mod_LoadSkinFiles();
3339 if (loadmodel->numskins < 1)
3340 loadmodel->numskins = 1;
3342 loadmodel->numframes = max(header.num_anims, 1);
3343 loadmodel->num_bones = header.num_joints;
3344 loadmodel->num_poses = max(header.num_frames, 1);
3345 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = header.num_meshes;
3346 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3347 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3348 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices; // updated later
3350 meshvertices = header.num_vertexes;
3351 meshtriangles = header.num_triangles;
3353 // do most allocations as one merged chunk
3354 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) : 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));
3355 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
3356 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
3357 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
3358 loadmodel->surfmesh.num_vertices = meshvertices;
3359 loadmodel->surfmesh.num_triangles = meshtriangles;
3360 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3361 if (r_enableshadowvolumes.integer)
3363 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3365 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
3366 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3367 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3368 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
3369 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
3370 if (vcolor4f || vcolor4ub)
3372 loadmodel->surfmesh.data_lightmapcolor4f = (float *)data;data += meshvertices * sizeof(float[4]);
3374 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
3375 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
3376 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
3377 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
3378 if (vblendindexes && vblendweights)
3380 loadmodel->surfmesh.num_blends = 0;
3381 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
3383 if (meshvertices <= 65536)
3385 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
3387 loadmodel->data_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
3388 if (vblendindexes && vblendweights)
3389 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
3391 for (i = 0;i < loadmodel->numskins;i++)
3393 loadmodel->skinscenes[i].firstframe = i;
3394 loadmodel->skinscenes[i].framecount = 1;
3395 loadmodel->skinscenes[i].loop = true;
3396 loadmodel->skinscenes[i].framerate = 10;
3399 // load the bone info
3400 if (header.version == 1)
3402 iqmjoint1_t *injoint1 = (iqmjoint1_t *)(pbase + header.ofs_joints);
3403 if (loadmodel->num_bones)
3404 joint1 = (iqmjoint1_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(iqmjoint1_t));
3405 for (i = 0;i < loadmodel->num_bones;i++)
3407 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3408 joint1[i].name = LittleLong(injoint1[i].name);
3409 joint1[i].parent = LittleLong(injoint1[i].parent);
3410 for (j = 0;j < 3;j++)
3412 joint1[i].origin[j] = LittleFloat(injoint1[i].origin[j]);
3413 joint1[i].rotation[j] = LittleFloat(injoint1[i].rotation[j]);
3414 joint1[i].scale[j] = LittleFloat(injoint1[i].scale[j]);
3416 strlcpy(loadmodel->data_bones[i].name, &text[joint1[i].name], sizeof(loadmodel->data_bones[i].name));
3417 loadmodel->data_bones[i].parent = joint1[i].parent;
3418 if (loadmodel->data_bones[i].parent >= i)
3419 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3420 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]);
3421 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3422 if (loadmodel->data_bones[i].parent >= 0)
3424 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3425 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3426 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3428 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3433 iqmjoint_t *injoint = (iqmjoint_t *)(pbase + header.ofs_joints);
3434 if (header.num_joints)
3435 joint = (iqmjoint_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(iqmjoint_t));
3436 for (i = 0;i < loadmodel->num_bones;i++)
3438 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3439 joint[i].name = LittleLong(injoint[i].name);
3440 joint[i].parent = LittleLong(injoint[i].parent);
3441 for (j = 0;j < 3;j++)
3443 joint[i].origin[j] = LittleFloat(injoint[i].origin[j]);
3444 joint[i].rotation[j] = LittleFloat(injoint[i].rotation[j]);
3445 joint[i].scale[j] = LittleFloat(injoint[i].scale[j]);
3447 joint[i].rotation[3] = LittleFloat(injoint[i].rotation[3]);
3448 strlcpy(loadmodel->data_bones[i].name, &text[joint[i].name], sizeof(loadmodel->data_bones[i].name));
3449 loadmodel->data_bones[i].parent = joint[i].parent;
3450 if (loadmodel->data_bones[i].parent >= i)
3451 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3452 if (joint[i].rotation[3] > 0)
3453 Vector4Negate(joint[i].rotation, joint[i].rotation);
3454 Vector4Normalize2(joint[i].rotation, joint[i].rotation);
3455 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]);
3456 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3457 if (loadmodel->data_bones[i].parent >= 0)
3459 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3460 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3461 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3463 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3467 // set up the animscenes based on the anims
3468 for (i = 0;i < (int)header.num_anims;i++)
3471 anim.name = LittleLong(anims[i].name);
3472 anim.first_frame = LittleLong(anims[i].first_frame);
3473 anim.num_frames = LittleLong(anims[i].num_frames);
3474 anim.framerate = LittleFloat(anims[i].framerate);
3475 anim.flags = LittleLong(anims[i].flags);
3476 strlcpy(loadmodel->animscenes[i].name, &text[anim.name], sizeof(loadmodel->animscenes[i].name));
3477 loadmodel->animscenes[i].firstframe = anim.first_frame;
3478 loadmodel->animscenes[i].framecount = anim.num_frames;
3479 loadmodel->animscenes[i].loop = ((anim.flags & IQM_LOOP) != 0);
3480 loadmodel->animscenes[i].framerate = anim.framerate;
3482 if (header.num_anims <= 0)
3484 strlcpy(loadmodel->animscenes[0].name, "static", sizeof(loadmodel->animscenes[0].name));
3485 loadmodel->animscenes[0].firstframe = 0;
3486 loadmodel->animscenes[0].framecount = 1;
3487 loadmodel->animscenes[0].loop = true;
3488 loadmodel->animscenes[0].framerate = 10;
3491 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
3492 if(mod_alias_force_animated.string[0])
3493 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer;
3494 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
3497 if (header.version == 1)
3499 iqmpose1_t *inpose1 = (iqmpose1_t *)(pbase + header.ofs_poses);
3500 if (header.num_poses)
3501 pose1 = (iqmpose1_t *)Mem_Alloc(loadmodel->mempool, header.num_poses * sizeof(iqmpose1_t));
3502 for (i = 0;i < (int)header.num_poses;i++)
3505 pose1[i].parent = LittleLong(inpose1[i].parent);
3506 pose1[i].channelmask = LittleLong(inpose1[i].channelmask);
3507 for (j = 0;j < 9;j++)
3509 pose1[i].channeloffset[j] = LittleFloat(inpose1[i].channeloffset[j]);
3510 pose1[i].channelscale[j] = LittleFloat(inpose1[i].channelscale[j]);
3512 f = fabs(pose1[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3513 f = fabs(pose1[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3514 f = fabs(pose1[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3515 f = fabs(pose1[i].channeloffset[0] + 0xFFFF*pose1[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3516 f = fabs(pose1[i].channeloffset[1] + 0xFFFF*pose1[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3517 f = fabs(pose1[i].channeloffset[2] + 0xFFFF*pose1[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3519 if (header.num_frames <= 0)
3521 for (i = 0;i < loadmodel->num_bones;i++)
3524 f = fabs(joint1[i].origin[0]); biggestorigin = max(biggestorigin, f);
3525 f = fabs(joint1[i].origin[1]); biggestorigin = max(biggestorigin, f);
3526 f = fabs(joint1[i].origin[2]); biggestorigin = max(biggestorigin, f);
3532 iqmpose_t *inpose = (iqmpose_t *)(pbase + header.ofs_poses);
3533 if (header.num_poses)
3534 pose = (iqmpose_t *)Mem_Alloc(loadmodel->mempool, header.num_poses * sizeof(iqmpose_t));
3535 for (i = 0;i < (int)header.num_poses;i++)
3538 pose[i].parent = LittleLong(inpose[i].parent);
3539 pose[i].channelmask = LittleLong(inpose[i].channelmask);
3540 for (j = 0;j < 10;j++)
3542 pose[i].channeloffset[j] = LittleFloat(inpose[i].channeloffset[j]);
3543 pose[i].channelscale[j] = LittleFloat(inpose[i].channelscale[j]);
3545 f = fabs(pose[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3546 f = fabs(pose[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3547 f = fabs(pose[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3548 f = fabs(pose[i].channeloffset[0] + 0xFFFF*pose[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3549 f = fabs(pose[i].channeloffset[1] + 0xFFFF*pose[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3550 f = fabs(pose[i].channeloffset[2] + 0xFFFF*pose[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3552 if (header.num_frames <= 0)
3554 for (i = 0;i < loadmodel->num_bones;i++)
3557 f = fabs(joint[i].origin[0]); biggestorigin = max(biggestorigin, f);
3558 f = fabs(joint[i].origin[1]); biggestorigin = max(biggestorigin, f);
3559 f = fabs(joint[i].origin[2]); biggestorigin = max(biggestorigin, f);
3563 loadmodel->num_posescale = biggestorigin / 32767.0f;
3564 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3566 // load the pose data
3567 // this unaligned memory access is safe (LittleShort reads as bytes)
3568 framedata = (const unsigned short *)(pbase + header.ofs_frames);
3569 if (header.version == 1)
3571 for (i = 0, k = 0;i < (int)header.num_frames;i++)
3573 for (j = 0;j < (int)header.num_poses;j++, k++)
3575 float qx, qy, qz, qw;
3576 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));
3577 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));
3578 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));
3579 qx = pose1[j].channeloffset[3] + (pose1[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[3] : 0);
3580 qy = pose1[j].channeloffset[4] + (pose1[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[4] : 0);
3581 qz = pose1[j].channeloffset[5] + (pose1[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[5] : 0);
3582 qw = 1.0f - (qx*qx + qy*qy + qz*qz);
3583 qw = qw > 0.0f ? -sqrt(qw) : 0.0f;
3584 loadmodel->data_poses7s[k*7 + 3] = 32767.0f * qx;
3585 loadmodel->data_poses7s[k*7 + 4] = 32767.0f * qy;
3586 loadmodel->data_poses7s[k*7 + 5] = 32767.0f * qz;
3587 loadmodel->data_poses7s[k*7 + 6] = 32767.0f * qw;
3588 // skip scale data for now
3589 if(pose1[j].channelmask&64) framedata++;
3590 if(pose1[j].channelmask&128) framedata++;
3591 if(pose1[j].channelmask&256) framedata++;
3594 if (header.num_frames <= 0)
3596 for (i = 0;i < loadmodel->num_bones;i++)
3598 float qx, qy, qz, qw;
3599 loadmodel->data_poses7s[i*7 + 0] = loadmodel->num_poseinvscale * joint1[i].origin[0];
3600 loadmodel->data_poses7s[i*7 + 1] = loadmodel->num_poseinvscale * joint1[i].origin[1];
3601 loadmodel->data_poses7s[i*7 + 2] = loadmodel->num_poseinvscale * joint1[i].origin[2];
3602 qx = joint1[i].rotation[0];
3603 qy = joint1[i].rotation[1];
3604 qz = joint1[i].rotation[2];
3605 qw = 1.0f - (qx*qx + qy*qy + qz*qz);
3606 qw = qw > 0.0f ? -sqrt(qw) : 0.0f;
3607 loadmodel->data_poses7s[i*7 + 3] = 32767.0f * qx;
3608 loadmodel->data_poses7s[i*7 + 4] = 32767.0f * qy;
3609 loadmodel->data_poses7s[i*7 + 5] = 32767.0f * qz;
3610 loadmodel->data_poses7s[i*7 + 6] = 32767.0f * qw;
3616 for (i = 0, k = 0;i < (int)header.num_frames;i++)
3618 for (j = 0;j < (int)header.num_poses;j++, k++)
3621 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));
3622 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));
3623 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));
3624 rot[0] = pose[j].channeloffset[3] + (pose[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[3] : 0);
3625 rot[1] = pose[j].channeloffset[4] + (pose[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[4] : 0);
3626 rot[2] = pose[j].channeloffset[5] + (pose[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[5] : 0);
3627 rot[3] = pose[j].channeloffset[6] + (pose[j].channelmask&64 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[6] : 0);
3629 Vector4Negate(rot, rot);
3630 Vector4Normalize2(rot, rot);
3631 loadmodel->data_poses7s[k*7 + 3] = 32767.0f * rot[0];
3632 loadmodel->data_poses7s[k*7 + 4] = 32767.0f * rot[1];
3633 loadmodel->data_poses7s[k*7 + 5] = 32767.0f * rot[2];
3634 loadmodel->data_poses7s[k*7 + 6] = 32767.0f * rot[3];
3635 // skip scale data for now
3636 if(pose[j].channelmask&128) framedata++;
3637 if(pose[j].channelmask&256) framedata++;
3638 if(pose[j].channelmask&512) framedata++;
3641 if (header.num_frames <= 0)
3643 for (i = 0;i < loadmodel->num_bones;i++)
3645 loadmodel->data_poses7s[i*7 + 0] = loadmodel->num_poseinvscale * joint[i].origin[0];
3646 loadmodel->data_poses7s[i*7 + 1] = loadmodel->num_poseinvscale * joint[i].origin[1];
3647 loadmodel->data_poses7s[i*7 + 2] = loadmodel->num_poseinvscale * joint[i].origin[2];
3648 loadmodel->data_poses7s[i*7 + 3] = 32767.0f * joint[i].rotation[0];
3649 loadmodel->data_poses7s[i*7 + 4] = 32767.0f * joint[i].rotation[1];
3650 loadmodel->data_poses7s[i*7 + 5] = 32767.0f * joint[i].rotation[2];
3651 loadmodel->data_poses7s[i*7 + 6] = 32767.0f * joint[i].rotation[3];
3656 // load bounding box data
3657 if (header.ofs_bounds)
3659 float xyradius = 0, radius = 0;
3660 VectorClear(loadmodel->normalmins);
3661 VectorClear(loadmodel->normalmaxs);
3662 for (i = 0; i < (int)header.num_frames;i++)
3665 bound.mins[0] = LittleFloat(bounds[i].mins[0]);
3666 bound.mins[1] = LittleFloat(bounds[i].mins[1]);
3667 bound.mins[2] = LittleFloat(bounds[i].mins[2]);
3668 bound.maxs[0] = LittleFloat(bounds[i].maxs[0]);
3669 bound.maxs[1] = LittleFloat(bounds[i].maxs[1]);
3670 bound.maxs[2] = LittleFloat(bounds[i].maxs[2]);
3671 bound.xyradius = LittleFloat(bounds[i].xyradius);
3672 bound.radius = LittleFloat(bounds[i].radius);
3675 VectorCopy(bound.mins, loadmodel->normalmins);
3676 VectorCopy(bound.maxs, loadmodel->normalmaxs);
3680 if (loadmodel->normalmins[0] > bound.mins[0]) loadmodel->normalmins[0] = bound.mins[0];
3681 if (loadmodel->normalmins[1] > bound.mins[1]) loadmodel->normalmins[1] = bound.mins[1];
3682 if (loadmodel->normalmins[2] > bound.mins[2]) loadmodel->normalmins[2] = bound.mins[2];
3683 if (loadmodel->normalmaxs[0] < bound.maxs[0]) loadmodel->normalmaxs[0] = bound.maxs[0];
3684 if (loadmodel->normalmaxs[1] < bound.maxs[1]) loadmodel->normalmaxs[1] = bound.maxs[1];
3685 if (loadmodel->normalmaxs[2] < bound.maxs[2]) loadmodel->normalmaxs[2] = bound.maxs[2];
3687 if (bound.xyradius > xyradius)
3688 xyradius = bound.xyradius;
3689 if (bound.radius > radius)
3690 radius = bound.radius;
3692 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -xyradius;
3693 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = xyradius;
3694 loadmodel->yawmins[2] = loadmodel->normalmins[2];
3695 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
3696 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
3697 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
3698 loadmodel->radius = radius;
3699 loadmodel->radius2 = radius * radius;
3702 // load triangle data
3703 // this unaligned memory access is safe (LittleLong reads as bytes)
3704 inelements = (const unsigned int *)(pbase + header.ofs_triangles);
3705 outelements = loadmodel->surfmesh.data_element3i;
3706 for (i = 0;i < (int)header.num_triangles;i++)
3708 outelements[0] = LittleLong(inelements[0]);
3709 outelements[1] = LittleLong(inelements[1]);
3710 outelements[2] = LittleLong(inelements[2]);
3714 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, header.num_vertexes, __FILE__, __LINE__);
3716 if (header.ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
3718 // this unaligned memory access is safe (LittleLong reads as bytes)
3719 inneighbors = (const int *)(pbase + header.ofs_neighbors);
3720 outneighbors = loadmodel->surfmesh.data_neighbor3i;
3721 for (i = 0;i < (int)header.num_triangles;i++)
3723 outneighbors[0] = LittleLong(inneighbors[0]);
3724 outneighbors[1] = LittleLong(inneighbors[1]);
3725 outneighbors[2] = LittleLong(inneighbors[2]);
3732 // this unaligned memory access is safe (LittleFloat reads as bytes)
3733 outvertex = loadmodel->surfmesh.data_vertex3f;
3734 for (i = 0;i < (int)header.num_vertexes;i++)
3736 outvertex[0] = LittleFloat(vposition[0]);
3737 outvertex[1] = LittleFloat(vposition[1]);
3738 outvertex[2] = LittleFloat(vposition[2]);
3743 outtexcoord = loadmodel->surfmesh.data_texcoordtexture2f;
3744 // this unaligned memory access is safe (LittleFloat reads as bytes)
3745 for (i = 0;i < (int)header.num_vertexes;i++)
3747 outtexcoord[0] = LittleFloat(vtexcoord[0]);
3748 outtexcoord[1] = LittleFloat(vtexcoord[1]);
3753 // this unaligned memory access is safe (LittleFloat reads as bytes)
3756 outnormal = loadmodel->surfmesh.data_normal3f;
3757 for (i = 0;i < (int)header.num_vertexes;i++)
3759 outnormal[0] = LittleFloat(vnormal[0]);
3760 outnormal[1] = LittleFloat(vnormal[1]);
3761 outnormal[2] = LittleFloat(vnormal[2]);
3767 // this unaligned memory access is safe (LittleFloat reads as bytes)
3768 if(vnormal && vtangent)
3770 outnormal = loadmodel->surfmesh.data_normal3f;
3771 outsvector = loadmodel->surfmesh.data_svector3f;
3772 outtvector = loadmodel->surfmesh.data_tvector3f;
3773 for (i = 0;i < (int)header.num_vertexes;i++)
3775 outsvector[0] = LittleFloat(vtangent[0]);
3776 outsvector[1] = LittleFloat(vtangent[1]);
3777 outsvector[2] = LittleFloat(vtangent[2]);
3778 if(LittleFloat(vtangent[3]) < 0)
3779 CrossProduct(outsvector, outnormal, outtvector);
3781 CrossProduct(outnormal, outsvector, outtvector);
3789 // this unaligned memory access is safe (all bytes)
3790 if (vblendindexes && vblendweights)
3792 for (i = 0; i < (int)header.num_vertexes;i++)
3794 blendweights_t weights;
3795 memcpy(weights.index, vblendindexes + i*4, 4);
3796 memcpy(weights.influence, vblendweights + i*4, 4);
3797 loadmodel->surfmesh.blends[i] = Mod_Skeletal_AddBlend(loadmodel, &weights);
3803 outcolor = loadmodel->surfmesh.data_lightmapcolor4f;
3804 // this unaligned memory access is safe (LittleFloat reads as bytes)
3805 for (i = 0;i < (int)header.num_vertexes;i++)
3807 outcolor[0] = LittleFloat(vcolor4f[0]);
3808 outcolor[1] = LittleFloat(vcolor4f[1]);
3809 outcolor[2] = LittleFloat(vcolor4f[2]);
3810 outcolor[3] = LittleFloat(vcolor4f[3]);
3817 outcolor = loadmodel->surfmesh.data_lightmapcolor4f;
3818 // this unaligned memory access is safe (all bytes)
3819 for (i = 0;i < (int)header.num_vertexes;i++)
3821 outcolor[0] = vcolor4ub[0] * (1.0f / 255.0f);
3822 outcolor[1] = vcolor4ub[1] * (1.0f / 255.0f);
3823 outcolor[2] = vcolor4ub[2] * (1.0f / 255.0f);
3824 outcolor[3] = vcolor4ub[3] * (1.0f / 255.0f);
3831 for (i = 0;i < (int)header.num_meshes;i++)
3834 msurface_t *surface;
3836 mesh.name = LittleLong(meshes[i].name);
3837 mesh.material = LittleLong(meshes[i].material);
3838 mesh.first_vertex = LittleLong(meshes[i].first_vertex);
3839 mesh.num_vertexes = LittleLong(meshes[i].num_vertexes);
3840 mesh.first_triangle = LittleLong(meshes[i].first_triangle);
3841 mesh.num_triangles = LittleLong(meshes[i].num_triangles);
3843 loadmodel->sortedmodelsurfaces[i] = i;
3844 surface = loadmodel->data_surfaces + i;
3845 surface->texture = loadmodel->data_textures + i;
3846 surface->num_firsttriangle = mesh.first_triangle;
3847 surface->num_triangles = mesh.num_triangles;
3848 surface->num_firstvertex = mesh.first_vertex;
3849 surface->num_vertices = mesh.num_vertexes;
3851 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, &text[mesh.name], &text[mesh.material]);
3854 Mod_FreeSkinFiles(skinfiles);
3855 Mod_MakeSortedSurfaces(loadmodel);
3857 // compute all the mesh information that was not loaded from the file
3858 if (loadmodel->surfmesh.data_element3s)
3859 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3860 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3862 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);
3863 if (!vnormal || !vtangent)
3864 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);
3865 if (!header.ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
3866 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3867 if (!header.ofs_bounds)
3868 Mod_Alias_CalculateBoundingBox();
3870 if (!loadmodel->surfmesh.isanimated && loadmodel->surfmesh.num_triangles >= 1)
3872 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3873 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3874 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3875 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3876 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3877 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
3880 if (joint ) Mem_Free(joint );joint = NULL;
3881 if (joint1 ) Mem_Free(joint1 );joint1 = NULL;
3882 if (pose ) Mem_Free(pose );pose = NULL;
3883 if (pose1 ) Mem_Free(pose1 );pose1 = NULL;
3885 // because shaders can do somewhat unexpected things, check for unusual features now
3886 for (i = 0;i < loadmodel->num_textures;i++)
3888 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
3889 mod->DrawSky = R_Q1BSP_DrawSky;
3890 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
3891 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;