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 datapointer += sizeof(daliasframe_t);
785 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
786 datapointer += sizeof(trivertx_t) * inverts;
792 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
794 if (cls.state == ca_dedicated)
798 skinframe = R_SkinFrame_LoadMissing();
799 memset(texture, 0, sizeof(*texture));
800 texture->currentframe = texture;
801 //texture->animated = false;
802 texture->numskinframes = 1;
803 texture->skinframerate = 1;
804 texture->skinframes[0] = skinframe;
805 texture->currentskinframe = skinframe;
806 //texture->backgroundnumskinframes = 0;
807 //texture->customblendfunc[0] = 0;
808 //texture->customblendfunc[1] = 0;
809 //texture->surfaceflags = 0;
810 //texture->supercontents = 0;
811 //texture->surfaceparms = 0;
812 //texture->textureflags = 0;
814 texture->basematerialflags = MATERIALFLAG_WALL;
815 if (texture->currentskinframe->hasalpha)
816 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
817 texture->currentmaterialflags = texture->basematerialflags;
818 texture->offsetmapping = OFFSETMAPPING_DEFAULT;
819 texture->offsetscale = 1;
820 texture->offsetbias = 0;
821 texture->specularscalemod = 1;
822 texture->specularpowermod = 1;
823 texture->surfaceflags = 0;
824 texture->supercontents = SUPERCONTENTS_SOLID;
825 if (!(texture->basematerialflags & MATERIALFLAG_BLENDED))
826 texture->supercontents |= SUPERCONTENTS_OPAQUE;
829 void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
832 char stripbuf[MAX_QPATH];
833 skinfileitem_t *skinfileitem;
834 if(developer_extra.integer)
835 Con_DPrintf("Looking up texture for %s (default: %s)\n", meshname, shadername);
838 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
839 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
841 memset(skin, 0, sizeof(*skin));
843 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
845 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
846 if (!strcmp(skinfileitem->name, meshname))
848 Image_StripImageExtension(skinfileitem->replacement, stripbuf, sizeof(stripbuf));
849 if(developer_extra.integer)
850 Con_DPrintf("--> got %s from skin file\n", stripbuf);
851 Mod_LoadTextureFromQ3Shader(skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
857 // don't render unmentioned meshes
858 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
859 if(developer_extra.integer)
860 Con_DPrintf("--> skipping\n");
861 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
867 if(developer_extra.integer)
868 Con_DPrintf("--> using default\n");
869 Image_StripImageExtension(shadername, stripbuf, sizeof(stripbuf));
870 Mod_LoadTextureFromQ3Shader(skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
874 #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);
875 #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);
876 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
878 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
879 float scales, scalet, interval;
883 stvert_t *pinstverts;
884 dtriangle_t *pintriangles;
885 daliasskintype_t *pinskintype;
886 daliasskingroup_t *pinskingroup;
887 daliasskininterval_t *pinskinintervals;
888 daliasframetype_t *pinframetype;
889 daliasgroup_t *pinframegroup;
890 unsigned char *datapointer, *startframes, *startskins;
891 char name[MAX_QPATH];
892 skinframe_t *tempskinframe;
893 animscene_t *tempskinscenes;
894 texture_t *tempaliasskins;
896 int *vertonseam, *vertremap;
897 skinfile_t *skinfiles;
900 datapointer = (unsigned char *)buffer;
901 pinmodel = (mdl_t *)datapointer;
902 datapointer += sizeof(mdl_t);
904 version = LittleLong (pinmodel->version);
905 if (version != ALIAS_VERSION)
906 Host_Error ("%s has wrong version number (%i should be %i)",
907 loadmodel->name, version, ALIAS_VERSION);
909 loadmodel->modeldatatypestring = "MDL";
911 loadmodel->type = mod_alias;
912 loadmodel->DrawSky = NULL;
913 loadmodel->DrawAddWaterPlanes = NULL;
914 loadmodel->Draw = R_Q1BSP_Draw;
915 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
916 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
917 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
918 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
919 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
920 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
921 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
922 loadmodel->DrawLight = R_Q1BSP_DrawLight;
923 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
924 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
925 // FIXME add TraceBrush!
926 loadmodel->PointSuperContents = NULL;
928 loadmodel->num_surfaces = 1;
929 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
930 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
931 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
932 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
933 loadmodel->sortedmodelsurfaces[0] = 0;
935 loadmodel->numskins = LittleLong(pinmodel->numskins);
936 BOUNDI(loadmodel->numskins,0,65536);
937 skinwidth = LittleLong (pinmodel->skinwidth);
938 BOUNDI(skinwidth,0,65536);
939 skinheight = LittleLong (pinmodel->skinheight);
940 BOUNDI(skinheight,0,65536);
941 numverts = LittleLong(pinmodel->numverts);
942 BOUNDI(numverts,0,65536);
943 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
944 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
945 loadmodel->numframes = LittleLong(pinmodel->numframes);
946 BOUNDI(loadmodel->numframes,0,65536);
947 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
948 BOUNDI((int)loadmodel->synctype,0,2);
949 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
950 i = LittleLong (pinmodel->flags);
951 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
953 for (i = 0;i < 3;i++)
955 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
956 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
959 startskins = datapointer;
961 for (i = 0;i < loadmodel->numskins;i++)
963 pinskintype = (daliasskintype_t *)datapointer;
964 datapointer += sizeof(daliasskintype_t);
965 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
969 pinskingroup = (daliasskingroup_t *)datapointer;
970 datapointer += sizeof(daliasskingroup_t);
971 groupskins = LittleLong(pinskingroup->numskins);
972 datapointer += sizeof(daliasskininterval_t) * groupskins;
975 for (j = 0;j < groupskins;j++)
977 datapointer += skinwidth * skinheight;
982 pinstverts = (stvert_t *)datapointer;
983 datapointer += sizeof(stvert_t) * numverts;
985 pintriangles = (dtriangle_t *)datapointer;
986 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
988 startframes = datapointer;
989 loadmodel->surfmesh.num_morphframes = 0;
990 for (i = 0;i < loadmodel->numframes;i++)
992 pinframetype = (daliasframetype_t *)datapointer;
993 datapointer += sizeof(daliasframetype_t);
994 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
998 pinframegroup = (daliasgroup_t *)datapointer;
999 datapointer += sizeof(daliasgroup_t);
1000 groupframes = LittleLong(pinframegroup->numframes);
1001 datapointer += sizeof(daliasinterval_t) * groupframes;
1004 for (j = 0;j < groupframes;j++)
1006 datapointer += sizeof(daliasframe_t);
1007 datapointer += sizeof(trivertx_t) * numverts;
1008 loadmodel->surfmesh.num_morphframes++;
1011 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1013 // store texture coordinates into temporary array, they will be stored
1014 // after usage is determined (triangle data)
1015 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
1016 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
1017 vertonseam = vertremap + numverts * 2;
1019 scales = 1.0 / skinwidth;
1020 scalet = 1.0 / skinheight;
1021 for (i = 0;i < numverts;i++)
1023 vertonseam[i] = LittleLong(pinstverts[i].onseam);
1024 vertst[i*2+0] = LittleLong(pinstverts[i].s) * scales;
1025 vertst[i*2+1] = LittleLong(pinstverts[i].t) * scalet;
1026 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
1027 vertst[(i+numverts)*2+1] = vertst[i*2+1];
1030 // load triangle data
1031 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1033 // read the triangle elements
1034 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1035 for (j = 0;j < 3;j++)
1036 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1037 // validate (note numverts is used because this is the original data)
1038 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1039 // now butcher the elements according to vertonseam and tri->facesfront
1040 // and then compact the vertex set to remove duplicates
1041 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1042 if (!LittleLong(pintriangles[i].facesfront)) // backface
1043 for (j = 0;j < 3;j++)
1044 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1045 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1047 // (this uses vertremap to count usage to save some memory)
1048 for (i = 0;i < numverts*2;i++)
1050 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1051 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1052 // build remapping table and compact array
1053 loadmodel->surfmesh.num_vertices = 0;
1054 for (i = 0;i < numverts*2;i++)
1058 vertremap[i] = loadmodel->surfmesh.num_vertices;
1059 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1060 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1061 loadmodel->surfmesh.num_vertices++;
1064 vertremap[i] = -1; // not used at all
1066 // remap the elements to the new vertex set
1067 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1068 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1069 // store the texture coordinates
1070 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1071 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1073 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1074 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1077 // generate ushort elements array if possible
1078 if (loadmodel->surfmesh.num_vertices <= 65536)
1079 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1080 if (loadmodel->surfmesh.data_element3s)
1081 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1082 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1085 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1086 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1087 if (r_enableshadowvolumes.integer)
1089 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1091 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1092 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices; // needed during loading, may be cleared by code later in this function
1093 if (loadmodel->surfmesh.data_neighbor3i)
1094 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1095 Mod_Alias_CalculateBoundingBox();
1096 Mod_Alias_MorphMesh_CompileFrames();
1099 Mem_Free(vertremap);
1102 skinfiles = Mod_LoadSkinFiles();
1105 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1106 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1107 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1108 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1109 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1110 Mod_FreeSkinFiles(skinfiles);
1111 for (i = 0;i < loadmodel->numskins;i++)
1113 loadmodel->skinscenes[i].firstframe = i;
1114 loadmodel->skinscenes[i].framecount = 1;
1115 loadmodel->skinscenes[i].loop = true;
1116 loadmodel->skinscenes[i].framerate = 10;
1121 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1122 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1123 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1124 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1126 datapointer = startskins;
1127 for (i = 0;i < loadmodel->numskins;i++)
1129 pinskintype = (daliasskintype_t *)datapointer;
1130 datapointer += sizeof(daliasskintype_t);
1132 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1139 pinskingroup = (daliasskingroup_t *)datapointer;
1140 datapointer += sizeof(daliasskingroup_t);
1142 groupskins = LittleLong (pinskingroup->numskins);
1144 pinskinintervals = (daliasskininterval_t *)datapointer;
1145 datapointer += sizeof(daliasskininterval_t) * groupskins;
1147 interval = LittleFloat(pinskinintervals[0].interval);
1148 if (interval < 0.01f)
1150 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1155 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1156 loadmodel->skinscenes[i].firstframe = totalskins;
1157 loadmodel->skinscenes[i].framecount = groupskins;
1158 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1159 loadmodel->skinscenes[i].loop = true;
1161 for (j = 0;j < groupskins;j++)
1164 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1166 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1167 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))
1168 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));
1169 datapointer += skinwidth * skinheight;
1173 // check for skins that don't exist in the model, but do exist as external images
1174 // (this was added because yummyluv kept pestering me about support for it)
1175 // TODO: support shaders here?
1176 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)))
1178 // expand the arrays to make room
1179 tempskinscenes = loadmodel->skinscenes;
1180 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1181 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1182 Mem_Free(tempskinscenes);
1184 tempaliasskins = loadmodel->data_textures;
1185 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1186 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1187 Mem_Free(tempaliasskins);
1189 // store the info about the new skin
1190 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1191 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1192 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1193 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1194 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1195 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1197 //increase skin counts
1198 loadmodel->numskins++;
1201 // fix up the pointers since they are pointing at the old textures array
1202 // FIXME: this is a hack!
1203 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1204 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1208 surface = loadmodel->data_surfaces;
1209 surface->texture = loadmodel->data_textures;
1210 surface->num_firsttriangle = 0;
1211 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1212 surface->num_firstvertex = 0;
1213 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1215 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1216 if(mod_alias_force_animated.string[0])
1217 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
1218 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_MDL_AnimateVertices : NULL;
1220 if (!loadmodel->surfmesh.isanimated)
1222 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1223 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1224 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1225 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1226 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1227 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1230 // because shaders can do somewhat unexpected things, check for unusual features now
1231 for (i = 0;i < loadmodel->num_textures;i++)
1233 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
1234 mod->DrawSky = R_Q1BSP_DrawSky;
1235 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
1236 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
1240 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1242 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1243 float iskinwidth, iskinheight;
1244 unsigned char *data;
1245 msurface_t *surface;
1247 unsigned char *base, *datapointer;
1248 md2frame_t *pinframe;
1250 md2triangle_t *intri;
1251 unsigned short *inst;
1252 struct md2verthash_s
1254 struct md2verthash_s *next;
1258 *hash, **md2verthash, *md2verthashdata;
1259 skinfile_t *skinfiles;
1261 pinmodel = (md2_t *)buffer;
1262 base = (unsigned char *)buffer;
1264 version = LittleLong (pinmodel->version);
1265 if (version != MD2ALIAS_VERSION)
1266 Host_Error ("%s has wrong version number (%i should be %i)",
1267 loadmodel->name, version, MD2ALIAS_VERSION);
1269 loadmodel->modeldatatypestring = "MD2";
1271 loadmodel->type = mod_alias;
1272 loadmodel->DrawSky = NULL;
1273 loadmodel->DrawAddWaterPlanes = NULL;
1274 loadmodel->Draw = R_Q1BSP_Draw;
1275 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1276 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1277 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1278 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1279 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1280 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1281 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1282 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1283 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1284 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1285 loadmodel->PointSuperContents = NULL;
1287 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1288 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1289 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1290 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1291 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1292 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1293 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1294 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1296 end = LittleLong(pinmodel->ofs_end);
1297 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1298 Host_Error ("%s is not a valid model", loadmodel->name);
1299 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1300 Host_Error ("%s is not a valid model", loadmodel->name);
1301 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1302 Host_Error ("%s is not a valid model", loadmodel->name);
1303 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1304 Host_Error ("%s is not a valid model", loadmodel->name);
1305 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1306 Host_Error ("%s is not a valid model", loadmodel->name);
1308 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1309 numxyz = LittleLong(pinmodel->num_xyz);
1310 numst = LittleLong(pinmodel->num_st);
1311 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1312 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1313 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1314 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1315 skinwidth = LittleLong(pinmodel->skinwidth);
1316 skinheight = LittleLong(pinmodel->skinheight);
1317 iskinwidth = 1.0f / skinwidth;
1318 iskinheight = 1.0f / skinheight;
1320 loadmodel->num_surfaces = 1;
1321 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1322 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));
1323 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1324 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1325 loadmodel->sortedmodelsurfaces[0] = 0;
1326 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1327 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1328 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1329 if (r_enableshadowvolumes.integer)
1331 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1334 loadmodel->synctype = ST_RAND;
1337 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1338 skinfiles = Mod_LoadSkinFiles();
1341 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1342 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1343 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1344 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1345 Mod_FreeSkinFiles(skinfiles);
1347 else if (loadmodel->numskins)
1349 // skins found (most likely not a player model)
1350 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1351 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1352 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1353 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1354 Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
1358 // no skins (most likely a player model)
1359 loadmodel->numskins = 1;
1360 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1361 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1362 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1363 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1366 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1367 for (i = 0;i < loadmodel->numskins;i++)
1369 loadmodel->skinscenes[i].firstframe = i;
1370 loadmodel->skinscenes[i].framecount = 1;
1371 loadmodel->skinscenes[i].loop = true;
1372 loadmodel->skinscenes[i].framerate = 10;
1375 // load the triangles and stvert data
1376 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1377 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1378 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1379 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1380 // swap the triangle list
1381 loadmodel->surfmesh.num_vertices = 0;
1382 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1384 for (j = 0;j < 3;j++)
1386 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1387 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1390 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1395 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1398 hashindex = (xyz * 256 + st) & 65535;
1399 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1400 if (hash->xyz == xyz && hash->st == st)
1404 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1407 hash->next = md2verthash[hashindex];
1408 md2verthash[hashindex] = hash;
1410 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1414 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1415 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));
1416 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1417 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1418 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1421 hash = md2verthashdata + i;
1422 vertremap[i] = hash->xyz;
1423 sts = LittleShort(inst[hash->st*2+0]);
1424 stt = LittleShort(inst[hash->st*2+1]);
1425 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1427 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1431 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1432 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1435 Mem_Free(md2verthash);
1436 Mem_Free(md2verthashdata);
1438 // generate ushort elements array if possible
1439 if (loadmodel->surfmesh.num_vertices <= 65536)
1440 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1441 if (loadmodel->surfmesh.data_element3s)
1442 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1443 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1446 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1447 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1452 pinframe = (md2frame_t *)datapointer;
1453 datapointer += sizeof(md2frame_t);
1454 // store the frame scale/translate into the appropriate array
1455 for (j = 0;j < 3;j++)
1457 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1458 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1460 // convert the vertices
1461 v = (trivertx_t *)datapointer;
1462 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1463 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1464 out[k] = v[vertremap[k]];
1465 datapointer += numxyz * sizeof(trivertx_t);
1467 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1468 loadmodel->animscenes[i].firstframe = i;
1469 loadmodel->animscenes[i].framecount = 1;
1470 loadmodel->animscenes[i].framerate = 10;
1471 loadmodel->animscenes[i].loop = true;
1474 Mem_Free(vertremap);
1476 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1477 if(mod_alias_force_animated.string[0])
1478 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
1479 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices; // needed during loading, may be cleared by code later in this function
1480 if (loadmodel->surfmesh.data_neighbor3i)
1481 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1482 Mod_Alias_CalculateBoundingBox();
1483 Mod_Alias_MorphMesh_CompileFrames();
1484 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_MDL_AnimateVertices : NULL;
1486 surface = loadmodel->data_surfaces;
1487 surface->texture = loadmodel->data_textures;
1488 surface->num_firsttriangle = 0;
1489 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1490 surface->num_firstvertex = 0;
1491 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1493 if (!loadmodel->surfmesh.isanimated)
1495 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1496 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1497 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1498 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1499 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1500 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1503 // because shaders can do somewhat unexpected things, check for unusual features now
1504 for (i = 0;i < loadmodel->num_textures;i++)
1506 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
1507 mod->DrawSky = R_Q1BSP_DrawSky;
1508 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
1509 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
1513 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1515 int i, j, k, version, meshvertices, meshtriangles;
1516 unsigned char *data;
1517 msurface_t *surface;
1518 md3modelheader_t *pinmodel;
1519 md3frameinfo_t *pinframe;
1522 skinfile_t *skinfiles;
1524 pinmodel = (md3modelheader_t *)buffer;
1526 if (memcmp(pinmodel->identifier, "IDP3", 4))
1527 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1528 version = LittleLong (pinmodel->version);
1529 if (version != MD3VERSION)
1530 Host_Error ("%s has wrong version number (%i should be %i)",
1531 loadmodel->name, version, MD3VERSION);
1533 skinfiles = Mod_LoadSkinFiles();
1534 if (loadmodel->numskins < 1)
1535 loadmodel->numskins = 1;
1537 loadmodel->modeldatatypestring = "MD3";
1539 loadmodel->type = mod_alias;
1540 loadmodel->DrawSky = NULL;
1541 loadmodel->DrawAddWaterPlanes = NULL;
1542 loadmodel->Draw = R_Q1BSP_Draw;
1543 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1544 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1545 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1546 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1547 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1548 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1549 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1550 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1551 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1552 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1553 loadmodel->PointSuperContents = NULL;
1554 loadmodel->synctype = ST_RAND;
1555 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1556 i = LittleLong (pinmodel->flags);
1557 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1559 // set up some global info about the model
1560 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1561 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1563 // make skinscenes for the skins (no groups)
1564 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1565 for (i = 0;i < loadmodel->numskins;i++)
1567 loadmodel->skinscenes[i].firstframe = i;
1568 loadmodel->skinscenes[i].framecount = 1;
1569 loadmodel->skinscenes[i].loop = true;
1570 loadmodel->skinscenes[i].framerate = 10;
1574 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1575 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1577 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1578 loadmodel->animscenes[i].firstframe = i;
1579 loadmodel->animscenes[i].framecount = 1;
1580 loadmodel->animscenes[i].framerate = 10;
1581 loadmodel->animscenes[i].loop = true;
1585 loadmodel->num_tagframes = loadmodel->numframes;
1586 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1587 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1588 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1590 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1591 for (j = 0;j < 9;j++)
1592 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1593 for (j = 0;j < 3;j++)
1594 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1595 //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);
1601 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)))
1603 if (memcmp(pinmesh->identifier, "IDP3", 4))
1604 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1605 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1606 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1607 meshvertices += LittleLong(pinmesh->num_vertices);
1608 meshtriangles += LittleLong(pinmesh->num_triangles);
1611 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1612 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1613 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1614 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));
1615 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1616 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1617 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1618 loadmodel->surfmesh.num_vertices = meshvertices;
1619 loadmodel->surfmesh.num_triangles = meshtriangles;
1620 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1621 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1622 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1623 if (r_enableshadowvolumes.integer)
1625 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1627 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1628 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1629 if (meshvertices <= 65536)
1631 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1636 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)))
1638 if (memcmp(pinmesh->identifier, "IDP3", 4))
1639 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1640 loadmodel->sortedmodelsurfaces[i] = i;
1641 surface = loadmodel->data_surfaces + i;
1642 surface->texture = loadmodel->data_textures + i;
1643 surface->num_firsttriangle = meshtriangles;
1644 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1645 surface->num_firstvertex = meshvertices;
1646 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1647 meshvertices += surface->num_vertices;
1648 meshtriangles += surface->num_triangles;
1650 for (j = 0;j < surface->num_triangles * 3;j++)
1651 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1652 for (j = 0;j < surface->num_vertices;j++)
1654 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1655 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1657 for (j = 0;j < loadmodel->numframes;j++)
1659 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1660 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1661 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1663 out->origin[0] = LittleShort(in->origin[0]);
1664 out->origin[1] = LittleShort(in->origin[1]);
1665 out->origin[2] = LittleShort(in->origin[2]);
1666 out->pitch = in->pitch;
1671 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1673 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1675 if (loadmodel->surfmesh.data_element3s)
1676 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1677 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1678 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1679 if(mod_alias_force_animated.string[0])
1680 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
1681 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices; // needed during loading, may be cleared by code later in this function
1682 if (loadmodel->surfmesh.data_neighbor3i)
1683 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1684 Mod_Alias_MorphMesh_CompileFrames();
1685 Mod_Alias_CalculateBoundingBox();
1686 Mod_FreeSkinFiles(skinfiles);
1687 Mod_MakeSortedSurfaces(loadmodel);
1688 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_MD3_AnimateVertices : NULL;
1690 if (!loadmodel->surfmesh.isanimated)
1692 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1693 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1694 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1695 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1696 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1697 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1700 // because shaders can do somewhat unexpected things, check for unusual features now
1701 for (i = 0;i < loadmodel->num_textures;i++)
1703 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
1704 mod->DrawSky = R_Q1BSP_DrawSky;
1705 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
1706 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
1710 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1712 zymtype1header_t *pinmodel, *pheader;
1713 unsigned char *pbase;
1714 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1715 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose, f, biggestorigin, tempvec[3], modelscale;
1716 zymvertex_t *verts, *vertdata;
1720 skinfile_t *skinfiles;
1721 unsigned char *data;
1722 msurface_t *surface;
1724 pinmodel = (zymtype1header_t *)buffer;
1725 pbase = (unsigned char *)buffer;
1726 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1727 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1728 if (BigLong(pinmodel->type) != 1)
1729 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1731 loadmodel->modeldatatypestring = "ZYM";
1733 loadmodel->type = mod_alias;
1734 loadmodel->synctype = ST_RAND;
1738 pheader->type = BigLong(pinmodel->type);
1739 pheader->filesize = BigLong(pinmodel->filesize);
1740 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1741 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1742 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1743 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1744 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1745 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1746 pheader->radius = BigFloat(pinmodel->radius);
1747 pheader->numverts = BigLong(pinmodel->numverts);
1748 pheader->numtris = BigLong(pinmodel->numtris);
1749 pheader->numshaders = BigLong(pinmodel->numshaders);
1750 pheader->numbones = BigLong(pinmodel->numbones);
1751 pheader->numscenes = BigLong(pinmodel->numscenes);
1752 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1753 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1754 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1755 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1756 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1757 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1758 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1759 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1760 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1761 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1762 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1763 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1764 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1765 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1766 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1767 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1768 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1769 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1771 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1773 Con_Printf("%s has no geometry\n", loadmodel->name);
1776 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1778 Con_Printf("%s has no animations\n", loadmodel->name);
1782 loadmodel->DrawSky = NULL;
1783 loadmodel->DrawAddWaterPlanes = NULL;
1784 loadmodel->Draw = R_Q1BSP_Draw;
1785 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1786 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1787 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1788 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1789 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1790 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1791 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1792 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1793 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1794 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1795 loadmodel->PointSuperContents = NULL;
1797 loadmodel->numframes = pheader->numscenes;
1798 loadmodel->num_surfaces = pheader->numshaders;
1800 skinfiles = Mod_LoadSkinFiles();
1801 if (loadmodel->numskins < 1)
1802 loadmodel->numskins = 1;
1804 // make skinscenes for the skins (no groups)
1805 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1806 for (i = 0;i < loadmodel->numskins;i++)
1808 loadmodel->skinscenes[i].firstframe = i;
1809 loadmodel->skinscenes[i].framecount = 1;
1810 loadmodel->skinscenes[i].loop = true;
1811 loadmodel->skinscenes[i].framerate = 10;
1815 modelradius = pheader->radius;
1816 for (i = 0;i < 3;i++)
1818 loadmodel->normalmins[i] = pheader->mins[i];
1819 loadmodel->normalmaxs[i] = pheader->maxs[i];
1820 loadmodel->rotatedmins[i] = -modelradius;
1821 loadmodel->rotatedmaxs[i] = modelradius;
1823 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1824 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1825 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1826 if (loadmodel->yawmaxs[0] > modelradius)
1827 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1828 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1829 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1830 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1831 loadmodel->radius = modelradius;
1832 loadmodel->radius2 = modelradius * modelradius;
1834 // go through the lumps, swapping things
1836 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1837 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1838 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1839 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1840 for (i = 0;i < pheader->numscenes;i++)
1842 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1843 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1844 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1845 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1846 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1847 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1848 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1849 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1850 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1851 if (loadmodel->animscenes[i].framerate < 0)
1852 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1856 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1857 loadmodel->num_bones = pheader->numbones;
1858 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1859 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1860 for (i = 0;i < pheader->numbones;i++)
1862 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1863 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1864 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1865 if (loadmodel->data_bones[i].parent >= i)
1866 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1869 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1870 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1871 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1872 for (i = 0;i < pheader->numverts;i++)
1874 vertbonecounts[i] = BigLong(bonecount[i]);
1875 if (vertbonecounts[i] != 1)
1876 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1879 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1881 meshvertices = pheader->numverts;
1882 meshtriangles = pheader->numtris;
1884 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1885 if(mod_alias_force_animated.string[0])
1886 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
1887 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
1888 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1889 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1890 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1891 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]));
1892 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1893 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1894 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1895 loadmodel->surfmesh.num_vertices = meshvertices;
1896 loadmodel->surfmesh.num_triangles = meshtriangles;
1897 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1898 if (r_enableshadowvolumes.integer)
1900 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1902 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1903 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1904 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1905 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1906 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1907 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1908 loadmodel->surfmesh.num_blends = 0;
1909 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
1910 if (loadmodel->surfmesh.num_vertices <= 65536)
1912 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1914 loadmodel->data_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
1915 loadmodel->surfmesh.data_blendweights = NULL;
1917 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1918 poses = (float *) (pheader->lump_poses.start + pbase);
1919 // figure out scale of model from root bone, for compatibility with old zmodel versions
1920 tempvec[0] = BigFloat(poses[0]);
1921 tempvec[1] = BigFloat(poses[1]);
1922 tempvec[2] = BigFloat(poses[2]);
1923 modelscale = VectorLength(tempvec);
1925 for (i = 0;i < loadmodel->num_bones * numposes * 12;i++)
1927 f = fabs(BigFloat(poses[i]));
1928 biggestorigin = max(biggestorigin, f);
1930 loadmodel->num_posescale = biggestorigin / 32767.0f;
1931 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
1932 for (i = 0;i < numposes;i++)
1934 const float *frameposes = (float *) (pheader->lump_poses.start + pbase) + 12*i*loadmodel->num_bones;
1935 for (j = 0;j < loadmodel->num_bones;j++)
1938 matrix4x4_t posematrix;
1939 for (k = 0;k < 12;k++)
1940 pose[k] = BigFloat(frameposes[j*12+k]);
1941 //if (j < loadmodel->num_bones)
1942 // 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));
1943 // scale child bones to match the root scale
1944 if (loadmodel->data_bones[j].parent >= 0)
1946 pose[3] *= modelscale;
1947 pose[7] *= modelscale;
1948 pose[11] *= modelscale;
1950 // normalize rotation matrix
1951 VectorNormalize(pose + 0);
1952 VectorNormalize(pose + 4);
1953 VectorNormalize(pose + 8);
1954 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
1955 Matrix4x4_ToBonePose7s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses7s + 7*(i*loadmodel->num_bones+j));
1959 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1960 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1961 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1962 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1963 // (converting from weight-blending skeletal animation to
1964 // deformation-based skeletal animation)
1965 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1966 for (i = 0;i < loadmodel->num_bones;i++)
1969 for (k = 0;k < 12;k++)
1970 m[k] = BigFloat(poses[i*12+k]);
1971 if (loadmodel->data_bones[i].parent >= 0)
1972 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1974 for (k = 0;k < 12;k++)
1975 bonepose[12*i+k] = m[k];
1977 for (j = 0;j < pheader->numverts;j++)
1979 // this format really should have had a per vertexweight weight value...
1980 // but since it does not, the weighting is completely ignored and
1981 // only one weight is allowed per vertex
1982 int boneindex = BigLong(vertdata[j].bonenum);
1983 const float *m = bonepose + 12 * boneindex;
1984 float relativeorigin[3];
1985 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1986 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1987 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1988 // transform the vertex bone weight into the base mesh
1989 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1990 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1991 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1992 // store the weight as the primary weight on this vertex
1993 loadmodel->surfmesh.blends[j] = boneindex;
1996 // normals and tangents are calculated after elements are loaded
1998 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1999 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
2000 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
2001 for (i = 0;i < pheader->numverts;i++)
2003 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
2004 // flip T coordinate for OpenGL
2005 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
2008 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
2009 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
2010 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
2012 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
2013 //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)
2014 // byteswap, validate, and swap winding order of tris
2015 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
2016 if (pheader->lump_render.length != count)
2017 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
2018 renderlist = (int *) (pheader->lump_render.start + pbase);
2019 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
2021 for (i = 0;i < loadmodel->num_surfaces;i++)
2023 int firstvertex, lastvertex;
2024 if (renderlist >= renderlistend)
2025 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2026 count = BigLong(*renderlist);renderlist++;
2027 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
2028 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2030 loadmodel->sortedmodelsurfaces[i] = i;
2031 surface = loadmodel->data_surfaces + i;
2032 surface->texture = loadmodel->data_textures + i;
2033 surface->num_firsttriangle = meshtriangles;
2034 surface->num_triangles = count;
2035 meshtriangles += surface->num_triangles;
2037 // load the elements
2038 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2039 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
2041 outelements[j*3+2] = BigLong(renderlist[0]);
2042 outelements[j*3+1] = BigLong(renderlist[1]);
2043 outelements[j*3+0] = BigLong(renderlist[2]);
2045 // validate the elements and find the used vertex range
2046 firstvertex = meshvertices;
2048 for (j = 0;j < surface->num_triangles * 3;j++)
2050 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
2051 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
2052 firstvertex = min(firstvertex, outelements[j]);
2053 lastvertex = max(lastvertex, outelements[j]);
2055 surface->num_firstvertex = firstvertex;
2056 surface->num_vertices = lastvertex + 1 - firstvertex;
2058 // since zym models do not have named sections, reuse their shader
2059 // name as the section name
2060 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
2061 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
2063 Mod_FreeSkinFiles(skinfiles);
2064 Mem_Free(vertbonecounts);
2066 Mod_MakeSortedSurfaces(loadmodel);
2068 // compute all the mesh information that was not loaded from the file
2069 if (loadmodel->surfmesh.data_element3s)
2070 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2071 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2072 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2073 Mod_BuildBaseBonePoses();
2074 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);
2075 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);
2076 if (loadmodel->surfmesh.data_neighbor3i)
2077 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2079 if (!loadmodel->surfmesh.isanimated)
2081 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2082 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2083 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2084 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2085 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2086 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2089 // because shaders can do somewhat unexpected things, check for unusual features now
2090 for (i = 0;i < loadmodel->num_textures;i++)
2092 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
2093 mod->DrawSky = R_Q1BSP_DrawSky;
2094 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
2095 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
2099 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2101 dpmheader_t *pheader;
2105 unsigned char *pbase;
2106 int i, j, k, meshvertices, meshtriangles;
2107 skinfile_t *skinfiles;
2108 unsigned char *data;
2110 float biggestorigin, tempvec[3], modelscale;
2114 pheader = (dpmheader_t *)buffer;
2115 pbase = (unsigned char *)buffer;
2116 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2117 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2118 if (BigLong(pheader->type) != 2)
2119 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2121 loadmodel->modeldatatypestring = "DPM";
2123 loadmodel->type = mod_alias;
2124 loadmodel->synctype = ST_RAND;
2127 pheader->type = BigLong(pheader->type);
2128 pheader->filesize = BigLong(pheader->filesize);
2129 pheader->mins[0] = BigFloat(pheader->mins[0]);
2130 pheader->mins[1] = BigFloat(pheader->mins[1]);
2131 pheader->mins[2] = BigFloat(pheader->mins[2]);
2132 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2133 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2134 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2135 pheader->yawradius = BigFloat(pheader->yawradius);
2136 pheader->allradius = BigFloat(pheader->allradius);
2137 pheader->num_bones = BigLong(pheader->num_bones);
2138 pheader->num_meshs = BigLong(pheader->num_meshs);
2139 pheader->num_frames = BigLong(pheader->num_frames);
2140 pheader->ofs_bones = BigLong(pheader->ofs_bones);
2141 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2142 pheader->ofs_frames = BigLong(pheader->ofs_frames);
2144 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2146 Con_Printf("%s has no geometry\n", loadmodel->name);
2149 if (pheader->num_frames < 1)
2151 Con_Printf("%s has no frames\n", loadmodel->name);
2155 loadmodel->DrawSky = NULL;
2156 loadmodel->DrawAddWaterPlanes = NULL;
2157 loadmodel->Draw = R_Q1BSP_Draw;
2158 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2159 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2160 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2161 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2162 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2163 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2164 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2165 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2166 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2167 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2168 loadmodel->PointSuperContents = NULL;
2171 for (i = 0;i < 3;i++)
2173 loadmodel->normalmins[i] = pheader->mins[i];
2174 loadmodel->normalmaxs[i] = pheader->maxs[i];
2175 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2176 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2177 loadmodel->rotatedmins[i] = -pheader->allradius;
2178 loadmodel->rotatedmaxs[i] = pheader->allradius;
2180 loadmodel->radius = pheader->allradius;
2181 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2183 // load external .skin files if present
2184 skinfiles = Mod_LoadSkinFiles();
2185 if (loadmodel->numskins < 1)
2186 loadmodel->numskins = 1;
2191 // gather combined statistics from the meshes
2192 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2193 for (i = 0;i < (int)pheader->num_meshs;i++)
2195 int numverts = BigLong(dpmmesh->num_verts);
2196 meshvertices += numverts;
2197 meshtriangles += BigLong(dpmmesh->num_tris);
2201 loadmodel->numframes = pheader->num_frames;
2202 loadmodel->num_bones = pheader->num_bones;
2203 loadmodel->num_poses = loadmodel->numframes;
2204 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2205 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2206 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2207 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
2208 if(mod_alias_force_animated.string[0])
2209 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
2210 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
2211 // do most allocations as one merged chunk
2212 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));
2213 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2214 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2215 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2216 loadmodel->surfmesh.num_vertices = meshvertices;
2217 loadmodel->surfmesh.num_triangles = meshtriangles;
2218 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2219 if (r_enableshadowvolumes.integer)
2221 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2223 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2224 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2225 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2226 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2227 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2228 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2229 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2230 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2231 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2232 loadmodel->surfmesh.num_blends = 0;
2233 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2234 if (meshvertices <= 65536)
2236 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2238 loadmodel->data_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
2239 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
2241 for (i = 0;i < loadmodel->numskins;i++)
2243 loadmodel->skinscenes[i].firstframe = i;
2244 loadmodel->skinscenes[i].framecount = 1;
2245 loadmodel->skinscenes[i].loop = true;
2246 loadmodel->skinscenes[i].framerate = 10;
2249 // load the bone info
2250 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2251 for (i = 0;i < loadmodel->num_bones;i++)
2253 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2254 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2255 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2256 if (loadmodel->data_bones[i].parent >= i)
2257 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2261 frames = (dpmframe_t *) (pbase + pheader->ofs_frames);
2262 // figure out scale of model from root bone, for compatibility with old dpmodel versions
2263 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2264 tempvec[0] = BigFloat(poses[0]);
2265 tempvec[1] = BigFloat(poses[1]);
2266 tempvec[2] = BigFloat(poses[2]);
2267 modelscale = VectorLength(tempvec);
2269 for (i = 0;i < loadmodel->numframes;i++)
2271 memcpy(loadmodel->animscenes[i].name, frames[i].name, sizeof(frames[i].name));
2272 loadmodel->animscenes[i].firstframe = i;
2273 loadmodel->animscenes[i].framecount = 1;
2274 loadmodel->animscenes[i].loop = true;
2275 loadmodel->animscenes[i].framerate = 10;
2276 // load the bone poses for this frame
2277 poses = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2278 for (j = 0;j < loadmodel->num_bones*12;j++)
2280 f = fabs(BigFloat(poses[j]));
2281 biggestorigin = max(biggestorigin, f);
2283 // stuff not processed here: mins, maxs, yawradius, allradius
2285 loadmodel->num_posescale = biggestorigin / 32767.0f;
2286 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2287 for (i = 0;i < loadmodel->numframes;i++)
2289 const float *frameposes = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2290 for (j = 0;j < loadmodel->num_bones;j++)
2293 matrix4x4_t posematrix;
2294 for (k = 0;k < 12;k++)
2295 pose[k] = BigFloat(frameposes[j*12+k]);
2296 // scale child bones to match the root scale
2297 if (loadmodel->data_bones[j].parent >= 0)
2299 pose[3] *= modelscale;
2300 pose[7] *= modelscale;
2301 pose[11] *= modelscale;
2303 // normalize rotation matrix
2304 VectorNormalize(pose + 0);
2305 VectorNormalize(pose + 4);
2306 VectorNormalize(pose + 8);
2307 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2308 Matrix4x4_ToBonePose7s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses7s + 7*(i*loadmodel->num_bones+j));
2312 // load the meshes now
2313 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2316 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2317 // (converting from weight-blending skeletal animation to
2318 // deformation-based skeletal animation)
2319 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2320 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2321 for (i = 0;i < loadmodel->num_bones;i++)
2324 for (k = 0;k < 12;k++)
2325 m[k] = BigFloat(poses[i*12+k]);
2326 if (loadmodel->data_bones[i].parent >= 0)
2327 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2329 for (k = 0;k < 12;k++)
2330 bonepose[12*i+k] = m[k];
2332 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2334 const int *inelements;
2336 const float *intexcoord;
2337 msurface_t *surface;
2339 loadmodel->sortedmodelsurfaces[i] = i;
2340 surface = loadmodel->data_surfaces + i;
2341 surface->texture = loadmodel->data_textures + i;
2342 surface->num_firsttriangle = meshtriangles;
2343 surface->num_triangles = BigLong(dpmmesh->num_tris);
2344 surface->num_firstvertex = meshvertices;
2345 surface->num_vertices = BigLong(dpmmesh->num_verts);
2346 meshvertices += surface->num_vertices;
2347 meshtriangles += surface->num_triangles;
2349 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2350 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2351 for (j = 0;j < surface->num_triangles;j++)
2353 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2354 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2355 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2356 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2361 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2362 for (j = 0;j < surface->num_vertices*2;j++)
2363 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2365 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2366 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2368 int weightindex[4] = { 0, 0, 0, 0 };
2369 float weightinfluence[4] = { 0, 0, 0, 0 };
2371 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2372 data += sizeof(dpmvertex_t);
2373 for (k = 0;k < numweights;k++)
2375 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2376 int boneindex = BigLong(vert->bonenum);
2377 const float *m = bonepose + 12 * boneindex;
2378 float influence = BigFloat(vert->influence);
2379 float relativeorigin[3], relativenormal[3];
2380 relativeorigin[0] = BigFloat(vert->origin[0]);
2381 relativeorigin[1] = BigFloat(vert->origin[1]);
2382 relativeorigin[2] = BigFloat(vert->origin[2]);
2383 relativenormal[0] = BigFloat(vert->normal[0]);
2384 relativenormal[1] = BigFloat(vert->normal[1]);
2385 relativenormal[2] = BigFloat(vert->normal[2]);
2386 // blend the vertex bone weights into the base mesh
2387 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2388 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2389 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2390 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2391 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2392 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2395 // store the first (and often only) weight
2396 weightinfluence[0] = influence;
2397 weightindex[0] = boneindex;
2401 // sort the new weight into this vertex's weight table
2402 // (which only accepts up to 4 bones per vertex)
2403 for (l = 0;l < 4;l++)
2405 if (weightinfluence[l] < influence)
2407 // move weaker influence weights out of the way first
2409 for (l2 = 3;l2 > l;l2--)
2411 weightinfluence[l2] = weightinfluence[l2-1];
2412 weightindex[l2] = weightindex[l2-1];
2414 // store the new weight
2415 weightinfluence[l] = influence;
2416 weightindex[l] = boneindex;
2421 data += sizeof(dpmbonevert_t);
2423 loadmodel->surfmesh.blends[j] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
2426 // since dpm models do not have named sections, reuse their shader name as the section name
2427 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2429 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2431 if (loadmodel->surfmesh.num_blends < meshvertices)
2432 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2434 Mod_FreeSkinFiles(skinfiles);
2435 Mod_MakeSortedSurfaces(loadmodel);
2437 // compute all the mesh information that was not loaded from the file
2438 if (loadmodel->surfmesh.data_element3s)
2439 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2440 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2441 Mod_BuildBaseBonePoses();
2442 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);
2443 if (loadmodel->surfmesh.data_neighbor3i)
2444 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2446 if (!loadmodel->surfmesh.isanimated)
2448 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2449 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2450 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2451 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2452 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2453 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2456 // because shaders can do somewhat unexpected things, check for unusual features now
2457 for (i = 0;i < loadmodel->num_textures;i++)
2459 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
2460 mod->DrawSky = R_Q1BSP_DrawSky;
2461 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
2462 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
2466 // no idea why PSK/PSA files contain weird quaternions but they do...
2467 #define PSKQUATNEGATIONS
2468 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2470 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2471 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2472 fs_offset_t filesize;
2477 pskboneinfo_t *bones;
2478 pskrawweights_t *rawweights;
2479 //pskboneinfo_t *animbones;
2480 pskaniminfo_t *anims;
2481 pskanimkeys_t *animkeys;
2482 void *animfilebuffer, *animbuffer, *animbufferend;
2483 unsigned char *data;
2485 skinfile_t *skinfiles;
2486 char animname[MAX_QPATH];
2488 float biggestorigin;
2490 pchunk = (pskchunk_t *)buffer;
2491 if (strcmp(pchunk->id, "ACTRHEAD"))
2492 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2494 loadmodel->modeldatatypestring = "PSK";
2496 loadmodel->type = mod_alias;
2497 loadmodel->DrawSky = NULL;
2498 loadmodel->DrawAddWaterPlanes = NULL;
2499 loadmodel->Draw = R_Q1BSP_Draw;
2500 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2501 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2502 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2503 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2504 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2505 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2506 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2507 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2508 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2509 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2510 loadmodel->PointSuperContents = NULL;
2511 loadmodel->synctype = ST_RAND;
2513 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2514 strlcat(animname, ".psa", sizeof(animname));
2515 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2516 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2518 animbufferend = animbuffer;
2537 while (buffer < bufferend)
2539 pchunk = (pskchunk_t *)buffer;
2540 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2541 version = LittleLong(pchunk->version);
2542 recordsize = LittleLong(pchunk->recordsize);
2543 numrecords = LittleLong(pchunk->numrecords);
2544 if (developer_extra.integer)
2545 Con_DPrintf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2546 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2547 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);
2548 if (!strcmp(pchunk->id, "ACTRHEAD"))
2552 else if (!strcmp(pchunk->id, "PNTS0000"))
2555 if (recordsize != sizeof(*p))
2556 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2557 // byteswap in place and keep the pointer
2558 numpnts = numrecords;
2559 pnts = (pskpnts_t *)buffer;
2560 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2562 p->origin[0] = LittleFloat(p->origin[0]);
2563 p->origin[1] = LittleFloat(p->origin[1]);
2564 p->origin[2] = LittleFloat(p->origin[2]);
2568 else if (!strcmp(pchunk->id, "VTXW0000"))
2571 if (recordsize != sizeof(*p))
2572 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2573 // byteswap in place and keep the pointer
2574 numvtxw = numrecords;
2575 vtxw = (pskvtxw_t *)buffer;
2576 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2578 p->pntsindex = LittleShort(p->pntsindex);
2579 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2580 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2581 if (p->pntsindex >= numpnts)
2583 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2589 else if (!strcmp(pchunk->id, "FACE0000"))
2592 if (recordsize != sizeof(*p))
2593 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2594 // byteswap in place and keep the pointer
2595 numfaces = numrecords;
2596 faces = (pskface_t *)buffer;
2597 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2599 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2600 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2601 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2602 p->group = LittleLong(p->group);
2603 if (p->vtxwindex[0] >= numvtxw)
2605 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2606 p->vtxwindex[0] = 0;
2608 if (p->vtxwindex[1] >= numvtxw)
2610 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2611 p->vtxwindex[1] = 0;
2613 if (p->vtxwindex[2] >= numvtxw)
2615 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2616 p->vtxwindex[2] = 0;
2621 else if (!strcmp(pchunk->id, "MATT0000"))
2624 if (recordsize != sizeof(*p))
2625 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2626 // byteswap in place and keep the pointer
2627 nummatts = numrecords;
2628 matts = (pskmatt_t *)buffer;
2629 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2635 else if (!strcmp(pchunk->id, "REFSKELT"))
2638 if (recordsize != sizeof(*p))
2639 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2640 // byteswap in place and keep the pointer
2641 numbones = numrecords;
2642 bones = (pskboneinfo_t *)buffer;
2643 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2645 p->numchildren = LittleLong(p->numchildren);
2646 p->parent = LittleLong(p->parent);
2647 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2648 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2649 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2650 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2651 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2652 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2653 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2654 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2655 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2656 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2657 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2658 #ifdef PSKQUATNEGATIONS
2661 p->basepose.quat[0] *= -1;
2662 p->basepose.quat[1] *= -1;
2663 p->basepose.quat[2] *= -1;
2667 p->basepose.quat[0] *= 1;
2668 p->basepose.quat[1] *= -1;
2669 p->basepose.quat[2] *= 1;
2672 if (p->parent < 0 || p->parent >= numbones)
2674 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2680 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2683 if (recordsize != sizeof(*p))
2684 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2685 // byteswap in place and keep the pointer
2686 numrawweights = numrecords;
2687 rawweights = (pskrawweights_t *)buffer;
2688 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2690 p->weight = LittleFloat(p->weight);
2691 p->pntsindex = LittleLong(p->pntsindex);
2692 p->boneindex = LittleLong(p->boneindex);
2693 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2695 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2698 if (p->boneindex < 0 || p->boneindex >= numbones)
2700 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2708 while (animbuffer < animbufferend)
2710 pchunk = (pskchunk_t *)animbuffer;
2711 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2712 version = LittleLong(pchunk->version);
2713 recordsize = LittleLong(pchunk->recordsize);
2714 numrecords = LittleLong(pchunk->numrecords);
2715 if (developer_extra.integer)
2716 Con_DPrintf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2717 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2718 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);
2719 if (!strcmp(pchunk->id, "ANIMHEAD"))
2723 else if (!strcmp(pchunk->id, "BONENAMES"))
2726 if (recordsize != sizeof(*p))
2727 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2728 // byteswap in place and keep the pointer
2729 numanimbones = numrecords;
2730 //animbones = (pskboneinfo_t *)animbuffer;
2731 // NOTE: supposedly psa does not need to match the psk model, the
2732 // bones missing from the psa would simply use their base
2733 // positions from the psk, but this is hard for me to implement
2734 // and people can easily make animations that match.
2735 if (numanimbones != numbones)
2736 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2737 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2739 p->numchildren = LittleLong(p->numchildren);
2740 p->parent = LittleLong(p->parent);
2741 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2742 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2743 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2744 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2745 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2746 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2747 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2748 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2749 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2750 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2751 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2752 #ifdef PSKQUATNEGATIONS
2755 p->basepose.quat[0] *= -1;
2756 p->basepose.quat[1] *= -1;
2757 p->basepose.quat[2] *= -1;
2761 p->basepose.quat[0] *= 1;
2762 p->basepose.quat[1] *= -1;
2763 p->basepose.quat[2] *= 1;
2766 if (p->parent < 0 || p->parent >= numanimbones)
2768 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2771 // check that bones are the same as in the base
2772 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2773 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2777 else if (!strcmp(pchunk->id, "ANIMINFO"))
2780 if (recordsize != sizeof(*p))
2781 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2782 // byteswap in place and keep the pointer
2783 numanims = numrecords;
2784 anims = (pskaniminfo_t *)animbuffer;
2785 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2787 p->numbones = LittleLong(p->numbones);
2788 p->playtime = LittleFloat(p->playtime);
2789 p->fps = LittleFloat(p->fps);
2790 p->firstframe = LittleLong(p->firstframe);
2791 p->numframes = LittleLong(p->numframes);
2792 if (p->numbones != numbones)
2793 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2797 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2800 if (recordsize != sizeof(*p))
2801 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2802 numanimkeys = numrecords;
2803 animkeys = (pskanimkeys_t *)animbuffer;
2804 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2806 p->origin[0] = LittleFloat(p->origin[0]);
2807 p->origin[1] = LittleFloat(p->origin[1]);
2808 p->origin[2] = LittleFloat(p->origin[2]);
2809 p->quat[0] = LittleFloat(p->quat[0]);
2810 p->quat[1] = LittleFloat(p->quat[1]);
2811 p->quat[2] = LittleFloat(p->quat[2]);
2812 p->quat[3] = LittleFloat(p->quat[3]);
2813 p->frametime = LittleFloat(p->frametime);
2814 #ifdef PSKQUATNEGATIONS
2815 if (index % numbones)
2830 // TODO: allocate bonepose stuff
2833 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2836 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights)
2837 Host_Error("%s: missing required chunks", loadmodel->name);
2841 loadmodel->numframes = 0;
2842 for (index = 0;index < numanims;index++)
2843 loadmodel->numframes += anims[index].numframes;
2844 if (numanimkeys != numbones * loadmodel->numframes)
2845 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2848 loadmodel->numframes = loadmodel->num_poses = 1;
2850 meshvertices = numvtxw;
2851 meshtriangles = numfaces;
2853 // load external .skin files if present
2854 skinfiles = Mod_LoadSkinFiles();
2855 if (loadmodel->numskins < 1)
2856 loadmodel->numskins = 1;
2857 loadmodel->num_bones = numbones;
2858 loadmodel->num_poses = loadmodel->numframes;
2859 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2860 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2861 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2862 loadmodel->surfmesh.num_vertices = meshvertices;
2863 loadmodel->surfmesh.num_triangles = meshtriangles;
2864 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
2865 if(mod_alias_force_animated.string[0])
2866 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
2867 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
2868 // do most allocations as one merged chunk
2869 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);
2870 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2871 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2872 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2873 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2874 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2875 if (r_enableshadowvolumes.integer)
2877 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2879 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2880 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2881 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2882 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2883 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2884 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2885 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2886 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2887 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2888 loadmodel->surfmesh.num_blends = 0;
2889 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2890 if (loadmodel->surfmesh.num_vertices <= 65536)
2892 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2894 loadmodel->data_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
2895 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(blendweights_t));
2897 for (i = 0;i < loadmodel->numskins;i++)
2899 loadmodel->skinscenes[i].firstframe = i;
2900 loadmodel->skinscenes[i].framecount = 1;
2901 loadmodel->skinscenes[i].loop = true;
2902 loadmodel->skinscenes[i].framerate = 10;
2906 for (index = 0, i = 0;index < nummatts;index++)
2908 // since psk models do not have named sections, reuse their shader name as the section name
2909 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2910 loadmodel->sortedmodelsurfaces[index] = index;
2911 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2912 loadmodel->data_surfaces[index].num_firstvertex = 0;
2913 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2916 // copy over the vertex locations and texcoords
2917 for (index = 0;index < numvtxw;index++)
2919 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2920 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2921 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2922 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2923 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2926 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2927 for (index = 0;index < numfaces;index++)
2928 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2929 for (index = 0, i = 0;index < nummatts;index++)
2931 loadmodel->data_surfaces[index].num_firsttriangle = i;
2932 i += loadmodel->data_surfaces[index].num_triangles;
2933 loadmodel->data_surfaces[index].num_triangles = 0;
2935 for (index = 0;index < numfaces;index++)
2937 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2938 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2939 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2940 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2943 // copy over the bones
2944 for (index = 0;index < numbones;index++)
2946 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2947 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2948 if (loadmodel->data_bones[index].parent >= index)
2949 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2952 // convert the basepose data
2953 if (loadmodel->num_bones)
2956 matrix4x4_t *basebonepose;
2957 float *outinvmatrix = loadmodel->data_baseboneposeinverse;
2958 matrix4x4_t bonematrix;
2959 matrix4x4_t tempbonematrix;
2960 basebonepose = (matrix4x4_t *)Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(matrix4x4_t));
2961 for (boneindex = 0;boneindex < loadmodel->num_bones;boneindex++)
2963 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]);
2964 if (loadmodel->data_bones[boneindex].parent >= 0)
2966 tempbonematrix = bonematrix;
2967 Matrix4x4_Concat(&bonematrix, basebonepose + loadmodel->data_bones[boneindex].parent, &tempbonematrix);
2969 basebonepose[boneindex] = bonematrix;
2970 Matrix4x4_Invert_Simple(&tempbonematrix, basebonepose + boneindex);
2971 Matrix4x4_ToArray12FloatD3D(&tempbonematrix, outinvmatrix + 12*boneindex);
2973 Mem_Free(basebonepose);
2976 // sort the psk point weights into the vertex weight tables
2977 // (which only accept up to 4 bones per vertex)
2978 for (index = 0;index < numvtxw;index++)
2980 int weightindex[4] = { 0, 0, 0, 0 };
2981 float weightinfluence[4] = { 0, 0, 0, 0 };
2983 for (j = 0;j < numrawweights;j++)
2985 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2987 int boneindex = rawweights[j].boneindex;
2988 float influence = rawweights[j].weight;
2989 for (l = 0;l < 4;l++)
2991 if (weightinfluence[l] < influence)
2993 // move lower influence weights out of the way first
2995 for (l2 = 3;l2 > l;l2--)
2997 weightinfluence[l2] = weightinfluence[l2-1];
2998 weightindex[l2] = weightindex[l2-1];
3000 // store the new weight
3001 weightinfluence[l] = influence;
3002 weightindex[l] = boneindex;
3008 loadmodel->surfmesh.blends[index] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
3010 if (loadmodel->surfmesh.num_blends < loadmodel->surfmesh.num_vertices)
3011 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
3013 // set up the animscenes based on the anims
3016 for (index = 0, i = 0;index < numanims;index++)
3018 for (j = 0;j < anims[index].numframes;j++, i++)
3020 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
3021 loadmodel->animscenes[i].firstframe = i;
3022 loadmodel->animscenes[i].framecount = 1;
3023 loadmodel->animscenes[i].loop = true;
3024 loadmodel->animscenes[i].framerate = anims[index].fps;
3027 // calculate the scaling value for bone origins so they can be compressed to short
3029 for (index = 0;index < numanimkeys;index++)
3031 pskanimkeys_t *k = animkeys + index;
3032 biggestorigin = max(biggestorigin, fabs(k->origin[0]));
3033 biggestorigin = max(biggestorigin, fabs(k->origin[1]));
3034 biggestorigin = max(biggestorigin, fabs(k->origin[2]));
3036 loadmodel->num_posescale = biggestorigin / 32767.0f;
3037 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3039 // load the poses from the animkeys
3040 for (index = 0;index < numanimkeys;index++)
3042 pskanimkeys_t *k = animkeys + index;
3044 Vector4Copy(k->quat, quat);
3046 Vector4Negate(quat, quat);
3047 Vector4Normalize2(quat, quat);
3048 // compress poses to the short[7] format for longterm storage
3049 loadmodel->data_poses7s[index*7+0] = k->origin[0] * loadmodel->num_poseinvscale;
3050 loadmodel->data_poses7s[index*7+1] = k->origin[1] * loadmodel->num_poseinvscale;
3051 loadmodel->data_poses7s[index*7+2] = k->origin[2] * loadmodel->num_poseinvscale;
3052 loadmodel->data_poses7s[index*7+3] = quat[0] * 32767.0f;
3053 loadmodel->data_poses7s[index*7+4] = quat[1] * 32767.0f;
3054 loadmodel->data_poses7s[index*7+5] = quat[2] * 32767.0f;
3055 loadmodel->data_poses7s[index*7+6] = quat[3] * 32767.0f;
3060 strlcpy(loadmodel->animscenes[0].name, "base", sizeof(loadmodel->animscenes[0].name));
3061 loadmodel->animscenes[0].firstframe = 0;
3062 loadmodel->animscenes[0].framecount = 1;
3063 loadmodel->animscenes[0].loop = true;
3064 loadmodel->animscenes[0].framerate = 10;
3066 // calculate the scaling value for bone origins so they can be compressed to short
3068 for (index = 0;index < numbones;index++)
3070 pskboneinfo_t *p = bones + index;
3071 biggestorigin = max(biggestorigin, fabs(p->basepose.origin[0]));
3072 biggestorigin = max(biggestorigin, fabs(p->basepose.origin[1]));
3073 biggestorigin = max(biggestorigin, fabs(p->basepose.origin[2]));
3075 loadmodel->num_posescale = biggestorigin / 32767.0f;
3076 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3078 // load the basepose as a frame
3079 for (index = 0;index < numbones;index++)
3081 pskboneinfo_t *p = bones + index;
3083 Vector4Copy(p->basepose.quat, quat);
3085 Vector4Negate(quat, quat);
3086 Vector4Normalize2(quat, quat);
3087 // compress poses to the short[7] format for longterm storage
3088 loadmodel->data_poses7s[index*7+0] = p->basepose.origin[0] * loadmodel->num_poseinvscale;
3089 loadmodel->data_poses7s[index*7+1] = p->basepose.origin[1] * loadmodel->num_poseinvscale;
3090 loadmodel->data_poses7s[index*7+2] = p->basepose.origin[2] * loadmodel->num_poseinvscale;
3091 loadmodel->data_poses7s[index*7+3] = quat[0] * 32767.0f;
3092 loadmodel->data_poses7s[index*7+4] = quat[1] * 32767.0f;
3093 loadmodel->data_poses7s[index*7+5] = quat[2] * 32767.0f;
3094 loadmodel->data_poses7s[index*7+6] = quat[3] * 32767.0f;
3098 Mod_FreeSkinFiles(skinfiles);
3100 Mem_Free(animfilebuffer);
3101 Mod_MakeSortedSurfaces(loadmodel);
3103 // compute all the mesh information that was not loaded from the file
3104 // TODO: honor smoothing groups somehow?
3105 if (loadmodel->surfmesh.data_element3s)
3106 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3107 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3108 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
3109 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);
3110 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);
3111 if (loadmodel->surfmesh.data_neighbor3i)
3112 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3113 Mod_Alias_CalculateBoundingBox();
3115 if (!loadmodel->surfmesh.isanimated)
3117 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3118 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3119 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3120 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3121 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3122 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
3125 // because shaders can do somewhat unexpected things, check for unusual features now
3126 for (i = 0;i < loadmodel->num_textures;i++)
3128 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
3129 mod->DrawSky = R_Q1BSP_DrawSky;
3130 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
3131 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
3135 void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
3137 unsigned char *data;
3139 const unsigned char *pbase, *pend;
3141 skinfile_t *skinfiles;
3142 int i, j, k, meshvertices, meshtriangles;
3143 float biggestorigin;
3144 const unsigned int *inelements;
3146 const int *inneighbors;
3148 float *outvertex, *outnormal, *outtexcoord, *outsvector, *outtvector, *outcolor;
3149 // this pointers into the file data are read only through Little* functions so they can be unaligned memory
3150 const float *vnormal = NULL;
3151 const float *vposition = NULL;
3152 const float *vtangent = NULL;
3153 const float *vtexcoord = NULL;
3154 const float *vcolor4f = NULL;
3155 const unsigned char *vblendindexes = NULL;
3156 const unsigned char *vblendweights = NULL;
3157 const unsigned char *vcolor4ub = NULL;
3158 const unsigned short *framedata = NULL;
3159 // temporary memory allocations (because the data in the file may be misaligned)
3160 iqmanim_t *anims = NULL;
3161 iqmbounds_t *bounds = NULL;
3162 iqmjoint1_t *joint1 = NULL;
3163 iqmjoint_t *joint = NULL;
3164 iqmmesh_t *meshes = NULL;
3165 iqmpose1_t *pose1 = NULL;
3166 iqmpose_t *pose = NULL;
3167 iqmvertexarray_t *vas = NULL;
3169 pbase = (unsigned char *)buffer;
3170 pend = (unsigned char *)bufferend;
3172 if (pbase + sizeof(iqmheader_t) > pend)
3173 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model %d", loadmodel->name, (int)(pend - pbase));
3175 // copy struct (otherwise it may be misaligned)
3176 // LordHavoc: okay it's definitely not misaligned here, but for consistency...
3177 memcpy(&header, pbase, sizeof(iqmheader_t));
3179 if (memcmp(header.id, "INTERQUAKEMODEL", 16))
3180 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model", loadmodel->name);
3181 if (LittleLong(header.version) != 1 && LittleLong(header.version) != 2)
3182 Host_Error ("Mod_INTERQUAKEMODEL_Load: only version 1 and 2 models are currently supported (name = %s)", loadmodel->name);
3184 loadmodel->modeldatatypestring = "IQM";
3186 loadmodel->type = mod_alias;
3187 loadmodel->synctype = ST_RAND;
3190 header.version = LittleLong(header.version);
3191 header.filesize = LittleLong(header.filesize);
3192 header.flags = LittleLong(header.flags);
3193 header.num_text = LittleLong(header.num_text);
3194 header.ofs_text = LittleLong(header.ofs_text);
3195 header.num_meshes = LittleLong(header.num_meshes);
3196 header.ofs_meshes = LittleLong(header.ofs_meshes);
3197 header.num_vertexarrays = LittleLong(header.num_vertexarrays);
3198 header.num_vertexes = LittleLong(header.num_vertexes);
3199 header.ofs_vertexarrays = LittleLong(header.ofs_vertexarrays);
3200 header.num_triangles = LittleLong(header.num_triangles);
3201 header.ofs_triangles = LittleLong(header.ofs_triangles);
3202 header.ofs_neighbors = LittleLong(header.ofs_neighbors);
3203 header.num_joints = LittleLong(header.num_joints);
3204 header.ofs_joints = LittleLong(header.ofs_joints);
3205 header.num_poses = LittleLong(header.num_poses);
3206 header.ofs_poses = LittleLong(header.ofs_poses);
3207 header.num_anims = LittleLong(header.num_anims);
3208 header.ofs_anims = LittleLong(header.ofs_anims);
3209 header.num_frames = LittleLong(header.num_frames);
3210 header.num_framechannels = LittleLong(header.num_framechannels);
3211 header.ofs_frames = LittleLong(header.ofs_frames);
3212 header.ofs_bounds = LittleLong(header.ofs_bounds);
3213 header.num_comment = LittleLong(header.num_comment);
3214 header.ofs_comment = LittleLong(header.ofs_comment);
3215 header.num_extensions = LittleLong(header.num_extensions);
3216 header.ofs_extensions = LittleLong(header.ofs_extensions);
3218 if (header.version == 1)
3220 if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint1_t) > pend ||
3221 pbase + header.ofs_poses + header.num_poses*sizeof(iqmpose1_t) > pend)
3223 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3229 if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint_t) > pend ||
3230 pbase + header.ofs_poses + header.num_poses*sizeof(iqmpose_t) > pend)
3232 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3236 if (pbase + header.ofs_text + header.num_text > pend ||
3237 pbase + header.ofs_meshes + header.num_meshes*sizeof(iqmmesh_t) > pend ||
3238 pbase + header.ofs_vertexarrays + header.num_vertexarrays*sizeof(iqmvertexarray_t) > pend ||
3239 pbase + header.ofs_triangles + header.num_triangles*sizeof(int[3]) > pend ||
3240 (header.ofs_neighbors && pbase + header.ofs_neighbors + header.num_triangles*sizeof(int[3]) > pend) ||
3241 pbase + header.ofs_anims + header.num_anims*sizeof(iqmanim_t) > pend ||
3242 pbase + header.ofs_frames + header.num_frames*header.num_framechannels*sizeof(unsigned short) > pend ||
3243 (header.ofs_bounds && pbase + header.ofs_bounds + header.num_frames*sizeof(iqmbounds_t) > pend) ||
3244 pbase + header.ofs_comment + header.num_comment > pend)
3246 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3250 // copy structs to make them aligned in memory (otherwise we crash on Sparc and PowerPC and others)
3251 if (header.num_vertexarrays)
3252 vas = (iqmvertexarray_t *)(pbase + header.ofs_vertexarrays);
3253 if (header.num_anims)
3254 anims = (iqmanim_t *)(pbase + header.ofs_anims);
3255 if (header.ofs_bounds)
3256 bounds = (iqmbounds_t *)(pbase + header.ofs_bounds);
3257 if (header.num_meshes)
3258 meshes = (iqmmesh_t *)(pbase + header.ofs_meshes);
3260 for (i = 0;i < (int)header.num_vertexarrays;i++)
3262 iqmvertexarray_t va;
3264 va.type = LittleLong(vas[i].type);
3265 va.flags = LittleLong(vas[i].flags);
3266 va.format = LittleLong(vas[i].format);
3267 va.size = LittleLong(vas[i].size);
3268 va.offset = LittleLong(vas[i].offset);
3269 vsize = header.num_vertexes*va.size;
3272 case IQM_FLOAT: vsize *= sizeof(float); break;
3273 case IQM_UBYTE: vsize *= sizeof(unsigned char); break;
3276 if (pbase + va.offset + vsize > pend)
3278 // no need to copy the vertex data for alignment because LittleLong/LittleShort will be invoked on reading them, and the destination is aligned
3282 if (va.format == IQM_FLOAT && va.size == 3)
3283 vposition = (const float *)(pbase + va.offset);
3286 if (va.format == IQM_FLOAT && va.size == 2)
3287 vtexcoord = (const float *)(pbase + va.offset);
3290 if (va.format == IQM_FLOAT && va.size == 3)
3291 vnormal = (const float *)(pbase + va.offset);
3294 if (va.format == IQM_FLOAT && va.size == 4)
3295 vtangent = (const float *)(pbase + va.offset);
3297 case IQM_BLENDINDEXES:
3298 if (va.format == IQM_UBYTE && va.size == 4)
3299 vblendindexes = (const unsigned char *)(pbase + va.offset);
3301 case IQM_BLENDWEIGHTS:
3302 if (va.format == IQM_UBYTE && va.size == 4)
3303 vblendweights = (const unsigned char *)(pbase + va.offset);
3306 if (va.format == IQM_FLOAT && va.size == 4)
3307 vcolor4f = (const float *)(pbase + va.offset);
3308 if (va.format == IQM_UBYTE && va.size == 4)
3309 vcolor4ub = (const unsigned char *)(pbase + va.offset);
3313 if (header.num_vertexes > 0 && (!vposition || !vtexcoord || ((header.num_frames > 0 || header.num_anims > 0) && (!vblendindexes || !vblendweights))))
3315 Con_Printf("%s is missing vertex array data\n", loadmodel->name);
3319 text = header.num_text && header.ofs_text ? (const char *)(pbase + header.ofs_text) : "";
3321 loadmodel->DrawSky = NULL;
3322 loadmodel->DrawAddWaterPlanes = NULL;
3323 loadmodel->Draw = R_Q1BSP_Draw;
3324 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
3325 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
3326 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
3327 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
3328 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
3329 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
3330 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
3331 loadmodel->DrawLight = R_Q1BSP_DrawLight;
3332 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
3333 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
3334 loadmodel->PointSuperContents = NULL;
3336 // load external .skin files if present
3337 skinfiles = Mod_LoadSkinFiles();
3338 if (loadmodel->numskins < 1)
3339 loadmodel->numskins = 1;
3341 loadmodel->numframes = max(header.num_anims, 1);
3342 loadmodel->num_bones = header.num_joints;
3343 loadmodel->num_poses = max(header.num_frames, 1);
3344 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = header.num_meshes;
3345 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3346 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3347 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices; // updated later
3349 meshvertices = header.num_vertexes;
3350 meshtriangles = header.num_triangles;
3352 // do most allocations as one merged chunk
3353 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));
3354 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
3355 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
3356 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
3357 loadmodel->surfmesh.num_vertices = meshvertices;
3358 loadmodel->surfmesh.num_triangles = meshtriangles;
3359 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3360 if (r_enableshadowvolumes.integer)
3362 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3364 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
3365 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3366 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3367 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
3368 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
3369 if (vcolor4f || vcolor4ub)
3371 loadmodel->surfmesh.data_lightmapcolor4f = (float *)data;data += meshvertices * sizeof(float[4]);
3373 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
3374 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
3375 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
3376 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
3377 if (vblendindexes && vblendweights)
3379 loadmodel->surfmesh.num_blends = 0;
3380 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
3382 if (meshvertices <= 65536)
3384 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
3386 loadmodel->data_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
3387 if (vblendindexes && vblendweights)
3388 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
3390 for (i = 0;i < loadmodel->numskins;i++)
3392 loadmodel->skinscenes[i].firstframe = i;
3393 loadmodel->skinscenes[i].framecount = 1;
3394 loadmodel->skinscenes[i].loop = true;
3395 loadmodel->skinscenes[i].framerate = 10;
3398 // load the bone info
3399 if (header.version == 1)
3401 iqmjoint1_t *injoint1 = (iqmjoint1_t *)(pbase + header.ofs_joints);
3402 if (loadmodel->num_bones)
3403 joint1 = (iqmjoint1_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(iqmjoint1_t));
3404 for (i = 0;i < loadmodel->num_bones;i++)
3406 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3407 joint1[i].name = LittleLong(injoint1[i].name);
3408 joint1[i].parent = LittleLong(injoint1[i].parent);
3409 for (j = 0;j < 3;j++)
3411 joint1[i].origin[j] = LittleFloat(injoint1[i].origin[j]);
3412 joint1[i].rotation[j] = LittleFloat(injoint1[i].rotation[j]);
3413 joint1[i].scale[j] = LittleFloat(injoint1[i].scale[j]);
3415 strlcpy(loadmodel->data_bones[i].name, &text[joint1[i].name], sizeof(loadmodel->data_bones[i].name));
3416 loadmodel->data_bones[i].parent = joint1[i].parent;
3417 if (loadmodel->data_bones[i].parent >= i)
3418 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3419 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]);
3420 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3421 if (loadmodel->data_bones[i].parent >= 0)
3423 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3424 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3425 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3427 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3432 iqmjoint_t *injoint = (iqmjoint_t *)(pbase + header.ofs_joints);
3433 if (header.num_joints)
3434 joint = (iqmjoint_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(iqmjoint_t));
3435 for (i = 0;i < loadmodel->num_bones;i++)
3437 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3438 joint[i].name = LittleLong(injoint[i].name);
3439 joint[i].parent = LittleLong(injoint[i].parent);
3440 for (j = 0;j < 3;j++)
3442 joint[i].origin[j] = LittleFloat(injoint[i].origin[j]);
3443 joint[i].rotation[j] = LittleFloat(injoint[i].rotation[j]);
3444 joint[i].scale[j] = LittleFloat(injoint[i].scale[j]);
3446 joint[i].rotation[3] = LittleFloat(injoint[i].rotation[3]);
3447 strlcpy(loadmodel->data_bones[i].name, &text[joint[i].name], sizeof(loadmodel->data_bones[i].name));
3448 loadmodel->data_bones[i].parent = joint[i].parent;
3449 if (loadmodel->data_bones[i].parent >= i)
3450 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3451 if (joint[i].rotation[3] > 0)
3452 Vector4Negate(joint[i].rotation, joint[i].rotation);
3453 Vector4Normalize2(joint[i].rotation, joint[i].rotation);
3454 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]);
3455 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3456 if (loadmodel->data_bones[i].parent >= 0)
3458 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3459 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3460 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3462 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3466 // set up the animscenes based on the anims
3467 for (i = 0;i < (int)header.num_anims;i++)
3470 anim.name = LittleLong(anims[i].name);
3471 anim.first_frame = LittleLong(anims[i].first_frame);
3472 anim.num_frames = LittleLong(anims[i].num_frames);
3473 anim.framerate = LittleFloat(anims[i].framerate);
3474 anim.flags = LittleLong(anims[i].flags);
3475 strlcpy(loadmodel->animscenes[i].name, &text[anim.name], sizeof(loadmodel->animscenes[i].name));
3476 loadmodel->animscenes[i].firstframe = anim.first_frame;
3477 loadmodel->animscenes[i].framecount = anim.num_frames;
3478 loadmodel->animscenes[i].loop = ((anim.flags & IQM_LOOP) != 0);
3479 loadmodel->animscenes[i].framerate = anim.framerate;
3481 if (header.num_anims <= 0)
3483 strlcpy(loadmodel->animscenes[0].name, "static", sizeof(loadmodel->animscenes[0].name));
3484 loadmodel->animscenes[0].firstframe = 0;
3485 loadmodel->animscenes[0].framecount = 1;
3486 loadmodel->animscenes[0].loop = true;
3487 loadmodel->animscenes[0].framerate = 10;
3490 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
3491 if(mod_alias_force_animated.string[0])
3492 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
3493 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
3496 if (header.version == 1)
3498 iqmpose1_t *inpose1 = (iqmpose1_t *)(pbase + header.ofs_poses);
3499 if (header.num_poses)
3500 pose1 = (iqmpose1_t *)Mem_Alloc(loadmodel->mempool, header.num_poses * sizeof(iqmpose1_t));
3501 for (i = 0;i < (int)header.num_poses;i++)
3504 pose1[i].parent = LittleLong(inpose1[i].parent);
3505 pose1[i].channelmask = LittleLong(inpose1[i].channelmask);
3506 for (j = 0;j < 9;j++)
3508 pose1[i].channeloffset[j] = LittleFloat(inpose1[i].channeloffset[j]);
3509 pose1[i].channelscale[j] = LittleFloat(inpose1[i].channelscale[j]);
3511 f = fabs(pose1[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3512 f = fabs(pose1[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3513 f = fabs(pose1[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3514 f = fabs(pose1[i].channeloffset[0] + 0xFFFF*pose1[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3515 f = fabs(pose1[i].channeloffset[1] + 0xFFFF*pose1[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3516 f = fabs(pose1[i].channeloffset[2] + 0xFFFF*pose1[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3518 if (header.num_frames <= 0)
3520 for (i = 0;i < loadmodel->num_bones;i++)
3523 f = fabs(joint1[i].origin[0]); biggestorigin = max(biggestorigin, f);
3524 f = fabs(joint1[i].origin[1]); biggestorigin = max(biggestorigin, f);
3525 f = fabs(joint1[i].origin[2]); biggestorigin = max(biggestorigin, f);
3531 iqmpose_t *inpose = (iqmpose_t *)(pbase + header.ofs_poses);
3532 if (header.num_poses)
3533 pose = (iqmpose_t *)Mem_Alloc(loadmodel->mempool, header.num_poses * sizeof(iqmpose_t));
3534 for (i = 0;i < (int)header.num_poses;i++)
3537 pose[i].parent = LittleLong(inpose[i].parent);
3538 pose[i].channelmask = LittleLong(inpose[i].channelmask);
3539 for (j = 0;j < 10;j++)
3541 pose[i].channeloffset[j] = LittleFloat(inpose[i].channeloffset[j]);
3542 pose[i].channelscale[j] = LittleFloat(inpose[i].channelscale[j]);
3544 f = fabs(pose[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3545 f = fabs(pose[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3546 f = fabs(pose[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3547 f = fabs(pose[i].channeloffset[0] + 0xFFFF*pose[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3548 f = fabs(pose[i].channeloffset[1] + 0xFFFF*pose[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3549 f = fabs(pose[i].channeloffset[2] + 0xFFFF*pose[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3551 if (header.num_frames <= 0)
3553 for (i = 0;i < loadmodel->num_bones;i++)
3556 f = fabs(joint[i].origin[0]); biggestorigin = max(biggestorigin, f);
3557 f = fabs(joint[i].origin[1]); biggestorigin = max(biggestorigin, f);
3558 f = fabs(joint[i].origin[2]); biggestorigin = max(biggestorigin, f);
3562 loadmodel->num_posescale = biggestorigin / 32767.0f;
3563 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3565 // load the pose data
3566 // this unaligned memory access is safe (LittleShort reads as bytes)
3567 framedata = (const unsigned short *)(pbase + header.ofs_frames);
3568 if (header.version == 1)
3570 for (i = 0, k = 0;i < (int)header.num_frames;i++)
3572 for (j = 0;j < (int)header.num_poses;j++, k++)
3574 float qx, qy, qz, qw;
3575 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));
3576 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));
3577 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));
3578 qx = pose1[j].channeloffset[3] + (pose1[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[3] : 0);
3579 qy = pose1[j].channeloffset[4] + (pose1[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[4] : 0);
3580 qz = pose1[j].channeloffset[5] + (pose1[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[5] : 0);
3581 qw = 1.0f - (qx*qx + qy*qy + qz*qz);
3582 qw = qw > 0.0f ? -sqrt(qw) : 0.0f;
3583 loadmodel->data_poses7s[k*7 + 3] = 32767.0f * qx;
3584 loadmodel->data_poses7s[k*7 + 4] = 32767.0f * qy;
3585 loadmodel->data_poses7s[k*7 + 5] = 32767.0f * qz;
3586 loadmodel->data_poses7s[k*7 + 6] = 32767.0f * qw;
3587 // skip scale data for now
3588 if(pose1[j].channelmask&64) framedata++;
3589 if(pose1[j].channelmask&128) framedata++;
3590 if(pose1[j].channelmask&256) framedata++;
3593 if (header.num_frames <= 0)
3595 for (i = 0;i < loadmodel->num_bones;i++)
3597 float qx, qy, qz, qw;
3598 loadmodel->data_poses7s[i*7 + 0] = loadmodel->num_poseinvscale * joint1[i].origin[0];
3599 loadmodel->data_poses7s[i*7 + 1] = loadmodel->num_poseinvscale * joint1[i].origin[1];
3600 loadmodel->data_poses7s[i*7 + 2] = loadmodel->num_poseinvscale * joint1[i].origin[2];
3601 qx = joint1[i].rotation[0];
3602 qy = joint1[i].rotation[1];
3603 qz = joint1[i].rotation[2];
3604 qw = 1.0f - (qx*qx + qy*qy + qz*qz);
3605 qw = qw > 0.0f ? -sqrt(qw) : 0.0f;
3606 loadmodel->data_poses7s[i*7 + 3] = 32767.0f * qx;
3607 loadmodel->data_poses7s[i*7 + 4] = 32767.0f * qy;
3608 loadmodel->data_poses7s[i*7 + 5] = 32767.0f * qz;
3609 loadmodel->data_poses7s[i*7 + 6] = 32767.0f * qw;
3615 for (i = 0, k = 0;i < (int)header.num_frames;i++)
3617 for (j = 0;j < (int)header.num_poses;j++, k++)
3620 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));
3621 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));
3622 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));
3623 rot[0] = pose[j].channeloffset[3] + (pose[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[3] : 0);
3624 rot[1] = pose[j].channeloffset[4] + (pose[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[4] : 0);
3625 rot[2] = pose[j].channeloffset[5] + (pose[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[5] : 0);
3626 rot[3] = pose[j].channeloffset[6] + (pose[j].channelmask&64 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[6] : 0);
3628 Vector4Negate(rot, rot);
3629 Vector4Normalize2(rot, rot);
3630 loadmodel->data_poses7s[k*7 + 3] = 32767.0f * rot[0];
3631 loadmodel->data_poses7s[k*7 + 4] = 32767.0f * rot[1];
3632 loadmodel->data_poses7s[k*7 + 5] = 32767.0f * rot[2];
3633 loadmodel->data_poses7s[k*7 + 6] = 32767.0f * rot[3];
3634 // skip scale data for now
3635 if(pose[j].channelmask&128) framedata++;
3636 if(pose[j].channelmask&256) framedata++;
3637 if(pose[j].channelmask&512) framedata++;
3640 if (header.num_frames <= 0)
3642 for (i = 0;i < loadmodel->num_bones;i++)
3644 loadmodel->data_poses7s[i*7 + 0] = loadmodel->num_poseinvscale * joint[i].origin[0];
3645 loadmodel->data_poses7s[i*7 + 1] = loadmodel->num_poseinvscale * joint[i].origin[1];
3646 loadmodel->data_poses7s[i*7 + 2] = loadmodel->num_poseinvscale * joint[i].origin[2];
3647 loadmodel->data_poses7s[i*7 + 3] = 32767.0f * joint[i].rotation[0];
3648 loadmodel->data_poses7s[i*7 + 4] = 32767.0f * joint[i].rotation[1];
3649 loadmodel->data_poses7s[i*7 + 5] = 32767.0f * joint[i].rotation[2];
3650 loadmodel->data_poses7s[i*7 + 6] = 32767.0f * joint[i].rotation[3];
3655 // load bounding box data
3656 if (header.ofs_bounds)
3658 float xyradius = 0, radius = 0;
3659 VectorClear(loadmodel->normalmins);
3660 VectorClear(loadmodel->normalmaxs);
3661 for (i = 0; i < (int)header.num_frames;i++)
3664 bound.mins[0] = LittleFloat(bounds[i].mins[0]);
3665 bound.mins[1] = LittleFloat(bounds[i].mins[1]);
3666 bound.mins[2] = LittleFloat(bounds[i].mins[2]);
3667 bound.maxs[0] = LittleFloat(bounds[i].maxs[0]);
3668 bound.maxs[1] = LittleFloat(bounds[i].maxs[1]);
3669 bound.maxs[2] = LittleFloat(bounds[i].maxs[2]);
3670 bound.xyradius = LittleFloat(bounds[i].xyradius);
3671 bound.radius = LittleFloat(bounds[i].radius);
3674 VectorCopy(bound.mins, loadmodel->normalmins);
3675 VectorCopy(bound.maxs, loadmodel->normalmaxs);
3679 if (loadmodel->normalmins[0] > bound.mins[0]) loadmodel->normalmins[0] = bound.mins[0];
3680 if (loadmodel->normalmins[1] > bound.mins[1]) loadmodel->normalmins[1] = bound.mins[1];
3681 if (loadmodel->normalmins[2] > bound.mins[2]) loadmodel->normalmins[2] = bound.mins[2];
3682 if (loadmodel->normalmaxs[0] < bound.maxs[0]) loadmodel->normalmaxs[0] = bound.maxs[0];
3683 if (loadmodel->normalmaxs[1] < bound.maxs[1]) loadmodel->normalmaxs[1] = bound.maxs[1];
3684 if (loadmodel->normalmaxs[2] < bound.maxs[2]) loadmodel->normalmaxs[2] = bound.maxs[2];
3686 if (bound.xyradius > xyradius)
3687 xyradius = bound.xyradius;
3688 if (bound.radius > radius)
3689 radius = bound.radius;
3691 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -xyradius;
3692 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = xyradius;
3693 loadmodel->yawmins[2] = loadmodel->normalmins[2];
3694 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
3695 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
3696 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
3697 loadmodel->radius = radius;
3698 loadmodel->radius2 = radius * radius;
3701 // load triangle data
3702 // this unaligned memory access is safe (LittleLong reads as bytes)
3703 inelements = (const unsigned int *)(pbase + header.ofs_triangles);
3704 outelements = loadmodel->surfmesh.data_element3i;
3705 for (i = 0;i < (int)header.num_triangles;i++)
3707 outelements[0] = LittleLong(inelements[0]);
3708 outelements[1] = LittleLong(inelements[1]);
3709 outelements[2] = LittleLong(inelements[2]);
3713 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, header.num_vertexes, __FILE__, __LINE__);
3715 if (header.ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
3717 // this unaligned memory access is safe (LittleLong reads as bytes)
3718 inneighbors = (const int *)(pbase + header.ofs_neighbors);
3719 outneighbors = loadmodel->surfmesh.data_neighbor3i;
3720 for (i = 0;i < (int)header.num_triangles;i++)
3722 outneighbors[0] = LittleLong(inneighbors[0]);
3723 outneighbors[1] = LittleLong(inneighbors[1]);
3724 outneighbors[2] = LittleLong(inneighbors[2]);
3731 // this unaligned memory access is safe (LittleFloat reads as bytes)
3732 outvertex = loadmodel->surfmesh.data_vertex3f;
3733 for (i = 0;i < (int)header.num_vertexes;i++)
3735 outvertex[0] = LittleFloat(vposition[0]);
3736 outvertex[1] = LittleFloat(vposition[1]);
3737 outvertex[2] = LittleFloat(vposition[2]);
3742 outtexcoord = loadmodel->surfmesh.data_texcoordtexture2f;
3743 // this unaligned memory access is safe (LittleFloat reads as bytes)
3744 for (i = 0;i < (int)header.num_vertexes;i++)
3746 outtexcoord[0] = LittleFloat(vtexcoord[0]);
3747 outtexcoord[1] = LittleFloat(vtexcoord[1]);
3752 // this unaligned memory access is safe (LittleFloat reads as bytes)
3755 outnormal = loadmodel->surfmesh.data_normal3f;
3756 for (i = 0;i < (int)header.num_vertexes;i++)
3758 outnormal[0] = LittleFloat(vnormal[0]);
3759 outnormal[1] = LittleFloat(vnormal[1]);
3760 outnormal[2] = LittleFloat(vnormal[2]);
3766 // this unaligned memory access is safe (LittleFloat reads as bytes)
3767 if(vnormal && vtangent)
3769 outnormal = loadmodel->surfmesh.data_normal3f;
3770 outsvector = loadmodel->surfmesh.data_svector3f;
3771 outtvector = loadmodel->surfmesh.data_tvector3f;
3772 for (i = 0;i < (int)header.num_vertexes;i++)
3774 outsvector[0] = LittleFloat(vtangent[0]);
3775 outsvector[1] = LittleFloat(vtangent[1]);
3776 outsvector[2] = LittleFloat(vtangent[2]);
3777 if(LittleFloat(vtangent[3]) < 0)
3778 CrossProduct(outsvector, outnormal, outtvector);
3780 CrossProduct(outnormal, outsvector, outtvector);
3788 // this unaligned memory access is safe (all bytes)
3789 if (vblendindexes && vblendweights)
3791 for (i = 0; i < (int)header.num_vertexes;i++)
3793 blendweights_t weights;
3794 memcpy(weights.index, vblendindexes + i*4, 4);
3795 memcpy(weights.influence, vblendweights + i*4, 4);
3796 loadmodel->surfmesh.blends[i] = Mod_Skeletal_AddBlend(loadmodel, &weights);
3802 outcolor = loadmodel->surfmesh.data_lightmapcolor4f;
3803 // this unaligned memory access is safe (LittleFloat reads as bytes)
3804 for (i = 0;i < (int)header.num_vertexes;i++)
3806 outcolor[0] = LittleFloat(vcolor4f[0]);
3807 outcolor[1] = LittleFloat(vcolor4f[1]);
3808 outcolor[2] = LittleFloat(vcolor4f[2]);
3809 outcolor[3] = LittleFloat(vcolor4f[3]);
3816 outcolor = loadmodel->surfmesh.data_lightmapcolor4f;
3817 // this unaligned memory access is safe (all bytes)
3818 for (i = 0;i < (int)header.num_vertexes;i++)
3820 outcolor[0] = vcolor4ub[0] * (1.0f / 255.0f);
3821 outcolor[1] = vcolor4ub[1] * (1.0f / 255.0f);
3822 outcolor[2] = vcolor4ub[2] * (1.0f / 255.0f);
3823 outcolor[3] = vcolor4ub[3] * (1.0f / 255.0f);
3830 for (i = 0;i < (int)header.num_meshes;i++)
3833 msurface_t *surface;
3835 mesh.name = LittleLong(meshes[i].name);
3836 mesh.material = LittleLong(meshes[i].material);
3837 mesh.first_vertex = LittleLong(meshes[i].first_vertex);
3838 mesh.num_vertexes = LittleLong(meshes[i].num_vertexes);
3839 mesh.first_triangle = LittleLong(meshes[i].first_triangle);
3840 mesh.num_triangles = LittleLong(meshes[i].num_triangles);
3842 loadmodel->sortedmodelsurfaces[i] = i;
3843 surface = loadmodel->data_surfaces + i;
3844 surface->texture = loadmodel->data_textures + i;
3845 surface->num_firsttriangle = mesh.first_triangle;
3846 surface->num_triangles = mesh.num_triangles;
3847 surface->num_firstvertex = mesh.first_vertex;
3848 surface->num_vertices = mesh.num_vertexes;
3850 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, &text[mesh.name], &text[mesh.material]);
3853 Mod_FreeSkinFiles(skinfiles);
3854 Mod_MakeSortedSurfaces(loadmodel);
3856 // compute all the mesh information that was not loaded from the file
3857 if (loadmodel->surfmesh.data_element3s)
3858 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3859 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3861 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);
3862 if (!vnormal || !vtangent)
3863 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);
3864 if (!header.ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
3865 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3866 if (!header.ofs_bounds)
3867 Mod_Alias_CalculateBoundingBox();
3869 if (!loadmodel->surfmesh.isanimated && loadmodel->surfmesh.num_triangles >= 1)
3871 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3872 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3873 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3874 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3875 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3876 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
3879 if (joint ) Mem_Free(joint );joint = NULL;
3880 if (joint1 ) Mem_Free(joint1 );joint1 = NULL;
3881 if (pose ) Mem_Free(pose );pose = NULL;
3882 if (pose1 ) Mem_Free(pose1 );pose1 = NULL;
3884 // because shaders can do somewhat unexpected things, check for unusual features now
3885 for (i = 0;i < loadmodel->num_textures;i++)
3887 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
3888 mod->DrawSky = R_Q1BSP_DrawSky;
3889 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
3890 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;