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]) + sizeof(unsigned short) + sizeof(unsigned char[2][4])) + 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->surfmesh.data_skeletalindex4ub = (unsigned char *)data;data += meshvertices * sizeof(unsigned char[4]);
1911 loadmodel->surfmesh.data_skeletalweight4ub = (unsigned char *)data;data += meshvertices * sizeof(unsigned char[4]);
1912 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1913 loadmodel->surfmesh.num_blends = 0;
1914 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
1915 if (loadmodel->surfmesh.num_vertices <= 65536)
1917 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1919 loadmodel->data_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
1920 loadmodel->surfmesh.data_blendweights = NULL;
1922 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1923 poses = (float *) (pheader->lump_poses.start + pbase);
1924 // figure out scale of model from root bone, for compatibility with old zmodel versions
1925 tempvec[0] = BigFloat(poses[0]);
1926 tempvec[1] = BigFloat(poses[1]);
1927 tempvec[2] = BigFloat(poses[2]);
1928 modelscale = VectorLength(tempvec);
1930 for (i = 0;i < loadmodel->num_bones * numposes * 12;i++)
1932 f = fabs(BigFloat(poses[i]));
1933 biggestorigin = max(biggestorigin, f);
1935 loadmodel->num_posescale = biggestorigin / 32767.0f;
1936 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
1937 for (i = 0;i < numposes;i++)
1939 const float *frameposes = (float *) (pheader->lump_poses.start + pbase) + 12*i*loadmodel->num_bones;
1940 for (j = 0;j < loadmodel->num_bones;j++)
1943 matrix4x4_t posematrix;
1944 for (k = 0;k < 12;k++)
1945 pose[k] = BigFloat(frameposes[j*12+k]);
1946 //if (j < loadmodel->num_bones)
1947 // 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));
1948 // scale child bones to match the root scale
1949 if (loadmodel->data_bones[j].parent >= 0)
1951 pose[3] *= modelscale;
1952 pose[7] *= modelscale;
1953 pose[11] *= modelscale;
1955 // normalize rotation matrix
1956 VectorNormalize(pose + 0);
1957 VectorNormalize(pose + 4);
1958 VectorNormalize(pose + 8);
1959 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
1960 Matrix4x4_ToBonePose7s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses7s + 7*(i*loadmodel->num_bones+j));
1964 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1965 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1966 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1967 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1968 // (converting from weight-blending skeletal animation to
1969 // deformation-based skeletal animation)
1970 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1971 for (i = 0;i < loadmodel->num_bones;i++)
1974 for (k = 0;k < 12;k++)
1975 m[k] = BigFloat(poses[i*12+k]);
1976 if (loadmodel->data_bones[i].parent >= 0)
1977 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1979 for (k = 0;k < 12;k++)
1980 bonepose[12*i+k] = m[k];
1982 for (j = 0;j < pheader->numverts;j++)
1984 // this format really should have had a per vertexweight weight value...
1985 // but since it does not, the weighting is completely ignored and
1986 // only one weight is allowed per vertex
1987 int boneindex = BigLong(vertdata[j].bonenum);
1988 const float *m = bonepose + 12 * boneindex;
1989 float relativeorigin[3];
1990 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1991 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1992 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1993 // transform the vertex bone weight into the base mesh
1994 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1995 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1996 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1997 // store the weight as the primary weight on this vertex
1998 loadmodel->surfmesh.blends[j] = boneindex;
1999 loadmodel->surfmesh.data_skeletalindex4ub[j*4 ] = boneindex;
2000 loadmodel->surfmesh.data_skeletalindex4ub[j*4+1] = 0;
2001 loadmodel->surfmesh.data_skeletalindex4ub[j*4+2] = 0;
2002 loadmodel->surfmesh.data_skeletalindex4ub[j*4+3] = 0;
2003 loadmodel->surfmesh.data_skeletalweight4ub[j*4 ] = 255;
2004 loadmodel->surfmesh.data_skeletalweight4ub[j*4+1] = 0;
2005 loadmodel->surfmesh.data_skeletalweight4ub[j*4+2] = 0;
2006 loadmodel->surfmesh.data_skeletalweight4ub[j*4+3] = 0;
2009 // normals and tangents are calculated after elements are loaded
2011 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
2012 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
2013 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
2014 for (i = 0;i < pheader->numverts;i++)
2016 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
2017 // flip T coordinate for OpenGL
2018 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
2021 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
2022 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
2023 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
2025 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
2026 //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)
2027 // byteswap, validate, and swap winding order of tris
2028 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
2029 if (pheader->lump_render.length != count)
2030 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
2031 renderlist = (int *) (pheader->lump_render.start + pbase);
2032 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
2034 for (i = 0;i < loadmodel->num_surfaces;i++)
2036 int firstvertex, lastvertex;
2037 if (renderlist >= renderlistend)
2038 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2039 count = BigLong(*renderlist);renderlist++;
2040 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
2041 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2043 loadmodel->sortedmodelsurfaces[i] = i;
2044 surface = loadmodel->data_surfaces + i;
2045 surface->texture = loadmodel->data_textures + i;
2046 surface->num_firsttriangle = meshtriangles;
2047 surface->num_triangles = count;
2048 meshtriangles += surface->num_triangles;
2050 // load the elements
2051 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2052 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
2054 outelements[j*3+2] = BigLong(renderlist[0]);
2055 outelements[j*3+1] = BigLong(renderlist[1]);
2056 outelements[j*3+0] = BigLong(renderlist[2]);
2058 // validate the elements and find the used vertex range
2059 firstvertex = meshvertices;
2061 for (j = 0;j < surface->num_triangles * 3;j++)
2063 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
2064 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
2065 firstvertex = min(firstvertex, outelements[j]);
2066 lastvertex = max(lastvertex, outelements[j]);
2068 surface->num_firstvertex = firstvertex;
2069 surface->num_vertices = lastvertex + 1 - firstvertex;
2071 // since zym models do not have named sections, reuse their shader
2072 // name as the section name
2073 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
2074 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
2076 Mod_FreeSkinFiles(skinfiles);
2077 Mem_Free(vertbonecounts);
2079 Mod_MakeSortedSurfaces(loadmodel);
2081 // compute all the mesh information that was not loaded from the file
2082 if (loadmodel->surfmesh.data_element3s)
2083 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2084 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2085 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2086 Mod_BuildBaseBonePoses();
2087 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);
2088 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);
2089 if (loadmodel->surfmesh.data_neighbor3i)
2090 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2092 if (!loadmodel->surfmesh.isanimated)
2094 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2095 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2096 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2097 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2098 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2099 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2102 // because shaders can do somewhat unexpected things, check for unusual features now
2103 for (i = 0;i < loadmodel->num_textures;i++)
2105 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
2106 mod->DrawSky = R_Q1BSP_DrawSky;
2107 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
2108 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
2112 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2114 dpmheader_t *pheader;
2118 unsigned char *pbase;
2119 int i, j, k, meshvertices, meshtriangles;
2120 skinfile_t *skinfiles;
2121 unsigned char *data;
2123 float biggestorigin, tempvec[3], modelscale;
2127 pheader = (dpmheader_t *)buffer;
2128 pbase = (unsigned char *)buffer;
2129 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2130 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2131 if (BigLong(pheader->type) != 2)
2132 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2134 loadmodel->modeldatatypestring = "DPM";
2136 loadmodel->type = mod_alias;
2137 loadmodel->synctype = ST_RAND;
2140 pheader->type = BigLong(pheader->type);
2141 pheader->filesize = BigLong(pheader->filesize);
2142 pheader->mins[0] = BigFloat(pheader->mins[0]);
2143 pheader->mins[1] = BigFloat(pheader->mins[1]);
2144 pheader->mins[2] = BigFloat(pheader->mins[2]);
2145 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2146 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2147 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2148 pheader->yawradius = BigFloat(pheader->yawradius);
2149 pheader->allradius = BigFloat(pheader->allradius);
2150 pheader->num_bones = BigLong(pheader->num_bones);
2151 pheader->num_meshs = BigLong(pheader->num_meshs);
2152 pheader->num_frames = BigLong(pheader->num_frames);
2153 pheader->ofs_bones = BigLong(pheader->ofs_bones);
2154 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2155 pheader->ofs_frames = BigLong(pheader->ofs_frames);
2157 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2159 Con_Printf("%s has no geometry\n", loadmodel->name);
2162 if (pheader->num_frames < 1)
2164 Con_Printf("%s has no frames\n", loadmodel->name);
2168 loadmodel->DrawSky = NULL;
2169 loadmodel->DrawAddWaterPlanes = NULL;
2170 loadmodel->Draw = R_Q1BSP_Draw;
2171 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2172 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2173 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2174 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2175 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2176 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2177 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2178 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2179 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2180 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2181 loadmodel->PointSuperContents = NULL;
2184 for (i = 0;i < 3;i++)
2186 loadmodel->normalmins[i] = pheader->mins[i];
2187 loadmodel->normalmaxs[i] = pheader->maxs[i];
2188 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2189 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2190 loadmodel->rotatedmins[i] = -pheader->allradius;
2191 loadmodel->rotatedmaxs[i] = pheader->allradius;
2193 loadmodel->radius = pheader->allradius;
2194 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2196 // load external .skin files if present
2197 skinfiles = Mod_LoadSkinFiles();
2198 if (loadmodel->numskins < 1)
2199 loadmodel->numskins = 1;
2204 // gather combined statistics from the meshes
2205 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2206 for (i = 0;i < (int)pheader->num_meshs;i++)
2208 int numverts = BigLong(dpmmesh->num_verts);
2209 meshvertices += numverts;
2210 meshtriangles += BigLong(dpmmesh->num_tris);
2214 loadmodel->numframes = pheader->num_frames;
2215 loadmodel->num_bones = pheader->num_bones;
2216 loadmodel->num_poses = loadmodel->numframes;
2217 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2218 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2219 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2220 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
2221 if(mod_alias_force_animated.string[0])
2222 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
2223 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
2224 // do most allocations as one merged chunk
2225 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + (r_enableshadowvolumes.integer ? meshtriangles * sizeof(int[3]) : 0) + meshvertices * (sizeof(float[14]) + sizeof(unsigned short) + sizeof(unsigned char[2][4])) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
2226 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2227 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2228 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2229 loadmodel->surfmesh.num_vertices = meshvertices;
2230 loadmodel->surfmesh.num_triangles = meshtriangles;
2231 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2232 if (r_enableshadowvolumes.integer)
2234 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2236 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2237 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2238 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2239 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2240 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2241 loadmodel->surfmesh.data_skeletalindex4ub = (unsigned char *)data;data += meshvertices * sizeof(unsigned char[4]);
2242 loadmodel->surfmesh.data_skeletalweight4ub = (unsigned char *)data;data += meshvertices * sizeof(unsigned char[4]);
2243 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2244 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2245 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2246 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2247 loadmodel->surfmesh.num_blends = 0;
2248 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2249 if (meshvertices <= 65536)
2251 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2253 loadmodel->data_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
2254 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
2256 for (i = 0;i < loadmodel->numskins;i++)
2258 loadmodel->skinscenes[i].firstframe = i;
2259 loadmodel->skinscenes[i].framecount = 1;
2260 loadmodel->skinscenes[i].loop = true;
2261 loadmodel->skinscenes[i].framerate = 10;
2264 // load the bone info
2265 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2266 for (i = 0;i < loadmodel->num_bones;i++)
2268 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2269 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2270 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2271 if (loadmodel->data_bones[i].parent >= i)
2272 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2276 frames = (dpmframe_t *) (pbase + pheader->ofs_frames);
2277 // figure out scale of model from root bone, for compatibility with old dpmodel versions
2278 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2279 tempvec[0] = BigFloat(poses[0]);
2280 tempvec[1] = BigFloat(poses[1]);
2281 tempvec[2] = BigFloat(poses[2]);
2282 modelscale = VectorLength(tempvec);
2284 for (i = 0;i < loadmodel->numframes;i++)
2286 memcpy(loadmodel->animscenes[i].name, frames[i].name, sizeof(frames[i].name));
2287 loadmodel->animscenes[i].firstframe = i;
2288 loadmodel->animscenes[i].framecount = 1;
2289 loadmodel->animscenes[i].loop = true;
2290 loadmodel->animscenes[i].framerate = 10;
2291 // load the bone poses for this frame
2292 poses = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2293 for (j = 0;j < loadmodel->num_bones*12;j++)
2295 f = fabs(BigFloat(poses[j]));
2296 biggestorigin = max(biggestorigin, f);
2298 // stuff not processed here: mins, maxs, yawradius, allradius
2300 loadmodel->num_posescale = biggestorigin / 32767.0f;
2301 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2302 for (i = 0;i < loadmodel->numframes;i++)
2304 const float *frameposes = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2305 for (j = 0;j < loadmodel->num_bones;j++)
2308 matrix4x4_t posematrix;
2309 for (k = 0;k < 12;k++)
2310 pose[k] = BigFloat(frameposes[j*12+k]);
2311 // scale child bones to match the root scale
2312 if (loadmodel->data_bones[j].parent >= 0)
2314 pose[3] *= modelscale;
2315 pose[7] *= modelscale;
2316 pose[11] *= modelscale;
2318 // normalize rotation matrix
2319 VectorNormalize(pose + 0);
2320 VectorNormalize(pose + 4);
2321 VectorNormalize(pose + 8);
2322 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2323 Matrix4x4_ToBonePose7s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses7s + 7*(i*loadmodel->num_bones+j));
2327 // load the meshes now
2328 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2331 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2332 // (converting from weight-blending skeletal animation to
2333 // deformation-based skeletal animation)
2334 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2335 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2336 for (i = 0;i < loadmodel->num_bones;i++)
2339 for (k = 0;k < 12;k++)
2340 m[k] = BigFloat(poses[i*12+k]);
2341 if (loadmodel->data_bones[i].parent >= 0)
2342 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2344 for (k = 0;k < 12;k++)
2345 bonepose[12*i+k] = m[k];
2347 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2349 const int *inelements;
2351 const float *intexcoord;
2352 msurface_t *surface;
2354 loadmodel->sortedmodelsurfaces[i] = i;
2355 surface = loadmodel->data_surfaces + i;
2356 surface->texture = loadmodel->data_textures + i;
2357 surface->num_firsttriangle = meshtriangles;
2358 surface->num_triangles = BigLong(dpmmesh->num_tris);
2359 surface->num_firstvertex = meshvertices;
2360 surface->num_vertices = BigLong(dpmmesh->num_verts);
2361 meshvertices += surface->num_vertices;
2362 meshtriangles += surface->num_triangles;
2364 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2365 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2366 for (j = 0;j < surface->num_triangles;j++)
2368 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2369 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2370 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2371 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2376 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2377 for (j = 0;j < surface->num_vertices*2;j++)
2378 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2380 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2381 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2383 int weightindex[4] = { 0, 0, 0, 0 };
2384 float weightinfluence[4] = { 0, 0, 0, 0 };
2386 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2387 data += sizeof(dpmvertex_t);
2388 for (k = 0;k < numweights;k++)
2390 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2391 int boneindex = BigLong(vert->bonenum);
2392 const float *m = bonepose + 12 * boneindex;
2393 float influence = BigFloat(vert->influence);
2394 float relativeorigin[3], relativenormal[3];
2395 relativeorigin[0] = BigFloat(vert->origin[0]);
2396 relativeorigin[1] = BigFloat(vert->origin[1]);
2397 relativeorigin[2] = BigFloat(vert->origin[2]);
2398 relativenormal[0] = BigFloat(vert->normal[0]);
2399 relativenormal[1] = BigFloat(vert->normal[1]);
2400 relativenormal[2] = BigFloat(vert->normal[2]);
2401 // blend the vertex bone weights into the base mesh
2402 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2403 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2404 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2405 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2406 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2407 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2410 // store the first (and often only) weight
2411 weightinfluence[0] = influence;
2412 weightindex[0] = boneindex;
2416 // sort the new weight into this vertex's weight table
2417 // (which only accepts up to 4 bones per vertex)
2418 for (l = 0;l < 4;l++)
2420 if (weightinfluence[l] < influence)
2422 // move weaker influence weights out of the way first
2424 for (l2 = 3;l2 > l;l2--)
2426 weightinfluence[l2] = weightinfluence[l2-1];
2427 weightindex[l2] = weightindex[l2-1];
2429 // store the new weight
2430 weightinfluence[l] = influence;
2431 weightindex[l] = boneindex;
2436 data += sizeof(dpmbonevert_t);
2438 loadmodel->surfmesh.blends[j] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
2439 loadmodel->surfmesh.data_skeletalindex4ub[j*4 ] = weightindex[0];
2440 loadmodel->surfmesh.data_skeletalindex4ub[j*4+1] = weightindex[1];
2441 loadmodel->surfmesh.data_skeletalindex4ub[j*4+2] = weightindex[2];
2442 loadmodel->surfmesh.data_skeletalindex4ub[j*4+3] = weightindex[3];
2443 loadmodel->surfmesh.data_skeletalweight4ub[j*4 ] = (unsigned char)(weightinfluence[0]*255.0f);
2444 loadmodel->surfmesh.data_skeletalweight4ub[j*4+1] = (unsigned char)(weightinfluence[1]*255.0f);
2445 loadmodel->surfmesh.data_skeletalweight4ub[j*4+2] = (unsigned char)(weightinfluence[2]*255.0f);
2446 loadmodel->surfmesh.data_skeletalweight4ub[j*4+3] = (unsigned char)(weightinfluence[3]*255.0f);
2449 // since dpm models do not have named sections, reuse their shader name as the section name
2450 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2452 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2454 if (loadmodel->surfmesh.num_blends < meshvertices)
2455 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2457 Mod_FreeSkinFiles(skinfiles);
2458 Mod_MakeSortedSurfaces(loadmodel);
2460 // compute all the mesh information that was not loaded from the file
2461 if (loadmodel->surfmesh.data_element3s)
2462 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2463 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2464 Mod_BuildBaseBonePoses();
2465 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);
2466 if (loadmodel->surfmesh.data_neighbor3i)
2467 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2469 if (!loadmodel->surfmesh.isanimated)
2471 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2472 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2473 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2474 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2475 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2476 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2479 // because shaders can do somewhat unexpected things, check for unusual features now
2480 for (i = 0;i < loadmodel->num_textures;i++)
2482 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
2483 mod->DrawSky = R_Q1BSP_DrawSky;
2484 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
2485 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
2489 // no idea why PSK/PSA files contain weird quaternions but they do...
2490 #define PSKQUATNEGATIONS
2491 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2493 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2494 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2495 fs_offset_t filesize;
2500 pskboneinfo_t *bones;
2501 pskrawweights_t *rawweights;
2502 //pskboneinfo_t *animbones;
2503 pskaniminfo_t *anims;
2504 pskanimkeys_t *animkeys;
2505 void *animfilebuffer, *animbuffer, *animbufferend;
2506 unsigned char *data;
2508 skinfile_t *skinfiles;
2509 char animname[MAX_QPATH];
2511 float biggestorigin;
2513 pchunk = (pskchunk_t *)buffer;
2514 if (strcmp(pchunk->id, "ACTRHEAD"))
2515 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2517 loadmodel->modeldatatypestring = "PSK";
2519 loadmodel->type = mod_alias;
2520 loadmodel->DrawSky = NULL;
2521 loadmodel->DrawAddWaterPlanes = NULL;
2522 loadmodel->Draw = R_Q1BSP_Draw;
2523 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2524 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2525 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2526 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2527 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2528 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2529 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2530 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2531 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2532 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2533 loadmodel->PointSuperContents = NULL;
2534 loadmodel->synctype = ST_RAND;
2536 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2537 strlcat(animname, ".psa", sizeof(animname));
2538 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2539 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2541 animbufferend = animbuffer;
2560 while (buffer < bufferend)
2562 pchunk = (pskchunk_t *)buffer;
2563 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2564 version = LittleLong(pchunk->version);
2565 recordsize = LittleLong(pchunk->recordsize);
2566 numrecords = LittleLong(pchunk->numrecords);
2567 if (developer_extra.integer)
2568 Con_DPrintf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2569 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2570 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);
2571 if (!strcmp(pchunk->id, "ACTRHEAD"))
2575 else if (!strcmp(pchunk->id, "PNTS0000"))
2578 if (recordsize != sizeof(*p))
2579 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2580 // byteswap in place and keep the pointer
2581 numpnts = numrecords;
2582 pnts = (pskpnts_t *)buffer;
2583 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2585 p->origin[0] = LittleFloat(p->origin[0]);
2586 p->origin[1] = LittleFloat(p->origin[1]);
2587 p->origin[2] = LittleFloat(p->origin[2]);
2591 else if (!strcmp(pchunk->id, "VTXW0000"))
2594 if (recordsize != sizeof(*p))
2595 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2596 // byteswap in place and keep the pointer
2597 numvtxw = numrecords;
2598 vtxw = (pskvtxw_t *)buffer;
2599 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2601 p->pntsindex = LittleShort(p->pntsindex);
2602 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2603 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2604 if (p->pntsindex >= numpnts)
2606 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2612 else if (!strcmp(pchunk->id, "FACE0000"))
2615 if (recordsize != sizeof(*p))
2616 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2617 // byteswap in place and keep the pointer
2618 numfaces = numrecords;
2619 faces = (pskface_t *)buffer;
2620 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2622 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2623 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2624 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2625 p->group = LittleLong(p->group);
2626 if (p->vtxwindex[0] >= numvtxw)
2628 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2629 p->vtxwindex[0] = 0;
2631 if (p->vtxwindex[1] >= numvtxw)
2633 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2634 p->vtxwindex[1] = 0;
2636 if (p->vtxwindex[2] >= numvtxw)
2638 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2639 p->vtxwindex[2] = 0;
2644 else if (!strcmp(pchunk->id, "MATT0000"))
2647 if (recordsize != sizeof(*p))
2648 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2649 // byteswap in place and keep the pointer
2650 nummatts = numrecords;
2651 matts = (pskmatt_t *)buffer;
2652 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2658 else if (!strcmp(pchunk->id, "REFSKELT"))
2661 if (recordsize != sizeof(*p))
2662 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2663 // byteswap in place and keep the pointer
2664 numbones = numrecords;
2665 bones = (pskboneinfo_t *)buffer;
2666 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2668 p->numchildren = LittleLong(p->numchildren);
2669 p->parent = LittleLong(p->parent);
2670 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2671 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2672 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2673 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2674 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2675 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2676 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2677 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2678 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2679 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2680 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2681 #ifdef PSKQUATNEGATIONS
2684 p->basepose.quat[0] *= -1;
2685 p->basepose.quat[1] *= -1;
2686 p->basepose.quat[2] *= -1;
2690 p->basepose.quat[0] *= 1;
2691 p->basepose.quat[1] *= -1;
2692 p->basepose.quat[2] *= 1;
2695 if (p->parent < 0 || p->parent >= numbones)
2697 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2703 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2706 if (recordsize != sizeof(*p))
2707 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2708 // byteswap in place and keep the pointer
2709 numrawweights = numrecords;
2710 rawweights = (pskrawweights_t *)buffer;
2711 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2713 p->weight = LittleFloat(p->weight);
2714 p->pntsindex = LittleLong(p->pntsindex);
2715 p->boneindex = LittleLong(p->boneindex);
2716 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2718 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2721 if (p->boneindex < 0 || p->boneindex >= numbones)
2723 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2731 while (animbuffer < animbufferend)
2733 pchunk = (pskchunk_t *)animbuffer;
2734 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2735 version = LittleLong(pchunk->version);
2736 recordsize = LittleLong(pchunk->recordsize);
2737 numrecords = LittleLong(pchunk->numrecords);
2738 if (developer_extra.integer)
2739 Con_DPrintf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2740 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2741 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);
2742 if (!strcmp(pchunk->id, "ANIMHEAD"))
2746 else if (!strcmp(pchunk->id, "BONENAMES"))
2749 if (recordsize != sizeof(*p))
2750 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2751 // byteswap in place and keep the pointer
2752 numanimbones = numrecords;
2753 //animbones = (pskboneinfo_t *)animbuffer;
2754 // NOTE: supposedly psa does not need to match the psk model, the
2755 // bones missing from the psa would simply use their base
2756 // positions from the psk, but this is hard for me to implement
2757 // and people can easily make animations that match.
2758 if (numanimbones != numbones)
2759 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2760 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2762 p->numchildren = LittleLong(p->numchildren);
2763 p->parent = LittleLong(p->parent);
2764 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2765 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2766 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2767 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2768 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2769 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2770 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2771 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2772 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2773 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2774 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2775 #ifdef PSKQUATNEGATIONS
2778 p->basepose.quat[0] *= -1;
2779 p->basepose.quat[1] *= -1;
2780 p->basepose.quat[2] *= -1;
2784 p->basepose.quat[0] *= 1;
2785 p->basepose.quat[1] *= -1;
2786 p->basepose.quat[2] *= 1;
2789 if (p->parent < 0 || p->parent >= numanimbones)
2791 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2794 // check that bones are the same as in the base
2795 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2796 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2800 else if (!strcmp(pchunk->id, "ANIMINFO"))
2803 if (recordsize != sizeof(*p))
2804 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2805 // byteswap in place and keep the pointer
2806 numanims = numrecords;
2807 anims = (pskaniminfo_t *)animbuffer;
2808 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2810 p->numbones = LittleLong(p->numbones);
2811 p->playtime = LittleFloat(p->playtime);
2812 p->fps = LittleFloat(p->fps);
2813 p->firstframe = LittleLong(p->firstframe);
2814 p->numframes = LittleLong(p->numframes);
2815 if (p->numbones != numbones)
2816 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2820 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2823 if (recordsize != sizeof(*p))
2824 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2825 numanimkeys = numrecords;
2826 animkeys = (pskanimkeys_t *)animbuffer;
2827 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2829 p->origin[0] = LittleFloat(p->origin[0]);
2830 p->origin[1] = LittleFloat(p->origin[1]);
2831 p->origin[2] = LittleFloat(p->origin[2]);
2832 p->quat[0] = LittleFloat(p->quat[0]);
2833 p->quat[1] = LittleFloat(p->quat[1]);
2834 p->quat[2] = LittleFloat(p->quat[2]);
2835 p->quat[3] = LittleFloat(p->quat[3]);
2836 p->frametime = LittleFloat(p->frametime);
2837 #ifdef PSKQUATNEGATIONS
2838 if (index % numbones)
2853 // TODO: allocate bonepose stuff
2856 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2859 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights)
2860 Host_Error("%s: missing required chunks", loadmodel->name);
2864 loadmodel->numframes = 0;
2865 for (index = 0;index < numanims;index++)
2866 loadmodel->numframes += anims[index].numframes;
2867 if (numanimkeys != numbones * loadmodel->numframes)
2868 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2871 loadmodel->numframes = loadmodel->num_poses = 1;
2873 meshvertices = numvtxw;
2874 meshtriangles = numfaces;
2876 // load external .skin files if present
2877 skinfiles = Mod_LoadSkinFiles();
2878 if (loadmodel->numskins < 1)
2879 loadmodel->numskins = 1;
2880 loadmodel->num_bones = numbones;
2881 loadmodel->num_poses = loadmodel->numframes;
2882 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2883 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2884 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2885 loadmodel->surfmesh.num_vertices = meshvertices;
2886 loadmodel->surfmesh.num_triangles = meshtriangles;
2887 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
2888 if(mod_alias_force_animated.string[0])
2889 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
2890 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
2891 // do most allocations as one merged chunk
2892 size = loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + loadmodel->surfmesh.num_triangles * sizeof(int[3]) + (r_enableshadowvolumes.integer ? loadmodel->surfmesh.num_triangles * sizeof(int[3]) : 0) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[2]) + loadmodel->surfmesh.num_vertices * sizeof(unsigned char[4]) + loadmodel->surfmesh.num_vertices * sizeof(unsigned char[4]) + loadmodel->surfmesh.num_vertices * sizeof(unsigned short) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t) + ((loadmodel->surfmesh.num_vertices <= 65536) ? (loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3])) : 0);
2893 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2894 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2895 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2896 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2897 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2898 if (r_enableshadowvolumes.integer)
2900 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2902 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2903 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2904 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2905 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2906 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2907 loadmodel->surfmesh.data_skeletalindex4ub = (unsigned char *)data;data += loadmodel->surfmesh.num_vertices * sizeof(unsigned char[4]);
2908 loadmodel->surfmesh.data_skeletalweight4ub = (unsigned char *)data;data += loadmodel->surfmesh.num_vertices * sizeof(unsigned char[4]);
2909 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2910 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2911 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2912 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2913 loadmodel->surfmesh.num_blends = 0;
2914 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2915 if (loadmodel->surfmesh.num_vertices <= 65536)
2917 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2919 loadmodel->data_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
2920 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(blendweights_t));
2922 for (i = 0;i < loadmodel->numskins;i++)
2924 loadmodel->skinscenes[i].firstframe = i;
2925 loadmodel->skinscenes[i].framecount = 1;
2926 loadmodel->skinscenes[i].loop = true;
2927 loadmodel->skinscenes[i].framerate = 10;
2931 for (index = 0, i = 0;index < nummatts;index++)
2933 // since psk models do not have named sections, reuse their shader name as the section name
2934 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2935 loadmodel->sortedmodelsurfaces[index] = index;
2936 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2937 loadmodel->data_surfaces[index].num_firstvertex = 0;
2938 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2941 // copy over the vertex locations and texcoords
2942 for (index = 0;index < numvtxw;index++)
2944 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2945 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2946 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2947 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2948 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2951 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2952 for (index = 0;index < numfaces;index++)
2953 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2954 for (index = 0, i = 0;index < nummatts;index++)
2956 loadmodel->data_surfaces[index].num_firsttriangle = i;
2957 i += loadmodel->data_surfaces[index].num_triangles;
2958 loadmodel->data_surfaces[index].num_triangles = 0;
2960 for (index = 0;index < numfaces;index++)
2962 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2963 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2964 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2965 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2968 // copy over the bones
2969 for (index = 0;index < numbones;index++)
2971 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2972 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2973 if (loadmodel->data_bones[index].parent >= index)
2974 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2977 // convert the basepose data
2978 if (loadmodel->num_bones)
2981 matrix4x4_t *basebonepose;
2982 float *outinvmatrix = loadmodel->data_baseboneposeinverse;
2983 matrix4x4_t bonematrix;
2984 matrix4x4_t tempbonematrix;
2985 basebonepose = (matrix4x4_t *)Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(matrix4x4_t));
2986 for (boneindex = 0;boneindex < loadmodel->num_bones;boneindex++)
2988 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]);
2989 if (loadmodel->data_bones[boneindex].parent >= 0)
2991 tempbonematrix = bonematrix;
2992 Matrix4x4_Concat(&bonematrix, basebonepose + loadmodel->data_bones[boneindex].parent, &tempbonematrix);
2994 basebonepose[boneindex] = bonematrix;
2995 Matrix4x4_Invert_Simple(&tempbonematrix, basebonepose + boneindex);
2996 Matrix4x4_ToArray12FloatD3D(&tempbonematrix, outinvmatrix + 12*boneindex);
2998 Mem_Free(basebonepose);
3001 // sort the psk point weights into the vertex weight tables
3002 // (which only accept up to 4 bones per vertex)
3003 for (index = 0;index < numvtxw;index++)
3005 int weightindex[4] = { 0, 0, 0, 0 };
3006 float weightinfluence[4] = { 0, 0, 0, 0 };
3008 for (j = 0;j < numrawweights;j++)
3010 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
3012 int boneindex = rawweights[j].boneindex;
3013 float influence = rawweights[j].weight;
3014 for (l = 0;l < 4;l++)
3016 if (weightinfluence[l] < influence)
3018 // move lower influence weights out of the way first
3020 for (l2 = 3;l2 > l;l2--)
3022 weightinfluence[l2] = weightinfluence[l2-1];
3023 weightindex[l2] = weightindex[l2-1];
3025 // store the new weight
3026 weightinfluence[l] = influence;
3027 weightindex[l] = boneindex;
3033 loadmodel->surfmesh.blends[index] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
3034 loadmodel->surfmesh.data_skeletalindex4ub[index*4 ] = weightindex[0];
3035 loadmodel->surfmesh.data_skeletalindex4ub[index*4+1] = weightindex[1];
3036 loadmodel->surfmesh.data_skeletalindex4ub[index*4+2] = weightindex[2];
3037 loadmodel->surfmesh.data_skeletalindex4ub[index*4+3] = weightindex[3];
3038 loadmodel->surfmesh.data_skeletalweight4ub[index*4 ] = (unsigned char)(weightinfluence[0]*255.0f);
3039 loadmodel->surfmesh.data_skeletalweight4ub[index*4+1] = (unsigned char)(weightinfluence[1]*255.0f);
3040 loadmodel->surfmesh.data_skeletalweight4ub[index*4+2] = (unsigned char)(weightinfluence[2]*255.0f);
3041 loadmodel->surfmesh.data_skeletalweight4ub[index*4+3] = (unsigned char)(weightinfluence[3]*255.0f);
3043 if (loadmodel->surfmesh.num_blends < loadmodel->surfmesh.num_vertices)
3044 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
3046 // set up the animscenes based on the anims
3049 for (index = 0, i = 0;index < numanims;index++)
3051 for (j = 0;j < anims[index].numframes;j++, i++)
3053 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
3054 loadmodel->animscenes[i].firstframe = i;
3055 loadmodel->animscenes[i].framecount = 1;
3056 loadmodel->animscenes[i].loop = true;
3057 loadmodel->animscenes[i].framerate = anims[index].fps;
3060 // calculate the scaling value for bone origins so they can be compressed to short
3062 for (index = 0;index < numanimkeys;index++)
3064 pskanimkeys_t *k = animkeys + index;
3065 biggestorigin = max(biggestorigin, fabs(k->origin[0]));
3066 biggestorigin = max(biggestorigin, fabs(k->origin[1]));
3067 biggestorigin = max(biggestorigin, fabs(k->origin[2]));
3069 loadmodel->num_posescale = biggestorigin / 32767.0f;
3070 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3072 // load the poses from the animkeys
3073 for (index = 0;index < numanimkeys;index++)
3075 pskanimkeys_t *k = animkeys + index;
3077 Vector4Copy(k->quat, quat);
3079 Vector4Negate(quat, quat);
3080 Vector4Normalize2(quat, quat);
3081 // compress poses to the short[7] format for longterm storage
3082 loadmodel->data_poses7s[index*7+0] = k->origin[0] * loadmodel->num_poseinvscale;
3083 loadmodel->data_poses7s[index*7+1] = k->origin[1] * loadmodel->num_poseinvscale;
3084 loadmodel->data_poses7s[index*7+2] = k->origin[2] * loadmodel->num_poseinvscale;
3085 loadmodel->data_poses7s[index*7+3] = quat[0] * 32767.0f;
3086 loadmodel->data_poses7s[index*7+4] = quat[1] * 32767.0f;
3087 loadmodel->data_poses7s[index*7+5] = quat[2] * 32767.0f;
3088 loadmodel->data_poses7s[index*7+6] = quat[3] * 32767.0f;
3093 strlcpy(loadmodel->animscenes[0].name, "base", sizeof(loadmodel->animscenes[0].name));
3094 loadmodel->animscenes[0].firstframe = 0;
3095 loadmodel->animscenes[0].framecount = 1;
3096 loadmodel->animscenes[0].loop = true;
3097 loadmodel->animscenes[0].framerate = 10;
3099 // calculate the scaling value for bone origins so they can be compressed to short
3101 for (index = 0;index < numbones;index++)
3103 pskboneinfo_t *p = bones + index;
3104 biggestorigin = max(biggestorigin, fabs(p->basepose.origin[0]));
3105 biggestorigin = max(biggestorigin, fabs(p->basepose.origin[1]));
3106 biggestorigin = max(biggestorigin, fabs(p->basepose.origin[2]));
3108 loadmodel->num_posescale = biggestorigin / 32767.0f;
3109 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3111 // load the basepose as a frame
3112 for (index = 0;index < numbones;index++)
3114 pskboneinfo_t *p = bones + index;
3116 Vector4Copy(p->basepose.quat, quat);
3118 Vector4Negate(quat, quat);
3119 Vector4Normalize2(quat, quat);
3120 // compress poses to the short[7] format for longterm storage
3121 loadmodel->data_poses7s[index*7+0] = p->basepose.origin[0] * loadmodel->num_poseinvscale;
3122 loadmodel->data_poses7s[index*7+1] = p->basepose.origin[1] * loadmodel->num_poseinvscale;
3123 loadmodel->data_poses7s[index*7+2] = p->basepose.origin[2] * loadmodel->num_poseinvscale;
3124 loadmodel->data_poses7s[index*7+3] = quat[0] * 32767.0f;
3125 loadmodel->data_poses7s[index*7+4] = quat[1] * 32767.0f;
3126 loadmodel->data_poses7s[index*7+5] = quat[2] * 32767.0f;
3127 loadmodel->data_poses7s[index*7+6] = quat[3] * 32767.0f;
3131 Mod_FreeSkinFiles(skinfiles);
3133 Mem_Free(animfilebuffer);
3134 Mod_MakeSortedSurfaces(loadmodel);
3136 // compute all the mesh information that was not loaded from the file
3137 // TODO: honor smoothing groups somehow?
3138 if (loadmodel->surfmesh.data_element3s)
3139 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3140 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3141 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
3142 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);
3143 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);
3144 if (loadmodel->surfmesh.data_neighbor3i)
3145 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3146 Mod_Alias_CalculateBoundingBox();
3148 if (!loadmodel->surfmesh.isanimated)
3150 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3151 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3152 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3153 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3154 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3155 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
3158 // because shaders can do somewhat unexpected things, check for unusual features now
3159 for (i = 0;i < loadmodel->num_textures;i++)
3161 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
3162 mod->DrawSky = R_Q1BSP_DrawSky;
3163 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
3164 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
3168 void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
3170 unsigned char *data;
3172 const unsigned char *pbase, *pend;
3174 skinfile_t *skinfiles;
3175 int i, j, k, meshvertices, meshtriangles;
3176 float biggestorigin;
3177 const unsigned int *inelements;
3179 const int *inneighbors;
3181 float *outvertex, *outnormal, *outtexcoord, *outsvector, *outtvector, *outcolor;
3182 // this pointers into the file data are read only through Little* functions so they can be unaligned memory
3183 const float *vnormal = NULL;
3184 const float *vposition = NULL;
3185 const float *vtangent = NULL;
3186 const float *vtexcoord = NULL;
3187 const float *vcolor4f = NULL;
3188 const unsigned char *vblendindexes = NULL;
3189 const unsigned char *vblendweights = NULL;
3190 const unsigned char *vcolor4ub = NULL;
3191 const unsigned short *framedata = NULL;
3192 // temporary memory allocations (because the data in the file may be misaligned)
3193 iqmanim_t *anims = NULL;
3194 iqmbounds_t *bounds = NULL;
3195 iqmjoint1_t *joint1 = NULL;
3196 iqmjoint_t *joint = NULL;
3197 iqmmesh_t *meshes = NULL;
3198 iqmpose1_t *pose1 = NULL;
3199 iqmpose_t *pose = NULL;
3200 iqmvertexarray_t *vas = NULL;
3202 pbase = (unsigned char *)buffer;
3203 pend = (unsigned char *)bufferend;
3205 if (pbase + sizeof(iqmheader_t) > pend)
3206 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model %d", loadmodel->name, (int)(pend - pbase));
3208 // copy struct (otherwise it may be misaligned)
3209 // LordHavoc: okay it's definitely not misaligned here, but for consistency...
3210 memcpy(&header, pbase, sizeof(iqmheader_t));
3212 if (memcmp(header.id, "INTERQUAKEMODEL", 16))
3213 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model", loadmodel->name);
3214 if (LittleLong(header.version) != 1 && LittleLong(header.version) != 2)
3215 Host_Error ("Mod_INTERQUAKEMODEL_Load: only version 1 and 2 models are currently supported (name = %s)", loadmodel->name);
3217 loadmodel->modeldatatypestring = "IQM";
3219 loadmodel->type = mod_alias;
3220 loadmodel->synctype = ST_RAND;
3223 header.version = LittleLong(header.version);
3224 header.filesize = LittleLong(header.filesize);
3225 header.flags = LittleLong(header.flags);
3226 header.num_text = LittleLong(header.num_text);
3227 header.ofs_text = LittleLong(header.ofs_text);
3228 header.num_meshes = LittleLong(header.num_meshes);
3229 header.ofs_meshes = LittleLong(header.ofs_meshes);
3230 header.num_vertexarrays = LittleLong(header.num_vertexarrays);
3231 header.num_vertexes = LittleLong(header.num_vertexes);
3232 header.ofs_vertexarrays = LittleLong(header.ofs_vertexarrays);
3233 header.num_triangles = LittleLong(header.num_triangles);
3234 header.ofs_triangles = LittleLong(header.ofs_triangles);
3235 header.ofs_neighbors = LittleLong(header.ofs_neighbors);
3236 header.num_joints = LittleLong(header.num_joints);
3237 header.ofs_joints = LittleLong(header.ofs_joints);
3238 header.num_poses = LittleLong(header.num_poses);
3239 header.ofs_poses = LittleLong(header.ofs_poses);
3240 header.num_anims = LittleLong(header.num_anims);
3241 header.ofs_anims = LittleLong(header.ofs_anims);
3242 header.num_frames = LittleLong(header.num_frames);
3243 header.num_framechannels = LittleLong(header.num_framechannels);
3244 header.ofs_frames = LittleLong(header.ofs_frames);
3245 header.ofs_bounds = LittleLong(header.ofs_bounds);
3246 header.num_comment = LittleLong(header.num_comment);
3247 header.ofs_comment = LittleLong(header.ofs_comment);
3248 header.num_extensions = LittleLong(header.num_extensions);
3249 header.ofs_extensions = LittleLong(header.ofs_extensions);
3251 if (header.version == 1)
3253 if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint1_t) > pend ||
3254 pbase + header.ofs_poses + header.num_poses*sizeof(iqmpose1_t) > pend)
3256 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3262 if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint_t) > pend ||
3263 pbase + header.ofs_poses + header.num_poses*sizeof(iqmpose_t) > pend)
3265 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3269 if (pbase + header.ofs_text + header.num_text > pend ||
3270 pbase + header.ofs_meshes + header.num_meshes*sizeof(iqmmesh_t) > pend ||
3271 pbase + header.ofs_vertexarrays + header.num_vertexarrays*sizeof(iqmvertexarray_t) > pend ||
3272 pbase + header.ofs_triangles + header.num_triangles*sizeof(int[3]) > pend ||
3273 (header.ofs_neighbors && pbase + header.ofs_neighbors + header.num_triangles*sizeof(int[3]) > pend) ||
3274 pbase + header.ofs_anims + header.num_anims*sizeof(iqmanim_t) > pend ||
3275 pbase + header.ofs_frames + header.num_frames*header.num_framechannels*sizeof(unsigned short) > pend ||
3276 (header.ofs_bounds && pbase + header.ofs_bounds + header.num_frames*sizeof(iqmbounds_t) > pend) ||
3277 pbase + header.ofs_comment + header.num_comment > pend)
3279 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3283 // copy structs to make them aligned in memory (otherwise we crash on Sparc and PowerPC and others)
3284 if (header.num_vertexarrays)
3285 vas = (iqmvertexarray_t *)(pbase + header.ofs_vertexarrays);
3286 if (header.num_anims)
3287 anims = (iqmanim_t *)(pbase + header.ofs_anims);
3288 if (header.ofs_bounds)
3289 bounds = (iqmbounds_t *)(pbase + header.ofs_bounds);
3290 if (header.num_meshes)
3291 meshes = (iqmmesh_t *)(pbase + header.ofs_meshes);
3293 for (i = 0;i < (int)header.num_vertexarrays;i++)
3295 iqmvertexarray_t va;
3297 va.type = LittleLong(vas[i].type);
3298 va.flags = LittleLong(vas[i].flags);
3299 va.format = LittleLong(vas[i].format);
3300 va.size = LittleLong(vas[i].size);
3301 va.offset = LittleLong(vas[i].offset);
3302 vsize = header.num_vertexes*va.size;
3305 case IQM_FLOAT: vsize *= sizeof(float); break;
3306 case IQM_UBYTE: vsize *= sizeof(unsigned char); break;
3309 if (pbase + va.offset + vsize > pend)
3311 // no need to copy the vertex data for alignment because LittleLong/LittleShort will be invoked on reading them, and the destination is aligned
3315 if (va.format == IQM_FLOAT && va.size == 3)
3316 vposition = (const float *)(pbase + va.offset);
3319 if (va.format == IQM_FLOAT && va.size == 2)
3320 vtexcoord = (const float *)(pbase + va.offset);
3323 if (va.format == IQM_FLOAT && va.size == 3)
3324 vnormal = (const float *)(pbase + va.offset);
3327 if (va.format == IQM_FLOAT && va.size == 4)
3328 vtangent = (const float *)(pbase + va.offset);
3330 case IQM_BLENDINDEXES:
3331 if (va.format == IQM_UBYTE && va.size == 4)
3332 vblendindexes = (const unsigned char *)(pbase + va.offset);
3334 case IQM_BLENDWEIGHTS:
3335 if (va.format == IQM_UBYTE && va.size == 4)
3336 vblendweights = (const unsigned char *)(pbase + va.offset);
3339 if (va.format == IQM_FLOAT && va.size == 4)
3340 vcolor4f = (const float *)(pbase + va.offset);
3341 if (va.format == IQM_UBYTE && va.size == 4)
3342 vcolor4ub = (const unsigned char *)(pbase + va.offset);
3346 if (header.num_vertexes > 0 && (!vposition || !vtexcoord || ((header.num_frames > 0 || header.num_anims > 0) && (!vblendindexes || !vblendweights))))
3348 Con_Printf("%s is missing vertex array data\n", loadmodel->name);
3352 text = header.num_text && header.ofs_text ? (const char *)(pbase + header.ofs_text) : "";
3354 loadmodel->DrawSky = NULL;
3355 loadmodel->DrawAddWaterPlanes = NULL;
3356 loadmodel->Draw = R_Q1BSP_Draw;
3357 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
3358 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
3359 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
3360 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
3361 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
3362 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
3363 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
3364 loadmodel->DrawLight = R_Q1BSP_DrawLight;
3365 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
3366 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
3367 loadmodel->PointSuperContents = NULL;
3369 // load external .skin files if present
3370 skinfiles = Mod_LoadSkinFiles();
3371 if (loadmodel->numskins < 1)
3372 loadmodel->numskins = 1;
3374 loadmodel->numframes = max(header.num_anims, 1);
3375 loadmodel->num_bones = header.num_joints;
3376 loadmodel->num_poses = max(header.num_frames, 1);
3377 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = header.num_meshes;
3378 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3379 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3380 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices; // updated later
3382 meshvertices = header.num_vertexes;
3383 meshtriangles = header.num_triangles;
3385 // do most allocations as one merged chunk
3386 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + (r_enableshadowvolumes.integer ? meshtriangles * sizeof(int[3]) : 0) + meshvertices * (sizeof(float[14]) + (vcolor4f || vcolor4ub ? sizeof(float[4]) : 0)) + (vblendindexes && vblendweights ? meshvertices * (sizeof(unsigned short) + sizeof(unsigned char[2][4])) : 0) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
3387 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
3388 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
3389 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
3390 loadmodel->surfmesh.num_vertices = meshvertices;
3391 loadmodel->surfmesh.num_triangles = meshtriangles;
3392 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3393 if (r_enableshadowvolumes.integer)
3395 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3397 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
3398 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3399 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3400 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
3401 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
3402 if (vcolor4f || vcolor4ub)
3404 loadmodel->surfmesh.data_lightmapcolor4f = (float *)data;data += meshvertices * sizeof(float[4]);
3406 if (vblendindexes && vblendweights)
3408 loadmodel->surfmesh.data_skeletalindex4ub = (unsigned char *)data;data += meshvertices * sizeof(unsigned char[4]);
3409 loadmodel->surfmesh.data_skeletalweight4ub = (unsigned char *)data;data += meshvertices * sizeof(unsigned char[4]);
3411 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
3412 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
3413 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
3414 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
3415 if (vblendindexes && vblendweights)
3417 loadmodel->surfmesh.num_blends = 0;
3418 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
3420 if (meshvertices <= 65536)
3422 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
3424 loadmodel->data_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
3425 if (vblendindexes && vblendweights)
3426 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
3428 for (i = 0;i < loadmodel->numskins;i++)
3430 loadmodel->skinscenes[i].firstframe = i;
3431 loadmodel->skinscenes[i].framecount = 1;
3432 loadmodel->skinscenes[i].loop = true;
3433 loadmodel->skinscenes[i].framerate = 10;
3436 // load the bone info
3437 if (header.version == 1)
3439 iqmjoint1_t *injoint1 = (iqmjoint1_t *)(pbase + header.ofs_joints);
3440 if (loadmodel->num_bones)
3441 joint1 = (iqmjoint1_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(iqmjoint1_t));
3442 for (i = 0;i < loadmodel->num_bones;i++)
3444 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3445 joint1[i].name = LittleLong(injoint1[i].name);
3446 joint1[i].parent = LittleLong(injoint1[i].parent);
3447 for (j = 0;j < 3;j++)
3449 joint1[i].origin[j] = LittleFloat(injoint1[i].origin[j]);
3450 joint1[i].rotation[j] = LittleFloat(injoint1[i].rotation[j]);
3451 joint1[i].scale[j] = LittleFloat(injoint1[i].scale[j]);
3453 strlcpy(loadmodel->data_bones[i].name, &text[joint1[i].name], sizeof(loadmodel->data_bones[i].name));
3454 loadmodel->data_bones[i].parent = joint1[i].parent;
3455 if (loadmodel->data_bones[i].parent >= i)
3456 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3457 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]);
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);
3470 iqmjoint_t *injoint = (iqmjoint_t *)(pbase + header.ofs_joints);
3471 if (header.num_joints)
3472 joint = (iqmjoint_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(iqmjoint_t));
3473 for (i = 0;i < loadmodel->num_bones;i++)
3475 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3476 joint[i].name = LittleLong(injoint[i].name);
3477 joint[i].parent = LittleLong(injoint[i].parent);
3478 for (j = 0;j < 3;j++)
3480 joint[i].origin[j] = LittleFloat(injoint[i].origin[j]);
3481 joint[i].rotation[j] = LittleFloat(injoint[i].rotation[j]);
3482 joint[i].scale[j] = LittleFloat(injoint[i].scale[j]);
3484 joint[i].rotation[3] = LittleFloat(injoint[i].rotation[3]);
3485 strlcpy(loadmodel->data_bones[i].name, &text[joint[i].name], sizeof(loadmodel->data_bones[i].name));
3486 loadmodel->data_bones[i].parent = joint[i].parent;
3487 if (loadmodel->data_bones[i].parent >= i)
3488 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3489 if (joint[i].rotation[3] > 0)
3490 Vector4Negate(joint[i].rotation, joint[i].rotation);
3491 Vector4Normalize2(joint[i].rotation, joint[i].rotation);
3492 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]);
3493 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3494 if (loadmodel->data_bones[i].parent >= 0)
3496 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3497 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3498 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3500 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3504 // set up the animscenes based on the anims
3505 for (i = 0;i < (int)header.num_anims;i++)
3508 anim.name = LittleLong(anims[i].name);
3509 anim.first_frame = LittleLong(anims[i].first_frame);
3510 anim.num_frames = LittleLong(anims[i].num_frames);
3511 anim.framerate = LittleFloat(anims[i].framerate);
3512 anim.flags = LittleLong(anims[i].flags);
3513 strlcpy(loadmodel->animscenes[i].name, &text[anim.name], sizeof(loadmodel->animscenes[i].name));
3514 loadmodel->animscenes[i].firstframe = anim.first_frame;
3515 loadmodel->animscenes[i].framecount = anim.num_frames;
3516 loadmodel->animscenes[i].loop = ((anim.flags & IQM_LOOP) != 0);
3517 loadmodel->animscenes[i].framerate = anim.framerate;
3519 if (header.num_anims <= 0)
3521 strlcpy(loadmodel->animscenes[0].name, "static", sizeof(loadmodel->animscenes[0].name));
3522 loadmodel->animscenes[0].firstframe = 0;
3523 loadmodel->animscenes[0].framecount = 1;
3524 loadmodel->animscenes[0].loop = true;
3525 loadmodel->animscenes[0].framerate = 10;
3528 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
3529 if(mod_alias_force_animated.string[0])
3530 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
3531 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
3534 if (header.version == 1)
3536 iqmpose1_t *inpose1 = (iqmpose1_t *)(pbase + header.ofs_poses);
3537 if (header.num_poses)
3538 pose1 = (iqmpose1_t *)Mem_Alloc(loadmodel->mempool, header.num_poses * sizeof(iqmpose1_t));
3539 for (i = 0;i < (int)header.num_poses;i++)
3542 pose1[i].parent = LittleLong(inpose1[i].parent);
3543 pose1[i].channelmask = LittleLong(inpose1[i].channelmask);
3544 for (j = 0;j < 9;j++)
3546 pose1[i].channeloffset[j] = LittleFloat(inpose1[i].channeloffset[j]);
3547 pose1[i].channelscale[j] = LittleFloat(inpose1[i].channelscale[j]);
3549 f = fabs(pose1[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3550 f = fabs(pose1[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3551 f = fabs(pose1[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3552 f = fabs(pose1[i].channeloffset[0] + 0xFFFF*pose1[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3553 f = fabs(pose1[i].channeloffset[1] + 0xFFFF*pose1[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3554 f = fabs(pose1[i].channeloffset[2] + 0xFFFF*pose1[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3556 if (header.num_frames <= 0)
3558 for (i = 0;i < loadmodel->num_bones;i++)
3561 f = fabs(joint1[i].origin[0]); biggestorigin = max(biggestorigin, f);
3562 f = fabs(joint1[i].origin[1]); biggestorigin = max(biggestorigin, f);
3563 f = fabs(joint1[i].origin[2]); biggestorigin = max(biggestorigin, f);
3569 iqmpose_t *inpose = (iqmpose_t *)(pbase + header.ofs_poses);
3570 if (header.num_poses)
3571 pose = (iqmpose_t *)Mem_Alloc(loadmodel->mempool, header.num_poses * sizeof(iqmpose_t));
3572 for (i = 0;i < (int)header.num_poses;i++)
3575 pose[i].parent = LittleLong(inpose[i].parent);
3576 pose[i].channelmask = LittleLong(inpose[i].channelmask);
3577 for (j = 0;j < 10;j++)
3579 pose[i].channeloffset[j] = LittleFloat(inpose[i].channeloffset[j]);
3580 pose[i].channelscale[j] = LittleFloat(inpose[i].channelscale[j]);
3582 f = fabs(pose[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3583 f = fabs(pose[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3584 f = fabs(pose[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3585 f = fabs(pose[i].channeloffset[0] + 0xFFFF*pose[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3586 f = fabs(pose[i].channeloffset[1] + 0xFFFF*pose[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3587 f = fabs(pose[i].channeloffset[2] + 0xFFFF*pose[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3589 if (header.num_frames <= 0)
3591 for (i = 0;i < loadmodel->num_bones;i++)
3594 f = fabs(joint[i].origin[0]); biggestorigin = max(biggestorigin, f);
3595 f = fabs(joint[i].origin[1]); biggestorigin = max(biggestorigin, f);
3596 f = fabs(joint[i].origin[2]); biggestorigin = max(biggestorigin, f);
3600 loadmodel->num_posescale = biggestorigin / 32767.0f;
3601 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3603 // load the pose data
3604 // this unaligned memory access is safe (LittleShort reads as bytes)
3605 framedata = (const unsigned short *)(pbase + header.ofs_frames);
3606 if (header.version == 1)
3608 for (i = 0, k = 0;i < (int)header.num_frames;i++)
3610 for (j = 0;j < (int)header.num_poses;j++, k++)
3612 float qx, qy, qz, qw;
3613 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));
3614 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));
3615 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));
3616 qx = pose1[j].channeloffset[3] + (pose1[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[3] : 0);
3617 qy = pose1[j].channeloffset[4] + (pose1[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[4] : 0);
3618 qz = pose1[j].channeloffset[5] + (pose1[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[5] : 0);
3619 qw = 1.0f - (qx*qx + qy*qy + qz*qz);
3620 qw = qw > 0.0f ? -sqrt(qw) : 0.0f;
3621 loadmodel->data_poses7s[k*7 + 3] = 32767.0f * qx;
3622 loadmodel->data_poses7s[k*7 + 4] = 32767.0f * qy;
3623 loadmodel->data_poses7s[k*7 + 5] = 32767.0f * qz;
3624 loadmodel->data_poses7s[k*7 + 6] = 32767.0f * qw;
3625 // skip scale data for now
3626 if(pose1[j].channelmask&64) framedata++;
3627 if(pose1[j].channelmask&128) framedata++;
3628 if(pose1[j].channelmask&256) framedata++;
3631 if (header.num_frames <= 0)
3633 for (i = 0;i < loadmodel->num_bones;i++)
3635 float qx, qy, qz, qw;
3636 loadmodel->data_poses7s[i*7 + 0] = loadmodel->num_poseinvscale * joint1[i].origin[0];
3637 loadmodel->data_poses7s[i*7 + 1] = loadmodel->num_poseinvscale * joint1[i].origin[1];
3638 loadmodel->data_poses7s[i*7 + 2] = loadmodel->num_poseinvscale * joint1[i].origin[2];
3639 qx = joint1[i].rotation[0];
3640 qy = joint1[i].rotation[1];
3641 qz = joint1[i].rotation[2];
3642 qw = 1.0f - (qx*qx + qy*qy + qz*qz);
3643 qw = qw > 0.0f ? -sqrt(qw) : 0.0f;
3644 loadmodel->data_poses7s[i*7 + 3] = 32767.0f * qx;
3645 loadmodel->data_poses7s[i*7 + 4] = 32767.0f * qy;
3646 loadmodel->data_poses7s[i*7 + 5] = 32767.0f * qz;
3647 loadmodel->data_poses7s[i*7 + 6] = 32767.0f * qw;
3653 for (i = 0, k = 0;i < (int)header.num_frames;i++)
3655 for (j = 0;j < (int)header.num_poses;j++, k++)
3658 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));
3659 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));
3660 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));
3661 rot[0] = pose[j].channeloffset[3] + (pose[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[3] : 0);
3662 rot[1] = pose[j].channeloffset[4] + (pose[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[4] : 0);
3663 rot[2] = pose[j].channeloffset[5] + (pose[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[5] : 0);
3664 rot[3] = pose[j].channeloffset[6] + (pose[j].channelmask&64 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[6] : 0);
3666 Vector4Negate(rot, rot);
3667 Vector4Normalize2(rot, rot);
3668 loadmodel->data_poses7s[k*7 + 3] = 32767.0f * rot[0];
3669 loadmodel->data_poses7s[k*7 + 4] = 32767.0f * rot[1];
3670 loadmodel->data_poses7s[k*7 + 5] = 32767.0f * rot[2];
3671 loadmodel->data_poses7s[k*7 + 6] = 32767.0f * rot[3];
3672 // skip scale data for now
3673 if(pose[j].channelmask&128) framedata++;
3674 if(pose[j].channelmask&256) framedata++;
3675 if(pose[j].channelmask&512) framedata++;
3678 if (header.num_frames <= 0)
3680 for (i = 0;i < loadmodel->num_bones;i++)
3682 loadmodel->data_poses7s[i*7 + 0] = loadmodel->num_poseinvscale * joint[i].origin[0];
3683 loadmodel->data_poses7s[i*7 + 1] = loadmodel->num_poseinvscale * joint[i].origin[1];
3684 loadmodel->data_poses7s[i*7 + 2] = loadmodel->num_poseinvscale * joint[i].origin[2];
3685 loadmodel->data_poses7s[i*7 + 3] = 32767.0f * joint[i].rotation[0];
3686 loadmodel->data_poses7s[i*7 + 4] = 32767.0f * joint[i].rotation[1];
3687 loadmodel->data_poses7s[i*7 + 5] = 32767.0f * joint[i].rotation[2];
3688 loadmodel->data_poses7s[i*7 + 6] = 32767.0f * joint[i].rotation[3];
3693 // load bounding box data
3694 if (header.ofs_bounds)
3696 float xyradius = 0, radius = 0;
3697 VectorClear(loadmodel->normalmins);
3698 VectorClear(loadmodel->normalmaxs);
3699 for (i = 0; i < (int)header.num_frames;i++)
3702 bound.mins[0] = LittleFloat(bounds[i].mins[0]);
3703 bound.mins[1] = LittleFloat(bounds[i].mins[1]);
3704 bound.mins[2] = LittleFloat(bounds[i].mins[2]);
3705 bound.maxs[0] = LittleFloat(bounds[i].maxs[0]);
3706 bound.maxs[1] = LittleFloat(bounds[i].maxs[1]);
3707 bound.maxs[2] = LittleFloat(bounds[i].maxs[2]);
3708 bound.xyradius = LittleFloat(bounds[i].xyradius);
3709 bound.radius = LittleFloat(bounds[i].radius);
3712 VectorCopy(bound.mins, loadmodel->normalmins);
3713 VectorCopy(bound.maxs, loadmodel->normalmaxs);
3717 if (loadmodel->normalmins[0] > bound.mins[0]) loadmodel->normalmins[0] = bound.mins[0];
3718 if (loadmodel->normalmins[1] > bound.mins[1]) loadmodel->normalmins[1] = bound.mins[1];
3719 if (loadmodel->normalmins[2] > bound.mins[2]) loadmodel->normalmins[2] = bound.mins[2];
3720 if (loadmodel->normalmaxs[0] < bound.maxs[0]) loadmodel->normalmaxs[0] = bound.maxs[0];
3721 if (loadmodel->normalmaxs[1] < bound.maxs[1]) loadmodel->normalmaxs[1] = bound.maxs[1];
3722 if (loadmodel->normalmaxs[2] < bound.maxs[2]) loadmodel->normalmaxs[2] = bound.maxs[2];
3724 if (bound.xyradius > xyradius)
3725 xyradius = bound.xyradius;
3726 if (bound.radius > radius)
3727 radius = bound.radius;
3729 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -xyradius;
3730 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = xyradius;
3731 loadmodel->yawmins[2] = loadmodel->normalmins[2];
3732 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
3733 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
3734 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
3735 loadmodel->radius = radius;
3736 loadmodel->radius2 = radius * radius;
3739 // load triangle data
3740 // this unaligned memory access is safe (LittleLong reads as bytes)
3741 inelements = (const unsigned int *)(pbase + header.ofs_triangles);
3742 outelements = loadmodel->surfmesh.data_element3i;
3743 for (i = 0;i < (int)header.num_triangles;i++)
3745 outelements[0] = LittleLong(inelements[0]);
3746 outelements[1] = LittleLong(inelements[1]);
3747 outelements[2] = LittleLong(inelements[2]);
3751 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, header.num_vertexes, __FILE__, __LINE__);
3753 if (header.ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
3755 // this unaligned memory access is safe (LittleLong reads as bytes)
3756 inneighbors = (const int *)(pbase + header.ofs_neighbors);
3757 outneighbors = loadmodel->surfmesh.data_neighbor3i;
3758 for (i = 0;i < (int)header.num_triangles;i++)
3760 outneighbors[0] = LittleLong(inneighbors[0]);
3761 outneighbors[1] = LittleLong(inneighbors[1]);
3762 outneighbors[2] = LittleLong(inneighbors[2]);
3769 // this unaligned memory access is safe (LittleFloat reads as bytes)
3770 outvertex = loadmodel->surfmesh.data_vertex3f;
3771 for (i = 0;i < (int)header.num_vertexes;i++)
3773 outvertex[0] = LittleFloat(vposition[0]);
3774 outvertex[1] = LittleFloat(vposition[1]);
3775 outvertex[2] = LittleFloat(vposition[2]);
3780 outtexcoord = loadmodel->surfmesh.data_texcoordtexture2f;
3781 // this unaligned memory access is safe (LittleFloat reads as bytes)
3782 for (i = 0;i < (int)header.num_vertexes;i++)
3784 outtexcoord[0] = LittleFloat(vtexcoord[0]);
3785 outtexcoord[1] = LittleFloat(vtexcoord[1]);
3790 // this unaligned memory access is safe (LittleFloat reads as bytes)
3793 outnormal = loadmodel->surfmesh.data_normal3f;
3794 for (i = 0;i < (int)header.num_vertexes;i++)
3796 outnormal[0] = LittleFloat(vnormal[0]);
3797 outnormal[1] = LittleFloat(vnormal[1]);
3798 outnormal[2] = LittleFloat(vnormal[2]);
3804 // this unaligned memory access is safe (LittleFloat reads as bytes)
3805 if(vnormal && vtangent)
3807 outnormal = loadmodel->surfmesh.data_normal3f;
3808 outsvector = loadmodel->surfmesh.data_svector3f;
3809 outtvector = loadmodel->surfmesh.data_tvector3f;
3810 for (i = 0;i < (int)header.num_vertexes;i++)
3812 outsvector[0] = LittleFloat(vtangent[0]);
3813 outsvector[1] = LittleFloat(vtangent[1]);
3814 outsvector[2] = LittleFloat(vtangent[2]);
3815 if(LittleFloat(vtangent[3]) < 0)
3816 CrossProduct(outsvector, outnormal, outtvector);
3818 CrossProduct(outnormal, outsvector, outtvector);
3826 // this unaligned memory access is safe (all bytes)
3827 if (vblendindexes && vblendweights)
3829 for (i = 0; i < (int)header.num_vertexes;i++)
3831 blendweights_t weights;
3832 memcpy(weights.index, vblendindexes + i*4, 4);
3833 memcpy(weights.influence, vblendweights + i*4, 4);
3834 loadmodel->surfmesh.blends[i] = Mod_Skeletal_AddBlend(loadmodel, &weights);
3835 loadmodel->surfmesh.data_skeletalindex4ub[i*4 ] = weights.index[0];
3836 loadmodel->surfmesh.data_skeletalindex4ub[i*4+1] = weights.index[1];
3837 loadmodel->surfmesh.data_skeletalindex4ub[i*4+2] = weights.index[2];
3838 loadmodel->surfmesh.data_skeletalindex4ub[i*4+3] = weights.index[3];
3839 loadmodel->surfmesh.data_skeletalweight4ub[i*4 ] = weights.influence[0];
3840 loadmodel->surfmesh.data_skeletalweight4ub[i*4+1] = weights.influence[1];
3841 loadmodel->surfmesh.data_skeletalweight4ub[i*4+2] = weights.influence[2];
3842 loadmodel->surfmesh.data_skeletalweight4ub[i*4+3] = weights.influence[3];
3848 outcolor = loadmodel->surfmesh.data_lightmapcolor4f;
3849 // this unaligned memory access is safe (LittleFloat reads as bytes)
3850 for (i = 0;i < (int)header.num_vertexes;i++)
3852 outcolor[0] = LittleFloat(vcolor4f[0]);
3853 outcolor[1] = LittleFloat(vcolor4f[1]);
3854 outcolor[2] = LittleFloat(vcolor4f[2]);
3855 outcolor[3] = LittleFloat(vcolor4f[3]);
3862 outcolor = loadmodel->surfmesh.data_lightmapcolor4f;
3863 // this unaligned memory access is safe (all bytes)
3864 for (i = 0;i < (int)header.num_vertexes;i++)
3866 outcolor[0] = vcolor4ub[0] * (1.0f / 255.0f);
3867 outcolor[1] = vcolor4ub[1] * (1.0f / 255.0f);
3868 outcolor[2] = vcolor4ub[2] * (1.0f / 255.0f);
3869 outcolor[3] = vcolor4ub[3] * (1.0f / 255.0f);
3876 for (i = 0;i < (int)header.num_meshes;i++)
3879 msurface_t *surface;
3881 mesh.name = LittleLong(meshes[i].name);
3882 mesh.material = LittleLong(meshes[i].material);
3883 mesh.first_vertex = LittleLong(meshes[i].first_vertex);
3884 mesh.num_vertexes = LittleLong(meshes[i].num_vertexes);
3885 mesh.first_triangle = LittleLong(meshes[i].first_triangle);
3886 mesh.num_triangles = LittleLong(meshes[i].num_triangles);
3888 loadmodel->sortedmodelsurfaces[i] = i;
3889 surface = loadmodel->data_surfaces + i;
3890 surface->texture = loadmodel->data_textures + i;
3891 surface->num_firsttriangle = mesh.first_triangle;
3892 surface->num_triangles = mesh.num_triangles;
3893 surface->num_firstvertex = mesh.first_vertex;
3894 surface->num_vertices = mesh.num_vertexes;
3896 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, &text[mesh.name], &text[mesh.material]);
3899 Mod_FreeSkinFiles(skinfiles);
3900 Mod_MakeSortedSurfaces(loadmodel);
3902 // compute all the mesh information that was not loaded from the file
3903 if (loadmodel->surfmesh.data_element3s)
3904 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3905 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3907 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);
3908 if (!vnormal || !vtangent)
3909 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);
3910 if (!header.ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
3911 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3912 if (!header.ofs_bounds)
3913 Mod_Alias_CalculateBoundingBox();
3915 if (!loadmodel->surfmesh.isanimated && loadmodel->surfmesh.num_triangles >= 1)
3917 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3918 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3919 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3920 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3921 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3922 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
3925 if (joint ) Mem_Free(joint );joint = NULL;
3926 if (joint1 ) Mem_Free(joint1 );joint1 = NULL;
3927 if (pose ) Mem_Free(pose );pose = NULL;
3928 if (pose1 ) Mem_Free(pose1 );pose1 = NULL;
3930 // because shaders can do somewhat unexpected things, check for unusual features now
3931 for (i = 0;i < loadmodel->num_textures;i++)
3933 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
3934 mod->DrawSky = R_Q1BSP_DrawSky;
3935 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
3936 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;