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;
827 texture->transparentsort = TRANSPARENTSORT_DISTANCE;
828 // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
829 // JUST GREP FOR "specularscalemod = 1".
832 void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
835 char stripbuf[MAX_QPATH];
836 skinfileitem_t *skinfileitem;
837 if(developer_extra.integer)
838 Con_DPrintf("Looking up texture for %s (default: %s)\n", meshname, shadername);
841 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
842 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
844 memset(skin, 0, sizeof(*skin));
846 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
848 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
849 if (!strcmp(skinfileitem->name, meshname))
851 Image_StripImageExtension(skinfileitem->replacement, stripbuf, sizeof(stripbuf));
852 if(developer_extra.integer)
853 Con_DPrintf("--> got %s from skin file\n", stripbuf);
854 Mod_LoadTextureFromQ3Shader(skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
860 // don't render unmentioned meshes
861 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
862 if(developer_extra.integer)
863 Con_DPrintf("--> skipping\n");
864 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
870 if(developer_extra.integer)
871 Con_DPrintf("--> using default\n");
872 Image_StripImageExtension(shadername, stripbuf, sizeof(stripbuf));
873 Mod_LoadTextureFromQ3Shader(skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
877 #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);
878 #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);
879 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
881 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
882 float scales, scalet, interval;
886 stvert_t *pinstverts;
887 dtriangle_t *pintriangles;
888 daliasskintype_t *pinskintype;
889 daliasskingroup_t *pinskingroup;
890 daliasskininterval_t *pinskinintervals;
891 daliasframetype_t *pinframetype;
892 daliasgroup_t *pinframegroup;
893 unsigned char *datapointer, *startframes, *startskins;
894 char name[MAX_QPATH];
895 skinframe_t *tempskinframe;
896 animscene_t *tempskinscenes;
897 texture_t *tempaliasskins;
899 int *vertonseam, *vertremap;
900 skinfile_t *skinfiles;
903 datapointer = (unsigned char *)buffer;
904 pinmodel = (mdl_t *)datapointer;
905 datapointer += sizeof(mdl_t);
907 version = LittleLong (pinmodel->version);
908 if (version != ALIAS_VERSION)
909 Host_Error ("%s has wrong version number (%i should be %i)",
910 loadmodel->name, version, ALIAS_VERSION);
912 loadmodel->modeldatatypestring = "MDL";
914 loadmodel->type = mod_alias;
915 loadmodel->DrawSky = NULL;
916 loadmodel->DrawAddWaterPlanes = NULL;
917 loadmodel->Draw = R_Q1BSP_Draw;
918 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
919 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
920 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
921 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
922 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
923 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
924 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
925 loadmodel->DrawLight = R_Q1BSP_DrawLight;
926 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
927 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
928 // FIXME add TraceBrush!
929 loadmodel->PointSuperContents = NULL;
931 loadmodel->num_surfaces = 1;
932 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
933 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
934 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
935 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
936 loadmodel->sortedmodelsurfaces[0] = 0;
938 loadmodel->numskins = LittleLong(pinmodel->numskins);
939 BOUNDI(loadmodel->numskins,0,65536);
940 skinwidth = LittleLong (pinmodel->skinwidth);
941 BOUNDI(skinwidth,0,65536);
942 skinheight = LittleLong (pinmodel->skinheight);
943 BOUNDI(skinheight,0,65536);
944 numverts = LittleLong(pinmodel->numverts);
945 BOUNDI(numverts,0,65536);
946 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
947 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
948 loadmodel->numframes = LittleLong(pinmodel->numframes);
949 BOUNDI(loadmodel->numframes,0,65536);
950 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
951 BOUNDI((int)loadmodel->synctype,0,2);
952 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
953 i = LittleLong (pinmodel->flags);
954 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
956 for (i = 0;i < 3;i++)
958 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
959 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
962 startskins = datapointer;
964 for (i = 0;i < loadmodel->numskins;i++)
966 pinskintype = (daliasskintype_t *)datapointer;
967 datapointer += sizeof(daliasskintype_t);
968 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
972 pinskingroup = (daliasskingroup_t *)datapointer;
973 datapointer += sizeof(daliasskingroup_t);
974 groupskins = LittleLong(pinskingroup->numskins);
975 datapointer += sizeof(daliasskininterval_t) * groupskins;
978 for (j = 0;j < groupskins;j++)
980 datapointer += skinwidth * skinheight;
985 pinstverts = (stvert_t *)datapointer;
986 datapointer += sizeof(stvert_t) * numverts;
988 pintriangles = (dtriangle_t *)datapointer;
989 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
991 startframes = datapointer;
992 loadmodel->surfmesh.num_morphframes = 0;
993 for (i = 0;i < loadmodel->numframes;i++)
995 pinframetype = (daliasframetype_t *)datapointer;
996 datapointer += sizeof(daliasframetype_t);
997 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
1001 pinframegroup = (daliasgroup_t *)datapointer;
1002 datapointer += sizeof(daliasgroup_t);
1003 groupframes = LittleLong(pinframegroup->numframes);
1004 datapointer += sizeof(daliasinterval_t) * groupframes;
1007 for (j = 0;j < groupframes;j++)
1009 datapointer += sizeof(daliasframe_t);
1010 datapointer += sizeof(trivertx_t) * numverts;
1011 loadmodel->surfmesh.num_morphframes++;
1014 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1016 // store texture coordinates into temporary array, they will be stored
1017 // after usage is determined (triangle data)
1018 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
1019 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
1020 vertonseam = vertremap + numverts * 2;
1022 scales = 1.0 / skinwidth;
1023 scalet = 1.0 / skinheight;
1024 for (i = 0;i < numverts;i++)
1026 vertonseam[i] = LittleLong(pinstverts[i].onseam);
1027 vertst[i*2+0] = LittleLong(pinstverts[i].s) * scales;
1028 vertst[i*2+1] = LittleLong(pinstverts[i].t) * scalet;
1029 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
1030 vertst[(i+numverts)*2+1] = vertst[i*2+1];
1033 // load triangle data
1034 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1036 // read the triangle elements
1037 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1038 for (j = 0;j < 3;j++)
1039 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1040 // validate (note numverts is used because this is the original data)
1041 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1042 // now butcher the elements according to vertonseam and tri->facesfront
1043 // and then compact the vertex set to remove duplicates
1044 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1045 if (!LittleLong(pintriangles[i].facesfront)) // backface
1046 for (j = 0;j < 3;j++)
1047 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1048 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1050 // (this uses vertremap to count usage to save some memory)
1051 for (i = 0;i < numverts*2;i++)
1053 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1054 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1055 // build remapping table and compact array
1056 loadmodel->surfmesh.num_vertices = 0;
1057 for (i = 0;i < numverts*2;i++)
1061 vertremap[i] = loadmodel->surfmesh.num_vertices;
1062 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1063 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1064 loadmodel->surfmesh.num_vertices++;
1067 vertremap[i] = -1; // not used at all
1069 // remap the elements to the new vertex set
1070 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1071 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1072 // store the texture coordinates
1073 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1074 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1076 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1077 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1080 // generate ushort elements array if possible
1081 if (loadmodel->surfmesh.num_vertices <= 65536)
1082 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1083 if (loadmodel->surfmesh.data_element3s)
1084 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1085 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1088 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1089 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1090 if (r_enableshadowvolumes.integer)
1092 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1094 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1095 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices; // needed during loading, may be cleared by code later in this function
1096 if (loadmodel->surfmesh.data_neighbor3i)
1097 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1098 Mod_Alias_CalculateBoundingBox();
1099 Mod_Alias_MorphMesh_CompileFrames();
1102 Mem_Free(vertremap);
1105 skinfiles = Mod_LoadSkinFiles();
1108 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1109 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1110 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1111 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1112 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1113 Mod_FreeSkinFiles(skinfiles);
1114 for (i = 0;i < loadmodel->numskins;i++)
1116 loadmodel->skinscenes[i].firstframe = i;
1117 loadmodel->skinscenes[i].framecount = 1;
1118 loadmodel->skinscenes[i].loop = true;
1119 loadmodel->skinscenes[i].framerate = 10;
1124 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1125 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1126 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1127 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1129 datapointer = startskins;
1130 for (i = 0;i < loadmodel->numskins;i++)
1132 pinskintype = (daliasskintype_t *)datapointer;
1133 datapointer += sizeof(daliasskintype_t);
1135 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1142 pinskingroup = (daliasskingroup_t *)datapointer;
1143 datapointer += sizeof(daliasskingroup_t);
1145 groupskins = LittleLong (pinskingroup->numskins);
1147 pinskinintervals = (daliasskininterval_t *)datapointer;
1148 datapointer += sizeof(daliasskininterval_t) * groupskins;
1150 interval = LittleFloat(pinskinintervals[0].interval);
1151 if (interval < 0.01f)
1153 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1158 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1159 loadmodel->skinscenes[i].firstframe = totalskins;
1160 loadmodel->skinscenes[i].framecount = groupskins;
1161 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1162 loadmodel->skinscenes[i].loop = true;
1164 for (j = 0;j < groupskins;j++)
1167 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1169 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1170 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))
1171 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));
1172 datapointer += skinwidth * skinheight;
1176 // check for skins that don't exist in the model, but do exist as external images
1177 // (this was added because yummyluv kept pestering me about support for it)
1178 // TODO: support shaders here?
1179 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)))
1181 // expand the arrays to make room
1182 tempskinscenes = loadmodel->skinscenes;
1183 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1184 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1185 Mem_Free(tempskinscenes);
1187 tempaliasskins = loadmodel->data_textures;
1188 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1189 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1190 Mem_Free(tempaliasskins);
1192 // store the info about the new skin
1193 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1194 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1195 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1196 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1197 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1198 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1200 //increase skin counts
1201 loadmodel->numskins++;
1204 // fix up the pointers since they are pointing at the old textures array
1205 // FIXME: this is a hack!
1206 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1207 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1211 surface = loadmodel->data_surfaces;
1212 surface->texture = loadmodel->data_textures;
1213 surface->num_firsttriangle = 0;
1214 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1215 surface->num_firstvertex = 0;
1216 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1218 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1219 if(mod_alias_force_animated.string[0])
1220 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
1221 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_MDL_AnimateVertices : NULL;
1223 if (!loadmodel->surfmesh.isanimated)
1225 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1226 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1227 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1228 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1229 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1230 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1233 // because shaders can do somewhat unexpected things, check for unusual features now
1234 for (i = 0;i < loadmodel->num_textures;i++)
1236 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
1237 mod->DrawSky = R_Q1BSP_DrawSky;
1238 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
1239 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
1243 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1245 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1246 float iskinwidth, iskinheight;
1247 unsigned char *data;
1248 msurface_t *surface;
1250 unsigned char *base, *datapointer;
1251 md2frame_t *pinframe;
1253 md2triangle_t *intri;
1254 unsigned short *inst;
1255 struct md2verthash_s
1257 struct md2verthash_s *next;
1261 *hash, **md2verthash, *md2verthashdata;
1262 skinfile_t *skinfiles;
1264 pinmodel = (md2_t *)buffer;
1265 base = (unsigned char *)buffer;
1267 version = LittleLong (pinmodel->version);
1268 if (version != MD2ALIAS_VERSION)
1269 Host_Error ("%s has wrong version number (%i should be %i)",
1270 loadmodel->name, version, MD2ALIAS_VERSION);
1272 loadmodel->modeldatatypestring = "MD2";
1274 loadmodel->type = mod_alias;
1275 loadmodel->DrawSky = NULL;
1276 loadmodel->DrawAddWaterPlanes = NULL;
1277 loadmodel->Draw = R_Q1BSP_Draw;
1278 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1279 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1280 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1281 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1282 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1283 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1284 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1285 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1286 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1287 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1288 loadmodel->PointSuperContents = NULL;
1290 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1291 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1292 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1293 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1294 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1295 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1296 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1297 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1299 end = LittleLong(pinmodel->ofs_end);
1300 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1301 Host_Error ("%s is not a valid model", loadmodel->name);
1302 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1303 Host_Error ("%s is not a valid model", loadmodel->name);
1304 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1305 Host_Error ("%s is not a valid model", loadmodel->name);
1306 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1307 Host_Error ("%s is not a valid model", loadmodel->name);
1308 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1309 Host_Error ("%s is not a valid model", loadmodel->name);
1311 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1312 numxyz = LittleLong(pinmodel->num_xyz);
1313 numst = LittleLong(pinmodel->num_st);
1314 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1315 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1316 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1317 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1318 skinwidth = LittleLong(pinmodel->skinwidth);
1319 skinheight = LittleLong(pinmodel->skinheight);
1320 iskinwidth = 1.0f / skinwidth;
1321 iskinheight = 1.0f / skinheight;
1323 loadmodel->num_surfaces = 1;
1324 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1325 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));
1326 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1327 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1328 loadmodel->sortedmodelsurfaces[0] = 0;
1329 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1330 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1331 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1332 if (r_enableshadowvolumes.integer)
1334 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1337 loadmodel->synctype = ST_RAND;
1340 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1341 skinfiles = Mod_LoadSkinFiles();
1344 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1345 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1346 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1347 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1348 Mod_FreeSkinFiles(skinfiles);
1350 else if (loadmodel->numskins)
1352 // skins found (most likely not a player model)
1353 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1354 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1355 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1356 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1357 Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
1361 // no skins (most likely a player model)
1362 loadmodel->numskins = 1;
1363 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1364 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1365 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1366 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1369 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1370 for (i = 0;i < loadmodel->numskins;i++)
1372 loadmodel->skinscenes[i].firstframe = i;
1373 loadmodel->skinscenes[i].framecount = 1;
1374 loadmodel->skinscenes[i].loop = true;
1375 loadmodel->skinscenes[i].framerate = 10;
1378 // load the triangles and stvert data
1379 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1380 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1381 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1382 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1383 // swap the triangle list
1384 loadmodel->surfmesh.num_vertices = 0;
1385 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1387 for (j = 0;j < 3;j++)
1389 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1390 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1393 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1398 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1401 hashindex = (xyz * 256 + st) & 65535;
1402 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1403 if (hash->xyz == xyz && hash->st == st)
1407 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1410 hash->next = md2verthash[hashindex];
1411 md2verthash[hashindex] = hash;
1413 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1417 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1418 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));
1419 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1420 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1421 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1424 hash = md2verthashdata + i;
1425 vertremap[i] = hash->xyz;
1426 sts = LittleShort(inst[hash->st*2+0]);
1427 stt = LittleShort(inst[hash->st*2+1]);
1428 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1430 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1434 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1435 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1438 Mem_Free(md2verthash);
1439 Mem_Free(md2verthashdata);
1441 // generate ushort elements array if possible
1442 if (loadmodel->surfmesh.num_vertices <= 65536)
1443 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1444 if (loadmodel->surfmesh.data_element3s)
1445 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1446 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1449 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1450 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1455 pinframe = (md2frame_t *)datapointer;
1456 datapointer += sizeof(md2frame_t);
1457 // store the frame scale/translate into the appropriate array
1458 for (j = 0;j < 3;j++)
1460 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1461 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1463 // convert the vertices
1464 v = (trivertx_t *)datapointer;
1465 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1466 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1467 out[k] = v[vertremap[k]];
1468 datapointer += numxyz * sizeof(trivertx_t);
1470 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1471 loadmodel->animscenes[i].firstframe = i;
1472 loadmodel->animscenes[i].framecount = 1;
1473 loadmodel->animscenes[i].framerate = 10;
1474 loadmodel->animscenes[i].loop = true;
1477 Mem_Free(vertremap);
1479 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1480 if(mod_alias_force_animated.string[0])
1481 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
1482 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices; // needed during loading, may be cleared by code later in this function
1483 if (loadmodel->surfmesh.data_neighbor3i)
1484 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1485 Mod_Alias_CalculateBoundingBox();
1486 Mod_Alias_MorphMesh_CompileFrames();
1487 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_MDL_AnimateVertices : NULL;
1489 surface = loadmodel->data_surfaces;
1490 surface->texture = loadmodel->data_textures;
1491 surface->num_firsttriangle = 0;
1492 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1493 surface->num_firstvertex = 0;
1494 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1496 if (!loadmodel->surfmesh.isanimated)
1498 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1499 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1500 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1501 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1502 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1503 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1506 // because shaders can do somewhat unexpected things, check for unusual features now
1507 for (i = 0;i < loadmodel->num_textures;i++)
1509 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
1510 mod->DrawSky = R_Q1BSP_DrawSky;
1511 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
1512 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
1516 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1518 int i, j, k, version, meshvertices, meshtriangles;
1519 unsigned char *data;
1520 msurface_t *surface;
1521 md3modelheader_t *pinmodel;
1522 md3frameinfo_t *pinframe;
1525 skinfile_t *skinfiles;
1527 pinmodel = (md3modelheader_t *)buffer;
1529 if (memcmp(pinmodel->identifier, "IDP3", 4))
1530 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1531 version = LittleLong (pinmodel->version);
1532 if (version != MD3VERSION)
1533 Host_Error ("%s has wrong version number (%i should be %i)",
1534 loadmodel->name, version, MD3VERSION);
1536 skinfiles = Mod_LoadSkinFiles();
1537 if (loadmodel->numskins < 1)
1538 loadmodel->numskins = 1;
1540 loadmodel->modeldatatypestring = "MD3";
1542 loadmodel->type = mod_alias;
1543 loadmodel->DrawSky = NULL;
1544 loadmodel->DrawAddWaterPlanes = NULL;
1545 loadmodel->Draw = R_Q1BSP_Draw;
1546 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1547 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1548 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1549 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1550 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1551 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1552 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1553 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1554 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1555 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1556 loadmodel->PointSuperContents = NULL;
1557 loadmodel->synctype = ST_RAND;
1558 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1559 i = LittleLong (pinmodel->flags);
1560 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1562 // set up some global info about the model
1563 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1564 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1566 // make skinscenes for the skins (no groups)
1567 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1568 for (i = 0;i < loadmodel->numskins;i++)
1570 loadmodel->skinscenes[i].firstframe = i;
1571 loadmodel->skinscenes[i].framecount = 1;
1572 loadmodel->skinscenes[i].loop = true;
1573 loadmodel->skinscenes[i].framerate = 10;
1577 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1578 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1580 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1581 loadmodel->animscenes[i].firstframe = i;
1582 loadmodel->animscenes[i].framecount = 1;
1583 loadmodel->animscenes[i].framerate = 10;
1584 loadmodel->animscenes[i].loop = true;
1588 loadmodel->num_tagframes = loadmodel->numframes;
1589 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1590 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1591 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1593 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1594 for (j = 0;j < 9;j++)
1595 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1596 for (j = 0;j < 3;j++)
1597 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1598 //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);
1604 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)))
1606 if (memcmp(pinmesh->identifier, "IDP3", 4))
1607 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1608 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1609 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1610 meshvertices += LittleLong(pinmesh->num_vertices);
1611 meshtriangles += LittleLong(pinmesh->num_triangles);
1614 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1615 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1616 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1617 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));
1618 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1619 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1620 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1621 loadmodel->surfmesh.num_vertices = meshvertices;
1622 loadmodel->surfmesh.num_triangles = meshtriangles;
1623 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1624 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1625 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1626 if (r_enableshadowvolumes.integer)
1628 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1630 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1631 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1632 if (meshvertices <= 65536)
1634 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1639 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)))
1641 if (memcmp(pinmesh->identifier, "IDP3", 4))
1642 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1643 loadmodel->sortedmodelsurfaces[i] = i;
1644 surface = loadmodel->data_surfaces + i;
1645 surface->texture = loadmodel->data_textures + i;
1646 surface->num_firsttriangle = meshtriangles;
1647 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1648 surface->num_firstvertex = meshvertices;
1649 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1650 meshvertices += surface->num_vertices;
1651 meshtriangles += surface->num_triangles;
1653 for (j = 0;j < surface->num_triangles * 3;j++)
1654 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1655 for (j = 0;j < surface->num_vertices;j++)
1657 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1658 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1660 for (j = 0;j < loadmodel->numframes;j++)
1662 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1663 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1664 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1666 out->origin[0] = LittleShort(in->origin[0]);
1667 out->origin[1] = LittleShort(in->origin[1]);
1668 out->origin[2] = LittleShort(in->origin[2]);
1669 out->pitch = in->pitch;
1674 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1676 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1678 if (loadmodel->surfmesh.data_element3s)
1679 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1680 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1681 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1682 if(mod_alias_force_animated.string[0])
1683 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
1684 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices; // needed during loading, may be cleared by code later in this function
1685 if (loadmodel->surfmesh.data_neighbor3i)
1686 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1687 Mod_Alias_MorphMesh_CompileFrames();
1688 Mod_Alias_CalculateBoundingBox();
1689 Mod_FreeSkinFiles(skinfiles);
1690 Mod_MakeSortedSurfaces(loadmodel);
1691 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_MD3_AnimateVertices : NULL;
1693 if (!loadmodel->surfmesh.isanimated)
1695 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1696 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1697 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1698 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1699 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1700 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1703 // because shaders can do somewhat unexpected things, check for unusual features now
1704 for (i = 0;i < loadmodel->num_textures;i++)
1706 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
1707 mod->DrawSky = R_Q1BSP_DrawSky;
1708 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
1709 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
1713 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1715 zymtype1header_t *pinmodel, *pheader;
1716 unsigned char *pbase;
1717 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1718 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose, f, biggestorigin, tempvec[3], modelscale;
1719 zymvertex_t *verts, *vertdata;
1723 skinfile_t *skinfiles;
1724 unsigned char *data;
1725 msurface_t *surface;
1727 pinmodel = (zymtype1header_t *)buffer;
1728 pbase = (unsigned char *)buffer;
1729 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1730 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1731 if (BigLong(pinmodel->type) != 1)
1732 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1734 loadmodel->modeldatatypestring = "ZYM";
1736 loadmodel->type = mod_alias;
1737 loadmodel->synctype = ST_RAND;
1741 pheader->type = BigLong(pinmodel->type);
1742 pheader->filesize = BigLong(pinmodel->filesize);
1743 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1744 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1745 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1746 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1747 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1748 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1749 pheader->radius = BigFloat(pinmodel->radius);
1750 pheader->numverts = BigLong(pinmodel->numverts);
1751 pheader->numtris = BigLong(pinmodel->numtris);
1752 pheader->numshaders = BigLong(pinmodel->numshaders);
1753 pheader->numbones = BigLong(pinmodel->numbones);
1754 pheader->numscenes = BigLong(pinmodel->numscenes);
1755 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1756 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1757 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1758 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1759 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1760 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1761 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1762 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1763 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1764 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1765 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1766 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1767 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1768 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1769 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1770 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1771 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1772 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1774 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1776 Con_Printf("%s has no geometry\n", loadmodel->name);
1779 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1781 Con_Printf("%s has no animations\n", loadmodel->name);
1785 loadmodel->DrawSky = NULL;
1786 loadmodel->DrawAddWaterPlanes = NULL;
1787 loadmodel->Draw = R_Q1BSP_Draw;
1788 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1789 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1790 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1791 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1792 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1793 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1794 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1795 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1796 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1797 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1798 loadmodel->PointSuperContents = NULL;
1800 loadmodel->numframes = pheader->numscenes;
1801 loadmodel->num_surfaces = pheader->numshaders;
1803 skinfiles = Mod_LoadSkinFiles();
1804 if (loadmodel->numskins < 1)
1805 loadmodel->numskins = 1;
1807 // make skinscenes for the skins (no groups)
1808 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1809 for (i = 0;i < loadmodel->numskins;i++)
1811 loadmodel->skinscenes[i].firstframe = i;
1812 loadmodel->skinscenes[i].framecount = 1;
1813 loadmodel->skinscenes[i].loop = true;
1814 loadmodel->skinscenes[i].framerate = 10;
1818 modelradius = pheader->radius;
1819 for (i = 0;i < 3;i++)
1821 loadmodel->normalmins[i] = pheader->mins[i];
1822 loadmodel->normalmaxs[i] = pheader->maxs[i];
1823 loadmodel->rotatedmins[i] = -modelradius;
1824 loadmodel->rotatedmaxs[i] = modelradius;
1826 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1827 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1828 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1829 if (loadmodel->yawmaxs[0] > modelradius)
1830 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1831 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1832 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1833 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1834 loadmodel->radius = modelradius;
1835 loadmodel->radius2 = modelradius * modelradius;
1837 // go through the lumps, swapping things
1839 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1840 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1841 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1842 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1843 for (i = 0;i < pheader->numscenes;i++)
1845 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1846 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1847 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1848 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1849 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1850 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1851 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1852 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1853 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1854 if (loadmodel->animscenes[i].framerate < 0)
1855 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1859 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1860 loadmodel->num_bones = pheader->numbones;
1861 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1862 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1863 for (i = 0;i < pheader->numbones;i++)
1865 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1866 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1867 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1868 if (loadmodel->data_bones[i].parent >= i)
1869 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1872 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1873 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1874 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1875 for (i = 0;i < pheader->numverts;i++)
1877 vertbonecounts[i] = BigLong(bonecount[i]);
1878 if (vertbonecounts[i] != 1)
1879 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1882 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1884 meshvertices = pheader->numverts;
1885 meshtriangles = pheader->numtris;
1887 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1888 if(mod_alias_force_animated.string[0])
1889 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
1890 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
1891 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1892 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1893 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1894 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]));
1895 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1896 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1897 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1898 loadmodel->surfmesh.num_vertices = meshvertices;
1899 loadmodel->surfmesh.num_triangles = meshtriangles;
1900 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1901 if (r_enableshadowvolumes.integer)
1903 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1905 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1906 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1907 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1908 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1909 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1910 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1911 loadmodel->surfmesh.num_blends = 0;
1912 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
1913 if (loadmodel->surfmesh.num_vertices <= 65536)
1915 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1917 loadmodel->data_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
1918 loadmodel->surfmesh.data_blendweights = NULL;
1920 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1921 poses = (float *) (pheader->lump_poses.start + pbase);
1922 // figure out scale of model from root bone, for compatibility with old zmodel versions
1923 tempvec[0] = BigFloat(poses[0]);
1924 tempvec[1] = BigFloat(poses[1]);
1925 tempvec[2] = BigFloat(poses[2]);
1926 modelscale = VectorLength(tempvec);
1928 for (i = 0;i < loadmodel->num_bones * numposes * 12;i++)
1930 f = fabs(BigFloat(poses[i]));
1931 biggestorigin = max(biggestorigin, f);
1933 loadmodel->num_posescale = biggestorigin / 32767.0f;
1934 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
1935 for (i = 0;i < numposes;i++)
1937 const float *frameposes = (float *) (pheader->lump_poses.start + pbase) + 12*i*loadmodel->num_bones;
1938 for (j = 0;j < loadmodel->num_bones;j++)
1941 matrix4x4_t posematrix;
1942 for (k = 0;k < 12;k++)
1943 pose[k] = BigFloat(frameposes[j*12+k]);
1944 //if (j < loadmodel->num_bones)
1945 // 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));
1946 // scale child bones to match the root scale
1947 if (loadmodel->data_bones[j].parent >= 0)
1949 pose[3] *= modelscale;
1950 pose[7] *= modelscale;
1951 pose[11] *= modelscale;
1953 // normalize rotation matrix
1954 VectorNormalize(pose + 0);
1955 VectorNormalize(pose + 4);
1956 VectorNormalize(pose + 8);
1957 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
1958 Matrix4x4_ToBonePose7s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses7s + 7*(i*loadmodel->num_bones+j));
1962 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1963 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1964 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1965 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1966 // (converting from weight-blending skeletal animation to
1967 // deformation-based skeletal animation)
1968 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1969 for (i = 0;i < loadmodel->num_bones;i++)
1972 for (k = 0;k < 12;k++)
1973 m[k] = BigFloat(poses[i*12+k]);
1974 if (loadmodel->data_bones[i].parent >= 0)
1975 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1977 for (k = 0;k < 12;k++)
1978 bonepose[12*i+k] = m[k];
1980 for (j = 0;j < pheader->numverts;j++)
1982 // this format really should have had a per vertexweight weight value...
1983 // but since it does not, the weighting is completely ignored and
1984 // only one weight is allowed per vertex
1985 int boneindex = BigLong(vertdata[j].bonenum);
1986 const float *m = bonepose + 12 * boneindex;
1987 float relativeorigin[3];
1988 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1989 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1990 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1991 // transform the vertex bone weight into the base mesh
1992 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1993 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1994 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1995 // store the weight as the primary weight on this vertex
1996 loadmodel->surfmesh.blends[j] = boneindex;
1999 // normals and tangents are calculated after elements are loaded
2001 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
2002 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
2003 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
2004 for (i = 0;i < pheader->numverts;i++)
2006 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
2007 // flip T coordinate for OpenGL
2008 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
2011 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
2012 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
2013 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
2015 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
2016 //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)
2017 // byteswap, validate, and swap winding order of tris
2018 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
2019 if (pheader->lump_render.length != count)
2020 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
2021 renderlist = (int *) (pheader->lump_render.start + pbase);
2022 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
2024 for (i = 0;i < loadmodel->num_surfaces;i++)
2026 int firstvertex, lastvertex;
2027 if (renderlist >= renderlistend)
2028 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2029 count = BigLong(*renderlist);renderlist++;
2030 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
2031 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2033 loadmodel->sortedmodelsurfaces[i] = i;
2034 surface = loadmodel->data_surfaces + i;
2035 surface->texture = loadmodel->data_textures + i;
2036 surface->num_firsttriangle = meshtriangles;
2037 surface->num_triangles = count;
2038 meshtriangles += surface->num_triangles;
2040 // load the elements
2041 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2042 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
2044 outelements[j*3+2] = BigLong(renderlist[0]);
2045 outelements[j*3+1] = BigLong(renderlist[1]);
2046 outelements[j*3+0] = BigLong(renderlist[2]);
2048 // validate the elements and find the used vertex range
2049 firstvertex = meshvertices;
2051 for (j = 0;j < surface->num_triangles * 3;j++)
2053 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
2054 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
2055 firstvertex = min(firstvertex, outelements[j]);
2056 lastvertex = max(lastvertex, outelements[j]);
2058 surface->num_firstvertex = firstvertex;
2059 surface->num_vertices = lastvertex + 1 - firstvertex;
2061 // since zym models do not have named sections, reuse their shader
2062 // name as the section name
2063 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
2064 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
2066 Mod_FreeSkinFiles(skinfiles);
2067 Mem_Free(vertbonecounts);
2069 Mod_MakeSortedSurfaces(loadmodel);
2071 // compute all the mesh information that was not loaded from the file
2072 if (loadmodel->surfmesh.data_element3s)
2073 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2074 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2075 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2076 Mod_BuildBaseBonePoses();
2077 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);
2078 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);
2079 if (loadmodel->surfmesh.data_neighbor3i)
2080 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2082 if (!loadmodel->surfmesh.isanimated)
2084 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2085 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2086 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2087 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2088 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2089 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2092 // because shaders can do somewhat unexpected things, check for unusual features now
2093 for (i = 0;i < loadmodel->num_textures;i++)
2095 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
2096 mod->DrawSky = R_Q1BSP_DrawSky;
2097 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
2098 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
2102 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2104 dpmheader_t *pheader;
2108 unsigned char *pbase;
2109 int i, j, k, meshvertices, meshtriangles;
2110 skinfile_t *skinfiles;
2111 unsigned char *data;
2113 float biggestorigin, tempvec[3], modelscale;
2117 pheader = (dpmheader_t *)buffer;
2118 pbase = (unsigned char *)buffer;
2119 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2120 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2121 if (BigLong(pheader->type) != 2)
2122 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2124 loadmodel->modeldatatypestring = "DPM";
2126 loadmodel->type = mod_alias;
2127 loadmodel->synctype = ST_RAND;
2130 pheader->type = BigLong(pheader->type);
2131 pheader->filesize = BigLong(pheader->filesize);
2132 pheader->mins[0] = BigFloat(pheader->mins[0]);
2133 pheader->mins[1] = BigFloat(pheader->mins[1]);
2134 pheader->mins[2] = BigFloat(pheader->mins[2]);
2135 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2136 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2137 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2138 pheader->yawradius = BigFloat(pheader->yawradius);
2139 pheader->allradius = BigFloat(pheader->allradius);
2140 pheader->num_bones = BigLong(pheader->num_bones);
2141 pheader->num_meshs = BigLong(pheader->num_meshs);
2142 pheader->num_frames = BigLong(pheader->num_frames);
2143 pheader->ofs_bones = BigLong(pheader->ofs_bones);
2144 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2145 pheader->ofs_frames = BigLong(pheader->ofs_frames);
2147 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2149 Con_Printf("%s has no geometry\n", loadmodel->name);
2152 if (pheader->num_frames < 1)
2154 Con_Printf("%s has no frames\n", loadmodel->name);
2158 loadmodel->DrawSky = NULL;
2159 loadmodel->DrawAddWaterPlanes = NULL;
2160 loadmodel->Draw = R_Q1BSP_Draw;
2161 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2162 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2163 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2164 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2165 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2166 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2167 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2168 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2169 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2170 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2171 loadmodel->PointSuperContents = NULL;
2174 for (i = 0;i < 3;i++)
2176 loadmodel->normalmins[i] = pheader->mins[i];
2177 loadmodel->normalmaxs[i] = pheader->maxs[i];
2178 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2179 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2180 loadmodel->rotatedmins[i] = -pheader->allradius;
2181 loadmodel->rotatedmaxs[i] = pheader->allradius;
2183 loadmodel->radius = pheader->allradius;
2184 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2186 // load external .skin files if present
2187 skinfiles = Mod_LoadSkinFiles();
2188 if (loadmodel->numskins < 1)
2189 loadmodel->numskins = 1;
2194 // gather combined statistics from the meshes
2195 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2196 for (i = 0;i < (int)pheader->num_meshs;i++)
2198 int numverts = BigLong(dpmmesh->num_verts);
2199 meshvertices += numverts;
2200 meshtriangles += BigLong(dpmmesh->num_tris);
2204 loadmodel->numframes = pheader->num_frames;
2205 loadmodel->num_bones = pheader->num_bones;
2206 loadmodel->num_poses = loadmodel->numframes;
2207 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2208 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2209 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2210 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
2211 if(mod_alias_force_animated.string[0])
2212 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
2213 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
2214 // do most allocations as one merged chunk
2215 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));
2216 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2217 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2218 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2219 loadmodel->surfmesh.num_vertices = meshvertices;
2220 loadmodel->surfmesh.num_triangles = meshtriangles;
2221 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2222 if (r_enableshadowvolumes.integer)
2224 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2226 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2227 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2228 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2229 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2230 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2231 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2232 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2233 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2234 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2235 loadmodel->surfmesh.num_blends = 0;
2236 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2237 if (meshvertices <= 65536)
2239 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2241 loadmodel->data_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
2242 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
2244 for (i = 0;i < loadmodel->numskins;i++)
2246 loadmodel->skinscenes[i].firstframe = i;
2247 loadmodel->skinscenes[i].framecount = 1;
2248 loadmodel->skinscenes[i].loop = true;
2249 loadmodel->skinscenes[i].framerate = 10;
2252 // load the bone info
2253 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2254 for (i = 0;i < loadmodel->num_bones;i++)
2256 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2257 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2258 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2259 if (loadmodel->data_bones[i].parent >= i)
2260 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2264 frames = (dpmframe_t *) (pbase + pheader->ofs_frames);
2265 // figure out scale of model from root bone, for compatibility with old dpmodel versions
2266 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2267 tempvec[0] = BigFloat(poses[0]);
2268 tempvec[1] = BigFloat(poses[1]);
2269 tempvec[2] = BigFloat(poses[2]);
2270 modelscale = VectorLength(tempvec);
2272 for (i = 0;i < loadmodel->numframes;i++)
2274 memcpy(loadmodel->animscenes[i].name, frames[i].name, sizeof(frames[i].name));
2275 loadmodel->animscenes[i].firstframe = i;
2276 loadmodel->animscenes[i].framecount = 1;
2277 loadmodel->animscenes[i].loop = true;
2278 loadmodel->animscenes[i].framerate = 10;
2279 // load the bone poses for this frame
2280 poses = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2281 for (j = 0;j < loadmodel->num_bones*12;j++)
2283 f = fabs(BigFloat(poses[j]));
2284 biggestorigin = max(biggestorigin, f);
2286 // stuff not processed here: mins, maxs, yawradius, allradius
2288 loadmodel->num_posescale = biggestorigin / 32767.0f;
2289 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2290 for (i = 0;i < loadmodel->numframes;i++)
2292 const float *frameposes = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2293 for (j = 0;j < loadmodel->num_bones;j++)
2296 matrix4x4_t posematrix;
2297 for (k = 0;k < 12;k++)
2298 pose[k] = BigFloat(frameposes[j*12+k]);
2299 // scale child bones to match the root scale
2300 if (loadmodel->data_bones[j].parent >= 0)
2302 pose[3] *= modelscale;
2303 pose[7] *= modelscale;
2304 pose[11] *= modelscale;
2306 // normalize rotation matrix
2307 VectorNormalize(pose + 0);
2308 VectorNormalize(pose + 4);
2309 VectorNormalize(pose + 8);
2310 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2311 Matrix4x4_ToBonePose7s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses7s + 7*(i*loadmodel->num_bones+j));
2315 // load the meshes now
2316 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2319 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2320 // (converting from weight-blending skeletal animation to
2321 // deformation-based skeletal animation)
2322 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2323 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2324 for (i = 0;i < loadmodel->num_bones;i++)
2327 for (k = 0;k < 12;k++)
2328 m[k] = BigFloat(poses[i*12+k]);
2329 if (loadmodel->data_bones[i].parent >= 0)
2330 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2332 for (k = 0;k < 12;k++)
2333 bonepose[12*i+k] = m[k];
2335 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2337 const int *inelements;
2339 const float *intexcoord;
2340 msurface_t *surface;
2342 loadmodel->sortedmodelsurfaces[i] = i;
2343 surface = loadmodel->data_surfaces + i;
2344 surface->texture = loadmodel->data_textures + i;
2345 surface->num_firsttriangle = meshtriangles;
2346 surface->num_triangles = BigLong(dpmmesh->num_tris);
2347 surface->num_firstvertex = meshvertices;
2348 surface->num_vertices = BigLong(dpmmesh->num_verts);
2349 meshvertices += surface->num_vertices;
2350 meshtriangles += surface->num_triangles;
2352 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2353 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2354 for (j = 0;j < surface->num_triangles;j++)
2356 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2357 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2358 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2359 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2364 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2365 for (j = 0;j < surface->num_vertices*2;j++)
2366 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2368 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2369 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2371 int weightindex[4] = { 0, 0, 0, 0 };
2372 float weightinfluence[4] = { 0, 0, 0, 0 };
2374 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2375 data += sizeof(dpmvertex_t);
2376 for (k = 0;k < numweights;k++)
2378 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2379 int boneindex = BigLong(vert->bonenum);
2380 const float *m = bonepose + 12 * boneindex;
2381 float influence = BigFloat(vert->influence);
2382 float relativeorigin[3], relativenormal[3];
2383 relativeorigin[0] = BigFloat(vert->origin[0]);
2384 relativeorigin[1] = BigFloat(vert->origin[1]);
2385 relativeorigin[2] = BigFloat(vert->origin[2]);
2386 relativenormal[0] = BigFloat(vert->normal[0]);
2387 relativenormal[1] = BigFloat(vert->normal[1]);
2388 relativenormal[2] = BigFloat(vert->normal[2]);
2389 // blend the vertex bone weights into the base mesh
2390 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2391 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2392 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2393 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2394 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2395 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2398 // store the first (and often only) weight
2399 weightinfluence[0] = influence;
2400 weightindex[0] = boneindex;
2404 // sort the new weight into this vertex's weight table
2405 // (which only accepts up to 4 bones per vertex)
2406 for (l = 0;l < 4;l++)
2408 if (weightinfluence[l] < influence)
2410 // move weaker influence weights out of the way first
2412 for (l2 = 3;l2 > l;l2--)
2414 weightinfluence[l2] = weightinfluence[l2-1];
2415 weightindex[l2] = weightindex[l2-1];
2417 // store the new weight
2418 weightinfluence[l] = influence;
2419 weightindex[l] = boneindex;
2424 data += sizeof(dpmbonevert_t);
2426 loadmodel->surfmesh.blends[j] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
2429 // since dpm models do not have named sections, reuse their shader name as the section name
2430 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2432 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2434 if (loadmodel->surfmesh.num_blends < meshvertices)
2435 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2437 Mod_FreeSkinFiles(skinfiles);
2438 Mod_MakeSortedSurfaces(loadmodel);
2440 // compute all the mesh information that was not loaded from the file
2441 if (loadmodel->surfmesh.data_element3s)
2442 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2443 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2444 Mod_BuildBaseBonePoses();
2445 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);
2446 if (loadmodel->surfmesh.data_neighbor3i)
2447 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2449 if (!loadmodel->surfmesh.isanimated)
2451 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2452 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2453 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2454 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2455 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2456 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2459 // because shaders can do somewhat unexpected things, check for unusual features now
2460 for (i = 0;i < loadmodel->num_textures;i++)
2462 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
2463 mod->DrawSky = R_Q1BSP_DrawSky;
2464 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
2465 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
2469 // no idea why PSK/PSA files contain weird quaternions but they do...
2470 #define PSKQUATNEGATIONS
2471 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2473 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2474 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2475 fs_offset_t filesize;
2480 pskboneinfo_t *bones;
2481 pskrawweights_t *rawweights;
2482 //pskboneinfo_t *animbones;
2483 pskaniminfo_t *anims;
2484 pskanimkeys_t *animkeys;
2485 void *animfilebuffer, *animbuffer, *animbufferend;
2486 unsigned char *data;
2488 skinfile_t *skinfiles;
2489 char animname[MAX_QPATH];
2491 float biggestorigin;
2493 pchunk = (pskchunk_t *)buffer;
2494 if (strcmp(pchunk->id, "ACTRHEAD"))
2495 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2497 loadmodel->modeldatatypestring = "PSK";
2499 loadmodel->type = mod_alias;
2500 loadmodel->DrawSky = NULL;
2501 loadmodel->DrawAddWaterPlanes = NULL;
2502 loadmodel->Draw = R_Q1BSP_Draw;
2503 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2504 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2505 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2506 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2507 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2508 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2509 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2510 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2511 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2512 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2513 loadmodel->PointSuperContents = NULL;
2514 loadmodel->synctype = ST_RAND;
2516 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2517 strlcat(animname, ".psa", sizeof(animname));
2518 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2519 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2521 animbufferend = animbuffer;
2540 while (buffer < bufferend)
2542 pchunk = (pskchunk_t *)buffer;
2543 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2544 version = LittleLong(pchunk->version);
2545 recordsize = LittleLong(pchunk->recordsize);
2546 numrecords = LittleLong(pchunk->numrecords);
2547 if (developer_extra.integer)
2548 Con_DPrintf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2549 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2550 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);
2551 if (!strcmp(pchunk->id, "ACTRHEAD"))
2555 else if (!strcmp(pchunk->id, "PNTS0000"))
2558 if (recordsize != sizeof(*p))
2559 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2560 // byteswap in place and keep the pointer
2561 numpnts = numrecords;
2562 pnts = (pskpnts_t *)buffer;
2563 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2565 p->origin[0] = LittleFloat(p->origin[0]);
2566 p->origin[1] = LittleFloat(p->origin[1]);
2567 p->origin[2] = LittleFloat(p->origin[2]);
2571 else if (!strcmp(pchunk->id, "VTXW0000"))
2574 if (recordsize != sizeof(*p))
2575 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2576 // byteswap in place and keep the pointer
2577 numvtxw = numrecords;
2578 vtxw = (pskvtxw_t *)buffer;
2579 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2581 p->pntsindex = LittleShort(p->pntsindex);
2582 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2583 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2584 if (p->pntsindex >= numpnts)
2586 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2592 else if (!strcmp(pchunk->id, "FACE0000"))
2595 if (recordsize != sizeof(*p))
2596 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2597 // byteswap in place and keep the pointer
2598 numfaces = numrecords;
2599 faces = (pskface_t *)buffer;
2600 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2602 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2603 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2604 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2605 p->group = LittleLong(p->group);
2606 if (p->vtxwindex[0] >= numvtxw)
2608 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2609 p->vtxwindex[0] = 0;
2611 if (p->vtxwindex[1] >= numvtxw)
2613 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2614 p->vtxwindex[1] = 0;
2616 if (p->vtxwindex[2] >= numvtxw)
2618 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2619 p->vtxwindex[2] = 0;
2624 else if (!strcmp(pchunk->id, "MATT0000"))
2627 if (recordsize != sizeof(*p))
2628 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2629 // byteswap in place and keep the pointer
2630 nummatts = numrecords;
2631 matts = (pskmatt_t *)buffer;
2632 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2638 else if (!strcmp(pchunk->id, "REFSKELT"))
2641 if (recordsize != sizeof(*p))
2642 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2643 // byteswap in place and keep the pointer
2644 numbones = numrecords;
2645 bones = (pskboneinfo_t *)buffer;
2646 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2648 p->numchildren = LittleLong(p->numchildren);
2649 p->parent = LittleLong(p->parent);
2650 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2651 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2652 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2653 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2654 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2655 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2656 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2657 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2658 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2659 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2660 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2661 #ifdef PSKQUATNEGATIONS
2664 p->basepose.quat[0] *= -1;
2665 p->basepose.quat[1] *= -1;
2666 p->basepose.quat[2] *= -1;
2670 p->basepose.quat[0] *= 1;
2671 p->basepose.quat[1] *= -1;
2672 p->basepose.quat[2] *= 1;
2675 if (p->parent < 0 || p->parent >= numbones)
2677 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2683 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2686 if (recordsize != sizeof(*p))
2687 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2688 // byteswap in place and keep the pointer
2689 numrawweights = numrecords;
2690 rawweights = (pskrawweights_t *)buffer;
2691 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2693 p->weight = LittleFloat(p->weight);
2694 p->pntsindex = LittleLong(p->pntsindex);
2695 p->boneindex = LittleLong(p->boneindex);
2696 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2698 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2701 if (p->boneindex < 0 || p->boneindex >= numbones)
2703 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2711 while (animbuffer < animbufferend)
2713 pchunk = (pskchunk_t *)animbuffer;
2714 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2715 version = LittleLong(pchunk->version);
2716 recordsize = LittleLong(pchunk->recordsize);
2717 numrecords = LittleLong(pchunk->numrecords);
2718 if (developer_extra.integer)
2719 Con_DPrintf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2720 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2721 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);
2722 if (!strcmp(pchunk->id, "ANIMHEAD"))
2726 else if (!strcmp(pchunk->id, "BONENAMES"))
2729 if (recordsize != sizeof(*p))
2730 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2731 // byteswap in place and keep the pointer
2732 numanimbones = numrecords;
2733 //animbones = (pskboneinfo_t *)animbuffer;
2734 // NOTE: supposedly psa does not need to match the psk model, the
2735 // bones missing from the psa would simply use their base
2736 // positions from the psk, but this is hard for me to implement
2737 // and people can easily make animations that match.
2738 if (numanimbones != numbones)
2739 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2740 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2742 p->numchildren = LittleLong(p->numchildren);
2743 p->parent = LittleLong(p->parent);
2744 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2745 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2746 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2747 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2748 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2749 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2750 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2751 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2752 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2753 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2754 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2755 #ifdef PSKQUATNEGATIONS
2758 p->basepose.quat[0] *= -1;
2759 p->basepose.quat[1] *= -1;
2760 p->basepose.quat[2] *= -1;
2764 p->basepose.quat[0] *= 1;
2765 p->basepose.quat[1] *= -1;
2766 p->basepose.quat[2] *= 1;
2769 if (p->parent < 0 || p->parent >= numanimbones)
2771 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2774 // check that bones are the same as in the base
2775 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2776 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2780 else if (!strcmp(pchunk->id, "ANIMINFO"))
2783 if (recordsize != sizeof(*p))
2784 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2785 // byteswap in place and keep the pointer
2786 numanims = numrecords;
2787 anims = (pskaniminfo_t *)animbuffer;
2788 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2790 p->numbones = LittleLong(p->numbones);
2791 p->playtime = LittleFloat(p->playtime);
2792 p->fps = LittleFloat(p->fps);
2793 p->firstframe = LittleLong(p->firstframe);
2794 p->numframes = LittleLong(p->numframes);
2795 if (p->numbones != numbones)
2796 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2800 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2803 if (recordsize != sizeof(*p))
2804 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2805 numanimkeys = numrecords;
2806 animkeys = (pskanimkeys_t *)animbuffer;
2807 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2809 p->origin[0] = LittleFloat(p->origin[0]);
2810 p->origin[1] = LittleFloat(p->origin[1]);
2811 p->origin[2] = LittleFloat(p->origin[2]);
2812 p->quat[0] = LittleFloat(p->quat[0]);
2813 p->quat[1] = LittleFloat(p->quat[1]);
2814 p->quat[2] = LittleFloat(p->quat[2]);
2815 p->quat[3] = LittleFloat(p->quat[3]);
2816 p->frametime = LittleFloat(p->frametime);
2817 #ifdef PSKQUATNEGATIONS
2818 if (index % numbones)
2833 // TODO: allocate bonepose stuff
2836 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2839 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights)
2840 Host_Error("%s: missing required chunks", loadmodel->name);
2844 loadmodel->numframes = 0;
2845 for (index = 0;index < numanims;index++)
2846 loadmodel->numframes += anims[index].numframes;
2847 if (numanimkeys != numbones * loadmodel->numframes)
2848 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2851 loadmodel->numframes = loadmodel->num_poses = 1;
2853 meshvertices = numvtxw;
2854 meshtriangles = numfaces;
2856 // load external .skin files if present
2857 skinfiles = Mod_LoadSkinFiles();
2858 if (loadmodel->numskins < 1)
2859 loadmodel->numskins = 1;
2860 loadmodel->num_bones = numbones;
2861 loadmodel->num_poses = loadmodel->numframes;
2862 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2863 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2864 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2865 loadmodel->surfmesh.num_vertices = meshvertices;
2866 loadmodel->surfmesh.num_triangles = meshtriangles;
2867 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
2868 if(mod_alias_force_animated.string[0])
2869 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
2870 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
2871 // do most allocations as one merged chunk
2872 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);
2873 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2874 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2875 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2876 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2877 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2878 if (r_enableshadowvolumes.integer)
2880 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2882 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2883 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2884 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2885 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2886 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2887 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2888 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2889 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2890 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2891 loadmodel->surfmesh.num_blends = 0;
2892 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2893 if (loadmodel->surfmesh.num_vertices <= 65536)
2895 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2897 loadmodel->data_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
2898 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(blendweights_t));
2900 for (i = 0;i < loadmodel->numskins;i++)
2902 loadmodel->skinscenes[i].firstframe = i;
2903 loadmodel->skinscenes[i].framecount = 1;
2904 loadmodel->skinscenes[i].loop = true;
2905 loadmodel->skinscenes[i].framerate = 10;
2909 for (index = 0, i = 0;index < nummatts;index++)
2911 // since psk models do not have named sections, reuse their shader name as the section name
2912 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2913 loadmodel->sortedmodelsurfaces[index] = index;
2914 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2915 loadmodel->data_surfaces[index].num_firstvertex = 0;
2916 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2919 // copy over the vertex locations and texcoords
2920 for (index = 0;index < numvtxw;index++)
2922 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2923 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2924 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2925 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2926 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2929 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2930 for (index = 0;index < numfaces;index++)
2931 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2932 for (index = 0, i = 0;index < nummatts;index++)
2934 loadmodel->data_surfaces[index].num_firsttriangle = i;
2935 i += loadmodel->data_surfaces[index].num_triangles;
2936 loadmodel->data_surfaces[index].num_triangles = 0;
2938 for (index = 0;index < numfaces;index++)
2940 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2941 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2942 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2943 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2946 // copy over the bones
2947 for (index = 0;index < numbones;index++)
2949 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2950 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2951 if (loadmodel->data_bones[index].parent >= index)
2952 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2955 // convert the basepose data
2956 if (loadmodel->num_bones)
2959 matrix4x4_t *basebonepose;
2960 float *outinvmatrix = loadmodel->data_baseboneposeinverse;
2961 matrix4x4_t bonematrix;
2962 matrix4x4_t tempbonematrix;
2963 basebonepose = (matrix4x4_t *)Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(matrix4x4_t));
2964 for (boneindex = 0;boneindex < loadmodel->num_bones;boneindex++)
2966 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]);
2967 if (loadmodel->data_bones[boneindex].parent >= 0)
2969 tempbonematrix = bonematrix;
2970 Matrix4x4_Concat(&bonematrix, basebonepose + loadmodel->data_bones[boneindex].parent, &tempbonematrix);
2972 basebonepose[boneindex] = bonematrix;
2973 Matrix4x4_Invert_Simple(&tempbonematrix, basebonepose + boneindex);
2974 Matrix4x4_ToArray12FloatD3D(&tempbonematrix, outinvmatrix + 12*boneindex);
2976 Mem_Free(basebonepose);
2979 // sort the psk point weights into the vertex weight tables
2980 // (which only accept up to 4 bones per vertex)
2981 for (index = 0;index < numvtxw;index++)
2983 int weightindex[4] = { 0, 0, 0, 0 };
2984 float weightinfluence[4] = { 0, 0, 0, 0 };
2986 for (j = 0;j < numrawweights;j++)
2988 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2990 int boneindex = rawweights[j].boneindex;
2991 float influence = rawweights[j].weight;
2992 for (l = 0;l < 4;l++)
2994 if (weightinfluence[l] < influence)
2996 // move lower influence weights out of the way first
2998 for (l2 = 3;l2 > l;l2--)
3000 weightinfluence[l2] = weightinfluence[l2-1];
3001 weightindex[l2] = weightindex[l2-1];
3003 // store the new weight
3004 weightinfluence[l] = influence;
3005 weightindex[l] = boneindex;
3011 loadmodel->surfmesh.blends[index] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
3013 if (loadmodel->surfmesh.num_blends < loadmodel->surfmesh.num_vertices)
3014 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
3016 // set up the animscenes based on the anims
3019 for (index = 0, i = 0;index < numanims;index++)
3021 for (j = 0;j < anims[index].numframes;j++, i++)
3023 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
3024 loadmodel->animscenes[i].firstframe = i;
3025 loadmodel->animscenes[i].framecount = 1;
3026 loadmodel->animscenes[i].loop = true;
3027 loadmodel->animscenes[i].framerate = anims[index].fps;
3030 // calculate the scaling value for bone origins so they can be compressed to short
3032 for (index = 0;index < numanimkeys;index++)
3034 pskanimkeys_t *k = animkeys + index;
3035 biggestorigin = max(biggestorigin, fabs(k->origin[0]));
3036 biggestorigin = max(biggestorigin, fabs(k->origin[1]));
3037 biggestorigin = max(biggestorigin, fabs(k->origin[2]));
3039 loadmodel->num_posescale = biggestorigin / 32767.0f;
3040 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3042 // load the poses from the animkeys
3043 for (index = 0;index < numanimkeys;index++)
3045 pskanimkeys_t *k = animkeys + index;
3047 Vector4Copy(k->quat, quat);
3049 Vector4Negate(quat, quat);
3050 Vector4Normalize2(quat, quat);
3051 // compress poses to the short[7] format for longterm storage
3052 loadmodel->data_poses7s[index*7+0] = k->origin[0] * loadmodel->num_poseinvscale;
3053 loadmodel->data_poses7s[index*7+1] = k->origin[1] * loadmodel->num_poseinvscale;
3054 loadmodel->data_poses7s[index*7+2] = k->origin[2] * loadmodel->num_poseinvscale;
3055 loadmodel->data_poses7s[index*7+3] = quat[0] * 32767.0f;
3056 loadmodel->data_poses7s[index*7+4] = quat[1] * 32767.0f;
3057 loadmodel->data_poses7s[index*7+5] = quat[2] * 32767.0f;
3058 loadmodel->data_poses7s[index*7+6] = quat[3] * 32767.0f;
3063 strlcpy(loadmodel->animscenes[0].name, "base", sizeof(loadmodel->animscenes[0].name));
3064 loadmodel->animscenes[0].firstframe = 0;
3065 loadmodel->animscenes[0].framecount = 1;
3066 loadmodel->animscenes[0].loop = true;
3067 loadmodel->animscenes[0].framerate = 10;
3069 // calculate the scaling value for bone origins so they can be compressed to short
3071 for (index = 0;index < numbones;index++)
3073 pskboneinfo_t *p = bones + index;
3074 biggestorigin = max(biggestorigin, fabs(p->basepose.origin[0]));
3075 biggestorigin = max(biggestorigin, fabs(p->basepose.origin[1]));
3076 biggestorigin = max(biggestorigin, fabs(p->basepose.origin[2]));
3078 loadmodel->num_posescale = biggestorigin / 32767.0f;
3079 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3081 // load the basepose as a frame
3082 for (index = 0;index < numbones;index++)
3084 pskboneinfo_t *p = bones + index;
3086 Vector4Copy(p->basepose.quat, quat);
3088 Vector4Negate(quat, quat);
3089 Vector4Normalize2(quat, quat);
3090 // compress poses to the short[7] format for longterm storage
3091 loadmodel->data_poses7s[index*7+0] = p->basepose.origin[0] * loadmodel->num_poseinvscale;
3092 loadmodel->data_poses7s[index*7+1] = p->basepose.origin[1] * loadmodel->num_poseinvscale;
3093 loadmodel->data_poses7s[index*7+2] = p->basepose.origin[2] * loadmodel->num_poseinvscale;
3094 loadmodel->data_poses7s[index*7+3] = quat[0] * 32767.0f;
3095 loadmodel->data_poses7s[index*7+4] = quat[1] * 32767.0f;
3096 loadmodel->data_poses7s[index*7+5] = quat[2] * 32767.0f;
3097 loadmodel->data_poses7s[index*7+6] = quat[3] * 32767.0f;
3101 Mod_FreeSkinFiles(skinfiles);
3103 Mem_Free(animfilebuffer);
3104 Mod_MakeSortedSurfaces(loadmodel);
3106 // compute all the mesh information that was not loaded from the file
3107 // TODO: honor smoothing groups somehow?
3108 if (loadmodel->surfmesh.data_element3s)
3109 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3110 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3111 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
3112 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);
3113 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);
3114 if (loadmodel->surfmesh.data_neighbor3i)
3115 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3116 Mod_Alias_CalculateBoundingBox();
3118 if (!loadmodel->surfmesh.isanimated)
3120 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3121 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3122 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3123 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3124 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3125 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
3128 // because shaders can do somewhat unexpected things, check for unusual features now
3129 for (i = 0;i < loadmodel->num_textures;i++)
3131 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
3132 mod->DrawSky = R_Q1BSP_DrawSky;
3133 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
3134 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
3138 void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
3140 unsigned char *data;
3142 const unsigned char *pbase, *pend;
3144 skinfile_t *skinfiles;
3145 int i, j, k, meshvertices, meshtriangles;
3146 float biggestorigin;
3147 const unsigned int *inelements;
3149 const int *inneighbors;
3151 float *outvertex, *outnormal, *outtexcoord, *outsvector, *outtvector, *outcolor;
3152 // this pointers into the file data are read only through Little* functions so they can be unaligned memory
3153 const float *vnormal = NULL;
3154 const float *vposition = NULL;
3155 const float *vtangent = NULL;
3156 const float *vtexcoord = NULL;
3157 const float *vcolor4f = NULL;
3158 const unsigned char *vblendindexes = NULL;
3159 const unsigned char *vblendweights = NULL;
3160 const unsigned char *vcolor4ub = NULL;
3161 const unsigned short *framedata = NULL;
3162 // temporary memory allocations (because the data in the file may be misaligned)
3163 iqmanim_t *anims = NULL;
3164 iqmbounds_t *bounds = NULL;
3165 iqmjoint1_t *joint1 = NULL;
3166 iqmjoint_t *joint = NULL;
3167 iqmmesh_t *meshes = NULL;
3168 iqmpose1_t *pose1 = NULL;
3169 iqmpose_t *pose = NULL;
3170 iqmvertexarray_t *vas = NULL;
3172 pbase = (unsigned char *)buffer;
3173 pend = (unsigned char *)bufferend;
3175 if (pbase + sizeof(iqmheader_t) > pend)
3176 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model %d", loadmodel->name, (int)(pend - pbase));
3178 // copy struct (otherwise it may be misaligned)
3179 // LordHavoc: okay it's definitely not misaligned here, but for consistency...
3180 memcpy(&header, pbase, sizeof(iqmheader_t));
3182 if (memcmp(header.id, "INTERQUAKEMODEL", 16))
3183 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model", loadmodel->name);
3184 if (LittleLong(header.version) != 1 && LittleLong(header.version) != 2)
3185 Host_Error ("Mod_INTERQUAKEMODEL_Load: only version 1 and 2 models are currently supported (name = %s)", loadmodel->name);
3187 loadmodel->modeldatatypestring = "IQM";
3189 loadmodel->type = mod_alias;
3190 loadmodel->synctype = ST_RAND;
3193 header.version = LittleLong(header.version);
3194 header.filesize = LittleLong(header.filesize);
3195 header.flags = LittleLong(header.flags);
3196 header.num_text = LittleLong(header.num_text);
3197 header.ofs_text = LittleLong(header.ofs_text);
3198 header.num_meshes = LittleLong(header.num_meshes);
3199 header.ofs_meshes = LittleLong(header.ofs_meshes);
3200 header.num_vertexarrays = LittleLong(header.num_vertexarrays);
3201 header.num_vertexes = LittleLong(header.num_vertexes);
3202 header.ofs_vertexarrays = LittleLong(header.ofs_vertexarrays);
3203 header.num_triangles = LittleLong(header.num_triangles);
3204 header.ofs_triangles = LittleLong(header.ofs_triangles);
3205 header.ofs_neighbors = LittleLong(header.ofs_neighbors);
3206 header.num_joints = LittleLong(header.num_joints);
3207 header.ofs_joints = LittleLong(header.ofs_joints);
3208 header.num_poses = LittleLong(header.num_poses);
3209 header.ofs_poses = LittleLong(header.ofs_poses);
3210 header.num_anims = LittleLong(header.num_anims);
3211 header.ofs_anims = LittleLong(header.ofs_anims);
3212 header.num_frames = LittleLong(header.num_frames);
3213 header.num_framechannels = LittleLong(header.num_framechannels);
3214 header.ofs_frames = LittleLong(header.ofs_frames);
3215 header.ofs_bounds = LittleLong(header.ofs_bounds);
3216 header.num_comment = LittleLong(header.num_comment);
3217 header.ofs_comment = LittleLong(header.ofs_comment);
3218 header.num_extensions = LittleLong(header.num_extensions);
3219 header.ofs_extensions = LittleLong(header.ofs_extensions);
3221 if (header.version == 1)
3223 if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint1_t) > pend ||
3224 pbase + header.ofs_poses + header.num_poses*sizeof(iqmpose1_t) > pend)
3226 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3232 if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint_t) > pend ||
3233 pbase + header.ofs_poses + header.num_poses*sizeof(iqmpose_t) > pend)
3235 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3239 if (pbase + header.ofs_text + header.num_text > pend ||
3240 pbase + header.ofs_meshes + header.num_meshes*sizeof(iqmmesh_t) > pend ||
3241 pbase + header.ofs_vertexarrays + header.num_vertexarrays*sizeof(iqmvertexarray_t) > pend ||
3242 pbase + header.ofs_triangles + header.num_triangles*sizeof(int[3]) > pend ||
3243 (header.ofs_neighbors && pbase + header.ofs_neighbors + header.num_triangles*sizeof(int[3]) > pend) ||
3244 pbase + header.ofs_anims + header.num_anims*sizeof(iqmanim_t) > pend ||
3245 pbase + header.ofs_frames + header.num_frames*header.num_framechannels*sizeof(unsigned short) > pend ||
3246 (header.ofs_bounds && pbase + header.ofs_bounds + header.num_frames*sizeof(iqmbounds_t) > pend) ||
3247 pbase + header.ofs_comment + header.num_comment > pend)
3249 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3253 // copy structs to make them aligned in memory (otherwise we crash on Sparc and PowerPC and others)
3254 if (header.num_vertexarrays)
3255 vas = (iqmvertexarray_t *)(pbase + header.ofs_vertexarrays);
3256 if (header.num_anims)
3257 anims = (iqmanim_t *)(pbase + header.ofs_anims);
3258 if (header.ofs_bounds)
3259 bounds = (iqmbounds_t *)(pbase + header.ofs_bounds);
3260 if (header.num_meshes)
3261 meshes = (iqmmesh_t *)(pbase + header.ofs_meshes);
3263 for (i = 0;i < (int)header.num_vertexarrays;i++)
3265 iqmvertexarray_t va;
3267 va.type = LittleLong(vas[i].type);
3268 va.flags = LittleLong(vas[i].flags);
3269 va.format = LittleLong(vas[i].format);
3270 va.size = LittleLong(vas[i].size);
3271 va.offset = LittleLong(vas[i].offset);
3272 vsize = header.num_vertexes*va.size;
3275 case IQM_FLOAT: vsize *= sizeof(float); break;
3276 case IQM_UBYTE: vsize *= sizeof(unsigned char); break;
3279 if (pbase + va.offset + vsize > pend)
3281 // no need to copy the vertex data for alignment because LittleLong/LittleShort will be invoked on reading them, and the destination is aligned
3285 if (va.format == IQM_FLOAT && va.size == 3)
3286 vposition = (const float *)(pbase + va.offset);
3289 if (va.format == IQM_FLOAT && va.size == 2)
3290 vtexcoord = (const float *)(pbase + va.offset);
3293 if (va.format == IQM_FLOAT && va.size == 3)
3294 vnormal = (const float *)(pbase + va.offset);
3297 if (va.format == IQM_FLOAT && va.size == 4)
3298 vtangent = (const float *)(pbase + va.offset);
3300 case IQM_BLENDINDEXES:
3301 if (va.format == IQM_UBYTE && va.size == 4)
3302 vblendindexes = (const unsigned char *)(pbase + va.offset);
3304 case IQM_BLENDWEIGHTS:
3305 if (va.format == IQM_UBYTE && va.size == 4)
3306 vblendweights = (const unsigned char *)(pbase + va.offset);
3309 if (va.format == IQM_FLOAT && va.size == 4)
3310 vcolor4f = (const float *)(pbase + va.offset);
3311 if (va.format == IQM_UBYTE && va.size == 4)
3312 vcolor4ub = (const unsigned char *)(pbase + va.offset);
3316 if (header.num_vertexes > 0 && (!vposition || !vtexcoord || ((header.num_frames > 0 || header.num_anims > 0) && (!vblendindexes || !vblendweights))))
3318 Con_Printf("%s is missing vertex array data\n", loadmodel->name);
3322 text = header.num_text && header.ofs_text ? (const char *)(pbase + header.ofs_text) : "";
3324 loadmodel->DrawSky = NULL;
3325 loadmodel->DrawAddWaterPlanes = NULL;
3326 loadmodel->Draw = R_Q1BSP_Draw;
3327 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
3328 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
3329 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
3330 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
3331 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
3332 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
3333 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
3334 loadmodel->DrawLight = R_Q1BSP_DrawLight;
3335 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
3336 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
3337 loadmodel->PointSuperContents = NULL;
3339 // load external .skin files if present
3340 skinfiles = Mod_LoadSkinFiles();
3341 if (loadmodel->numskins < 1)
3342 loadmodel->numskins = 1;
3344 loadmodel->numframes = max(header.num_anims, 1);
3345 loadmodel->num_bones = header.num_joints;
3346 loadmodel->num_poses = max(header.num_frames, 1);
3347 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = header.num_meshes;
3348 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3349 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3350 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices; // updated later
3352 meshvertices = header.num_vertexes;
3353 meshtriangles = header.num_triangles;
3355 // do most allocations as one merged chunk
3356 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));
3357 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
3358 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
3359 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
3360 loadmodel->surfmesh.num_vertices = meshvertices;
3361 loadmodel->surfmesh.num_triangles = meshtriangles;
3362 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3363 if (r_enableshadowvolumes.integer)
3365 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3367 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
3368 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3369 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3370 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
3371 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
3372 if (vcolor4f || vcolor4ub)
3374 loadmodel->surfmesh.data_lightmapcolor4f = (float *)data;data += meshvertices * sizeof(float[4]);
3376 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
3377 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
3378 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
3379 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
3380 if (vblendindexes && vblendweights)
3382 loadmodel->surfmesh.num_blends = 0;
3383 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
3385 if (meshvertices <= 65536)
3387 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
3389 loadmodel->data_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
3390 if (vblendindexes && vblendweights)
3391 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
3393 for (i = 0;i < loadmodel->numskins;i++)
3395 loadmodel->skinscenes[i].firstframe = i;
3396 loadmodel->skinscenes[i].framecount = 1;
3397 loadmodel->skinscenes[i].loop = true;
3398 loadmodel->skinscenes[i].framerate = 10;
3401 // load the bone info
3402 if (header.version == 1)
3404 iqmjoint1_t *injoint1 = (iqmjoint1_t *)(pbase + header.ofs_joints);
3405 if (loadmodel->num_bones)
3406 joint1 = (iqmjoint1_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(iqmjoint1_t));
3407 for (i = 0;i < loadmodel->num_bones;i++)
3409 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3410 joint1[i].name = LittleLong(injoint1[i].name);
3411 joint1[i].parent = LittleLong(injoint1[i].parent);
3412 for (j = 0;j < 3;j++)
3414 joint1[i].origin[j] = LittleFloat(injoint1[i].origin[j]);
3415 joint1[i].rotation[j] = LittleFloat(injoint1[i].rotation[j]);
3416 joint1[i].scale[j] = LittleFloat(injoint1[i].scale[j]);
3418 strlcpy(loadmodel->data_bones[i].name, &text[joint1[i].name], sizeof(loadmodel->data_bones[i].name));
3419 loadmodel->data_bones[i].parent = joint1[i].parent;
3420 if (loadmodel->data_bones[i].parent >= i)
3421 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3422 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]);
3423 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3424 if (loadmodel->data_bones[i].parent >= 0)
3426 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3427 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3428 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3430 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3435 iqmjoint_t *injoint = (iqmjoint_t *)(pbase + header.ofs_joints);
3436 if (header.num_joints)
3437 joint = (iqmjoint_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(iqmjoint_t));
3438 for (i = 0;i < loadmodel->num_bones;i++)
3440 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3441 joint[i].name = LittleLong(injoint[i].name);
3442 joint[i].parent = LittleLong(injoint[i].parent);
3443 for (j = 0;j < 3;j++)
3445 joint[i].origin[j] = LittleFloat(injoint[i].origin[j]);
3446 joint[i].rotation[j] = LittleFloat(injoint[i].rotation[j]);
3447 joint[i].scale[j] = LittleFloat(injoint[i].scale[j]);
3449 joint[i].rotation[3] = LittleFloat(injoint[i].rotation[3]);
3450 strlcpy(loadmodel->data_bones[i].name, &text[joint[i].name], sizeof(loadmodel->data_bones[i].name));
3451 loadmodel->data_bones[i].parent = joint[i].parent;
3452 if (loadmodel->data_bones[i].parent >= i)
3453 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3454 if (joint[i].rotation[3] > 0)
3455 Vector4Negate(joint[i].rotation, joint[i].rotation);
3456 Vector4Normalize2(joint[i].rotation, joint[i].rotation);
3457 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]);
3458 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3459 if (loadmodel->data_bones[i].parent >= 0)
3461 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3462 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3463 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3465 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3469 // set up the animscenes based on the anims
3470 for (i = 0;i < (int)header.num_anims;i++)
3473 anim.name = LittleLong(anims[i].name);
3474 anim.first_frame = LittleLong(anims[i].first_frame);
3475 anim.num_frames = LittleLong(anims[i].num_frames);
3476 anim.framerate = LittleFloat(anims[i].framerate);
3477 anim.flags = LittleLong(anims[i].flags);
3478 strlcpy(loadmodel->animscenes[i].name, &text[anim.name], sizeof(loadmodel->animscenes[i].name));
3479 loadmodel->animscenes[i].firstframe = anim.first_frame;
3480 loadmodel->animscenes[i].framecount = anim.num_frames;
3481 loadmodel->animscenes[i].loop = ((anim.flags & IQM_LOOP) != 0);
3482 loadmodel->animscenes[i].framerate = anim.framerate;
3484 if (header.num_anims <= 0)
3486 strlcpy(loadmodel->animscenes[0].name, "static", sizeof(loadmodel->animscenes[0].name));
3487 loadmodel->animscenes[0].firstframe = 0;
3488 loadmodel->animscenes[0].framecount = 1;
3489 loadmodel->animscenes[0].loop = true;
3490 loadmodel->animscenes[0].framerate = 10;
3493 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
3494 if(mod_alias_force_animated.string[0])
3495 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
3496 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
3499 if (header.version == 1)
3501 iqmpose1_t *inpose1 = (iqmpose1_t *)(pbase + header.ofs_poses);
3502 if (header.num_poses)
3503 pose1 = (iqmpose1_t *)Mem_Alloc(loadmodel->mempool, header.num_poses * sizeof(iqmpose1_t));
3504 for (i = 0;i < (int)header.num_poses;i++)
3507 pose1[i].parent = LittleLong(inpose1[i].parent);
3508 pose1[i].channelmask = LittleLong(inpose1[i].channelmask);
3509 for (j = 0;j < 9;j++)
3511 pose1[i].channeloffset[j] = LittleFloat(inpose1[i].channeloffset[j]);
3512 pose1[i].channelscale[j] = LittleFloat(inpose1[i].channelscale[j]);
3514 f = fabs(pose1[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3515 f = fabs(pose1[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3516 f = fabs(pose1[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3517 f = fabs(pose1[i].channeloffset[0] + 0xFFFF*pose1[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3518 f = fabs(pose1[i].channeloffset[1] + 0xFFFF*pose1[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3519 f = fabs(pose1[i].channeloffset[2] + 0xFFFF*pose1[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3521 if (header.num_frames <= 0)
3523 for (i = 0;i < loadmodel->num_bones;i++)
3526 f = fabs(joint1[i].origin[0]); biggestorigin = max(biggestorigin, f);
3527 f = fabs(joint1[i].origin[1]); biggestorigin = max(biggestorigin, f);
3528 f = fabs(joint1[i].origin[2]); biggestorigin = max(biggestorigin, f);
3534 iqmpose_t *inpose = (iqmpose_t *)(pbase + header.ofs_poses);
3535 if (header.num_poses)
3536 pose = (iqmpose_t *)Mem_Alloc(loadmodel->mempool, header.num_poses * sizeof(iqmpose_t));
3537 for (i = 0;i < (int)header.num_poses;i++)
3540 pose[i].parent = LittleLong(inpose[i].parent);
3541 pose[i].channelmask = LittleLong(inpose[i].channelmask);
3542 for (j = 0;j < 10;j++)
3544 pose[i].channeloffset[j] = LittleFloat(inpose[i].channeloffset[j]);
3545 pose[i].channelscale[j] = LittleFloat(inpose[i].channelscale[j]);
3547 f = fabs(pose[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3548 f = fabs(pose[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3549 f = fabs(pose[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3550 f = fabs(pose[i].channeloffset[0] + 0xFFFF*pose[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3551 f = fabs(pose[i].channeloffset[1] + 0xFFFF*pose[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3552 f = fabs(pose[i].channeloffset[2] + 0xFFFF*pose[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3554 if (header.num_frames <= 0)
3556 for (i = 0;i < loadmodel->num_bones;i++)
3559 f = fabs(joint[i].origin[0]); biggestorigin = max(biggestorigin, f);
3560 f = fabs(joint[i].origin[1]); biggestorigin = max(biggestorigin, f);
3561 f = fabs(joint[i].origin[2]); biggestorigin = max(biggestorigin, f);
3565 loadmodel->num_posescale = biggestorigin / 32767.0f;
3566 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3568 // load the pose data
3569 // this unaligned memory access is safe (LittleShort reads as bytes)
3570 framedata = (const unsigned short *)(pbase + header.ofs_frames);
3571 if (header.version == 1)
3573 for (i = 0, k = 0;i < (int)header.num_frames;i++)
3575 for (j = 0;j < (int)header.num_poses;j++, k++)
3577 float qx, qy, qz, qw;
3578 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));
3579 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));
3580 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));
3581 qx = pose1[j].channeloffset[3] + (pose1[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[3] : 0);
3582 qy = pose1[j].channeloffset[4] + (pose1[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[4] : 0);
3583 qz = pose1[j].channeloffset[5] + (pose1[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[5] : 0);
3584 qw = 1.0f - (qx*qx + qy*qy + qz*qz);
3585 qw = qw > 0.0f ? -sqrt(qw) : 0.0f;
3586 loadmodel->data_poses7s[k*7 + 3] = 32767.0f * qx;
3587 loadmodel->data_poses7s[k*7 + 4] = 32767.0f * qy;
3588 loadmodel->data_poses7s[k*7 + 5] = 32767.0f * qz;
3589 loadmodel->data_poses7s[k*7 + 6] = 32767.0f * qw;
3590 // skip scale data for now
3591 if(pose1[j].channelmask&64) framedata++;
3592 if(pose1[j].channelmask&128) framedata++;
3593 if(pose1[j].channelmask&256) framedata++;
3596 if (header.num_frames <= 0)
3598 for (i = 0;i < loadmodel->num_bones;i++)
3600 float qx, qy, qz, qw;
3601 loadmodel->data_poses7s[i*7 + 0] = loadmodel->num_poseinvscale * joint1[i].origin[0];
3602 loadmodel->data_poses7s[i*7 + 1] = loadmodel->num_poseinvscale * joint1[i].origin[1];
3603 loadmodel->data_poses7s[i*7 + 2] = loadmodel->num_poseinvscale * joint1[i].origin[2];
3604 qx = joint1[i].rotation[0];
3605 qy = joint1[i].rotation[1];
3606 qz = joint1[i].rotation[2];
3607 qw = 1.0f - (qx*qx + qy*qy + qz*qz);
3608 qw = qw > 0.0f ? -sqrt(qw) : 0.0f;
3609 loadmodel->data_poses7s[i*7 + 3] = 32767.0f * qx;
3610 loadmodel->data_poses7s[i*7 + 4] = 32767.0f * qy;
3611 loadmodel->data_poses7s[i*7 + 5] = 32767.0f * qz;
3612 loadmodel->data_poses7s[i*7 + 6] = 32767.0f * qw;
3618 for (i = 0, k = 0;i < (int)header.num_frames;i++)
3620 for (j = 0;j < (int)header.num_poses;j++, k++)
3623 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));
3624 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));
3625 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));
3626 rot[0] = pose[j].channeloffset[3] + (pose[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[3] : 0);
3627 rot[1] = pose[j].channeloffset[4] + (pose[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[4] : 0);
3628 rot[2] = pose[j].channeloffset[5] + (pose[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[5] : 0);
3629 rot[3] = pose[j].channeloffset[6] + (pose[j].channelmask&64 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[6] : 0);
3631 Vector4Negate(rot, rot);
3632 Vector4Normalize2(rot, rot);
3633 loadmodel->data_poses7s[k*7 + 3] = 32767.0f * rot[0];
3634 loadmodel->data_poses7s[k*7 + 4] = 32767.0f * rot[1];
3635 loadmodel->data_poses7s[k*7 + 5] = 32767.0f * rot[2];
3636 loadmodel->data_poses7s[k*7 + 6] = 32767.0f * rot[3];
3637 // skip scale data for now
3638 if(pose[j].channelmask&128) framedata++;
3639 if(pose[j].channelmask&256) framedata++;
3640 if(pose[j].channelmask&512) framedata++;
3643 if (header.num_frames <= 0)
3645 for (i = 0;i < loadmodel->num_bones;i++)
3647 loadmodel->data_poses7s[i*7 + 0] = loadmodel->num_poseinvscale * joint[i].origin[0];
3648 loadmodel->data_poses7s[i*7 + 1] = loadmodel->num_poseinvscale * joint[i].origin[1];
3649 loadmodel->data_poses7s[i*7 + 2] = loadmodel->num_poseinvscale * joint[i].origin[2];
3650 loadmodel->data_poses7s[i*7 + 3] = 32767.0f * joint[i].rotation[0];
3651 loadmodel->data_poses7s[i*7 + 4] = 32767.0f * joint[i].rotation[1];
3652 loadmodel->data_poses7s[i*7 + 5] = 32767.0f * joint[i].rotation[2];
3653 loadmodel->data_poses7s[i*7 + 6] = 32767.0f * joint[i].rotation[3];
3658 // load bounding box data
3659 if (header.ofs_bounds)
3661 float xyradius = 0, radius = 0;
3662 VectorClear(loadmodel->normalmins);
3663 VectorClear(loadmodel->normalmaxs);
3664 for (i = 0; i < (int)header.num_frames;i++)
3667 bound.mins[0] = LittleFloat(bounds[i].mins[0]);
3668 bound.mins[1] = LittleFloat(bounds[i].mins[1]);
3669 bound.mins[2] = LittleFloat(bounds[i].mins[2]);
3670 bound.maxs[0] = LittleFloat(bounds[i].maxs[0]);
3671 bound.maxs[1] = LittleFloat(bounds[i].maxs[1]);
3672 bound.maxs[2] = LittleFloat(bounds[i].maxs[2]);
3673 bound.xyradius = LittleFloat(bounds[i].xyradius);
3674 bound.radius = LittleFloat(bounds[i].radius);
3677 VectorCopy(bound.mins, loadmodel->normalmins);
3678 VectorCopy(bound.maxs, loadmodel->normalmaxs);
3682 if (loadmodel->normalmins[0] > bound.mins[0]) loadmodel->normalmins[0] = bound.mins[0];
3683 if (loadmodel->normalmins[1] > bound.mins[1]) loadmodel->normalmins[1] = bound.mins[1];
3684 if (loadmodel->normalmins[2] > bound.mins[2]) loadmodel->normalmins[2] = bound.mins[2];
3685 if (loadmodel->normalmaxs[0] < bound.maxs[0]) loadmodel->normalmaxs[0] = bound.maxs[0];
3686 if (loadmodel->normalmaxs[1] < bound.maxs[1]) loadmodel->normalmaxs[1] = bound.maxs[1];
3687 if (loadmodel->normalmaxs[2] < bound.maxs[2]) loadmodel->normalmaxs[2] = bound.maxs[2];
3689 if (bound.xyradius > xyradius)
3690 xyradius = bound.xyradius;
3691 if (bound.radius > radius)
3692 radius = bound.radius;
3694 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -xyradius;
3695 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = xyradius;
3696 loadmodel->yawmins[2] = loadmodel->normalmins[2];
3697 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
3698 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
3699 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
3700 loadmodel->radius = radius;
3701 loadmodel->radius2 = radius * radius;
3704 // load triangle data
3705 // this unaligned memory access is safe (LittleLong reads as bytes)
3706 inelements = (const unsigned int *)(pbase + header.ofs_triangles);
3707 outelements = loadmodel->surfmesh.data_element3i;
3708 for (i = 0;i < (int)header.num_triangles;i++)
3710 outelements[0] = LittleLong(inelements[0]);
3711 outelements[1] = LittleLong(inelements[1]);
3712 outelements[2] = LittleLong(inelements[2]);
3716 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, header.num_vertexes, __FILE__, __LINE__);
3718 if (header.ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
3720 // this unaligned memory access is safe (LittleLong reads as bytes)
3721 inneighbors = (const int *)(pbase + header.ofs_neighbors);
3722 outneighbors = loadmodel->surfmesh.data_neighbor3i;
3723 for (i = 0;i < (int)header.num_triangles;i++)
3725 outneighbors[0] = LittleLong(inneighbors[0]);
3726 outneighbors[1] = LittleLong(inneighbors[1]);
3727 outneighbors[2] = LittleLong(inneighbors[2]);
3734 // this unaligned memory access is safe (LittleFloat reads as bytes)
3735 outvertex = loadmodel->surfmesh.data_vertex3f;
3736 for (i = 0;i < (int)header.num_vertexes;i++)
3738 outvertex[0] = LittleFloat(vposition[0]);
3739 outvertex[1] = LittleFloat(vposition[1]);
3740 outvertex[2] = LittleFloat(vposition[2]);
3745 outtexcoord = loadmodel->surfmesh.data_texcoordtexture2f;
3746 // this unaligned memory access is safe (LittleFloat reads as bytes)
3747 for (i = 0;i < (int)header.num_vertexes;i++)
3749 outtexcoord[0] = LittleFloat(vtexcoord[0]);
3750 outtexcoord[1] = LittleFloat(vtexcoord[1]);
3755 // this unaligned memory access is safe (LittleFloat reads as bytes)
3758 outnormal = loadmodel->surfmesh.data_normal3f;
3759 for (i = 0;i < (int)header.num_vertexes;i++)
3761 outnormal[0] = LittleFloat(vnormal[0]);
3762 outnormal[1] = LittleFloat(vnormal[1]);
3763 outnormal[2] = LittleFloat(vnormal[2]);
3769 // this unaligned memory access is safe (LittleFloat reads as bytes)
3770 if(vnormal && vtangent)
3772 outnormal = loadmodel->surfmesh.data_normal3f;
3773 outsvector = loadmodel->surfmesh.data_svector3f;
3774 outtvector = loadmodel->surfmesh.data_tvector3f;
3775 for (i = 0;i < (int)header.num_vertexes;i++)
3777 outsvector[0] = LittleFloat(vtangent[0]);
3778 outsvector[1] = LittleFloat(vtangent[1]);
3779 outsvector[2] = LittleFloat(vtangent[2]);
3780 if(LittleFloat(vtangent[3]) < 0)
3781 CrossProduct(outsvector, outnormal, outtvector);
3783 CrossProduct(outnormal, outsvector, outtvector);
3791 // this unaligned memory access is safe (all bytes)
3792 if (vblendindexes && vblendweights)
3794 for (i = 0; i < (int)header.num_vertexes;i++)
3796 blendweights_t weights;
3797 memcpy(weights.index, vblendindexes + i*4, 4);
3798 memcpy(weights.influence, vblendweights + i*4, 4);
3799 loadmodel->surfmesh.blends[i] = Mod_Skeletal_AddBlend(loadmodel, &weights);
3805 outcolor = loadmodel->surfmesh.data_lightmapcolor4f;
3806 // this unaligned memory access is safe (LittleFloat reads as bytes)
3807 for (i = 0;i < (int)header.num_vertexes;i++)
3809 outcolor[0] = LittleFloat(vcolor4f[0]);
3810 outcolor[1] = LittleFloat(vcolor4f[1]);
3811 outcolor[2] = LittleFloat(vcolor4f[2]);
3812 outcolor[3] = LittleFloat(vcolor4f[3]);
3819 outcolor = loadmodel->surfmesh.data_lightmapcolor4f;
3820 // this unaligned memory access is safe (all bytes)
3821 for (i = 0;i < (int)header.num_vertexes;i++)
3823 outcolor[0] = vcolor4ub[0] * (1.0f / 255.0f);
3824 outcolor[1] = vcolor4ub[1] * (1.0f / 255.0f);
3825 outcolor[2] = vcolor4ub[2] * (1.0f / 255.0f);
3826 outcolor[3] = vcolor4ub[3] * (1.0f / 255.0f);
3833 for (i = 0;i < (int)header.num_meshes;i++)
3836 msurface_t *surface;
3838 mesh.name = LittleLong(meshes[i].name);
3839 mesh.material = LittleLong(meshes[i].material);
3840 mesh.first_vertex = LittleLong(meshes[i].first_vertex);
3841 mesh.num_vertexes = LittleLong(meshes[i].num_vertexes);
3842 mesh.first_triangle = LittleLong(meshes[i].first_triangle);
3843 mesh.num_triangles = LittleLong(meshes[i].num_triangles);
3845 loadmodel->sortedmodelsurfaces[i] = i;
3846 surface = loadmodel->data_surfaces + i;
3847 surface->texture = loadmodel->data_textures + i;
3848 surface->num_firsttriangle = mesh.first_triangle;
3849 surface->num_triangles = mesh.num_triangles;
3850 surface->num_firstvertex = mesh.first_vertex;
3851 surface->num_vertices = mesh.num_vertexes;
3853 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, &text[mesh.name], &text[mesh.material]);
3856 Mod_FreeSkinFiles(skinfiles);
3857 Mod_MakeSortedSurfaces(loadmodel);
3859 // compute all the mesh information that was not loaded from the file
3860 if (loadmodel->surfmesh.data_element3s)
3861 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3862 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3864 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);
3865 if (!vnormal || !vtangent)
3866 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);
3867 if (!header.ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
3868 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3869 if (!header.ofs_bounds)
3870 Mod_Alias_CalculateBoundingBox();
3872 if (!loadmodel->surfmesh.isanimated && loadmodel->surfmesh.num_triangles >= 1)
3874 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3875 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3876 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3877 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3878 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3879 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
3882 if (joint ) Mem_Free(joint );joint = NULL;
3883 if (joint1 ) Mem_Free(joint1 );joint1 = NULL;
3884 if (pose ) Mem_Free(pose );pose = NULL;
3885 if (pose1 ) Mem_Free(pose1 );pose1 = NULL;
3887 // because shaders can do somewhat unexpected things, check for unusual features now
3888 for (i = 0;i < loadmodel->num_textures;i++)
3890 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
3891 mod->DrawSky = R_Q1BSP_DrawSky;
3892 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
3893 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;