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 = (float *)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 = (float *)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);
2508 animbufferend = animbuffer;
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)
2827 Host_Error("%s: missing required chunks", loadmodel->name);
2831 loadmodel->numframes = 0;
2832 for (index = 0;index < numanims;index++)
2833 loadmodel->numframes += anims[index].numframes;
2834 if (numanimkeys != numbones * loadmodel->numframes)
2835 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2838 loadmodel->numframes = loadmodel->num_poses = 1;
2840 meshvertices = numvtxw;
2841 meshtriangles = numfaces;
2843 // load external .skin files if present
2844 skinfiles = Mod_LoadSkinFiles();
2845 if (loadmodel->numskins < 1)
2846 loadmodel->numskins = 1;
2847 loadmodel->num_bones = numbones;
2848 loadmodel->num_poses = loadmodel->numframes;
2849 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2850 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2851 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2852 loadmodel->surfmesh.num_vertices = meshvertices;
2853 loadmodel->surfmesh.num_triangles = meshtriangles;
2854 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
2855 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
2856 // do most allocations as one merged chunk
2857 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);
2858 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2859 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2860 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2861 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2862 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2863 if (r_enableshadowvolumes.integer)
2865 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2867 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2868 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2869 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2870 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2871 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2872 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2873 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2874 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2875 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2876 loadmodel->surfmesh.num_blends = 0;
2877 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2878 if (loadmodel->surfmesh.num_vertices <= 65536)
2880 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2882 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2883 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(blendweights_t));
2885 for (i = 0;i < loadmodel->numskins;i++)
2887 loadmodel->skinscenes[i].firstframe = i;
2888 loadmodel->skinscenes[i].framecount = 1;
2889 loadmodel->skinscenes[i].loop = true;
2890 loadmodel->skinscenes[i].framerate = 10;
2894 for (index = 0, i = 0;index < nummatts;index++)
2896 // since psk models do not have named sections, reuse their shader name as the section name
2897 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2898 loadmodel->sortedmodelsurfaces[index] = index;
2899 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2900 loadmodel->data_surfaces[index].num_firstvertex = 0;
2901 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2904 // copy over the vertex locations and texcoords
2905 for (index = 0;index < numvtxw;index++)
2907 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2908 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2909 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2910 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2911 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2914 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2915 for (index = 0;index < numfaces;index++)
2916 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2917 for (index = 0, i = 0;index < nummatts;index++)
2919 loadmodel->data_surfaces[index].num_firsttriangle = i;
2920 i += loadmodel->data_surfaces[index].num_triangles;
2921 loadmodel->data_surfaces[index].num_triangles = 0;
2923 for (index = 0;index < numfaces;index++)
2925 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2926 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2927 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2928 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2931 // copy over the bones
2932 for (index = 0;index < numbones;index++)
2934 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2935 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2936 if (loadmodel->data_bones[index].parent >= index)
2937 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2940 // convert the basepose data
2941 if (loadmodel->num_bones)
2944 matrix4x4_t *basebonepose;
2945 float *outinvmatrix = loadmodel->data_baseboneposeinverse;
2946 matrix4x4_t bonematrix;
2947 matrix4x4_t tempbonematrix;
2948 basebonepose = (matrix4x4_t *)Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(matrix4x4_t));
2949 for (boneindex = 0;boneindex < loadmodel->num_bones;boneindex++)
2951 Matrix4x4_FromOriginQuat(&bonematrix, bones[boneindex].basepose.origin[0], bones[boneindex].basepose.origin[1], bones[boneindex].basepose.origin[2], bones[boneindex].basepose.quat[0], bones[boneindex].basepose.quat[1], bones[boneindex].basepose.quat[2], bones[boneindex].basepose.quat[3]);
2952 if (loadmodel->data_bones[boneindex].parent >= 0)
2954 tempbonematrix = bonematrix;
2955 Matrix4x4_Concat(&bonematrix, basebonepose + loadmodel->data_bones[boneindex].parent, &tempbonematrix);
2957 basebonepose[boneindex] = bonematrix;
2958 Matrix4x4_Invert_Simple(&tempbonematrix, basebonepose + boneindex);
2959 Matrix4x4_ToArray12FloatD3D(&tempbonematrix, outinvmatrix + 12*boneindex);
2961 Mem_Free(basebonepose);
2964 // sort the psk point weights into the vertex weight tables
2965 // (which only accept up to 4 bones per vertex)
2966 for (index = 0;index < numvtxw;index++)
2968 int weightindex[4] = { 0, 0, 0, 0 };
2969 float weightinfluence[4] = { 0, 0, 0, 0 };
2971 for (j = 0;j < numrawweights;j++)
2973 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2975 int boneindex = rawweights[j].boneindex;
2976 float influence = rawweights[j].weight;
2977 for (l = 0;l < 4;l++)
2979 if (weightinfluence[l] < influence)
2981 // move lower influence weights out of the way first
2983 for (l2 = 3;l2 > l;l2--)
2985 weightinfluence[l2] = weightinfluence[l2-1];
2986 weightindex[l2] = weightindex[l2-1];
2988 // store the new weight
2989 weightinfluence[l] = influence;
2990 weightindex[l] = boneindex;
2996 loadmodel->surfmesh.blends[index] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
2998 if (loadmodel->surfmesh.num_blends < loadmodel->surfmesh.num_vertices)
2999 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
3001 // set up the animscenes based on the anims
3004 for (index = 0, i = 0;index < numanims;index++)
3006 for (j = 0;j < anims[index].numframes;j++, i++)
3008 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
3009 loadmodel->animscenes[i].firstframe = i;
3010 loadmodel->animscenes[i].framecount = 1;
3011 loadmodel->animscenes[i].loop = true;
3012 loadmodel->animscenes[i].framerate = anims[index].fps;
3015 // calculate the scaling value for bone origins so they can be compressed to short
3017 for (index = 0;index < numanimkeys;index++)
3019 pskanimkeys_t *k = animkeys + index;
3020 biggestorigin = max(biggestorigin, fabs(k->origin[0]));
3021 biggestorigin = max(biggestorigin, fabs(k->origin[1]));
3022 biggestorigin = max(biggestorigin, fabs(k->origin[2]));
3024 loadmodel->num_posescale = biggestorigin / 32767.0f;
3025 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3027 // load the poses from the animkeys
3028 for (index = 0;index < numanimkeys;index++)
3030 pskanimkeys_t *k = animkeys + index;
3032 Vector4Copy(k->quat, quat);
3034 Vector4Negate(quat, quat);
3035 Vector4Normalize2(quat, quat);
3036 // compress poses to the short[6] format for longterm storage
3037 loadmodel->data_poses6s[index*6+0] = k->origin[0] * loadmodel->num_poseinvscale;
3038 loadmodel->data_poses6s[index*6+1] = k->origin[1] * loadmodel->num_poseinvscale;
3039 loadmodel->data_poses6s[index*6+2] = k->origin[2] * loadmodel->num_poseinvscale;
3040 loadmodel->data_poses6s[index*6+3] = quat[0] * 32767.0f;
3041 loadmodel->data_poses6s[index*6+4] = quat[1] * 32767.0f;
3042 loadmodel->data_poses6s[index*6+5] = quat[2] * 32767.0f;
3047 strlcpy(loadmodel->animscenes[0].name, "base", sizeof(loadmodel->animscenes[0].name));
3048 loadmodel->animscenes[0].firstframe = 0;
3049 loadmodel->animscenes[0].framecount = 1;
3050 loadmodel->animscenes[0].loop = true;
3051 loadmodel->animscenes[0].framerate = 10;
3053 // calculate the scaling value for bone origins so they can be compressed to short
3055 for (index = 0;index < numbones;index++)
3057 pskboneinfo_t *p = bones + index;
3058 biggestorigin = max(biggestorigin, fabs(p->basepose.origin[0]));
3059 biggestorigin = max(biggestorigin, fabs(p->basepose.origin[1]));
3060 biggestorigin = max(biggestorigin, fabs(p->basepose.origin[2]));
3062 loadmodel->num_posescale = biggestorigin / 32767.0f;
3063 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3065 // load the basepose as a frame
3066 for (index = 0;index < numbones;index++)
3068 pskboneinfo_t *p = bones + index;
3070 Vector4Copy(p->basepose.quat, quat);
3072 Vector4Negate(quat, quat);
3073 Vector4Normalize2(quat, quat);
3074 // compress poses to the short[6] format for longterm storage
3075 loadmodel->data_poses6s[index*6+0] = p->basepose.origin[0] * loadmodel->num_poseinvscale;
3076 loadmodel->data_poses6s[index*6+1] = p->basepose.origin[1] * loadmodel->num_poseinvscale;
3077 loadmodel->data_poses6s[index*6+2] = p->basepose.origin[2] * loadmodel->num_poseinvscale;
3078 loadmodel->data_poses6s[index*6+3] = quat[0] * 32767.0f;
3079 loadmodel->data_poses6s[index*6+4] = quat[1] * 32767.0f;
3080 loadmodel->data_poses6s[index*6+5] = quat[2] * 32767.0f;
3084 Mod_FreeSkinFiles(skinfiles);
3086 Mem_Free(animfilebuffer);
3087 Mod_MakeSortedSurfaces(loadmodel);
3089 // compute all the mesh information that was not loaded from the file
3090 // TODO: honor smoothing groups somehow?
3091 if (loadmodel->surfmesh.data_element3s)
3092 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3093 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3094 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
3095 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);
3096 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);
3097 if (loadmodel->surfmesh.data_neighbor3i)
3098 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3099 Mod_Alias_CalculateBoundingBox();
3101 if (!loadmodel->surfmesh.isanimated)
3103 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3104 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3105 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3106 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3107 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3108 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
3111 // because shaders can do somewhat unexpected things, check for unusual features now
3112 for (i = 0;i < loadmodel->num_textures;i++)
3114 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
3115 mod->DrawSky = R_Q1BSP_DrawSky;
3116 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
3117 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
3121 void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
3123 unsigned char *data;
3125 const unsigned char *pbase, *pend;
3127 skinfile_t *skinfiles;
3128 int i, j, k, meshvertices, meshtriangles;
3129 float biggestorigin;
3130 const unsigned int *inelements;
3132 const int *inneighbors;
3134 float *outvertex, *outnormal, *outtexcoord, *outsvector, *outtvector, *outcolor;
3135 // this pointers into the file data are read only through Little* functions so they can be unaligned memory
3136 const float *vnormal = NULL;
3137 const float *vposition = NULL;
3138 const float *vtangent = NULL;
3139 const float *vtexcoord = NULL;
3140 const float *vcolor4f = NULL;
3141 const unsigned char *vblendindexes = NULL;
3142 const unsigned char *vblendweights = NULL;
3143 const unsigned char *vcolor4ub = NULL;
3144 const unsigned short *framedata = NULL;
3145 // temporary memory allocations (because the data in the file may be misaligned)
3146 iqmanim_t *anims = NULL;
3147 iqmbounds_t *bounds = NULL;
3148 iqmjoint1_t *joint1 = NULL;
3149 iqmjoint_t *joint = NULL;
3150 iqmmesh_t *meshes = NULL;
3151 iqmpose1_t *pose1 = NULL;
3152 iqmpose_t *pose = NULL;
3153 iqmvertexarray_t *vas = NULL;
3155 pbase = (unsigned char *)buffer;
3156 pend = (unsigned char *)bufferend;
3158 if (pbase + sizeof(iqmheader_t) > pend)
3159 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model %d", loadmodel->name, (int)(pend - pbase));
3161 // copy struct (otherwise it may be misaligned)
3162 // LordHavoc: okay it's definitely not misaligned here, but for consistency...
3163 memcpy(&header, pbase, sizeof(iqmheader_t));
3165 if (memcmp(header.id, "INTERQUAKEMODEL", 16))
3166 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model", loadmodel->name);
3167 if (LittleLong(header.version) != 1 && LittleLong(header.version) != 2)
3168 Host_Error ("Mod_INTERQUAKEMODEL_Load: only version 1 and 2 models are currently supported (name = %s)", loadmodel->name);
3170 loadmodel->modeldatatypestring = "IQM";
3172 loadmodel->type = mod_alias;
3173 loadmodel->synctype = ST_RAND;
3176 header.version = LittleLong(header.version);
3177 header.filesize = LittleLong(header.filesize);
3178 header.flags = LittleLong(header.flags);
3179 header.num_text = LittleLong(header.num_text);
3180 header.ofs_text = LittleLong(header.ofs_text);
3181 header.num_meshes = LittleLong(header.num_meshes);
3182 header.ofs_meshes = LittleLong(header.ofs_meshes);
3183 header.num_vertexarrays = LittleLong(header.num_vertexarrays);
3184 header.num_vertexes = LittleLong(header.num_vertexes);
3185 header.ofs_vertexarrays = LittleLong(header.ofs_vertexarrays);
3186 header.num_triangles = LittleLong(header.num_triangles);
3187 header.ofs_triangles = LittleLong(header.ofs_triangles);
3188 header.ofs_neighbors = LittleLong(header.ofs_neighbors);
3189 header.num_joints = LittleLong(header.num_joints);
3190 header.ofs_joints = LittleLong(header.ofs_joints);
3191 header.num_poses = LittleLong(header.num_poses);
3192 header.ofs_poses = LittleLong(header.ofs_poses);
3193 header.num_anims = LittleLong(header.num_anims);
3194 header.ofs_anims = LittleLong(header.ofs_anims);
3195 header.num_frames = LittleLong(header.num_frames);
3196 header.num_framechannels = LittleLong(header.num_framechannels);
3197 header.ofs_frames = LittleLong(header.ofs_frames);
3198 header.ofs_bounds = LittleLong(header.ofs_bounds);
3199 header.num_comment = LittleLong(header.num_comment);
3200 header.ofs_comment = LittleLong(header.ofs_comment);
3201 header.num_extensions = LittleLong(header.num_extensions);
3202 header.ofs_extensions = LittleLong(header.ofs_extensions);
3204 if (header.version == 1)
3206 if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint1_t) > pend ||
3207 pbase + header.ofs_poses + header.num_poses*sizeof(iqmpose1_t) > pend)
3209 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3215 if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint_t) > pend ||
3216 pbase + header.ofs_poses + header.num_poses*sizeof(iqmpose_t) > pend)
3218 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3222 if (pbase + header.ofs_text + header.num_text > pend ||
3223 pbase + header.ofs_meshes + header.num_meshes*sizeof(iqmmesh_t) > pend ||
3224 pbase + header.ofs_vertexarrays + header.num_vertexarrays*sizeof(iqmvertexarray_t) > pend ||
3225 pbase + header.ofs_triangles + header.num_triangles*sizeof(int[3]) > pend ||
3226 (header.ofs_neighbors && pbase + header.ofs_neighbors + header.num_triangles*sizeof(int[3]) > pend) ||
3227 pbase + header.ofs_anims + header.num_anims*sizeof(iqmanim_t) > pend ||
3228 pbase + header.ofs_frames + header.num_frames*header.num_framechannels*sizeof(unsigned short) > pend ||
3229 (header.ofs_bounds && pbase + header.ofs_bounds + header.num_frames*sizeof(iqmbounds_t) > pend) ||
3230 pbase + header.ofs_comment + header.num_comment > pend)
3232 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3236 // copy structs to make them aligned in memory (otherwise we crash on Sparc and PowerPC and others)
3237 if (header.num_vertexarrays)
3238 vas = (iqmvertexarray_t *)(pbase + header.ofs_vertexarrays);
3239 if (header.num_anims)
3240 anims = (iqmanim_t *)(pbase + header.ofs_anims);
3241 if (header.ofs_bounds)
3242 bounds = (iqmbounds_t *)(pbase + header.ofs_bounds);
3243 if (header.num_meshes)
3244 meshes = (iqmmesh_t *)(pbase + header.ofs_meshes);
3246 for (i = 0;i < (int)header.num_vertexarrays;i++)
3248 iqmvertexarray_t va;
3250 va.type = LittleLong(vas[i].type);
3251 va.flags = LittleLong(vas[i].flags);
3252 va.format = LittleLong(vas[i].format);
3253 va.size = LittleLong(vas[i].size);
3254 va.offset = LittleLong(vas[i].offset);
3255 vsize = header.num_vertexes*va.size;
3258 case IQM_FLOAT: vsize *= sizeof(float); break;
3259 case IQM_UBYTE: vsize *= sizeof(unsigned char); break;
3262 if (pbase + va.offset + vsize > pend)
3264 // no need to copy the vertex data for alignment because LittleLong/LittleShort will be invoked on reading them, and the destination is aligned
3268 if (va.format == IQM_FLOAT && va.size == 3)
3269 vposition = (const float *)(pbase + va.offset);
3272 if (va.format == IQM_FLOAT && va.size == 2)
3273 vtexcoord = (const float *)(pbase + va.offset);
3276 if (va.format == IQM_FLOAT && va.size == 3)
3277 vnormal = (const float *)(pbase + va.offset);
3280 if (va.format == IQM_FLOAT && va.size == 4)
3281 vtangent = (const float *)(pbase + va.offset);
3283 case IQM_BLENDINDEXES:
3284 if (va.format == IQM_UBYTE && va.size == 4)
3285 vblendindexes = (const unsigned char *)(pbase + va.offset);
3287 case IQM_BLENDWEIGHTS:
3288 if (va.format == IQM_UBYTE && va.size == 4)
3289 vblendweights = (const unsigned char *)(pbase + va.offset);
3292 if (va.format == IQM_FLOAT && va.size == 4)
3293 vcolor4f = (const float *)(pbase + va.offset);
3294 if (va.format == IQM_UBYTE && va.size == 4)
3295 vcolor4ub = (const unsigned char *)(pbase + va.offset);
3299 if (header.num_vertexes > 0 && (!vposition || !vtexcoord || ((header.num_frames > 0 || header.num_anims > 0) && (!vblendindexes || !vblendweights))))
3301 Con_Printf("%s is missing vertex array data\n", loadmodel->name);
3305 text = header.num_text && header.ofs_text ? (const char *)(pbase + header.ofs_text) : "";
3307 loadmodel->DrawSky = NULL;
3308 loadmodel->DrawAddWaterPlanes = NULL;
3309 loadmodel->Draw = R_Q1BSP_Draw;
3310 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
3311 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
3312 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
3313 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
3314 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
3315 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
3316 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
3317 loadmodel->DrawLight = R_Q1BSP_DrawLight;
3318 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
3319 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
3320 loadmodel->PointSuperContents = NULL;
3322 // load external .skin files if present
3323 skinfiles = Mod_LoadSkinFiles();
3324 if (loadmodel->numskins < 1)
3325 loadmodel->numskins = 1;
3327 loadmodel->numframes = max(header.num_anims, 1);
3328 loadmodel->num_bones = header.num_joints;
3329 loadmodel->num_poses = max(header.num_frames, 1);
3330 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = header.num_meshes;
3331 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3332 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3333 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices; // updated later
3335 meshvertices = header.num_vertexes;
3336 meshtriangles = header.num_triangles;
3338 // do most allocations as one merged chunk
3339 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));
3340 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
3341 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
3342 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
3343 loadmodel->surfmesh.num_vertices = meshvertices;
3344 loadmodel->surfmesh.num_triangles = meshtriangles;
3345 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3346 if (r_enableshadowvolumes.integer)
3348 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3350 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
3351 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3352 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3353 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
3354 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
3355 if (vcolor4f || vcolor4ub)
3357 loadmodel->surfmesh.data_lightmapcolor4f = (float *)data;data += meshvertices * sizeof(float[4]);
3359 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
3360 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
3361 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
3362 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
3363 if (vblendindexes && vblendweights)
3365 loadmodel->surfmesh.num_blends = 0;
3366 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
3368 if (meshvertices <= 65536)
3370 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
3372 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
3373 if (vblendindexes && vblendweights)
3374 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
3376 for (i = 0;i < loadmodel->numskins;i++)
3378 loadmodel->skinscenes[i].firstframe = i;
3379 loadmodel->skinscenes[i].framecount = 1;
3380 loadmodel->skinscenes[i].loop = true;
3381 loadmodel->skinscenes[i].framerate = 10;
3384 // load the bone info
3385 if (header.version == 1)
3387 iqmjoint1_t *injoint1 = (iqmjoint1_t *)(pbase + header.ofs_joints);
3388 if (loadmodel->num_bones)
3389 joint1 = (iqmjoint1_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(iqmjoint1_t));
3390 for (i = 0;i < loadmodel->num_bones;i++)
3392 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3393 joint1[i].name = LittleLong(injoint1[i].name);
3394 joint1[i].parent = LittleLong(injoint1[i].parent);
3395 for (j = 0;j < 3;j++)
3397 joint1[i].origin[j] = LittleFloat(injoint1[i].origin[j]);
3398 joint1[i].rotation[j] = LittleFloat(injoint1[i].rotation[j]);
3399 joint1[i].scale[j] = LittleFloat(injoint1[i].scale[j]);
3401 strlcpy(loadmodel->data_bones[i].name, &text[joint1[i].name], sizeof(loadmodel->data_bones[i].name));
3402 loadmodel->data_bones[i].parent = joint1[i].parent;
3403 if (loadmodel->data_bones[i].parent >= i)
3404 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3405 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]);
3406 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3407 if (loadmodel->data_bones[i].parent >= 0)
3409 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3410 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3411 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3413 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3418 iqmjoint_t *injoint = (iqmjoint_t *)(pbase + header.ofs_joints);
3419 if (header.num_joints)
3420 joint = (iqmjoint_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(iqmjoint_t));
3421 for (i = 0;i < loadmodel->num_bones;i++)
3423 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3424 joint[i].name = LittleLong(injoint[i].name);
3425 joint[i].parent = LittleLong(injoint[i].parent);
3426 for (j = 0;j < 3;j++)
3428 joint[i].origin[j] = LittleFloat(injoint[i].origin[j]);
3429 joint[i].rotation[j] = LittleFloat(injoint[i].rotation[j]);
3430 joint[i].scale[j] = LittleFloat(injoint[i].scale[j]);
3432 joint[i].rotation[3] = LittleFloat(injoint[i].rotation[3]);
3433 strlcpy(loadmodel->data_bones[i].name, &text[joint[i].name], sizeof(loadmodel->data_bones[i].name));
3434 loadmodel->data_bones[i].parent = joint[i].parent;
3435 if (loadmodel->data_bones[i].parent >= i)
3436 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3437 if (joint[i].rotation[3] > 0)
3438 Vector4Negate(joint[i].rotation, joint[i].rotation);
3439 Vector4Normalize2(joint[i].rotation, joint[i].rotation);
3440 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]);
3441 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3442 if (loadmodel->data_bones[i].parent >= 0)
3444 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3445 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3446 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3448 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3452 // set up the animscenes based on the anims
3453 for (i = 0;i < (int)header.num_anims;i++)
3456 anim.name = LittleLong(anims[i].name);
3457 anim.first_frame = LittleLong(anims[i].first_frame);
3458 anim.num_frames = LittleLong(anims[i].num_frames);
3459 anim.framerate = LittleFloat(anims[i].framerate);
3460 anim.flags = LittleLong(anims[i].flags);
3461 strlcpy(loadmodel->animscenes[i].name, &text[anim.name], sizeof(loadmodel->animscenes[i].name));
3462 loadmodel->animscenes[i].firstframe = anim.first_frame;
3463 loadmodel->animscenes[i].framecount = anim.num_frames;
3464 loadmodel->animscenes[i].loop = ((anim.flags & IQM_LOOP) != 0);
3465 loadmodel->animscenes[i].framerate = anim.framerate;
3467 if (header.num_anims <= 0)
3469 strlcpy(loadmodel->animscenes[0].name, "static", sizeof(loadmodel->animscenes[0].name));
3470 loadmodel->animscenes[0].firstframe = 0;
3471 loadmodel->animscenes[0].framecount = 1;
3472 loadmodel->animscenes[0].loop = true;
3473 loadmodel->animscenes[0].framerate = 10;
3476 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
3477 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
3480 if (header.version == 1)
3482 iqmpose1_t *inpose1 = (iqmpose1_t *)(pbase + header.ofs_poses);
3483 if (header.num_poses)
3484 pose1 = (iqmpose1_t *)Mem_Alloc(loadmodel->mempool, header.num_poses * sizeof(iqmpose1_t));
3485 for (i = 0;i < (int)header.num_poses;i++)
3488 pose1[i].parent = LittleLong(inpose1[i].parent);
3489 pose1[i].channelmask = LittleLong(inpose1[i].channelmask);
3490 for (j = 0;j < 9;j++)
3492 pose1[i].channeloffset[j] = LittleFloat(inpose1[i].channeloffset[j]);
3493 pose1[i].channelscale[j] = LittleFloat(inpose1[i].channelscale[j]);
3495 f = fabs(pose1[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3496 f = fabs(pose1[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3497 f = fabs(pose1[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3498 f = fabs(pose1[i].channeloffset[0] + 0xFFFF*pose1[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3499 f = fabs(pose1[i].channeloffset[1] + 0xFFFF*pose1[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3500 f = fabs(pose1[i].channeloffset[2] + 0xFFFF*pose1[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3502 if (header.num_frames <= 0)
3504 for (i = 0;i < loadmodel->num_bones;i++)
3507 f = fabs(joint1[i].origin[0]); biggestorigin = max(biggestorigin, f);
3508 f = fabs(joint1[i].origin[1]); biggestorigin = max(biggestorigin, f);
3509 f = fabs(joint1[i].origin[2]); biggestorigin = max(biggestorigin, f);
3515 iqmpose_t *inpose = (iqmpose_t *)(pbase + header.ofs_poses);
3516 if (header.num_poses)
3517 pose = (iqmpose_t *)Mem_Alloc(loadmodel->mempool, header.num_poses * sizeof(iqmpose_t));
3518 for (i = 0;i < (int)header.num_poses;i++)
3521 pose[i].parent = LittleLong(inpose[i].parent);
3522 pose[i].channelmask = LittleLong(inpose[i].channelmask);
3523 for (j = 0;j < 10;j++)
3525 pose[i].channeloffset[j] = LittleFloat(inpose[i].channeloffset[j]);
3526 pose[i].channelscale[j] = LittleFloat(inpose[i].channelscale[j]);
3528 f = fabs(pose[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3529 f = fabs(pose[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3530 f = fabs(pose[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3531 f = fabs(pose[i].channeloffset[0] + 0xFFFF*pose[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3532 f = fabs(pose[i].channeloffset[1] + 0xFFFF*pose[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3533 f = fabs(pose[i].channeloffset[2] + 0xFFFF*pose[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3535 if (header.num_frames <= 0)
3537 for (i = 0;i < loadmodel->num_bones;i++)
3540 f = fabs(joint[i].origin[0]); biggestorigin = max(biggestorigin, f);
3541 f = fabs(joint[i].origin[1]); biggestorigin = max(biggestorigin, f);
3542 f = fabs(joint[i].origin[2]); biggestorigin = max(biggestorigin, f);
3546 loadmodel->num_posescale = biggestorigin / 32767.0f;
3547 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3549 // load the pose data
3550 // this unaligned memory access is safe (LittleShort reads as bytes)
3551 framedata = (const unsigned short *)(pbase + header.ofs_frames);
3552 if (header.version == 1)
3554 for (i = 0, k = 0;i < (int)header.num_frames;i++)
3556 for (j = 0;j < (int)header.num_poses;j++, k++)
3558 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));
3559 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));
3560 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));
3561 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));
3562 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));
3563 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));
3564 // skip scale data for now
3565 if(pose1[j].channelmask&64) framedata++;
3566 if(pose1[j].channelmask&128) framedata++;
3567 if(pose1[j].channelmask&256) framedata++;
3570 if (header.num_frames <= 0)
3572 for (i = 0;i < loadmodel->num_bones;i++)
3574 loadmodel->data_poses6s[i*6 + 0] = loadmodel->num_poseinvscale * joint1[i].origin[0];
3575 loadmodel->data_poses6s[i*6 + 1] = loadmodel->num_poseinvscale * joint1[i].origin[1];
3576 loadmodel->data_poses6s[i*6 + 2] = loadmodel->num_poseinvscale * joint1[i].origin[2];
3577 loadmodel->data_poses6s[i*6 + 3] = 32767.0f * joint1[i].rotation[0];
3578 loadmodel->data_poses6s[i*6 + 4] = 32767.0f * joint1[i].rotation[1];
3579 loadmodel->data_poses6s[i*6 + 5] = 32767.0f * joint1[i].rotation[2];
3585 for (i = 0, k = 0;i < (int)header.num_frames;i++)
3587 for (j = 0;j < (int)header.num_poses;j++, k++)
3590 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));
3591 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));
3592 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));
3593 rot[0] = pose[j].channeloffset[3] + (pose[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[3] : 0);
3594 rot[1] = pose[j].channeloffset[4] + (pose[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[4] : 0);
3595 rot[2] = pose[j].channeloffset[5] + (pose[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[5] : 0);
3596 rot[3] = pose[j].channeloffset[6] + (pose[j].channelmask&64 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[6] : 0);
3598 Vector4Negate(rot, rot);
3599 Vector4Normalize2(rot, rot);
3600 loadmodel->data_poses6s[k*6 + 3] = 32767.0f * rot[0];
3601 loadmodel->data_poses6s[k*6 + 4] = 32767.0f * rot[1];
3602 loadmodel->data_poses6s[k*6 + 5] = 32767.0f * rot[2];
3603 // skip scale data for now
3604 if(pose[j].channelmask&128) framedata++;
3605 if(pose[j].channelmask&256) framedata++;
3606 if(pose[j].channelmask&512) framedata++;
3609 if (header.num_frames <= 0)
3611 for (i = 0;i < loadmodel->num_bones;i++)
3613 loadmodel->data_poses6s[i*6 + 0] = loadmodel->num_poseinvscale * joint[i].origin[0];
3614 loadmodel->data_poses6s[i*6 + 1] = loadmodel->num_poseinvscale * joint[i].origin[1];
3615 loadmodel->data_poses6s[i*6 + 2] = loadmodel->num_poseinvscale * joint[i].origin[2];
3616 loadmodel->data_poses6s[i*6 + 3] = 32767.0f * joint[i].rotation[0];
3617 loadmodel->data_poses6s[i*6 + 4] = 32767.0f * joint[i].rotation[1];
3618 loadmodel->data_poses6s[i*6 + 5] = 32767.0f * joint[i].rotation[2];
3623 // load bounding box data
3624 if (header.ofs_bounds)
3626 float xyradius = 0, radius = 0;
3627 VectorClear(loadmodel->normalmins);
3628 VectorClear(loadmodel->normalmaxs);
3629 for (i = 0; i < (int)header.num_frames;i++)
3632 bound.mins[0] = LittleFloat(bounds[i].mins[0]);
3633 bound.mins[1] = LittleFloat(bounds[i].mins[1]);
3634 bound.mins[2] = LittleFloat(bounds[i].mins[2]);
3635 bound.maxs[0] = LittleFloat(bounds[i].maxs[0]);
3636 bound.maxs[1] = LittleFloat(bounds[i].maxs[1]);
3637 bound.maxs[2] = LittleFloat(bounds[i].maxs[2]);
3638 bound.xyradius = LittleFloat(bounds[i].xyradius);
3639 bound.radius = LittleFloat(bounds[i].radius);
3642 VectorCopy(bound.mins, loadmodel->normalmins);
3643 VectorCopy(bound.maxs, loadmodel->normalmaxs);
3647 if (loadmodel->normalmins[0] > bound.mins[0]) loadmodel->normalmins[0] = bound.mins[0];
3648 if (loadmodel->normalmins[1] > bound.mins[1]) loadmodel->normalmins[1] = bound.mins[1];
3649 if (loadmodel->normalmins[2] > bound.mins[2]) loadmodel->normalmins[2] = bound.mins[2];
3650 if (loadmodel->normalmaxs[0] < bound.maxs[0]) loadmodel->normalmaxs[0] = bound.maxs[0];
3651 if (loadmodel->normalmaxs[1] < bound.maxs[1]) loadmodel->normalmaxs[1] = bound.maxs[1];
3652 if (loadmodel->normalmaxs[2] < bound.maxs[2]) loadmodel->normalmaxs[2] = bound.maxs[2];
3654 if (bound.xyradius > xyradius)
3655 xyradius = bound.xyradius;
3656 if (bound.radius > radius)
3657 radius = bound.radius;
3659 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -xyradius;
3660 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = xyradius;
3661 loadmodel->yawmins[2] = loadmodel->normalmins[2];
3662 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
3663 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
3664 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
3665 loadmodel->radius = radius;
3666 loadmodel->radius2 = radius * radius;
3669 // load triangle data
3670 // this unaligned memory access is safe (LittleLong reads as bytes)
3671 inelements = (const unsigned int *)(pbase + header.ofs_triangles);
3672 outelements = loadmodel->surfmesh.data_element3i;
3673 for (i = 0;i < (int)header.num_triangles;i++)
3675 outelements[0] = LittleLong(inelements[0]);
3676 outelements[1] = LittleLong(inelements[1]);
3677 outelements[2] = LittleLong(inelements[2]);
3681 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, header.num_vertexes, __FILE__, __LINE__);
3683 if (header.ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
3685 // this unaligned memory access is safe (LittleLong reads as bytes)
3686 inneighbors = (const int *)(pbase + header.ofs_neighbors);
3687 outneighbors = loadmodel->surfmesh.data_neighbor3i;
3688 for (i = 0;i < (int)header.num_triangles;i++)
3690 outneighbors[0] = LittleLong(inneighbors[0]);
3691 outneighbors[1] = LittleLong(inneighbors[1]);
3692 outneighbors[2] = LittleLong(inneighbors[2]);
3699 // this unaligned memory access is safe (LittleFloat reads as bytes)
3700 outvertex = loadmodel->surfmesh.data_vertex3f;
3701 for (i = 0;i < (int)header.num_vertexes;i++)
3703 outvertex[0] = LittleFloat(vposition[0]);
3704 outvertex[1] = LittleFloat(vposition[1]);
3705 outvertex[2] = LittleFloat(vposition[2]);
3710 outtexcoord = loadmodel->surfmesh.data_texcoordtexture2f;
3711 // this unaligned memory access is safe (LittleFloat reads as bytes)
3712 for (i = 0;i < (int)header.num_vertexes;i++)
3714 outtexcoord[0] = LittleFloat(vtexcoord[0]);
3715 outtexcoord[1] = LittleFloat(vtexcoord[1]);
3720 // this unaligned memory access is safe (LittleFloat reads as bytes)
3723 outnormal = loadmodel->surfmesh.data_normal3f;
3724 for (i = 0;i < (int)header.num_vertexes;i++)
3726 outnormal[0] = LittleFloat(vnormal[0]);
3727 outnormal[1] = LittleFloat(vnormal[1]);
3728 outnormal[2] = LittleFloat(vnormal[2]);
3734 // this unaligned memory access is safe (LittleFloat reads as bytes)
3735 if(vnormal && vtangent)
3737 outnormal = loadmodel->surfmesh.data_normal3f;
3738 outsvector = loadmodel->surfmesh.data_svector3f;
3739 outtvector = loadmodel->surfmesh.data_tvector3f;
3740 for (i = 0;i < (int)header.num_vertexes;i++)
3742 outsvector[0] = LittleFloat(vtangent[0]);
3743 outsvector[1] = LittleFloat(vtangent[1]);
3744 outsvector[2] = LittleFloat(vtangent[2]);
3745 if(LittleFloat(vtangent[3]) < 0)
3746 CrossProduct(outsvector, outnormal, outtvector);
3748 CrossProduct(outnormal, outsvector, outtvector);
3756 // this unaligned memory access is safe (all bytes)
3757 if (vblendindexes && vblendweights)
3759 for (i = 0; i < (int)header.num_vertexes;i++)
3761 blendweights_t weights;
3762 memcpy(weights.index, vblendindexes + i*4, 4);
3763 memcpy(weights.influence, vblendweights + i*4, 4);
3764 loadmodel->surfmesh.blends[i] = Mod_Skeletal_AddBlend(loadmodel, &weights);
3770 outcolor = loadmodel->surfmesh.data_lightmapcolor4f;
3771 // this unaligned memory access is safe (LittleFloat reads as bytes)
3772 for (i = 0;i < (int)header.num_vertexes;i++)
3774 outcolor[0] = LittleFloat(vcolor4f[0]);
3775 outcolor[1] = LittleFloat(vcolor4f[1]);
3776 outcolor[2] = LittleFloat(vcolor4f[2]);
3777 outcolor[3] = LittleFloat(vcolor4f[3]);
3784 outcolor = loadmodel->surfmesh.data_lightmapcolor4f;
3785 // this unaligned memory access is safe (all bytes)
3786 for (i = 0;i < (int)header.num_vertexes;i++)
3788 outcolor[0] = vcolor4ub[0] * (1.0f / 255.0f);
3789 outcolor[1] = vcolor4ub[1] * (1.0f / 255.0f);
3790 outcolor[2] = vcolor4ub[2] * (1.0f / 255.0f);
3791 outcolor[3] = vcolor4ub[3] * (1.0f / 255.0f);
3798 for (i = 0;i < (int)header.num_meshes;i++)
3801 msurface_t *surface;
3803 mesh.name = LittleLong(meshes[i].name);
3804 mesh.material = LittleLong(meshes[i].material);
3805 mesh.first_vertex = LittleLong(meshes[i].first_vertex);
3806 mesh.num_vertexes = LittleLong(meshes[i].num_vertexes);
3807 mesh.first_triangle = LittleLong(meshes[i].first_triangle);
3808 mesh.num_triangles = LittleLong(meshes[i].num_triangles);
3810 loadmodel->sortedmodelsurfaces[i] = i;
3811 surface = loadmodel->data_surfaces + i;
3812 surface->texture = loadmodel->data_textures + i;
3813 surface->num_firsttriangle = mesh.first_triangle;
3814 surface->num_triangles = mesh.num_triangles;
3815 surface->num_firstvertex = mesh.first_vertex;
3816 surface->num_vertices = mesh.num_vertexes;
3818 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, &text[mesh.name], &text[mesh.material]);
3821 Mod_FreeSkinFiles(skinfiles);
3822 Mod_MakeSortedSurfaces(loadmodel);
3824 // compute all the mesh information that was not loaded from the file
3825 if (loadmodel->surfmesh.data_element3s)
3826 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3827 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3829 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);
3830 if (!vnormal || !vtangent)
3831 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);
3832 if (!header.ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
3833 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3834 if (!header.ofs_bounds)
3835 Mod_Alias_CalculateBoundingBox();
3837 if (!loadmodel->surfmesh.isanimated && loadmodel->surfmesh.num_triangles >= 1)
3839 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3840 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3841 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3842 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3843 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3844 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
3847 if (joint ) Mem_Free(joint );joint = NULL;
3848 if (joint1 ) Mem_Free(joint1 );joint1 = NULL;
3849 if (pose ) Mem_Free(pose );pose = NULL;
3850 if (pose1 ) Mem_Free(pose1 );pose1 = NULL;
3852 // because shaders can do somewhat unexpected things, check for unusual features now
3853 for (i = 0;i < loadmodel->num_textures;i++)
3855 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
3856 mod->DrawSky = R_Q1BSP_DrawSky;
3857 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
3858 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;