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"};
41 float mod_md3_sin[320];
43 static size_t Mod_Skeletal_AnimateVertices_maxbonepose = 0;
44 static void *Mod_Skeletal_AnimateVertices_bonepose = NULL;
45 void Mod_Skeletal_FreeBuffers(void)
47 if(Mod_Skeletal_AnimateVertices_bonepose)
48 Mem_Free(Mod_Skeletal_AnimateVertices_bonepose);
49 Mod_Skeletal_AnimateVertices_maxbonepose = 0;
50 Mod_Skeletal_AnimateVertices_bonepose = NULL;
52 void *Mod_Skeletal_AnimateVertices_AllocBuffers(size_t nbytes)
54 if(Mod_Skeletal_AnimateVertices_maxbonepose < nbytes)
56 if(Mod_Skeletal_AnimateVertices_bonepose)
57 Mem_Free(Mod_Skeletal_AnimateVertices_bonepose);
58 Mod_Skeletal_AnimateVertices_bonepose = Z_Malloc(nbytes);
59 Mod_Skeletal_AnimateVertices_maxbonepose = nbytes;
61 return Mod_Skeletal_AnimateVertices_bonepose;
64 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)
67 if (!model->surfmesh.num_vertices)
70 if (!model->num_bones)
72 if (vertex3f) memcpy(vertex3f, model->surfmesh.data_vertex3f, model->surfmesh.num_vertices*sizeof(float[3]));
73 if (normal3f) memcpy(normal3f, model->surfmesh.data_normal3f, model->surfmesh.num_vertices*sizeof(float[3]));
74 if (svector3f) memcpy(svector3f, model->surfmesh.data_svector3f, model->surfmesh.num_vertices*sizeof(float[3]));
75 if (tvector3f) memcpy(tvector3f, model->surfmesh.data_tvector3f, model->surfmesh.num_vertices*sizeof(float[3]));
80 if(r_skeletal_use_sse_defined)
81 if(r_skeletal_use_sse.integer)
83 Mod_Skeletal_AnimateVertices_SSE(model, frameblend, skeleton, vertex3f, normal3f, svector3f, tvector3f);
87 Mod_Skeletal_AnimateVertices_Generic(model, frameblend, skeleton, vertex3f, normal3f, svector3f, tvector3f);
90 void Mod_AliasInit (void)
93 Cvar_RegisterVariable(&r_skeletal_debugbone);
94 Cvar_RegisterVariable(&r_skeletal_debugbonecomponent);
95 Cvar_RegisterVariable(&r_skeletal_debugbonevalue);
96 Cvar_RegisterVariable(&r_skeletal_debugtranslatex);
97 Cvar_RegisterVariable(&r_skeletal_debugtranslatey);
98 Cvar_RegisterVariable(&r_skeletal_debugtranslatez);
99 Cvar_RegisterVariable(&mod_alias_supporttagscale);
100 for (i = 0;i < 320;i++)
101 mod_md3_sin[i] = sin(i * M_PI * 2.0f / 256.0);
105 Con_Printf("Skeletal animation uses SSE code path\n");
106 r_skeletal_use_sse_defined = true;
107 Cvar_RegisterVariable(&r_skeletal_use_sse);
110 Con_Printf("Skeletal animation uses generic code path (SSE disabled or not detected)\n");
112 Con_Printf("Skeletal animation uses generic code path (SSE not compiled in)\n");
116 static int Mod_Skeletal_AddBlend(dp_model_t *model, const blendweights_t *newweights)
119 blendweights_t *weights;
120 if(!newweights->influence[1])
121 return newweights->index[0];
122 weights = model->surfmesh.data_blendweights;
123 for (i = 0;i < model->surfmesh.num_blends;i++, weights++)
125 if (!memcmp(weights, newweights, sizeof(blendweights_t)))
126 return model->num_bones + i;
128 model->surfmesh.num_blends++;
129 memcpy(weights, newweights, sizeof(blendweights_t));
130 return model->num_bones + i;
133 static int Mod_Skeletal_CompressBlend(dp_model_t *model, const int *newindex, const float *newinfluence)
137 blendweights_t newweights;
141 for (i = 0;i < 4;i++)
142 scale += newinfluence[i];
143 scale = 255.0f / scale;
145 for (i = 0;i < 4;i++)
147 newweights.index[i] = newindex[i];
148 newweights.influence[i] = (unsigned char)(newinfluence[i] * scale);
149 total += newweights.influence[i];
153 for (i = 0;i < 4;i++)
155 if(newweights.influence[i] > 0 && total > 255)
157 newweights.influence[i]--;
164 for (i = 0; i < 4;i++)
166 if(newweights.influence[i] < 255 && total < 255)
168 newweights.influence[i]++;
173 return Mod_Skeletal_AddBlend(model, &newweights);
176 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)
179 int i, numblends, blendnum;
180 int numverts = model->surfmesh.num_vertices;
182 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
184 //VectorMA(translate, model->surfmesh.num_morphmdlframetranslate, frameblend[blendnum].lerp, translate);
185 if (frameblend[blendnum].lerp > 0)
186 numblends = blendnum + 1;
188 // special case for the first blend because it avoids some adds and the need to memset the arrays first
189 for (blendnum = 0;blendnum < numblends;blendnum++)
191 const md3vertex_t *verts = model->surfmesh.data_morphmd3vertex + numverts * frameblend[blendnum].subframe;
194 float scale = frameblend[blendnum].lerp * (1.0f / 64.0f);
197 for (i = 0;i < numverts;i++)
199 vertex3f[i * 3 + 0] = verts[i].origin[0] * scale;
200 vertex3f[i * 3 + 1] = verts[i].origin[1] * scale;
201 vertex3f[i * 3 + 2] = verts[i].origin[2] * scale;
206 for (i = 0;i < numverts;i++)
208 vertex3f[i * 3 + 0] += verts[i].origin[0] * scale;
209 vertex3f[i * 3 + 1] += verts[i].origin[1] * scale;
210 vertex3f[i * 3 + 2] += verts[i].origin[2] * scale;
214 // the yaw and pitch stored in md3 models are 8bit quantized angles
215 // (0-255), and as such a lookup table is very well suited to
216 // decoding them, and since cosine is equivalent to sine with an
217 // extra 45 degree rotation, this uses one lookup table for both
218 // sine and cosine with a +64 bias to get cosine.
221 float lerp = frameblend[blendnum].lerp;
224 for (i = 0;i < numverts;i++)
226 normal3f[i * 3 + 0] = mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
227 normal3f[i * 3 + 1] = mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
228 normal3f[i * 3 + 2] = mod_md3_sin[verts[i].pitch + 64] * lerp;
233 for (i = 0;i < numverts;i++)
235 normal3f[i * 3 + 0] += mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
236 normal3f[i * 3 + 1] += mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
237 normal3f[i * 3 + 2] += mod_md3_sin[verts[i].pitch + 64] * lerp;
243 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
244 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
247 for (i = 0;i < numverts;i++, texvecvert++)
249 VectorScale(texvecvert->svec, f, svector3f + i*3);
250 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
255 for (i = 0;i < numverts;i++, texvecvert++)
257 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
258 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
264 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)
267 int i, numblends, blendnum;
268 int numverts = model->surfmesh.num_vertices;
270 VectorClear(translate);
272 // blend the frame translates to avoid redundantly doing so on each vertex
273 // (a bit of a brain twister but it works)
274 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
276 if (model->surfmesh.data_morphmd2framesize6f)
277 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6 + 3, translate);
279 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.num_morphmdlframetranslate, translate);
280 if (frameblend[blendnum].lerp > 0)
281 numblends = blendnum + 1;
283 // special case for the first blend because it avoids some adds and the need to memset the arrays first
284 for (blendnum = 0;blendnum < numblends;blendnum++)
286 const trivertx_t *verts = model->surfmesh.data_morphmdlvertex + numverts * frameblend[blendnum].subframe;
290 if (model->surfmesh.data_morphmd2framesize6f)
291 VectorScale(model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6, frameblend[blendnum].lerp, scale);
293 VectorScale(model->surfmesh.num_morphmdlframescale, frameblend[blendnum].lerp, scale);
296 for (i = 0;i < numverts;i++)
298 vertex3f[i * 3 + 0] = translate[0] + verts[i].v[0] * scale[0];
299 vertex3f[i * 3 + 1] = translate[1] + verts[i].v[1] * scale[1];
300 vertex3f[i * 3 + 2] = translate[2] + verts[i].v[2] * scale[2];
305 for (i = 0;i < numverts;i++)
307 vertex3f[i * 3 + 0] += verts[i].v[0] * scale[0];
308 vertex3f[i * 3 + 1] += verts[i].v[1] * scale[1];
309 vertex3f[i * 3 + 2] += verts[i].v[2] * scale[2];
313 // the vertex normals in mdl models are an index into a table of
314 // 162 unique values, this very crude quantization reduces the
315 // vertex normal to only one byte, which saves a lot of space but
316 // also makes lighting pretty coarse
319 float lerp = frameblend[blendnum].lerp;
322 for (i = 0;i < numverts;i++)
324 const float *vn = m_bytenormals[verts[i].lightnormalindex];
325 VectorScale(vn, lerp, normal3f + i*3);
330 for (i = 0;i < numverts;i++)
332 const float *vn = m_bytenormals[verts[i].lightnormalindex];
333 VectorMA(normal3f + i*3, lerp, vn, normal3f + i*3);
339 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
340 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
343 for (i = 0;i < numverts;i++, texvecvert++)
345 VectorScale(texvecvert->svec, f, svector3f + i*3);
346 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
351 for (i = 0;i < numverts;i++, texvecvert++)
353 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
354 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
361 int Mod_Alias_GetTagMatrix(const dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, int tagindex, matrix4x4_t *outmatrix)
364 matrix4x4_t parentbonematrix;
365 matrix4x4_t tempbonematrix;
366 matrix4x4_t bonematrix;
367 matrix4x4_t blendmatrix;
374 *outmatrix = identitymatrix;
375 if (skeleton && skeleton->relativetransforms)
377 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
379 *outmatrix = skeleton->relativetransforms[tagindex];
380 while ((tagindex = model->data_bones[tagindex].parent) >= 0)
383 Matrix4x4_Concat(outmatrix, &skeleton->relativetransforms[tagindex], &temp);
386 else if (model->num_bones)
388 if (tagindex < 0 || tagindex >= model->num_bones)
390 Matrix4x4_Clear(&blendmatrix);
391 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
393 lerp = frameblend[blendindex].lerp;
394 Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
395 parenttagindex = tagindex;
396 while ((parenttagindex = model->data_bones[parenttagindex].parent) >= 0)
398 Matrix4x4_FromBonePose6s(&parentbonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + parenttagindex));
399 tempbonematrix = bonematrix;
400 Matrix4x4_Concat(&bonematrix, &parentbonematrix, &tempbonematrix);
402 Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
404 *outmatrix = blendmatrix;
406 else if (model->num_tags)
408 if (tagindex < 0 || tagindex >= model->num_tags)
410 for (k = 0;k < 12;k++)
412 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
414 lerp = frameblend[blendindex].lerp;
415 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
416 for (k = 0;k < 12;k++)
417 blendtag[k] += input[k] * lerp;
419 Matrix4x4_FromArray12FloatGL(outmatrix, blendtag);
422 if(!mod_alias_supporttagscale.integer)
423 Matrix4x4_Normalize3(outmatrix, outmatrix);
428 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)
433 matrix4x4_t bonematrix;
434 matrix4x4_t blendmatrix;
438 if (skeleton && skeleton->relativetransforms)
440 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
442 *parentindex = skeleton->model->data_bones[tagindex].parent;
443 *tagname = skeleton->model->data_bones[tagindex].name;
444 *tag_localmatrix = skeleton->relativetransforms[tagindex];
447 else if (model->num_bones)
449 if (tagindex < 0 || tagindex >= model->num_bones)
451 *parentindex = model->data_bones[tagindex].parent;
452 *tagname = model->data_bones[tagindex].name;
453 Matrix4x4_Clear(&blendmatrix);
454 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
456 lerp = frameblend[blendindex].lerp;
457 Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
458 Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
460 *tag_localmatrix = blendmatrix;
463 else if (model->num_tags)
465 if (tagindex < 0 || tagindex >= model->num_tags)
468 *tagname = model->data_tags[tagindex].name;
469 for (k = 0;k < 12;k++)
471 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
473 lerp = frameblend[blendindex].lerp;
474 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
475 for (k = 0;k < 12;k++)
476 blendtag[k] += input[k] * lerp;
478 Matrix4x4_FromArray12FloatGL(tag_localmatrix, blendtag);
485 int Mod_Alias_GetTagIndexForName(const dp_model_t *model, unsigned int skin, const char *tagname)
488 if(skin >= (unsigned int)model->numskins)
490 if (model->num_bones)
491 for (i = 0;i < model->num_bones;i++)
492 if (!strcasecmp(tagname, model->data_bones[i].name))
495 for (i = 0;i < model->num_tags;i++)
496 if (!strcasecmp(tagname, model->data_tags[i].name))
501 static void Mod_BuildBaseBonePoses(void)
504 matrix4x4_t *basebonepose;
505 float *outinvmatrix = loadmodel->data_baseboneposeinverse;
506 matrix4x4_t bonematrix;
507 matrix4x4_t tempbonematrix;
508 if (!loadmodel->num_bones)
510 basebonepose = (matrix4x4_t *)Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(matrix4x4_t));
511 for (boneindex = 0;boneindex < loadmodel->num_bones;boneindex++)
513 Matrix4x4_FromBonePose6s(&bonematrix, loadmodel->num_posescale, loadmodel->data_poses6s + 6 * boneindex);
514 if (loadmodel->data_bones[boneindex].parent >= 0)
516 tempbonematrix = bonematrix;
517 Matrix4x4_Concat(&bonematrix, basebonepose + loadmodel->data_bones[boneindex].parent, &tempbonematrix);
519 basebonepose[boneindex] = bonematrix;
520 Matrix4x4_Invert_Simple(&tempbonematrix, basebonepose + boneindex);
521 Matrix4x4_ToArray12FloatD3D(&tempbonematrix, outinvmatrix + 12*boneindex);
523 Mem_Free(basebonepose);
526 static void Mod_Alias_CalculateBoundingBox(void)
529 qboolean firstvertex = true;
530 float dist, yawradius, radius;
532 VectorClear(loadmodel->normalmins);
533 VectorClear(loadmodel->normalmaxs);
536 if (loadmodel->AnimateVertices)
539 frameblend_t frameblend[MAX_FRAMEBLENDS];
540 memset(frameblend, 0, sizeof(frameblend));
541 frameblend[0].lerp = 1;
542 vertex3f = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
543 for (frameblend[0].subframe = 0;frameblend[0].subframe < loadmodel->num_poses;frameblend[0].subframe++)
545 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, vertex3f, NULL, NULL, NULL);
546 for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
551 VectorCopy(v, loadmodel->normalmins);
552 VectorCopy(v, loadmodel->normalmaxs);
556 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
557 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
558 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
559 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
560 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
561 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
563 dist = v[0] * v[0] + v[1] * v[1];
564 if (yawradius < dist)
576 for (vnum = 0, v = loadmodel->surfmesh.data_vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
581 VectorCopy(v, loadmodel->normalmins);
582 VectorCopy(v, loadmodel->normalmaxs);
586 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
587 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
588 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
589 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
590 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
591 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
593 dist = v[0] * v[0] + v[1] * v[1];
594 if (yawradius < dist)
601 radius = sqrt(radius);
602 yawradius = sqrt(yawradius);
603 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
604 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
605 loadmodel->yawmins[2] = loadmodel->normalmins[2];
606 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
607 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
608 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
609 loadmodel->radius = radius;
610 loadmodel->radius2 = radius * radius;
613 static void Mod_Alias_MorphMesh_CompileFrames(void)
616 frameblend_t frameblend[MAX_FRAMEBLENDS];
617 unsigned char *datapointer;
618 memset(frameblend, 0, sizeof(frameblend));
619 frameblend[0].lerp = 1;
620 datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
621 loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
622 loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
623 loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
624 loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
625 loadmodel->surfmesh.data_morphtexvecvertex = (texvecvertex_t *)datapointer;datapointer += loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices * sizeof(texvecvertex_t);
626 // 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)
627 for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
629 frameblend[0].subframe = i;
630 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
631 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);
632 // encode the svector and tvector in 3 byte format for permanent storage
633 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
635 VectorScaleCast(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
636 VectorScaleCast(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
641 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)
644 float segmentmins[3], segmentmaxs[3];
646 float vertex3fbuf[1024*3];
647 float *vertex3f = vertex3fbuf;
648 memset(trace, 0, sizeof(*trace));
650 trace->realfraction = 1;
651 trace->hitsupercontentsmask = hitsupercontentsmask;
652 if (model->surfmesh.num_vertices > 1024)
653 vertex3f = Mem_Alloc(tempmempool, model->surfmesh.num_vertices * sizeof(float[3]));
654 segmentmins[0] = min(start[0], end[0]) - 1;
655 segmentmins[1] = min(start[1], end[1]) - 1;
656 segmentmins[2] = min(start[2], end[2]) - 1;
657 segmentmaxs[0] = max(start[0], end[0]) + 1;
658 segmentmaxs[1] = max(start[1], end[1]) + 1;
659 segmentmaxs[2] = max(start[2], end[2]) + 1;
660 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
661 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
662 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);
663 if (vertex3f != vertex3fbuf)
667 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)
670 vec3_t shiftstart, shiftend;
671 float segmentmins[3], segmentmaxs[3];
673 float vertex3fbuf[1024*3];
674 float *vertex3f = vertex3fbuf;
675 colboxbrushf_t thisbrush_start, thisbrush_end;
676 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
678 if (VectorCompare(boxmins, boxmaxs))
680 VectorAdd(start, boxmins, shiftstart);
681 VectorAdd(end, boxmins, shiftend);
682 Mod_MDLMD2MD3_TraceLine(model, frameblend, skeleton, trace, shiftstart, shiftend, hitsupercontentsmask);
683 VectorSubtract(trace->endpos, boxmins, trace->endpos);
687 // box trace, performed as brush trace
688 memset(trace, 0, sizeof(*trace));
690 trace->realfraction = 1;
691 trace->hitsupercontentsmask = hitsupercontentsmask;
692 if (model->surfmesh.num_vertices > 1024)
693 vertex3f = Mem_Alloc(tempmempool, model->surfmesh.num_vertices * sizeof(float[3]));
694 segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
695 segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
696 segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
697 segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
698 segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
699 segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
700 VectorAdd(start, boxmins, boxstartmins);
701 VectorAdd(start, boxmaxs, boxstartmaxs);
702 VectorAdd(end, boxmins, boxendmins);
703 VectorAdd(end, boxmaxs, boxendmaxs);
704 Collision_BrushForBox(&thisbrush_start, boxstartmins, boxstartmaxs, 0, 0, NULL);
705 Collision_BrushForBox(&thisbrush_end, boxendmins, boxendmaxs, 0, 0, NULL);
706 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
707 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
708 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);
709 if (vertex3f != vertex3fbuf)
713 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
716 for (i = 0;i < inverts;i++)
718 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
720 j = vertremap[i]; // not onseam
723 j = vertremap[i+inverts]; // onseam
729 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
731 int i, f, pose, groupframes;
733 daliasframetype_t *pframetype;
734 daliasframe_t *pinframe;
735 daliasgroup_t *group;
736 daliasinterval_t *intervals;
739 scene = loadmodel->animscenes;
740 for (f = 0;f < loadmodel->numframes;f++)
742 pframetype = (daliasframetype_t *)datapointer;
743 datapointer += sizeof(daliasframetype_t);
744 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
746 // a single frame is still treated as a group
753 group = (daliasgroup_t *)datapointer;
754 datapointer += sizeof(daliasgroup_t);
755 groupframes = LittleLong (group->numframes);
757 // intervals (time per frame)
758 intervals = (daliasinterval_t *)datapointer;
759 datapointer += sizeof(daliasinterval_t) * groupframes;
761 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
762 if (interval < 0.01f)
764 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
769 // get scene name from first frame
770 pinframe = (daliasframe_t *)datapointer;
772 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
773 scene->firstframe = pose;
774 scene->framecount = groupframes;
775 scene->framerate = 1.0f / interval;
780 for (i = 0;i < groupframes;i++)
782 pinframe = (daliasframe_t *)datapointer;
783 datapointer += sizeof(daliasframe_t);
784 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
785 datapointer += sizeof(trivertx_t) * inverts;
791 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
793 if (cls.state == ca_dedicated)
797 skinframe = R_SkinFrame_LoadMissing();
798 memset(texture, 0, sizeof(*texture));
799 texture->currentframe = texture;
800 //texture->animated = false;
801 texture->numskinframes = 1;
802 texture->skinframerate = 1;
803 texture->skinframes[0] = skinframe;
804 texture->currentskinframe = skinframe;
805 //texture->backgroundnumskinframes = 0;
806 //texture->customblendfunc[0] = 0;
807 //texture->customblendfunc[1] = 0;
808 //texture->surfaceflags = 0;
809 //texture->supercontents = 0;
810 //texture->surfaceparms = 0;
811 //texture->textureflags = 0;
813 texture->basematerialflags = MATERIALFLAG_WALL;
814 if (texture->currentskinframe->hasalpha)
815 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
816 texture->currentmaterialflags = texture->basematerialflags;
817 texture->offsetmapping = OFFSETMAPPING_DEFAULT;
818 texture->offsetscale = 1;
819 texture->offsetbias = 0;
820 texture->specularscalemod = 1;
821 texture->specularpowermod = 1;
822 texture->surfaceflags = 0;
823 texture->supercontents = SUPERCONTENTS_SOLID;
824 if (!(texture->basematerialflags & MATERIALFLAG_BLENDED))
825 texture->supercontents |= SUPERCONTENTS_OPAQUE;
828 void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
831 char stripbuf[MAX_QPATH];
832 skinfileitem_t *skinfileitem;
833 if(developer_extra.integer)
834 Con_DPrintf("Looking up texture for %s (default: %s)\n", meshname, shadername);
837 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
838 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
840 memset(skin, 0, sizeof(*skin));
842 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
844 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
845 if (!strcmp(skinfileitem->name, meshname))
847 Image_StripImageExtension(skinfileitem->replacement, stripbuf, sizeof(stripbuf));
848 if(developer_extra.integer)
849 Con_DPrintf("--> got %s from skin file\n", stripbuf);
850 Mod_LoadTextureFromQ3Shader(skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
856 // don't render unmentioned meshes
857 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
858 if(developer_extra.integer)
859 Con_DPrintf("--> skipping\n");
860 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
866 if(developer_extra.integer)
867 Con_DPrintf("--> using default\n");
868 Image_StripImageExtension(shadername, stripbuf, sizeof(stripbuf));
869 Mod_LoadTextureFromQ3Shader(skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
873 #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);
874 #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);
875 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
877 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
878 float scales, scalet, interval;
882 stvert_t *pinstverts;
883 dtriangle_t *pintriangles;
884 daliasskintype_t *pinskintype;
885 daliasskingroup_t *pinskingroup;
886 daliasskininterval_t *pinskinintervals;
887 daliasframetype_t *pinframetype;
888 daliasgroup_t *pinframegroup;
889 unsigned char *datapointer, *startframes, *startskins;
890 char name[MAX_QPATH];
891 skinframe_t *tempskinframe;
892 animscene_t *tempskinscenes;
893 texture_t *tempaliasskins;
895 int *vertonseam, *vertremap;
896 skinfile_t *skinfiles;
899 datapointer = (unsigned char *)buffer;
900 pinmodel = (mdl_t *)datapointer;
901 datapointer += sizeof(mdl_t);
903 version = LittleLong (pinmodel->version);
904 if (version != ALIAS_VERSION)
905 Host_Error ("%s has wrong version number (%i should be %i)",
906 loadmodel->name, version, ALIAS_VERSION);
908 loadmodel->modeldatatypestring = "MDL";
910 loadmodel->type = mod_alias;
911 loadmodel->DrawSky = NULL;
912 loadmodel->DrawAddWaterPlanes = NULL;
913 loadmodel->Draw = R_Q1BSP_Draw;
914 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
915 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
916 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
917 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
918 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
919 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
920 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
921 loadmodel->DrawLight = R_Q1BSP_DrawLight;
922 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
923 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
924 // FIXME add TraceBrush!
925 loadmodel->PointSuperContents = NULL;
927 loadmodel->num_surfaces = 1;
928 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
929 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
930 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
931 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
932 loadmodel->sortedmodelsurfaces[0] = 0;
934 loadmodel->numskins = LittleLong(pinmodel->numskins);
935 BOUNDI(loadmodel->numskins,0,65536);
936 skinwidth = LittleLong (pinmodel->skinwidth);
937 BOUNDI(skinwidth,0,65536);
938 skinheight = LittleLong (pinmodel->skinheight);
939 BOUNDI(skinheight,0,65536);
940 numverts = LittleLong(pinmodel->numverts);
941 BOUNDI(numverts,0,65536);
942 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
943 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
944 loadmodel->numframes = LittleLong(pinmodel->numframes);
945 BOUNDI(loadmodel->numframes,0,65536);
946 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
947 BOUNDI((int)loadmodel->synctype,0,2);
948 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
949 i = LittleLong (pinmodel->flags);
950 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
952 for (i = 0;i < 3;i++)
954 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
955 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
958 startskins = datapointer;
960 for (i = 0;i < loadmodel->numskins;i++)
962 pinskintype = (daliasskintype_t *)datapointer;
963 datapointer += sizeof(daliasskintype_t);
964 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
968 pinskingroup = (daliasskingroup_t *)datapointer;
969 datapointer += sizeof(daliasskingroup_t);
970 groupskins = LittleLong(pinskingroup->numskins);
971 datapointer += sizeof(daliasskininterval_t) * groupskins;
974 for (j = 0;j < groupskins;j++)
976 datapointer += skinwidth * skinheight;
981 pinstverts = (stvert_t *)datapointer;
982 datapointer += sizeof(stvert_t) * numverts;
984 pintriangles = (dtriangle_t *)datapointer;
985 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
987 startframes = datapointer;
988 loadmodel->surfmesh.num_morphframes = 0;
989 for (i = 0;i < loadmodel->numframes;i++)
991 pinframetype = (daliasframetype_t *)datapointer;
992 datapointer += sizeof(daliasframetype_t);
993 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
997 pinframegroup = (daliasgroup_t *)datapointer;
998 datapointer += sizeof(daliasgroup_t);
999 groupframes = LittleLong(pinframegroup->numframes);
1000 datapointer += sizeof(daliasinterval_t) * groupframes;
1003 for (j = 0;j < groupframes;j++)
1005 datapointer += sizeof(daliasframe_t);
1006 datapointer += sizeof(trivertx_t) * numverts;
1007 loadmodel->surfmesh.num_morphframes++;
1010 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1012 // store texture coordinates into temporary array, they will be stored
1013 // after usage is determined (triangle data)
1014 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
1015 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
1016 vertonseam = vertremap + numverts * 2;
1018 scales = 1.0 / skinwidth;
1019 scalet = 1.0 / skinheight;
1020 for (i = 0;i < numverts;i++)
1022 vertonseam[i] = LittleLong(pinstverts[i].onseam);
1023 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
1024 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
1025 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
1026 vertst[(i+numverts)*2+1] = vertst[i*2+1];
1029 // load triangle data
1030 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1032 // read the triangle elements
1033 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1034 for (j = 0;j < 3;j++)
1035 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1036 // validate (note numverts is used because this is the original data)
1037 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1038 // now butcher the elements according to vertonseam and tri->facesfront
1039 // and then compact the vertex set to remove duplicates
1040 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1041 if (!LittleLong(pintriangles[i].facesfront)) // backface
1042 for (j = 0;j < 3;j++)
1043 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1044 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1046 // (this uses vertremap to count usage to save some memory)
1047 for (i = 0;i < numverts*2;i++)
1049 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1050 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1051 // build remapping table and compact array
1052 loadmodel->surfmesh.num_vertices = 0;
1053 for (i = 0;i < numverts*2;i++)
1057 vertremap[i] = loadmodel->surfmesh.num_vertices;
1058 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1059 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1060 loadmodel->surfmesh.num_vertices++;
1063 vertremap[i] = -1; // not used at all
1065 // remap the elements to the new vertex set
1066 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1067 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1068 // store the texture coordinates
1069 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1070 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1072 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1073 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1076 // generate ushort elements array if possible
1077 if (loadmodel->surfmesh.num_vertices <= 65536)
1078 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1079 if (loadmodel->surfmesh.data_element3s)
1080 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1081 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1084 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1085 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1086 if (r_enableshadowvolumes.integer)
1088 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1090 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1091 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices; // needed during loading, may be cleared by code later in this function
1092 if (loadmodel->surfmesh.data_neighbor3i)
1093 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1094 Mod_Alias_CalculateBoundingBox();
1095 Mod_Alias_MorphMesh_CompileFrames();
1096 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_MDL_AnimateVertices : NULL;
1099 Mem_Free(vertremap);
1102 skinfiles = Mod_LoadSkinFiles();
1105 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1106 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1107 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1108 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1109 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1110 Mod_FreeSkinFiles(skinfiles);
1111 for (i = 0;i < loadmodel->numskins;i++)
1113 loadmodel->skinscenes[i].firstframe = i;
1114 loadmodel->skinscenes[i].framecount = 1;
1115 loadmodel->skinscenes[i].loop = true;
1116 loadmodel->skinscenes[i].framerate = 10;
1121 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1122 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1123 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1124 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1126 datapointer = startskins;
1127 for (i = 0;i < loadmodel->numskins;i++)
1129 pinskintype = (daliasskintype_t *)datapointer;
1130 datapointer += sizeof(daliasskintype_t);
1132 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1139 pinskingroup = (daliasskingroup_t *)datapointer;
1140 datapointer += sizeof(daliasskingroup_t);
1142 groupskins = LittleLong (pinskingroup->numskins);
1144 pinskinintervals = (daliasskininterval_t *)datapointer;
1145 datapointer += sizeof(daliasskininterval_t) * groupskins;
1147 interval = LittleFloat(pinskinintervals[0].interval);
1148 if (interval < 0.01f)
1150 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1155 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1156 loadmodel->skinscenes[i].firstframe = totalskins;
1157 loadmodel->skinscenes[i].framecount = groupskins;
1158 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1159 loadmodel->skinscenes[i].loop = true;
1161 for (j = 0;j < groupskins;j++)
1164 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1166 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1167 if (!Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, name, false, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS))
1168 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, R_SkinFrame_LoadInternalQuake(name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP, true, r_fullbrights.integer, (unsigned char *)datapointer, skinwidth, skinheight));
1169 datapointer += skinwidth * skinheight;
1173 // check for skins that don't exist in the model, but do exist as external images
1174 // (this was added because yummyluv kept pestering me about support for it)
1175 // TODO: support shaders here?
1176 while ((tempskinframe = R_SkinFrame_LoadExternal(va(vabuf, sizeof(vabuf), "%s_%i", loadmodel->name, loadmodel->numskins), (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS, false)))
1178 // expand the arrays to make room
1179 tempskinscenes = loadmodel->skinscenes;
1180 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1181 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1182 Mem_Free(tempskinscenes);
1184 tempaliasskins = loadmodel->data_textures;
1185 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1186 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1187 Mem_Free(tempaliasskins);
1189 // store the info about the new skin
1190 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1191 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1192 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1193 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1194 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1195 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1197 //increase skin counts
1198 loadmodel->numskins++;
1201 // fix up the pointers since they are pointing at the old textures array
1202 // FIXME: this is a hack!
1203 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1204 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1208 surface = loadmodel->data_surfaces;
1209 surface->texture = loadmodel->data_textures;
1210 surface->num_firsttriangle = 0;
1211 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1212 surface->num_firstvertex = 0;
1213 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1215 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1216 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_MDL_AnimateVertices : NULL;
1218 if (!loadmodel->surfmesh.isanimated)
1220 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1221 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1222 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1223 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1224 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1225 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1228 // because shaders can do somewhat unexpected things, check for unusual features now
1229 for (i = 0;i < loadmodel->num_textures;i++)
1231 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
1232 mod->DrawSky = R_Q1BSP_DrawSky;
1233 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
1234 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
1238 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1240 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1241 float iskinwidth, iskinheight;
1242 unsigned char *data;
1243 msurface_t *surface;
1245 unsigned char *base, *datapointer;
1246 md2frame_t *pinframe;
1248 md2triangle_t *intri;
1249 unsigned short *inst;
1250 struct md2verthash_s
1252 struct md2verthash_s *next;
1256 *hash, **md2verthash, *md2verthashdata;
1257 skinfile_t *skinfiles;
1259 pinmodel = (md2_t *)buffer;
1260 base = (unsigned char *)buffer;
1262 version = LittleLong (pinmodel->version);
1263 if (version != MD2ALIAS_VERSION)
1264 Host_Error ("%s has wrong version number (%i should be %i)",
1265 loadmodel->name, version, MD2ALIAS_VERSION);
1267 loadmodel->modeldatatypestring = "MD2";
1269 loadmodel->type = mod_alias;
1270 loadmodel->DrawSky = NULL;
1271 loadmodel->DrawAddWaterPlanes = NULL;
1272 loadmodel->Draw = R_Q1BSP_Draw;
1273 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1274 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1275 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1276 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1277 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1278 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1279 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1280 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1281 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1282 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1283 loadmodel->PointSuperContents = NULL;
1285 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1286 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1287 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1288 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1289 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1290 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1291 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1292 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1294 end = LittleLong(pinmodel->ofs_end);
1295 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1296 Host_Error ("%s is not a valid model", loadmodel->name);
1297 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1298 Host_Error ("%s is not a valid model", loadmodel->name);
1299 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1300 Host_Error ("%s is not a valid model", loadmodel->name);
1301 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1302 Host_Error ("%s is not a valid model", loadmodel->name);
1303 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1304 Host_Error ("%s is not a valid model", loadmodel->name);
1306 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1307 numxyz = LittleLong(pinmodel->num_xyz);
1308 numst = LittleLong(pinmodel->num_st);
1309 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1310 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1311 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1312 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1313 skinwidth = LittleLong(pinmodel->skinwidth);
1314 skinheight = LittleLong(pinmodel->skinheight);
1315 iskinwidth = 1.0f / skinwidth;
1316 iskinheight = 1.0f / skinheight;
1318 loadmodel->num_surfaces = 1;
1319 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1320 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));
1321 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1322 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1323 loadmodel->sortedmodelsurfaces[0] = 0;
1324 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1325 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1326 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1327 if (r_enableshadowvolumes.integer)
1329 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1332 loadmodel->synctype = ST_RAND;
1335 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1336 skinfiles = Mod_LoadSkinFiles();
1339 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1340 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1341 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1342 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1343 Mod_FreeSkinFiles(skinfiles);
1345 else if (loadmodel->numskins)
1347 // skins found (most likely not a player model)
1348 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1349 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1350 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1351 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1352 Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
1356 // no skins (most likely a player model)
1357 loadmodel->numskins = 1;
1358 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1359 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1360 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1361 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1364 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1365 for (i = 0;i < loadmodel->numskins;i++)
1367 loadmodel->skinscenes[i].firstframe = i;
1368 loadmodel->skinscenes[i].framecount = 1;
1369 loadmodel->skinscenes[i].loop = true;
1370 loadmodel->skinscenes[i].framerate = 10;
1373 // load the triangles and stvert data
1374 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1375 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1376 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1377 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1378 // swap the triangle list
1379 loadmodel->surfmesh.num_vertices = 0;
1380 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1382 for (j = 0;j < 3;j++)
1384 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1385 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1388 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1393 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1396 hashindex = (xyz * 256 + st) & 65535;
1397 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1398 if (hash->xyz == xyz && hash->st == st)
1402 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1405 hash->next = md2verthash[hashindex];
1406 md2verthash[hashindex] = hash;
1408 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1412 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1413 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));
1414 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1415 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1416 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1419 hash = md2verthashdata + i;
1420 vertremap[i] = hash->xyz;
1421 sts = LittleShort(inst[hash->st*2+0]);
1422 stt = LittleShort(inst[hash->st*2+1]);
1423 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1425 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1429 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1430 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1433 Mem_Free(md2verthash);
1434 Mem_Free(md2verthashdata);
1436 // generate ushort elements array if possible
1437 if (loadmodel->surfmesh.num_vertices <= 65536)
1438 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1439 if (loadmodel->surfmesh.data_element3s)
1440 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1441 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1444 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1445 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1450 pinframe = (md2frame_t *)datapointer;
1451 datapointer += sizeof(md2frame_t);
1452 // store the frame scale/translate into the appropriate array
1453 for (j = 0;j < 3;j++)
1455 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1456 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1458 // convert the vertices
1459 v = (trivertx_t *)datapointer;
1460 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1461 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1462 out[k] = v[vertremap[k]];
1463 datapointer += numxyz * sizeof(trivertx_t);
1465 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1466 loadmodel->animscenes[i].firstframe = i;
1467 loadmodel->animscenes[i].framecount = 1;
1468 loadmodel->animscenes[i].framerate = 10;
1469 loadmodel->animscenes[i].loop = true;
1472 Mem_Free(vertremap);
1474 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1475 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices; // needed during loading, may be cleared by code later in this function
1476 if (loadmodel->surfmesh.data_neighbor3i)
1477 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1478 Mod_Alias_CalculateBoundingBox();
1479 Mod_Alias_MorphMesh_CompileFrames();
1480 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_MDL_AnimateVertices : NULL;
1482 surface = loadmodel->data_surfaces;
1483 surface->texture = loadmodel->data_textures;
1484 surface->num_firsttriangle = 0;
1485 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1486 surface->num_firstvertex = 0;
1487 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1489 if (!loadmodel->surfmesh.isanimated)
1491 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1492 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1493 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1494 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1495 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1496 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1499 // because shaders can do somewhat unexpected things, check for unusual features now
1500 for (i = 0;i < loadmodel->num_textures;i++)
1502 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
1503 mod->DrawSky = R_Q1BSP_DrawSky;
1504 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
1505 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
1509 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1511 int i, j, k, version, meshvertices, meshtriangles;
1512 unsigned char *data;
1513 msurface_t *surface;
1514 md3modelheader_t *pinmodel;
1515 md3frameinfo_t *pinframe;
1518 skinfile_t *skinfiles;
1520 pinmodel = (md3modelheader_t *)buffer;
1522 if (memcmp(pinmodel->identifier, "IDP3", 4))
1523 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1524 version = LittleLong (pinmodel->version);
1525 if (version != MD3VERSION)
1526 Host_Error ("%s has wrong version number (%i should be %i)",
1527 loadmodel->name, version, MD3VERSION);
1529 skinfiles = Mod_LoadSkinFiles();
1530 if (loadmodel->numskins < 1)
1531 loadmodel->numskins = 1;
1533 loadmodel->modeldatatypestring = "MD3";
1535 loadmodel->type = mod_alias;
1536 loadmodel->DrawSky = NULL;
1537 loadmodel->DrawAddWaterPlanes = NULL;
1538 loadmodel->Draw = R_Q1BSP_Draw;
1539 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1540 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1541 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1542 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1543 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1544 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1545 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1546 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1547 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1548 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1549 loadmodel->PointSuperContents = NULL;
1550 loadmodel->synctype = ST_RAND;
1551 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1552 i = LittleLong (pinmodel->flags);
1553 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1555 // set up some global info about the model
1556 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1557 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1559 // make skinscenes for the skins (no groups)
1560 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1561 for (i = 0;i < loadmodel->numskins;i++)
1563 loadmodel->skinscenes[i].firstframe = i;
1564 loadmodel->skinscenes[i].framecount = 1;
1565 loadmodel->skinscenes[i].loop = true;
1566 loadmodel->skinscenes[i].framerate = 10;
1570 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1571 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1573 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1574 loadmodel->animscenes[i].firstframe = i;
1575 loadmodel->animscenes[i].framecount = 1;
1576 loadmodel->animscenes[i].framerate = 10;
1577 loadmodel->animscenes[i].loop = true;
1581 loadmodel->num_tagframes = loadmodel->numframes;
1582 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1583 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1584 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1586 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1587 for (j = 0;j < 9;j++)
1588 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1589 for (j = 0;j < 3;j++)
1590 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1591 //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);
1597 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)))
1599 if (memcmp(pinmesh->identifier, "IDP3", 4))
1600 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1601 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1602 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1603 meshvertices += LittleLong(pinmesh->num_vertices);
1604 meshtriangles += LittleLong(pinmesh->num_triangles);
1607 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1608 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1609 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1610 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));
1611 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1612 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1613 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1614 loadmodel->surfmesh.num_vertices = meshvertices;
1615 loadmodel->surfmesh.num_triangles = meshtriangles;
1616 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1617 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1618 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1619 if (r_enableshadowvolumes.integer)
1621 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1623 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1624 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1625 if (meshvertices <= 65536)
1627 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1632 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)))
1634 if (memcmp(pinmesh->identifier, "IDP3", 4))
1635 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1636 loadmodel->sortedmodelsurfaces[i] = i;
1637 surface = loadmodel->data_surfaces + i;
1638 surface->texture = loadmodel->data_textures + i;
1639 surface->num_firsttriangle = meshtriangles;
1640 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1641 surface->num_firstvertex = meshvertices;
1642 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1643 meshvertices += surface->num_vertices;
1644 meshtriangles += surface->num_triangles;
1646 for (j = 0;j < surface->num_triangles * 3;j++)
1647 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1648 for (j = 0;j < surface->num_vertices;j++)
1650 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1651 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1653 for (j = 0;j < loadmodel->numframes;j++)
1655 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1656 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1657 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1659 out->origin[0] = LittleShort(in->origin[0]);
1660 out->origin[1] = LittleShort(in->origin[1]);
1661 out->origin[2] = LittleShort(in->origin[2]);
1662 out->pitch = in->pitch;
1667 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1669 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1671 if (loadmodel->surfmesh.data_element3s)
1672 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1673 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1674 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1675 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices; // needed during loading, may be cleared by code later in this function
1676 if (loadmodel->surfmesh.data_neighbor3i)
1677 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1678 Mod_Alias_MorphMesh_CompileFrames();
1679 Mod_Alias_CalculateBoundingBox();
1680 Mod_FreeSkinFiles(skinfiles);
1681 Mod_MakeSortedSurfaces(loadmodel);
1682 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_MD3_AnimateVertices : NULL;
1684 if (!loadmodel->surfmesh.isanimated)
1686 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1687 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1688 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1689 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1690 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1691 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1694 // because shaders can do somewhat unexpected things, check for unusual features now
1695 for (i = 0;i < loadmodel->num_textures;i++)
1697 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
1698 mod->DrawSky = R_Q1BSP_DrawSky;
1699 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
1700 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
1704 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1706 zymtype1header_t *pinmodel, *pheader;
1707 unsigned char *pbase;
1708 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1709 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose, f, biggestorigin, tempvec[3], modelscale;
1710 zymvertex_t *verts, *vertdata;
1714 skinfile_t *skinfiles;
1715 unsigned char *data;
1716 msurface_t *surface;
1718 pinmodel = (zymtype1header_t *)buffer;
1719 pbase = (unsigned char *)buffer;
1720 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1721 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1722 if (BigLong(pinmodel->type) != 1)
1723 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1725 loadmodel->modeldatatypestring = "ZYM";
1727 loadmodel->type = mod_alias;
1728 loadmodel->synctype = ST_RAND;
1732 pheader->type = BigLong(pinmodel->type);
1733 pheader->filesize = BigLong(pinmodel->filesize);
1734 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1735 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1736 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1737 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1738 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1739 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1740 pheader->radius = BigFloat(pinmodel->radius);
1741 pheader->numverts = BigLong(pinmodel->numverts);
1742 pheader->numtris = BigLong(pinmodel->numtris);
1743 pheader->numshaders = BigLong(pinmodel->numshaders);
1744 pheader->numbones = BigLong(pinmodel->numbones);
1745 pheader->numscenes = BigLong(pinmodel->numscenes);
1746 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1747 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1748 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1749 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1750 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1751 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1752 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1753 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1754 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1755 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1756 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1757 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1758 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1759 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1760 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1761 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1762 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1763 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1765 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1767 Con_Printf("%s has no geometry\n", loadmodel->name);
1770 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1772 Con_Printf("%s has no animations\n", loadmodel->name);
1776 loadmodel->DrawSky = NULL;
1777 loadmodel->DrawAddWaterPlanes = NULL;
1778 loadmodel->Draw = R_Q1BSP_Draw;
1779 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1780 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1781 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1782 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1783 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1784 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1785 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1786 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1787 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1788 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1789 loadmodel->PointSuperContents = NULL;
1791 loadmodel->numframes = pheader->numscenes;
1792 loadmodel->num_surfaces = pheader->numshaders;
1794 skinfiles = Mod_LoadSkinFiles();
1795 if (loadmodel->numskins < 1)
1796 loadmodel->numskins = 1;
1798 // make skinscenes for the skins (no groups)
1799 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1800 for (i = 0;i < loadmodel->numskins;i++)
1802 loadmodel->skinscenes[i].firstframe = i;
1803 loadmodel->skinscenes[i].framecount = 1;
1804 loadmodel->skinscenes[i].loop = true;
1805 loadmodel->skinscenes[i].framerate = 10;
1809 modelradius = pheader->radius;
1810 for (i = 0;i < 3;i++)
1812 loadmodel->normalmins[i] = pheader->mins[i];
1813 loadmodel->normalmaxs[i] = pheader->maxs[i];
1814 loadmodel->rotatedmins[i] = -modelradius;
1815 loadmodel->rotatedmaxs[i] = modelradius;
1817 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1818 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1819 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1820 if (loadmodel->yawmaxs[0] > modelradius)
1821 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1822 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1823 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1824 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1825 loadmodel->radius = modelradius;
1826 loadmodel->radius2 = modelradius * modelradius;
1828 // go through the lumps, swapping things
1830 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1831 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1832 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1833 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1834 for (i = 0;i < pheader->numscenes;i++)
1836 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1837 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1838 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1839 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1840 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1841 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1842 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1843 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1844 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1845 if (loadmodel->animscenes[i].framerate < 0)
1846 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1850 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1851 loadmodel->num_bones = pheader->numbones;
1852 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1853 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1854 for (i = 0;i < pheader->numbones;i++)
1856 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1857 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1858 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1859 if (loadmodel->data_bones[i].parent >= i)
1860 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1863 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1864 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1865 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1866 for (i = 0;i < pheader->numverts;i++)
1868 vertbonecounts[i] = BigLong(bonecount[i]);
1869 if (vertbonecounts[i] != 1)
1870 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1873 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1875 meshvertices = pheader->numverts;
1876 meshtriangles = pheader->numtris;
1878 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1879 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
1880 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1881 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1882 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1883 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (r_enableshadowvolumes.integer ? meshtriangles * sizeof(int[3]) : 0) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshvertices * sizeof(float[14]) + meshvertices * sizeof(unsigned short) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]) + loadmodel->num_bones * sizeof(float[12]));
1884 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1885 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1886 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1887 loadmodel->surfmesh.num_vertices = meshvertices;
1888 loadmodel->surfmesh.num_triangles = meshtriangles;
1889 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1890 if (r_enableshadowvolumes.integer)
1892 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1894 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1895 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1896 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1897 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1898 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1899 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1900 loadmodel->surfmesh.num_blends = 0;
1901 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
1902 if (loadmodel->surfmesh.num_vertices <= 65536)
1904 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1906 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
1907 loadmodel->surfmesh.data_blendweights = NULL;
1909 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1910 poses = (float *) (pheader->lump_poses.start + pbase);
1911 // figure out scale of model from root bone, for compatibility with old zmodel versions
1912 tempvec[0] = BigFloat(poses[0]);
1913 tempvec[1] = BigFloat(poses[1]);
1914 tempvec[2] = BigFloat(poses[2]);
1915 modelscale = VectorLength(tempvec);
1917 for (i = 0;i < loadmodel->num_bones * numposes * 12;i++)
1919 f = fabs(BigFloat(poses[i]));
1920 biggestorigin = max(biggestorigin, f);
1922 loadmodel->num_posescale = biggestorigin / 32767.0f;
1923 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
1924 for (i = 0;i < numposes;i++)
1926 const float *frameposes = (float *) (pheader->lump_poses.start + pbase) + 12*i*loadmodel->num_bones;
1927 for (j = 0;j < loadmodel->num_bones;j++)
1930 matrix4x4_t posematrix;
1931 for (k = 0;k < 12;k++)
1932 pose[k] = BigFloat(frameposes[j*12+k]);
1933 //if (j < loadmodel->num_bones)
1934 // 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));
1935 // scale child bones to match the root scale
1936 if (loadmodel->data_bones[j].parent >= 0)
1938 pose[3] *= modelscale;
1939 pose[7] *= modelscale;
1940 pose[11] *= modelscale;
1942 // normalize rotation matrix
1943 VectorNormalize(pose + 0);
1944 VectorNormalize(pose + 4);
1945 VectorNormalize(pose + 8);
1946 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
1947 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
1951 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1952 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1953 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1954 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1955 // (converting from weight-blending skeletal animation to
1956 // deformation-based skeletal animation)
1957 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1958 for (i = 0;i < loadmodel->num_bones;i++)
1961 for (k = 0;k < 12;k++)
1962 m[k] = BigFloat(poses[i*12+k]);
1963 if (loadmodel->data_bones[i].parent >= 0)
1964 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1966 for (k = 0;k < 12;k++)
1967 bonepose[12*i+k] = m[k];
1969 for (j = 0;j < pheader->numverts;j++)
1971 // this format really should have had a per vertexweight weight value...
1972 // but since it does not, the weighting is completely ignored and
1973 // only one weight is allowed per vertex
1974 int boneindex = BigLong(vertdata[j].bonenum);
1975 const float *m = bonepose + 12 * boneindex;
1976 float relativeorigin[3];
1977 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1978 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1979 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1980 // transform the vertex bone weight into the base mesh
1981 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1982 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1983 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1984 // store the weight as the primary weight on this vertex
1985 loadmodel->surfmesh.blends[j] = boneindex;
1988 // normals and tangents are calculated after elements are loaded
1990 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1991 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1992 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1993 for (i = 0;i < pheader->numverts;i++)
1995 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1996 // flip T coordinate for OpenGL
1997 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
2000 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
2001 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
2002 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
2004 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
2005 //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)
2006 // byteswap, validate, and swap winding order of tris
2007 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
2008 if (pheader->lump_render.length != count)
2009 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
2010 renderlist = (int *) (pheader->lump_render.start + pbase);
2011 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
2013 for (i = 0;i < loadmodel->num_surfaces;i++)
2015 int firstvertex, lastvertex;
2016 if (renderlist >= renderlistend)
2017 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2018 count = BigLong(*renderlist);renderlist++;
2019 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
2020 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2022 loadmodel->sortedmodelsurfaces[i] = i;
2023 surface = loadmodel->data_surfaces + i;
2024 surface->texture = loadmodel->data_textures + i;
2025 surface->num_firsttriangle = meshtriangles;
2026 surface->num_triangles = count;
2027 meshtriangles += surface->num_triangles;
2029 // load the elements
2030 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2031 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
2033 outelements[j*3+2] = BigLong(renderlist[0]);
2034 outelements[j*3+1] = BigLong(renderlist[1]);
2035 outelements[j*3+0] = BigLong(renderlist[2]);
2037 // validate the elements and find the used vertex range
2038 firstvertex = meshvertices;
2040 for (j = 0;j < surface->num_triangles * 3;j++)
2042 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
2043 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
2044 firstvertex = min(firstvertex, outelements[j]);
2045 lastvertex = max(lastvertex, outelements[j]);
2047 surface->num_firstvertex = firstvertex;
2048 surface->num_vertices = lastvertex + 1 - firstvertex;
2050 // since zym models do not have named sections, reuse their shader
2051 // name as the section name
2052 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
2053 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
2055 Mod_FreeSkinFiles(skinfiles);
2056 Mem_Free(vertbonecounts);
2058 Mod_MakeSortedSurfaces(loadmodel);
2060 // compute all the mesh information that was not loaded from the file
2061 if (loadmodel->surfmesh.data_element3s)
2062 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2063 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2064 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2065 Mod_BuildBaseBonePoses();
2066 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);
2067 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);
2068 if (loadmodel->surfmesh.data_neighbor3i)
2069 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2071 if (!loadmodel->surfmesh.isanimated)
2073 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2074 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2075 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2076 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2077 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2078 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2081 // because shaders can do somewhat unexpected things, check for unusual features now
2082 for (i = 0;i < loadmodel->num_textures;i++)
2084 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
2085 mod->DrawSky = R_Q1BSP_DrawSky;
2086 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
2087 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
2091 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2093 dpmheader_t *pheader;
2097 unsigned char *pbase;
2098 int i, j, k, meshvertices, meshtriangles;
2099 skinfile_t *skinfiles;
2100 unsigned char *data;
2102 float biggestorigin, tempvec[3], modelscale;
2106 pheader = (dpmheader_t *)buffer;
2107 pbase = (unsigned char *)buffer;
2108 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2109 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2110 if (BigLong(pheader->type) != 2)
2111 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2113 loadmodel->modeldatatypestring = "DPM";
2115 loadmodel->type = mod_alias;
2116 loadmodel->synctype = ST_RAND;
2119 pheader->type = BigLong(pheader->type);
2120 pheader->filesize = BigLong(pheader->filesize);
2121 pheader->mins[0] = BigFloat(pheader->mins[0]);
2122 pheader->mins[1] = BigFloat(pheader->mins[1]);
2123 pheader->mins[2] = BigFloat(pheader->mins[2]);
2124 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2125 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2126 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2127 pheader->yawradius = BigFloat(pheader->yawradius);
2128 pheader->allradius = BigFloat(pheader->allradius);
2129 pheader->num_bones = BigLong(pheader->num_bones);
2130 pheader->num_meshs = BigLong(pheader->num_meshs);
2131 pheader->num_frames = BigLong(pheader->num_frames);
2132 pheader->ofs_bones = BigLong(pheader->ofs_bones);
2133 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2134 pheader->ofs_frames = BigLong(pheader->ofs_frames);
2136 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2138 Con_Printf("%s has no geometry\n", loadmodel->name);
2141 if (pheader->num_frames < 1)
2143 Con_Printf("%s has no frames\n", loadmodel->name);
2147 loadmodel->DrawSky = NULL;
2148 loadmodel->DrawAddWaterPlanes = NULL;
2149 loadmodel->Draw = R_Q1BSP_Draw;
2150 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2151 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2152 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2153 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2154 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2155 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2156 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2157 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2158 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2159 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2160 loadmodel->PointSuperContents = NULL;
2163 for (i = 0;i < 3;i++)
2165 loadmodel->normalmins[i] = pheader->mins[i];
2166 loadmodel->normalmaxs[i] = pheader->maxs[i];
2167 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2168 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2169 loadmodel->rotatedmins[i] = -pheader->allradius;
2170 loadmodel->rotatedmaxs[i] = pheader->allradius;
2172 loadmodel->radius = pheader->allradius;
2173 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2175 // load external .skin files if present
2176 skinfiles = Mod_LoadSkinFiles();
2177 if (loadmodel->numskins < 1)
2178 loadmodel->numskins = 1;
2183 // gather combined statistics from the meshes
2184 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2185 for (i = 0;i < (int)pheader->num_meshs;i++)
2187 int numverts = BigLong(dpmmesh->num_verts);
2188 meshvertices += numverts;
2189 meshtriangles += BigLong(dpmmesh->num_tris);
2193 loadmodel->numframes = pheader->num_frames;
2194 loadmodel->num_bones = pheader->num_bones;
2195 loadmodel->num_poses = loadmodel->numframes;
2196 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2197 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2198 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2199 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
2200 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
2201 // do most allocations as one merged chunk
2202 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + (r_enableshadowvolumes.integer ? meshtriangles * sizeof(int[3]) : 0) + meshvertices * (sizeof(float[14]) + sizeof(unsigned short)) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
2203 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2204 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2205 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2206 loadmodel->surfmesh.num_vertices = meshvertices;
2207 loadmodel->surfmesh.num_triangles = meshtriangles;
2208 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2209 if (r_enableshadowvolumes.integer)
2211 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2213 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2214 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2215 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2216 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2217 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2218 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2219 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2220 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2221 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2222 loadmodel->surfmesh.num_blends = 0;
2223 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2224 if (meshvertices <= 65536)
2226 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2228 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2229 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
2231 for (i = 0;i < loadmodel->numskins;i++)
2233 loadmodel->skinscenes[i].firstframe = i;
2234 loadmodel->skinscenes[i].framecount = 1;
2235 loadmodel->skinscenes[i].loop = true;
2236 loadmodel->skinscenes[i].framerate = 10;
2239 // load the bone info
2240 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2241 for (i = 0;i < loadmodel->num_bones;i++)
2243 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2244 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2245 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2246 if (loadmodel->data_bones[i].parent >= i)
2247 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2251 frames = (dpmframe_t *) (pbase + pheader->ofs_frames);
2252 // figure out scale of model from root bone, for compatibility with old dpmodel versions
2253 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2254 tempvec[0] = BigFloat(poses[0]);
2255 tempvec[1] = BigFloat(poses[1]);
2256 tempvec[2] = BigFloat(poses[2]);
2257 modelscale = VectorLength(tempvec);
2259 for (i = 0;i < loadmodel->numframes;i++)
2261 memcpy(loadmodel->animscenes[i].name, frames[i].name, sizeof(frames[i].name));
2262 loadmodel->animscenes[i].firstframe = i;
2263 loadmodel->animscenes[i].framecount = 1;
2264 loadmodel->animscenes[i].loop = true;
2265 loadmodel->animscenes[i].framerate = 10;
2266 // load the bone poses for this frame
2267 poses = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2268 for (j = 0;j < loadmodel->num_bones*12;j++)
2270 f = fabs(BigFloat(poses[j]));
2271 biggestorigin = max(biggestorigin, f);
2273 // stuff not processed here: mins, maxs, yawradius, allradius
2275 loadmodel->num_posescale = biggestorigin / 32767.0f;
2276 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2277 for (i = 0;i < loadmodel->numframes;i++)
2279 const float *frameposes = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2280 for (j = 0;j < loadmodel->num_bones;j++)
2283 matrix4x4_t posematrix;
2284 for (k = 0;k < 12;k++)
2285 pose[k] = BigFloat(frameposes[j*12+k]);
2286 // scale child bones to match the root scale
2287 if (loadmodel->data_bones[j].parent >= 0)
2289 pose[3] *= modelscale;
2290 pose[7] *= modelscale;
2291 pose[11] *= modelscale;
2293 // normalize rotation matrix
2294 VectorNormalize(pose + 0);
2295 VectorNormalize(pose + 4);
2296 VectorNormalize(pose + 8);
2297 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2298 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
2302 // load the meshes now
2303 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2306 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2307 // (converting from weight-blending skeletal animation to
2308 // deformation-based skeletal animation)
2309 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2310 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2311 for (i = 0;i < loadmodel->num_bones;i++)
2314 for (k = 0;k < 12;k++)
2315 m[k] = BigFloat(poses[i*12+k]);
2316 if (loadmodel->data_bones[i].parent >= 0)
2317 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2319 for (k = 0;k < 12;k++)
2320 bonepose[12*i+k] = m[k];
2322 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2324 const int *inelements;
2326 const float *intexcoord;
2327 msurface_t *surface;
2329 loadmodel->sortedmodelsurfaces[i] = i;
2330 surface = loadmodel->data_surfaces + i;
2331 surface->texture = loadmodel->data_textures + i;
2332 surface->num_firsttriangle = meshtriangles;
2333 surface->num_triangles = BigLong(dpmmesh->num_tris);
2334 surface->num_firstvertex = meshvertices;
2335 surface->num_vertices = BigLong(dpmmesh->num_verts);
2336 meshvertices += surface->num_vertices;
2337 meshtriangles += surface->num_triangles;
2339 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2340 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2341 for (j = 0;j < surface->num_triangles;j++)
2343 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2344 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2345 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2346 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2351 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2352 for (j = 0;j < surface->num_vertices*2;j++)
2353 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2355 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2356 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2358 int weightindex[4] = { 0, 0, 0, 0 };
2359 float weightinfluence[4] = { 0, 0, 0, 0 };
2361 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2362 data += sizeof(dpmvertex_t);
2363 for (k = 0;k < numweights;k++)
2365 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2366 int boneindex = BigLong(vert->bonenum);
2367 const float *m = bonepose + 12 * boneindex;
2368 float influence = BigFloat(vert->influence);
2369 float relativeorigin[3], relativenormal[3];
2370 relativeorigin[0] = BigFloat(vert->origin[0]);
2371 relativeorigin[1] = BigFloat(vert->origin[1]);
2372 relativeorigin[2] = BigFloat(vert->origin[2]);
2373 relativenormal[0] = BigFloat(vert->normal[0]);
2374 relativenormal[1] = BigFloat(vert->normal[1]);
2375 relativenormal[2] = BigFloat(vert->normal[2]);
2376 // blend the vertex bone weights into the base mesh
2377 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2378 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2379 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2380 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2381 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2382 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2385 // store the first (and often only) weight
2386 weightinfluence[0] = influence;
2387 weightindex[0] = boneindex;
2391 // sort the new weight into this vertex's weight table
2392 // (which only accepts up to 4 bones per vertex)
2393 for (l = 0;l < 4;l++)
2395 if (weightinfluence[l] < influence)
2397 // move weaker influence weights out of the way first
2399 for (l2 = 3;l2 > l;l2--)
2401 weightinfluence[l2] = weightinfluence[l2-1];
2402 weightindex[l2] = weightindex[l2-1];
2404 // store the new weight
2405 weightinfluence[l] = influence;
2406 weightindex[l] = boneindex;
2411 data += sizeof(dpmbonevert_t);
2413 loadmodel->surfmesh.blends[j] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
2416 // since dpm models do not have named sections, reuse their shader name as the section name
2417 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2419 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2421 if (loadmodel->surfmesh.num_blends < meshvertices)
2422 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2424 Mod_FreeSkinFiles(skinfiles);
2425 Mod_MakeSortedSurfaces(loadmodel);
2427 // compute all the mesh information that was not loaded from the file
2428 if (loadmodel->surfmesh.data_element3s)
2429 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2430 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2431 Mod_BuildBaseBonePoses();
2432 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);
2433 if (loadmodel->surfmesh.data_neighbor3i)
2434 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2436 if (!loadmodel->surfmesh.isanimated)
2438 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2439 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2440 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2441 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2442 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2443 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2446 // because shaders can do somewhat unexpected things, check for unusual features now
2447 for (i = 0;i < loadmodel->num_textures;i++)
2449 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
2450 mod->DrawSky = R_Q1BSP_DrawSky;
2451 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
2452 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
2456 // no idea why PSK/PSA files contain weird quaternions but they do...
2457 #define PSKQUATNEGATIONS
2458 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2460 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2461 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2462 fs_offset_t filesize;
2467 pskboneinfo_t *bones;
2468 pskrawweights_t *rawweights;
2469 //pskboneinfo_t *animbones;
2470 pskaniminfo_t *anims;
2471 pskanimkeys_t *animkeys;
2472 void *animfilebuffer, *animbuffer, *animbufferend;
2473 unsigned char *data;
2475 skinfile_t *skinfiles;
2476 char animname[MAX_QPATH];
2478 float biggestorigin;
2480 pchunk = (pskchunk_t *)buffer;
2481 if (strcmp(pchunk->id, "ACTRHEAD"))
2482 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2484 loadmodel->modeldatatypestring = "PSK";
2486 loadmodel->type = mod_alias;
2487 loadmodel->DrawSky = NULL;
2488 loadmodel->DrawAddWaterPlanes = NULL;
2489 loadmodel->Draw = R_Q1BSP_Draw;
2490 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2491 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2492 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2493 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2494 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2495 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2496 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2497 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2498 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2499 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2500 loadmodel->PointSuperContents = NULL;
2501 loadmodel->synctype = ST_RAND;
2503 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2504 strlcat(animname, ".psa", sizeof(animname));
2505 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2506 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2507 if (animbuffer == NULL)
2508 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2527 while (buffer < bufferend)
2529 pchunk = (pskchunk_t *)buffer;
2530 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2531 version = LittleLong(pchunk->version);
2532 recordsize = LittleLong(pchunk->recordsize);
2533 numrecords = LittleLong(pchunk->numrecords);
2534 if (developer_extra.integer)
2535 Con_DPrintf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2536 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2537 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);
2538 if (!strcmp(pchunk->id, "ACTRHEAD"))
2542 else if (!strcmp(pchunk->id, "PNTS0000"))
2545 if (recordsize != sizeof(*p))
2546 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2547 // byteswap in place and keep the pointer
2548 numpnts = numrecords;
2549 pnts = (pskpnts_t *)buffer;
2550 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2552 p->origin[0] = LittleFloat(p->origin[0]);
2553 p->origin[1] = LittleFloat(p->origin[1]);
2554 p->origin[2] = LittleFloat(p->origin[2]);
2558 else if (!strcmp(pchunk->id, "VTXW0000"))
2561 if (recordsize != sizeof(*p))
2562 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2563 // byteswap in place and keep the pointer
2564 numvtxw = numrecords;
2565 vtxw = (pskvtxw_t *)buffer;
2566 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2568 p->pntsindex = LittleShort(p->pntsindex);
2569 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2570 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2571 if (p->pntsindex >= numpnts)
2573 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2579 else if (!strcmp(pchunk->id, "FACE0000"))
2582 if (recordsize != sizeof(*p))
2583 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2584 // byteswap in place and keep the pointer
2585 numfaces = numrecords;
2586 faces = (pskface_t *)buffer;
2587 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2589 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2590 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2591 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2592 p->group = LittleLong(p->group);
2593 if (p->vtxwindex[0] >= numvtxw)
2595 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2596 p->vtxwindex[0] = 0;
2598 if (p->vtxwindex[1] >= numvtxw)
2600 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2601 p->vtxwindex[1] = 0;
2603 if (p->vtxwindex[2] >= numvtxw)
2605 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2606 p->vtxwindex[2] = 0;
2611 else if (!strcmp(pchunk->id, "MATT0000"))
2614 if (recordsize != sizeof(*p))
2615 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2616 // byteswap in place and keep the pointer
2617 nummatts = numrecords;
2618 matts = (pskmatt_t *)buffer;
2619 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2625 else if (!strcmp(pchunk->id, "REFSKELT"))
2628 if (recordsize != sizeof(*p))
2629 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2630 // byteswap in place and keep the pointer
2631 numbones = numrecords;
2632 bones = (pskboneinfo_t *)buffer;
2633 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2635 p->numchildren = LittleLong(p->numchildren);
2636 p->parent = LittleLong(p->parent);
2637 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2638 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2639 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2640 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2641 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2642 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2643 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2644 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2645 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2646 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2647 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2648 #ifdef PSKQUATNEGATIONS
2651 p->basepose.quat[0] *= -1;
2652 p->basepose.quat[1] *= -1;
2653 p->basepose.quat[2] *= -1;
2657 p->basepose.quat[0] *= 1;
2658 p->basepose.quat[1] *= -1;
2659 p->basepose.quat[2] *= 1;
2662 if (p->parent < 0 || p->parent >= numbones)
2664 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2670 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2673 if (recordsize != sizeof(*p))
2674 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2675 // byteswap in place and keep the pointer
2676 numrawweights = numrecords;
2677 rawweights = (pskrawweights_t *)buffer;
2678 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2680 p->weight = LittleFloat(p->weight);
2681 p->pntsindex = LittleLong(p->pntsindex);
2682 p->boneindex = LittleLong(p->boneindex);
2683 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2685 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2688 if (p->boneindex < 0 || p->boneindex >= numbones)
2690 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2698 while (animbuffer < animbufferend)
2700 pchunk = (pskchunk_t *)animbuffer;
2701 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2702 version = LittleLong(pchunk->version);
2703 recordsize = LittleLong(pchunk->recordsize);
2704 numrecords = LittleLong(pchunk->numrecords);
2705 if (developer_extra.integer)
2706 Con_DPrintf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2707 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2708 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);
2709 if (!strcmp(pchunk->id, "ANIMHEAD"))
2713 else if (!strcmp(pchunk->id, "BONENAMES"))
2716 if (recordsize != sizeof(*p))
2717 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2718 // byteswap in place and keep the pointer
2719 numanimbones = numrecords;
2720 //animbones = (pskboneinfo_t *)animbuffer;
2721 // NOTE: supposedly psa does not need to match the psk model, the
2722 // bones missing from the psa would simply use their base
2723 // positions from the psk, but this is hard for me to implement
2724 // and people can easily make animations that match.
2725 if (numanimbones != numbones)
2726 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2727 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2729 p->numchildren = LittleLong(p->numchildren);
2730 p->parent = LittleLong(p->parent);
2731 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2732 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2733 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2734 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2735 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2736 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2737 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2738 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2739 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2740 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2741 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2742 #ifdef PSKQUATNEGATIONS
2745 p->basepose.quat[0] *= -1;
2746 p->basepose.quat[1] *= -1;
2747 p->basepose.quat[2] *= -1;
2751 p->basepose.quat[0] *= 1;
2752 p->basepose.quat[1] *= -1;
2753 p->basepose.quat[2] *= 1;
2756 if (p->parent < 0 || p->parent >= numanimbones)
2758 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2761 // check that bones are the same as in the base
2762 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2763 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2767 else if (!strcmp(pchunk->id, "ANIMINFO"))
2770 if (recordsize != sizeof(*p))
2771 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2772 // byteswap in place and keep the pointer
2773 numanims = numrecords;
2774 anims = (pskaniminfo_t *)animbuffer;
2775 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2777 p->numbones = LittleLong(p->numbones);
2778 p->playtime = LittleFloat(p->playtime);
2779 p->fps = LittleFloat(p->fps);
2780 p->firstframe = LittleLong(p->firstframe);
2781 p->numframes = LittleLong(p->numframes);
2782 if (p->numbones != numbones)
2783 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2787 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2790 if (recordsize != sizeof(*p))
2791 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2792 numanimkeys = numrecords;
2793 animkeys = (pskanimkeys_t *)animbuffer;
2794 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2796 p->origin[0] = LittleFloat(p->origin[0]);
2797 p->origin[1] = LittleFloat(p->origin[1]);
2798 p->origin[2] = LittleFloat(p->origin[2]);
2799 p->quat[0] = LittleFloat(p->quat[0]);
2800 p->quat[1] = LittleFloat(p->quat[1]);
2801 p->quat[2] = LittleFloat(p->quat[2]);
2802 p->quat[3] = LittleFloat(p->quat[3]);
2803 p->frametime = LittleFloat(p->frametime);
2804 #ifdef PSKQUATNEGATIONS
2805 if (index % numbones)
2820 // TODO: allocate bonepose stuff
2823 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2826 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2827 Host_Error("%s: missing required chunks", loadmodel->name);
2829 loadmodel->numframes = 0;
2830 for (index = 0;index < numanims;index++)
2831 loadmodel->numframes += anims[index].numframes;
2833 if (numanimkeys != numbones * loadmodel->numframes)
2834 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2836 meshvertices = numvtxw;
2837 meshtriangles = numfaces;
2839 // load external .skin files if present
2840 skinfiles = Mod_LoadSkinFiles();
2841 if (loadmodel->numskins < 1)
2842 loadmodel->numskins = 1;
2843 loadmodel->num_bones = numbones;
2844 loadmodel->num_poses = loadmodel->numframes;
2845 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2846 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2847 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2848 loadmodel->surfmesh.num_vertices = meshvertices;
2849 loadmodel->surfmesh.num_triangles = meshtriangles;
2850 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
2851 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
2852 // do most allocations as one merged chunk
2853 size = loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + loadmodel->surfmesh.num_triangles * sizeof(int[3]) + (r_enableshadowvolumes.integer ? loadmodel->surfmesh.num_triangles * sizeof(int[3]) : 0) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[2]) + loadmodel->surfmesh.num_vertices * sizeof(unsigned short) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]) + 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);
2854 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2855 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2856 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2857 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2858 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2859 if (r_enableshadowvolumes.integer)
2861 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2863 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2864 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2865 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2866 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2867 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2868 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2869 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2870 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2871 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2872 loadmodel->surfmesh.num_blends = 0;
2873 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2874 if (loadmodel->surfmesh.num_vertices <= 65536)
2876 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2878 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2879 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(blendweights_t));
2881 for (i = 0;i < loadmodel->numskins;i++)
2883 loadmodel->skinscenes[i].firstframe = i;
2884 loadmodel->skinscenes[i].framecount = 1;
2885 loadmodel->skinscenes[i].loop = true;
2886 loadmodel->skinscenes[i].framerate = 10;
2890 for (index = 0, i = 0;index < nummatts;index++)
2892 // since psk models do not have named sections, reuse their shader name as the section name
2893 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2894 loadmodel->sortedmodelsurfaces[index] = index;
2895 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2896 loadmodel->data_surfaces[index].num_firstvertex = 0;
2897 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2900 // copy over the vertex locations and texcoords
2901 for (index = 0;index < numvtxw;index++)
2903 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2904 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2905 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2906 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2907 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2910 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2911 for (index = 0;index < numfaces;index++)
2912 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2913 for (index = 0, i = 0;index < nummatts;index++)
2915 loadmodel->data_surfaces[index].num_firsttriangle = i;
2916 i += loadmodel->data_surfaces[index].num_triangles;
2917 loadmodel->data_surfaces[index].num_triangles = 0;
2919 for (index = 0;index < numfaces;index++)
2921 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2922 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2923 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2924 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2927 // copy over the bones
2928 for (index = 0;index < numbones;index++)
2930 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2931 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2932 if (loadmodel->data_bones[index].parent >= index)
2933 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2936 // sort the psk point weights into the vertex weight tables
2937 // (which only accept up to 4 bones per vertex)
2938 for (index = 0;index < numvtxw;index++)
2940 int weightindex[4] = { 0, 0, 0, 0 };
2941 float weightinfluence[4] = { 0, 0, 0, 0 };
2943 for (j = 0;j < numrawweights;j++)
2945 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2947 int boneindex = rawweights[j].boneindex;
2948 float influence = rawweights[j].weight;
2949 for (l = 0;l < 4;l++)
2951 if (weightinfluence[l] < influence)
2953 // move lower influence weights out of the way first
2955 for (l2 = 3;l2 > l;l2--)
2957 weightinfluence[l2] = weightinfluence[l2-1];
2958 weightindex[l2] = weightindex[l2-1];
2960 // store the new weight
2961 weightinfluence[l] = influence;
2962 weightindex[l] = boneindex;
2968 loadmodel->surfmesh.blends[index] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
2970 if (loadmodel->surfmesh.num_blends < loadmodel->surfmesh.num_vertices)
2971 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2973 // set up the animscenes based on the anims
2974 for (index = 0, i = 0;index < numanims;index++)
2976 for (j = 0;j < anims[index].numframes;j++, i++)
2978 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2979 loadmodel->animscenes[i].firstframe = i;
2980 loadmodel->animscenes[i].framecount = 1;
2981 loadmodel->animscenes[i].loop = true;
2982 loadmodel->animscenes[i].framerate = anims[index].fps;
2986 // calculate the scaling value for bone origins so they can be compressed to short
2988 for (index = 0;index < numanimkeys;index++)
2990 pskanimkeys_t *k = animkeys + index;
2991 biggestorigin = max(biggestorigin, fabs(k->origin[0]));
2992 biggestorigin = max(biggestorigin, fabs(k->origin[1]));
2993 biggestorigin = max(biggestorigin, fabs(k->origin[2]));
2995 loadmodel->num_posescale = biggestorigin / 32767.0f;
2996 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2998 // load the poses from the animkeys
2999 for (index = 0;index < numanimkeys;index++)
3001 pskanimkeys_t *k = animkeys + index;
3003 Vector4Copy(k->quat, quat);
3005 Vector4Negate(quat, quat);
3006 Vector4Normalize2(quat, quat);
3007 // compress poses to the short[6] format for longterm storage
3008 loadmodel->data_poses6s[index*6+0] = k->origin[0] * loadmodel->num_poseinvscale;
3009 loadmodel->data_poses6s[index*6+1] = k->origin[1] * loadmodel->num_poseinvscale;
3010 loadmodel->data_poses6s[index*6+2] = k->origin[2] * loadmodel->num_poseinvscale;
3011 loadmodel->data_poses6s[index*6+3] = quat[0] * 32767.0f;
3012 loadmodel->data_poses6s[index*6+4] = quat[1] * 32767.0f;
3013 loadmodel->data_poses6s[index*6+5] = quat[2] * 32767.0f;
3015 Mod_FreeSkinFiles(skinfiles);
3016 Mem_Free(animfilebuffer);
3017 Mod_MakeSortedSurfaces(loadmodel);
3019 // compute all the mesh information that was not loaded from the file
3020 // TODO: honor smoothing groups somehow?
3021 if (loadmodel->surfmesh.data_element3s)
3022 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3023 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3024 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
3025 Mod_BuildBaseBonePoses();
3026 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);
3027 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);
3028 if (loadmodel->surfmesh.data_neighbor3i)
3029 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3030 Mod_Alias_CalculateBoundingBox();
3032 if (!loadmodel->surfmesh.isanimated)
3034 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3035 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3036 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3037 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3038 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3039 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
3042 // because shaders can do somewhat unexpected things, check for unusual features now
3043 for (i = 0;i < loadmodel->num_textures;i++)
3045 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
3046 mod->DrawSky = R_Q1BSP_DrawSky;
3047 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
3048 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
3052 void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
3054 unsigned char *data;
3056 const unsigned char *pbase, *pend;
3058 skinfile_t *skinfiles;
3059 int i, j, k, meshvertices, meshtriangles;
3060 float biggestorigin;
3061 const unsigned int *inelements;
3063 const int *inneighbors;
3065 float *outvertex, *outnormal, *outtexcoord, *outsvector, *outtvector, *outcolor;
3066 // this pointers into the file data are read only through Little* functions so they can be unaligned memory
3067 const float *vnormal = NULL;
3068 const float *vposition = NULL;
3069 const float *vtangent = NULL;
3070 const float *vtexcoord = NULL;
3071 const float *vcolor4f = NULL;
3072 const unsigned char *vblendindexes = NULL;
3073 const unsigned char *vblendweights = NULL;
3074 const unsigned char *vcolor4ub = NULL;
3075 const unsigned short *framedata = NULL;
3076 // temporary memory allocations (because the data in the file may be misaligned)
3077 iqmanim_t *anims = NULL;
3078 iqmbounds_t *bounds = NULL;
3079 iqmjoint1_t *joint1 = NULL;
3080 iqmjoint_t *joint = NULL;
3081 iqmmesh_t *meshes = NULL;
3082 iqmpose1_t *pose1 = NULL;
3083 iqmpose_t *pose = NULL;
3084 iqmvertexarray_t *vas = NULL;
3086 pbase = (unsigned char *)buffer;
3087 pend = (unsigned char *)bufferend;
3089 if (pbase + sizeof(iqmheader_t) > pend)
3090 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model %d", loadmodel->name, (int)(pend - pbase));
3092 // copy struct (otherwise it may be misaligned)
3093 // LordHavoc: okay it's definitely not misaligned here, but for consistency...
3094 memcpy(&header, pbase, sizeof(iqmheader_t));
3096 if (memcmp(header.id, "INTERQUAKEMODEL", 16))
3097 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model", loadmodel->name);
3098 if (LittleLong(header.version) != 1 && LittleLong(header.version) != 2)
3099 Host_Error ("Mod_INTERQUAKEMODEL_Load: only version 1 and 2 models are currently supported (name = %s)", loadmodel->name);
3101 loadmodel->modeldatatypestring = "IQM";
3103 loadmodel->type = mod_alias;
3104 loadmodel->synctype = ST_RAND;
3107 header.version = LittleLong(header.version);
3108 header.filesize = LittleLong(header.filesize);
3109 header.flags = LittleLong(header.flags);
3110 header.num_text = LittleLong(header.num_text);
3111 header.ofs_text = LittleLong(header.ofs_text);
3112 header.num_meshes = LittleLong(header.num_meshes);
3113 header.ofs_meshes = LittleLong(header.ofs_meshes);
3114 header.num_vertexarrays = LittleLong(header.num_vertexarrays);
3115 header.num_vertexes = LittleLong(header.num_vertexes);
3116 header.ofs_vertexarrays = LittleLong(header.ofs_vertexarrays);
3117 header.num_triangles = LittleLong(header.num_triangles);
3118 header.ofs_triangles = LittleLong(header.ofs_triangles);
3119 header.ofs_neighbors = LittleLong(header.ofs_neighbors);
3120 header.num_joints = LittleLong(header.num_joints);
3121 header.ofs_joints = LittleLong(header.ofs_joints);
3122 header.num_poses = LittleLong(header.num_poses);
3123 header.ofs_poses = LittleLong(header.ofs_poses);
3124 header.num_anims = LittleLong(header.num_anims);
3125 header.ofs_anims = LittleLong(header.ofs_anims);
3126 header.num_frames = LittleLong(header.num_frames);
3127 header.num_framechannels = LittleLong(header.num_framechannels);
3128 header.ofs_frames = LittleLong(header.ofs_frames);
3129 header.ofs_bounds = LittleLong(header.ofs_bounds);
3130 header.num_comment = LittleLong(header.num_comment);
3131 header.ofs_comment = LittleLong(header.ofs_comment);
3132 header.num_extensions = LittleLong(header.num_extensions);
3133 header.ofs_extensions = LittleLong(header.ofs_extensions);
3135 if (header.version == 1)
3137 if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint1_t) > pend ||
3138 pbase + header.ofs_poses + header.num_poses*sizeof(iqmpose1_t) > pend)
3140 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3146 if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint_t) > pend ||
3147 pbase + header.ofs_poses + header.num_poses*sizeof(iqmpose_t) > pend)
3149 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3153 if (pbase + header.ofs_text + header.num_text > pend ||
3154 pbase + header.ofs_meshes + header.num_meshes*sizeof(iqmmesh_t) > pend ||
3155 pbase + header.ofs_vertexarrays + header.num_vertexarrays*sizeof(iqmvertexarray_t) > pend ||
3156 pbase + header.ofs_triangles + header.num_triangles*sizeof(int[3]) > pend ||
3157 (header.ofs_neighbors && pbase + header.ofs_neighbors + header.num_triangles*sizeof(int[3]) > pend) ||
3158 pbase + header.ofs_anims + header.num_anims*sizeof(iqmanim_t) > pend ||
3159 pbase + header.ofs_frames + header.num_frames*header.num_framechannels*sizeof(unsigned short) > pend ||
3160 (header.ofs_bounds && pbase + header.ofs_bounds + header.num_frames*sizeof(iqmbounds_t) > pend) ||
3161 pbase + header.ofs_comment + header.num_comment > pend)
3163 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3167 // copy structs to make them aligned in memory (otherwise we crash on Sparc and PowerPC and others)
3168 if (header.num_vertexarrays)
3169 vas = (iqmvertexarray_t *)(pbase + header.ofs_vertexarrays);
3170 if (header.num_anims)
3171 anims = (iqmanim_t *)(pbase + header.ofs_anims);
3172 if (header.ofs_bounds)
3173 bounds = (iqmbounds_t *)(pbase + header.ofs_bounds);
3174 if (header.num_meshes)
3175 meshes = (iqmmesh_t *)(pbase + header.ofs_meshes);
3177 for (i = 0;i < (int)header.num_vertexarrays;i++)
3179 iqmvertexarray_t va;
3181 va.type = LittleLong(vas[i].type);
3182 va.flags = LittleLong(vas[i].flags);
3183 va.format = LittleLong(vas[i].format);
3184 va.size = LittleLong(vas[i].size);
3185 va.offset = LittleLong(vas[i].offset);
3186 vsize = header.num_vertexes*va.size;
3189 case IQM_FLOAT: vsize *= sizeof(float); break;
3190 case IQM_UBYTE: vsize *= sizeof(unsigned char); break;
3193 if (pbase + va.offset + vsize > pend)
3195 // no need to copy the vertex data for alignment because LittleLong/LittleShort will be invoked on reading them, and the destination is aligned
3199 if (va.format == IQM_FLOAT && va.size == 3)
3200 vposition = (const float *)(pbase + va.offset);
3203 if (va.format == IQM_FLOAT && va.size == 2)
3204 vtexcoord = (const float *)(pbase + va.offset);
3207 if (va.format == IQM_FLOAT && va.size == 3)
3208 vnormal = (const float *)(pbase + va.offset);
3211 if (va.format == IQM_FLOAT && va.size == 4)
3212 vtangent = (const float *)(pbase + va.offset);
3214 case IQM_BLENDINDEXES:
3215 if (va.format == IQM_UBYTE && va.size == 4)
3216 vblendindexes = (const unsigned char *)(pbase + va.offset);
3218 case IQM_BLENDWEIGHTS:
3219 if (va.format == IQM_UBYTE && va.size == 4)
3220 vblendweights = (const unsigned char *)(pbase + va.offset);
3223 if (va.format == IQM_FLOAT && va.size == 4)
3224 vcolor4f = (const float *)(pbase + va.offset);
3225 if (va.format == IQM_UBYTE && va.size == 4)
3226 vcolor4ub = (const unsigned char *)(pbase + va.offset);
3230 if (header.num_vertexes > 0 && (!vposition || !vtexcoord || ((header.num_frames > 0 || header.num_anims > 0) && (!vblendindexes || !vblendweights))))
3232 Con_Printf("%s is missing vertex array data\n", loadmodel->name);
3236 text = header.num_text && header.ofs_text ? (const char *)(pbase + header.ofs_text) : "";
3238 loadmodel->DrawSky = NULL;
3239 loadmodel->DrawAddWaterPlanes = NULL;
3240 loadmodel->Draw = R_Q1BSP_Draw;
3241 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
3242 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
3243 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
3244 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
3245 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
3246 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
3247 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
3248 loadmodel->DrawLight = R_Q1BSP_DrawLight;
3249 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
3250 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
3251 loadmodel->PointSuperContents = NULL;
3253 // load external .skin files if present
3254 skinfiles = Mod_LoadSkinFiles();
3255 if (loadmodel->numskins < 1)
3256 loadmodel->numskins = 1;
3258 loadmodel->numframes = max(header.num_anims, 1);
3259 loadmodel->num_bones = header.num_joints;
3260 loadmodel->num_poses = max(header.num_frames, 1);
3261 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = header.num_meshes;
3262 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3263 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3264 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices; // updated later
3266 meshvertices = header.num_vertexes;
3267 meshtriangles = header.num_triangles;
3269 // do most allocations as one merged chunk
3270 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + (r_enableshadowvolumes.integer ? meshtriangles * sizeof(int[3]) : 0) + meshvertices * (sizeof(float[14]) + (vcolor4f || vcolor4ub ? sizeof(float[4]) : 0)) + (vblendindexes && vblendweights ? meshvertices * sizeof(unsigned short) : 0) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
3271 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
3272 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
3273 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
3274 loadmodel->surfmesh.num_vertices = meshvertices;
3275 loadmodel->surfmesh.num_triangles = meshtriangles;
3276 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3277 if (r_enableshadowvolumes.integer)
3279 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3281 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
3282 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3283 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3284 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
3285 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
3286 if (vcolor4f || vcolor4ub)
3288 loadmodel->surfmesh.data_lightmapcolor4f = (float *)data;data += meshvertices * sizeof(float[4]);
3290 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
3291 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
3292 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
3293 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
3294 if (vblendindexes && vblendweights)
3296 loadmodel->surfmesh.num_blends = 0;
3297 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
3299 if (meshvertices <= 65536)
3301 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
3303 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
3304 if (vblendindexes && vblendweights)
3305 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
3307 for (i = 0;i < loadmodel->numskins;i++)
3309 loadmodel->skinscenes[i].firstframe = i;
3310 loadmodel->skinscenes[i].framecount = 1;
3311 loadmodel->skinscenes[i].loop = true;
3312 loadmodel->skinscenes[i].framerate = 10;
3315 // load the bone info
3316 if (header.version == 1)
3318 iqmjoint1_t *injoint1 = (iqmjoint1_t *)(pbase + header.ofs_joints);
3319 if (loadmodel->num_bones)
3320 joint1 = (iqmjoint1_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(iqmjoint1_t));
3321 for (i = 0;i < loadmodel->num_bones;i++)
3323 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3324 joint1[i].name = LittleLong(injoint1[i].name);
3325 joint1[i].parent = LittleLong(injoint1[i].parent);
3326 for (j = 0;j < 3;j++)
3328 joint1[i].origin[j] = LittleFloat(injoint1[i].origin[j]);
3329 joint1[i].rotation[j] = LittleFloat(injoint1[i].rotation[j]);
3330 joint1[i].scale[j] = LittleFloat(injoint1[i].scale[j]);
3332 strlcpy(loadmodel->data_bones[i].name, &text[joint1[i].name], sizeof(loadmodel->data_bones[i].name));
3333 loadmodel->data_bones[i].parent = joint1[i].parent;
3334 if (loadmodel->data_bones[i].parent >= i)
3335 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3336 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]);
3337 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3338 if (loadmodel->data_bones[i].parent >= 0)
3340 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3341 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3342 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3344 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3349 iqmjoint_t *injoint = (iqmjoint_t *)(pbase + header.ofs_joints);
3350 if (header.num_joints)
3351 joint = (iqmjoint_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(iqmjoint_t));
3352 for (i = 0;i < loadmodel->num_bones;i++)
3354 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3355 joint[i].name = LittleLong(injoint[i].name);
3356 joint[i].parent = LittleLong(injoint[i].parent);
3357 for (j = 0;j < 3;j++)
3359 joint[i].origin[j] = LittleFloat(injoint[i].origin[j]);
3360 joint[i].rotation[j] = LittleFloat(injoint[i].rotation[j]);
3361 joint[i].scale[j] = LittleFloat(injoint[i].scale[j]);
3363 joint[i].rotation[3] = LittleFloat(injoint[i].rotation[3]);
3364 strlcpy(loadmodel->data_bones[i].name, &text[joint[i].name], sizeof(loadmodel->data_bones[i].name));
3365 loadmodel->data_bones[i].parent = joint[i].parent;
3366 if (loadmodel->data_bones[i].parent >= i)
3367 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3368 if (joint[i].rotation[3] > 0)
3369 Vector4Negate(joint[i].rotation, joint[i].rotation);
3370 Vector4Normalize2(joint[i].rotation, joint[i].rotation);
3371 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]);
3372 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3373 if (loadmodel->data_bones[i].parent >= 0)
3375 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3376 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3377 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3379 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3383 // set up the animscenes based on the anims
3384 for (i = 0;i < (int)header.num_anims;i++)
3387 anim.name = LittleLong(anims[i].name);
3388 anim.first_frame = LittleLong(anims[i].first_frame);
3389 anim.num_frames = LittleLong(anims[i].num_frames);
3390 anim.framerate = LittleFloat(anims[i].framerate);
3391 anim.flags = LittleLong(anims[i].flags);
3392 strlcpy(loadmodel->animscenes[i].name, &text[anim.name], sizeof(loadmodel->animscenes[i].name));
3393 loadmodel->animscenes[i].firstframe = anim.first_frame;
3394 loadmodel->animscenes[i].framecount = anim.num_frames;
3395 loadmodel->animscenes[i].loop = ((anim.flags & IQM_LOOP) != 0);
3396 loadmodel->animscenes[i].framerate = anim.framerate;
3398 if (header.num_anims <= 0)
3400 strlcpy(loadmodel->animscenes[0].name, "static", sizeof(loadmodel->animscenes[0].name));
3401 loadmodel->animscenes[0].firstframe = 0;
3402 loadmodel->animscenes[0].framecount = 1;
3403 loadmodel->animscenes[0].loop = true;
3404 loadmodel->animscenes[0].framerate = 10;
3407 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
3408 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
3411 if (header.version == 1)
3413 iqmpose1_t *inpose1 = (iqmpose1_t *)(pbase + header.ofs_poses);
3414 if (header.num_poses)
3415 pose1 = (iqmpose1_t *)Mem_Alloc(loadmodel->mempool, header.num_poses * sizeof(iqmpose1_t));
3416 for (i = 0;i < (int)header.num_poses;i++)
3419 pose1[i].parent = LittleLong(inpose1[i].parent);
3420 pose1[i].channelmask = LittleLong(inpose1[i].channelmask);
3421 for (j = 0;j < 9;j++)
3423 pose1[i].channeloffset[j] = LittleFloat(inpose1[i].channeloffset[j]);
3424 pose1[i].channelscale[j] = LittleFloat(inpose1[i].channelscale[j]);
3426 f = fabs(pose1[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3427 f = fabs(pose1[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3428 f = fabs(pose1[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3429 f = fabs(pose1[i].channeloffset[0] + 0xFFFF*pose1[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3430 f = fabs(pose1[i].channeloffset[1] + 0xFFFF*pose1[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3431 f = fabs(pose1[i].channeloffset[2] + 0xFFFF*pose1[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3433 if (header.num_frames <= 0)
3435 for (i = 0;i < loadmodel->num_bones;i++)
3438 f = fabs(joint1[i].origin[0]); biggestorigin = max(biggestorigin, f);
3439 f = fabs(joint1[i].origin[1]); biggestorigin = max(biggestorigin, f);
3440 f = fabs(joint1[i].origin[2]); biggestorigin = max(biggestorigin, f);
3446 iqmpose_t *inpose = (iqmpose_t *)(pbase + header.ofs_poses);
3447 if (header.num_poses)
3448 pose = (iqmpose_t *)Mem_Alloc(loadmodel->mempool, header.num_poses * sizeof(iqmpose_t));
3449 for (i = 0;i < (int)header.num_poses;i++)
3452 pose[i].parent = LittleLong(inpose[i].parent);
3453 pose[i].channelmask = LittleLong(inpose[i].channelmask);
3454 for (j = 0;j < 10;j++)
3456 pose[i].channeloffset[j] = LittleFloat(inpose[i].channeloffset[j]);
3457 pose[i].channelscale[j] = LittleFloat(inpose[i].channelscale[j]);
3459 f = fabs(pose[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3460 f = fabs(pose[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3461 f = fabs(pose[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3462 f = fabs(pose[i].channeloffset[0] + 0xFFFF*pose[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3463 f = fabs(pose[i].channeloffset[1] + 0xFFFF*pose[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3464 f = fabs(pose[i].channeloffset[2] + 0xFFFF*pose[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3466 if (header.num_frames <= 0)
3468 for (i = 0;i < loadmodel->num_bones;i++)
3471 f = fabs(joint[i].origin[0]); biggestorigin = max(biggestorigin, f);
3472 f = fabs(joint[i].origin[1]); biggestorigin = max(biggestorigin, f);
3473 f = fabs(joint[i].origin[2]); biggestorigin = max(biggestorigin, f);
3477 loadmodel->num_posescale = biggestorigin / 32767.0f;
3478 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3480 // load the pose data
3481 // this unaligned memory access is safe (LittleShort reads as bytes)
3482 framedata = (const unsigned short *)(pbase + header.ofs_frames);
3483 if (header.version == 1)
3485 for (i = 0, k = 0;i < (int)header.num_frames;i++)
3487 for (j = 0;j < (int)header.num_poses;j++, k++)
3489 loadmodel->data_poses6s[k*6 + 0] = loadmodel->num_poseinvscale * (pose1[j].channeloffset[0] + (pose1[j].channelmask&1 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[0] : 0));
3490 loadmodel->data_poses6s[k*6 + 1] = loadmodel->num_poseinvscale * (pose1[j].channeloffset[1] + (pose1[j].channelmask&2 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[1] : 0));
3491 loadmodel->data_poses6s[k*6 + 2] = loadmodel->num_poseinvscale * (pose1[j].channeloffset[2] + (pose1[j].channelmask&4 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[2] : 0));
3492 loadmodel->data_poses6s[k*6 + 3] = 32767.0f * (pose1[j].channeloffset[3] + (pose1[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[3] : 0));
3493 loadmodel->data_poses6s[k*6 + 4] = 32767.0f * (pose1[j].channeloffset[4] + (pose1[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[4] : 0));
3494 loadmodel->data_poses6s[k*6 + 5] = 32767.0f * (pose1[j].channeloffset[5] + (pose1[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[5] : 0));
3495 // skip scale data for now
3496 if(pose1[j].channelmask&64) framedata++;
3497 if(pose1[j].channelmask&128) framedata++;
3498 if(pose1[j].channelmask&256) framedata++;
3501 if (header.num_frames <= 0)
3503 for (i = 0;i < loadmodel->num_bones;i++)
3505 loadmodel->data_poses6s[i*6 + 0] = loadmodel->num_poseinvscale * joint1[i].origin[0];
3506 loadmodel->data_poses6s[i*6 + 1] = loadmodel->num_poseinvscale * joint1[i].origin[1];
3507 loadmodel->data_poses6s[i*6 + 2] = loadmodel->num_poseinvscale * joint1[i].origin[2];
3508 loadmodel->data_poses6s[i*6 + 3] = 32767.0f * joint1[i].rotation[0];
3509 loadmodel->data_poses6s[i*6 + 4] = 32767.0f * joint1[i].rotation[1];
3510 loadmodel->data_poses6s[i*6 + 5] = 32767.0f * joint1[i].rotation[2];
3516 for (i = 0, k = 0;i < (int)header.num_frames;i++)
3518 for (j = 0;j < (int)header.num_poses;j++, k++)
3521 loadmodel->data_poses6s[k*6 + 0] = loadmodel->num_poseinvscale * (pose[j].channeloffset[0] + (pose[j].channelmask&1 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[0] : 0));
3522 loadmodel->data_poses6s[k*6 + 1] = loadmodel->num_poseinvscale * (pose[j].channeloffset[1] + (pose[j].channelmask&2 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[1] : 0));
3523 loadmodel->data_poses6s[k*6 + 2] = loadmodel->num_poseinvscale * (pose[j].channeloffset[2] + (pose[j].channelmask&4 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[2] : 0));
3524 rot[0] = pose[j].channeloffset[3] + (pose[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[3] : 0);
3525 rot[1] = pose[j].channeloffset[4] + (pose[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[4] : 0);
3526 rot[2] = pose[j].channeloffset[5] + (pose[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[5] : 0);
3527 rot[3] = pose[j].channeloffset[6] + (pose[j].channelmask&64 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[6] : 0);
3529 Vector4Negate(rot, rot);
3530 Vector4Normalize2(rot, rot);
3531 loadmodel->data_poses6s[k*6 + 3] = 32767.0f * rot[0];
3532 loadmodel->data_poses6s[k*6 + 4] = 32767.0f * rot[1];
3533 loadmodel->data_poses6s[k*6 + 5] = 32767.0f * rot[2];
3534 // skip scale data for now
3535 if(pose[j].channelmask&128) framedata++;
3536 if(pose[j].channelmask&256) framedata++;
3537 if(pose[j].channelmask&512) framedata++;
3540 if (header.num_frames <= 0)
3542 for (i = 0;i < loadmodel->num_bones;i++)
3544 loadmodel->data_poses6s[i*6 + 0] = loadmodel->num_poseinvscale * joint[i].origin[0];
3545 loadmodel->data_poses6s[i*6 + 1] = loadmodel->num_poseinvscale * joint[i].origin[1];
3546 loadmodel->data_poses6s[i*6 + 2] = loadmodel->num_poseinvscale * joint[i].origin[2];
3547 loadmodel->data_poses6s[i*6 + 3] = 32767.0f * joint[i].rotation[0];
3548 loadmodel->data_poses6s[i*6 + 4] = 32767.0f * joint[i].rotation[1];
3549 loadmodel->data_poses6s[i*6 + 5] = 32767.0f * joint[i].rotation[2];
3554 // load bounding box data
3555 if (header.ofs_bounds)
3557 float xyradius = 0, radius = 0;
3558 VectorClear(loadmodel->normalmins);
3559 VectorClear(loadmodel->normalmaxs);
3560 for (i = 0; i < (int)header.num_frames;i++)
3563 bound.mins[0] = LittleFloat(bounds[i].mins[0]);
3564 bound.mins[1] = LittleFloat(bounds[i].mins[1]);
3565 bound.mins[2] = LittleFloat(bounds[i].mins[2]);
3566 bound.maxs[0] = LittleFloat(bounds[i].maxs[0]);
3567 bound.maxs[1] = LittleFloat(bounds[i].maxs[1]);
3568 bound.maxs[2] = LittleFloat(bounds[i].maxs[2]);
3569 bound.xyradius = LittleFloat(bounds[i].xyradius);
3570 bound.radius = LittleFloat(bounds[i].radius);
3573 VectorCopy(bound.mins, loadmodel->normalmins);
3574 VectorCopy(bound.maxs, loadmodel->normalmaxs);
3578 if (loadmodel->normalmins[0] > bound.mins[0]) loadmodel->normalmins[0] = bound.mins[0];
3579 if (loadmodel->normalmins[1] > bound.mins[1]) loadmodel->normalmins[1] = bound.mins[1];
3580 if (loadmodel->normalmins[2] > bound.mins[2]) loadmodel->normalmins[2] = bound.mins[2];
3581 if (loadmodel->normalmaxs[0] < bound.maxs[0]) loadmodel->normalmaxs[0] = bound.maxs[0];
3582 if (loadmodel->normalmaxs[1] < bound.maxs[1]) loadmodel->normalmaxs[1] = bound.maxs[1];
3583 if (loadmodel->normalmaxs[2] < bound.maxs[2]) loadmodel->normalmaxs[2] = bound.maxs[2];
3585 if (bound.xyradius > xyradius)
3586 xyradius = bound.xyradius;
3587 if (bound.radius > radius)
3588 radius = bound.radius;
3590 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -xyradius;
3591 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = xyradius;
3592 loadmodel->yawmins[2] = loadmodel->normalmins[2];
3593 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
3594 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
3595 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
3596 loadmodel->radius = radius;
3597 loadmodel->radius2 = radius * radius;
3600 // load triangle data
3601 // this unaligned memory access is safe (LittleLong reads as bytes)
3602 inelements = (const unsigned int *)(pbase + header.ofs_triangles);
3603 outelements = loadmodel->surfmesh.data_element3i;
3604 for (i = 0;i < (int)header.num_triangles;i++)
3606 outelements[0] = LittleLong(inelements[0]);
3607 outelements[1] = LittleLong(inelements[1]);
3608 outelements[2] = LittleLong(inelements[2]);
3612 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, header.num_vertexes, __FILE__, __LINE__);
3614 if (header.ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
3616 // this unaligned memory access is safe (LittleLong reads as bytes)
3617 inneighbors = (const int *)(pbase + header.ofs_neighbors);
3618 outneighbors = loadmodel->surfmesh.data_neighbor3i;
3619 for (i = 0;i < (int)header.num_triangles;i++)
3621 outneighbors[0] = LittleLong(inneighbors[0]);
3622 outneighbors[1] = LittleLong(inneighbors[1]);
3623 outneighbors[2] = LittleLong(inneighbors[2]);
3630 // this unaligned memory access is safe (LittleFloat reads as bytes)
3631 outvertex = loadmodel->surfmesh.data_vertex3f;
3632 for (i = 0;i < (int)header.num_vertexes;i++)
3634 outvertex[0] = LittleFloat(vposition[0]);
3635 outvertex[1] = LittleFloat(vposition[1]);
3636 outvertex[2] = LittleFloat(vposition[2]);
3641 outtexcoord = loadmodel->surfmesh.data_texcoordtexture2f;
3642 // this unaligned memory access is safe (LittleFloat reads as bytes)
3643 for (i = 0;i < (int)header.num_vertexes;i++)
3645 outtexcoord[0] = LittleFloat(vtexcoord[0]);
3646 outtexcoord[1] = LittleFloat(vtexcoord[1]);
3651 // this unaligned memory access is safe (LittleFloat reads as bytes)
3654 outnormal = loadmodel->surfmesh.data_normal3f;
3655 for (i = 0;i < (int)header.num_vertexes;i++)
3657 outnormal[0] = LittleFloat(vnormal[0]);
3658 outnormal[1] = LittleFloat(vnormal[1]);
3659 outnormal[2] = LittleFloat(vnormal[2]);
3665 // this unaligned memory access is safe (LittleFloat reads as bytes)
3666 if(vnormal && vtangent)
3668 outnormal = loadmodel->surfmesh.data_normal3f;
3669 outsvector = loadmodel->surfmesh.data_svector3f;
3670 outtvector = loadmodel->surfmesh.data_tvector3f;
3671 for (i = 0;i < (int)header.num_vertexes;i++)
3673 outsvector[0] = LittleFloat(vtangent[0]);
3674 outsvector[1] = LittleFloat(vtangent[1]);
3675 outsvector[2] = LittleFloat(vtangent[2]);
3676 if(LittleFloat(vtangent[3]) < 0)
3677 CrossProduct(outsvector, outnormal, outtvector);
3679 CrossProduct(outnormal, outsvector, outtvector);
3687 // this unaligned memory access is safe (all bytes)
3688 if (vblendindexes && vblendweights)
3690 for (i = 0; i < (int)header.num_vertexes;i++)
3692 blendweights_t weights;
3693 memcpy(weights.index, vblendindexes + i*4, 4);
3694 memcpy(weights.influence, vblendweights + i*4, 4);
3695 loadmodel->surfmesh.blends[i] = Mod_Skeletal_AddBlend(loadmodel, &weights);
3701 outcolor = loadmodel->surfmesh.data_lightmapcolor4f;
3702 // this unaligned memory access is safe (LittleFloat reads as bytes)
3703 for (i = 0;i < (int)header.num_vertexes;i++)
3705 outcolor[0] = LittleFloat(vcolor4f[0]);
3706 outcolor[1] = LittleFloat(vcolor4f[1]);
3707 outcolor[2] = LittleFloat(vcolor4f[2]);
3708 outcolor[3] = LittleFloat(vcolor4f[3]);
3715 outcolor = loadmodel->surfmesh.data_lightmapcolor4f;
3716 // this unaligned memory access is safe (all bytes)
3717 for (i = 0;i < (int)header.num_vertexes;i++)
3719 outcolor[0] = vcolor4ub[0] * (1.0f / 255.0f);
3720 outcolor[1] = vcolor4ub[1] * (1.0f / 255.0f);
3721 outcolor[2] = vcolor4ub[2] * (1.0f / 255.0f);
3722 outcolor[3] = vcolor4ub[3] * (1.0f / 255.0f);
3729 for (i = 0;i < (int)header.num_meshes;i++)
3732 msurface_t *surface;
3734 mesh.name = LittleLong(meshes[i].name);
3735 mesh.material = LittleLong(meshes[i].material);
3736 mesh.first_vertex = LittleLong(meshes[i].first_vertex);
3737 mesh.num_vertexes = LittleLong(meshes[i].num_vertexes);
3738 mesh.first_triangle = LittleLong(meshes[i].first_triangle);
3739 mesh.num_triangles = LittleLong(meshes[i].num_triangles);
3741 loadmodel->sortedmodelsurfaces[i] = i;
3742 surface = loadmodel->data_surfaces + i;
3743 surface->texture = loadmodel->data_textures + i;
3744 surface->num_firsttriangle = mesh.first_triangle;
3745 surface->num_triangles = mesh.num_triangles;
3746 surface->num_firstvertex = mesh.first_vertex;
3747 surface->num_vertices = mesh.num_vertexes;
3749 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, &text[mesh.name], &text[mesh.material]);
3752 Mod_FreeSkinFiles(skinfiles);
3753 Mod_MakeSortedSurfaces(loadmodel);
3755 // compute all the mesh information that was not loaded from the file
3756 if (loadmodel->surfmesh.data_element3s)
3757 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3758 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3760 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);
3761 if (!vnormal || !vtangent)
3762 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);
3763 if (!header.ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
3764 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3765 if (!header.ofs_bounds)
3766 Mod_Alias_CalculateBoundingBox();
3768 if (!loadmodel->surfmesh.isanimated && loadmodel->surfmesh.num_triangles >= 1)
3770 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3771 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3772 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3773 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3774 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3775 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
3778 if (joint ) Mem_Free(joint );joint = NULL;
3779 if (joint1 ) Mem_Free(joint1 );joint1 = NULL;
3780 if (pose ) Mem_Free(pose );pose = NULL;
3781 if (pose1 ) Mem_Free(pose1 );pose1 = NULL;
3783 // because shaders can do somewhat unexpected things, check for unusual features now
3784 for (i = 0;i < loadmodel->num_textures;i++)
3786 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
3787 mod->DrawSky = R_Q1BSP_DrawSky;
3788 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
3789 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;