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_FromBonePose7s(&bonematrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
395 parenttagindex = tagindex;
396 while ((parenttagindex = model->data_bones[parenttagindex].parent) >= 0)
398 Matrix4x4_FromBonePose7s(&parentbonematrix, model->num_posescale, model->data_poses7s + 7 * (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_FromBonePose7s(&bonematrix, model->num_posescale, model->data_poses7s + 7 * (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_FromBonePose7s(&bonematrix, loadmodel->num_posescale, loadmodel->data_poses7s + 7 * 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) * scales;
1024 vertst[i*2+1] = LittleLong(pinstverts[i].t) * 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[7]) + 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_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
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_ToBonePose7s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses7s + 7*(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[7]) + 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_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
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_ToBonePose7s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses7s + 7*(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[7]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t) + ((loadmodel->surfmesh.num_vertices <= 65536) ? (loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3])) : 0);
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_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
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[7] format for longterm storage
3037 loadmodel->data_poses7s[index*7+0] = k->origin[0] * loadmodel->num_poseinvscale;
3038 loadmodel->data_poses7s[index*7+1] = k->origin[1] * loadmodel->num_poseinvscale;
3039 loadmodel->data_poses7s[index*7+2] = k->origin[2] * loadmodel->num_poseinvscale;
3040 loadmodel->data_poses7s[index*7+3] = quat[0] * 32767.0f;
3041 loadmodel->data_poses7s[index*7+4] = quat[1] * 32767.0f;
3042 loadmodel->data_poses7s[index*7+5] = quat[2] * 32767.0f;
3043 loadmodel->data_poses7s[index*7+6] = quat[3] * 32767.0f;
3048 strlcpy(loadmodel->animscenes[0].name, "base", sizeof(loadmodel->animscenes[0].name));
3049 loadmodel->animscenes[0].firstframe = 0;
3050 loadmodel->animscenes[0].framecount = 1;
3051 loadmodel->animscenes[0].loop = true;
3052 loadmodel->animscenes[0].framerate = 10;
3054 // calculate the scaling value for bone origins so they can be compressed to short
3056 for (index = 0;index < numbones;index++)
3058 pskboneinfo_t *p = bones + index;
3059 biggestorigin = max(biggestorigin, fabs(p->basepose.origin[0]));
3060 biggestorigin = max(biggestorigin, fabs(p->basepose.origin[1]));
3061 biggestorigin = max(biggestorigin, fabs(p->basepose.origin[2]));
3063 loadmodel->num_posescale = biggestorigin / 32767.0f;
3064 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3066 // load the basepose as a frame
3067 for (index = 0;index < numbones;index++)
3069 pskboneinfo_t *p = bones + index;
3071 Vector4Copy(p->basepose.quat, quat);
3073 Vector4Negate(quat, quat);
3074 Vector4Normalize2(quat, quat);
3075 // compress poses to the short[7] format for longterm storage
3076 loadmodel->data_poses7s[index*7+0] = p->basepose.origin[0] * loadmodel->num_poseinvscale;
3077 loadmodel->data_poses7s[index*7+1] = p->basepose.origin[1] * loadmodel->num_poseinvscale;
3078 loadmodel->data_poses7s[index*7+2] = p->basepose.origin[2] * loadmodel->num_poseinvscale;
3079 loadmodel->data_poses7s[index*7+3] = quat[0] * 32767.0f;
3080 loadmodel->data_poses7s[index*7+4] = quat[1] * 32767.0f;
3081 loadmodel->data_poses7s[index*7+5] = quat[2] * 32767.0f;
3082 loadmodel->data_poses7s[index*7+6] = quat[3] * 32767.0f;
3086 Mod_FreeSkinFiles(skinfiles);
3088 Mem_Free(animfilebuffer);
3089 Mod_MakeSortedSurfaces(loadmodel);
3091 // compute all the mesh information that was not loaded from the file
3092 // TODO: honor smoothing groups somehow?
3093 if (loadmodel->surfmesh.data_element3s)
3094 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3095 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3096 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
3097 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);
3098 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);
3099 if (loadmodel->surfmesh.data_neighbor3i)
3100 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3101 Mod_Alias_CalculateBoundingBox();
3103 if (!loadmodel->surfmesh.isanimated)
3105 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3106 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3107 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3108 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3109 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3110 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
3113 // because shaders can do somewhat unexpected things, check for unusual features now
3114 for (i = 0;i < loadmodel->num_textures;i++)
3116 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
3117 mod->DrawSky = R_Q1BSP_DrawSky;
3118 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
3119 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
3123 void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
3125 unsigned char *data;
3127 const unsigned char *pbase, *pend;
3129 skinfile_t *skinfiles;
3130 int i, j, k, meshvertices, meshtriangles;
3131 float biggestorigin;
3132 const unsigned int *inelements;
3134 const int *inneighbors;
3136 float *outvertex, *outnormal, *outtexcoord, *outsvector, *outtvector, *outcolor;
3137 // this pointers into the file data are read only through Little* functions so they can be unaligned memory
3138 const float *vnormal = NULL;
3139 const float *vposition = NULL;
3140 const float *vtangent = NULL;
3141 const float *vtexcoord = NULL;
3142 const float *vcolor4f = NULL;
3143 const unsigned char *vblendindexes = NULL;
3144 const unsigned char *vblendweights = NULL;
3145 const unsigned char *vcolor4ub = NULL;
3146 const unsigned short *framedata = NULL;
3147 // temporary memory allocations (because the data in the file may be misaligned)
3148 iqmanim_t *anims = NULL;
3149 iqmbounds_t *bounds = NULL;
3150 iqmjoint1_t *joint1 = NULL;
3151 iqmjoint_t *joint = NULL;
3152 iqmmesh_t *meshes = NULL;
3153 iqmpose1_t *pose1 = NULL;
3154 iqmpose_t *pose = NULL;
3155 iqmvertexarray_t *vas = NULL;
3157 pbase = (unsigned char *)buffer;
3158 pend = (unsigned char *)bufferend;
3160 if (pbase + sizeof(iqmheader_t) > pend)
3161 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model %d", loadmodel->name, (int)(pend - pbase));
3163 // copy struct (otherwise it may be misaligned)
3164 // LordHavoc: okay it's definitely not misaligned here, but for consistency...
3165 memcpy(&header, pbase, sizeof(iqmheader_t));
3167 if (memcmp(header.id, "INTERQUAKEMODEL", 16))
3168 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model", loadmodel->name);
3169 if (LittleLong(header.version) != 1 && LittleLong(header.version) != 2)
3170 Host_Error ("Mod_INTERQUAKEMODEL_Load: only version 1 and 2 models are currently supported (name = %s)", loadmodel->name);
3172 loadmodel->modeldatatypestring = "IQM";
3174 loadmodel->type = mod_alias;
3175 loadmodel->synctype = ST_RAND;
3178 header.version = LittleLong(header.version);
3179 header.filesize = LittleLong(header.filesize);
3180 header.flags = LittleLong(header.flags);
3181 header.num_text = LittleLong(header.num_text);
3182 header.ofs_text = LittleLong(header.ofs_text);
3183 header.num_meshes = LittleLong(header.num_meshes);
3184 header.ofs_meshes = LittleLong(header.ofs_meshes);
3185 header.num_vertexarrays = LittleLong(header.num_vertexarrays);
3186 header.num_vertexes = LittleLong(header.num_vertexes);
3187 header.ofs_vertexarrays = LittleLong(header.ofs_vertexarrays);
3188 header.num_triangles = LittleLong(header.num_triangles);
3189 header.ofs_triangles = LittleLong(header.ofs_triangles);
3190 header.ofs_neighbors = LittleLong(header.ofs_neighbors);
3191 header.num_joints = LittleLong(header.num_joints);
3192 header.ofs_joints = LittleLong(header.ofs_joints);
3193 header.num_poses = LittleLong(header.num_poses);
3194 header.ofs_poses = LittleLong(header.ofs_poses);
3195 header.num_anims = LittleLong(header.num_anims);
3196 header.ofs_anims = LittleLong(header.ofs_anims);
3197 header.num_frames = LittleLong(header.num_frames);
3198 header.num_framechannels = LittleLong(header.num_framechannels);
3199 header.ofs_frames = LittleLong(header.ofs_frames);
3200 header.ofs_bounds = LittleLong(header.ofs_bounds);
3201 header.num_comment = LittleLong(header.num_comment);
3202 header.ofs_comment = LittleLong(header.ofs_comment);
3203 header.num_extensions = LittleLong(header.num_extensions);
3204 header.ofs_extensions = LittleLong(header.ofs_extensions);
3206 if (header.version == 1)
3208 if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint1_t) > pend ||
3209 pbase + header.ofs_poses + header.num_poses*sizeof(iqmpose1_t) > pend)
3211 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3217 if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint_t) > pend ||
3218 pbase + header.ofs_poses + header.num_poses*sizeof(iqmpose_t) > pend)
3220 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3224 if (pbase + header.ofs_text + header.num_text > pend ||
3225 pbase + header.ofs_meshes + header.num_meshes*sizeof(iqmmesh_t) > pend ||
3226 pbase + header.ofs_vertexarrays + header.num_vertexarrays*sizeof(iqmvertexarray_t) > pend ||
3227 pbase + header.ofs_triangles + header.num_triangles*sizeof(int[3]) > pend ||
3228 (header.ofs_neighbors && pbase + header.ofs_neighbors + header.num_triangles*sizeof(int[3]) > pend) ||
3229 pbase + header.ofs_anims + header.num_anims*sizeof(iqmanim_t) > pend ||
3230 pbase + header.ofs_frames + header.num_frames*header.num_framechannels*sizeof(unsigned short) > pend ||
3231 (header.ofs_bounds && pbase + header.ofs_bounds + header.num_frames*sizeof(iqmbounds_t) > pend) ||
3232 pbase + header.ofs_comment + header.num_comment > pend)
3234 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3238 // copy structs to make them aligned in memory (otherwise we crash on Sparc and PowerPC and others)
3239 if (header.num_vertexarrays)
3240 vas = (iqmvertexarray_t *)(pbase + header.ofs_vertexarrays);
3241 if (header.num_anims)
3242 anims = (iqmanim_t *)(pbase + header.ofs_anims);
3243 if (header.ofs_bounds)
3244 bounds = (iqmbounds_t *)(pbase + header.ofs_bounds);
3245 if (header.num_meshes)
3246 meshes = (iqmmesh_t *)(pbase + header.ofs_meshes);
3248 for (i = 0;i < (int)header.num_vertexarrays;i++)
3250 iqmvertexarray_t va;
3252 va.type = LittleLong(vas[i].type);
3253 va.flags = LittleLong(vas[i].flags);
3254 va.format = LittleLong(vas[i].format);
3255 va.size = LittleLong(vas[i].size);
3256 va.offset = LittleLong(vas[i].offset);
3257 vsize = header.num_vertexes*va.size;
3260 case IQM_FLOAT: vsize *= sizeof(float); break;
3261 case IQM_UBYTE: vsize *= sizeof(unsigned char); break;
3264 if (pbase + va.offset + vsize > pend)
3266 // no need to copy the vertex data for alignment because LittleLong/LittleShort will be invoked on reading them, and the destination is aligned
3270 if (va.format == IQM_FLOAT && va.size == 3)
3271 vposition = (const float *)(pbase + va.offset);
3274 if (va.format == IQM_FLOAT && va.size == 2)
3275 vtexcoord = (const float *)(pbase + va.offset);
3278 if (va.format == IQM_FLOAT && va.size == 3)
3279 vnormal = (const float *)(pbase + va.offset);
3282 if (va.format == IQM_FLOAT && va.size == 4)
3283 vtangent = (const float *)(pbase + va.offset);
3285 case IQM_BLENDINDEXES:
3286 if (va.format == IQM_UBYTE && va.size == 4)
3287 vblendindexes = (const unsigned char *)(pbase + va.offset);
3289 case IQM_BLENDWEIGHTS:
3290 if (va.format == IQM_UBYTE && va.size == 4)
3291 vblendweights = (const unsigned char *)(pbase + va.offset);
3294 if (va.format == IQM_FLOAT && va.size == 4)
3295 vcolor4f = (const float *)(pbase + va.offset);
3296 if (va.format == IQM_UBYTE && va.size == 4)
3297 vcolor4ub = (const unsigned char *)(pbase + va.offset);
3301 if (header.num_vertexes > 0 && (!vposition || !vtexcoord || ((header.num_frames > 0 || header.num_anims > 0) && (!vblendindexes || !vblendweights))))
3303 Con_Printf("%s is missing vertex array data\n", loadmodel->name);
3307 text = header.num_text && header.ofs_text ? (const char *)(pbase + header.ofs_text) : "";
3309 loadmodel->DrawSky = NULL;
3310 loadmodel->DrawAddWaterPlanes = NULL;
3311 loadmodel->Draw = R_Q1BSP_Draw;
3312 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
3313 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
3314 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
3315 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
3316 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
3317 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
3318 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
3319 loadmodel->DrawLight = R_Q1BSP_DrawLight;
3320 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
3321 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
3322 loadmodel->PointSuperContents = NULL;
3324 // load external .skin files if present
3325 skinfiles = Mod_LoadSkinFiles();
3326 if (loadmodel->numskins < 1)
3327 loadmodel->numskins = 1;
3329 loadmodel->numframes = max(header.num_anims, 1);
3330 loadmodel->num_bones = header.num_joints;
3331 loadmodel->num_poses = max(header.num_frames, 1);
3332 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = header.num_meshes;
3333 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3334 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3335 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices; // updated later
3337 meshvertices = header.num_vertexes;
3338 meshtriangles = header.num_triangles;
3340 // do most allocations as one merged chunk
3341 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + (r_enableshadowvolumes.integer ? meshtriangles * sizeof(int[3]) : 0) + meshvertices * (sizeof(float[14]) + (vcolor4f || vcolor4ub ? sizeof(float[4]) : 0)) + (vblendindexes && vblendweights ? meshvertices * sizeof(unsigned short) : 0) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
3342 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
3343 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
3344 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
3345 loadmodel->surfmesh.num_vertices = meshvertices;
3346 loadmodel->surfmesh.num_triangles = meshtriangles;
3347 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3348 if (r_enableshadowvolumes.integer)
3350 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3352 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
3353 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3354 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3355 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
3356 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
3357 if (vcolor4f || vcolor4ub)
3359 loadmodel->surfmesh.data_lightmapcolor4f = (float *)data;data += meshvertices * sizeof(float[4]);
3361 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
3362 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
3363 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
3364 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
3365 if (vblendindexes && vblendweights)
3367 loadmodel->surfmesh.num_blends = 0;
3368 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
3370 if (meshvertices <= 65536)
3372 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
3374 loadmodel->data_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
3375 if (vblendindexes && vblendweights)
3376 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
3378 for (i = 0;i < loadmodel->numskins;i++)
3380 loadmodel->skinscenes[i].firstframe = i;
3381 loadmodel->skinscenes[i].framecount = 1;
3382 loadmodel->skinscenes[i].loop = true;
3383 loadmodel->skinscenes[i].framerate = 10;
3386 // load the bone info
3387 if (header.version == 1)
3389 iqmjoint1_t *injoint1 = (iqmjoint1_t *)(pbase + header.ofs_joints);
3390 if (loadmodel->num_bones)
3391 joint1 = (iqmjoint1_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(iqmjoint1_t));
3392 for (i = 0;i < loadmodel->num_bones;i++)
3394 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3395 joint1[i].name = LittleLong(injoint1[i].name);
3396 joint1[i].parent = LittleLong(injoint1[i].parent);
3397 for (j = 0;j < 3;j++)
3399 joint1[i].origin[j] = LittleFloat(injoint1[i].origin[j]);
3400 joint1[i].rotation[j] = LittleFloat(injoint1[i].rotation[j]);
3401 joint1[i].scale[j] = LittleFloat(injoint1[i].scale[j]);
3403 strlcpy(loadmodel->data_bones[i].name, &text[joint1[i].name], sizeof(loadmodel->data_bones[i].name));
3404 loadmodel->data_bones[i].parent = joint1[i].parent;
3405 if (loadmodel->data_bones[i].parent >= i)
3406 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3407 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]);
3408 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3409 if (loadmodel->data_bones[i].parent >= 0)
3411 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3412 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3413 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3415 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3420 iqmjoint_t *injoint = (iqmjoint_t *)(pbase + header.ofs_joints);
3421 if (header.num_joints)
3422 joint = (iqmjoint_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(iqmjoint_t));
3423 for (i = 0;i < loadmodel->num_bones;i++)
3425 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3426 joint[i].name = LittleLong(injoint[i].name);
3427 joint[i].parent = LittleLong(injoint[i].parent);
3428 for (j = 0;j < 3;j++)
3430 joint[i].origin[j] = LittleFloat(injoint[i].origin[j]);
3431 joint[i].rotation[j] = LittleFloat(injoint[i].rotation[j]);
3432 joint[i].scale[j] = LittleFloat(injoint[i].scale[j]);
3434 joint[i].rotation[3] = LittleFloat(injoint[i].rotation[3]);
3435 strlcpy(loadmodel->data_bones[i].name, &text[joint[i].name], sizeof(loadmodel->data_bones[i].name));
3436 loadmodel->data_bones[i].parent = joint[i].parent;
3437 if (loadmodel->data_bones[i].parent >= i)
3438 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3439 if (joint[i].rotation[3] > 0)
3440 Vector4Negate(joint[i].rotation, joint[i].rotation);
3441 Vector4Normalize2(joint[i].rotation, joint[i].rotation);
3442 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]);
3443 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3444 if (loadmodel->data_bones[i].parent >= 0)
3446 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3447 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3448 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3450 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3454 // set up the animscenes based on the anims
3455 for (i = 0;i < (int)header.num_anims;i++)
3458 anim.name = LittleLong(anims[i].name);
3459 anim.first_frame = LittleLong(anims[i].first_frame);
3460 anim.num_frames = LittleLong(anims[i].num_frames);
3461 anim.framerate = LittleFloat(anims[i].framerate);
3462 anim.flags = LittleLong(anims[i].flags);
3463 strlcpy(loadmodel->animscenes[i].name, &text[anim.name], sizeof(loadmodel->animscenes[i].name));
3464 loadmodel->animscenes[i].firstframe = anim.first_frame;
3465 loadmodel->animscenes[i].framecount = anim.num_frames;
3466 loadmodel->animscenes[i].loop = ((anim.flags & IQM_LOOP) != 0);
3467 loadmodel->animscenes[i].framerate = anim.framerate;
3469 if (header.num_anims <= 0)
3471 strlcpy(loadmodel->animscenes[0].name, "static", sizeof(loadmodel->animscenes[0].name));
3472 loadmodel->animscenes[0].firstframe = 0;
3473 loadmodel->animscenes[0].framecount = 1;
3474 loadmodel->animscenes[0].loop = true;
3475 loadmodel->animscenes[0].framerate = 10;
3478 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
3479 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
3482 if (header.version == 1)
3484 iqmpose1_t *inpose1 = (iqmpose1_t *)(pbase + header.ofs_poses);
3485 if (header.num_poses)
3486 pose1 = (iqmpose1_t *)Mem_Alloc(loadmodel->mempool, header.num_poses * sizeof(iqmpose1_t));
3487 for (i = 0;i < (int)header.num_poses;i++)
3490 pose1[i].parent = LittleLong(inpose1[i].parent);
3491 pose1[i].channelmask = LittleLong(inpose1[i].channelmask);
3492 for (j = 0;j < 9;j++)
3494 pose1[i].channeloffset[j] = LittleFloat(inpose1[i].channeloffset[j]);
3495 pose1[i].channelscale[j] = LittleFloat(inpose1[i].channelscale[j]);
3497 f = fabs(pose1[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3498 f = fabs(pose1[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3499 f = fabs(pose1[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3500 f = fabs(pose1[i].channeloffset[0] + 0xFFFF*pose1[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3501 f = fabs(pose1[i].channeloffset[1] + 0xFFFF*pose1[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3502 f = fabs(pose1[i].channeloffset[2] + 0xFFFF*pose1[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3504 if (header.num_frames <= 0)
3506 for (i = 0;i < loadmodel->num_bones;i++)
3509 f = fabs(joint1[i].origin[0]); biggestorigin = max(biggestorigin, f);
3510 f = fabs(joint1[i].origin[1]); biggestorigin = max(biggestorigin, f);
3511 f = fabs(joint1[i].origin[2]); biggestorigin = max(biggestorigin, f);
3517 iqmpose_t *inpose = (iqmpose_t *)(pbase + header.ofs_poses);
3518 if (header.num_poses)
3519 pose = (iqmpose_t *)Mem_Alloc(loadmodel->mempool, header.num_poses * sizeof(iqmpose_t));
3520 for (i = 0;i < (int)header.num_poses;i++)
3523 pose[i].parent = LittleLong(inpose[i].parent);
3524 pose[i].channelmask = LittleLong(inpose[i].channelmask);
3525 for (j = 0;j < 10;j++)
3527 pose[i].channeloffset[j] = LittleFloat(inpose[i].channeloffset[j]);
3528 pose[i].channelscale[j] = LittleFloat(inpose[i].channelscale[j]);
3530 f = fabs(pose[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3531 f = fabs(pose[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3532 f = fabs(pose[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3533 f = fabs(pose[i].channeloffset[0] + 0xFFFF*pose[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3534 f = fabs(pose[i].channeloffset[1] + 0xFFFF*pose[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3535 f = fabs(pose[i].channeloffset[2] + 0xFFFF*pose[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3537 if (header.num_frames <= 0)
3539 for (i = 0;i < loadmodel->num_bones;i++)
3542 f = fabs(joint[i].origin[0]); biggestorigin = max(biggestorigin, f);
3543 f = fabs(joint[i].origin[1]); biggestorigin = max(biggestorigin, f);
3544 f = fabs(joint[i].origin[2]); biggestorigin = max(biggestorigin, f);
3548 loadmodel->num_posescale = biggestorigin / 32767.0f;
3549 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3551 // load the pose data
3552 // this unaligned memory access is safe (LittleShort reads as bytes)
3553 framedata = (const unsigned short *)(pbase + header.ofs_frames);
3554 if (header.version == 1)
3556 for (i = 0, k = 0;i < (int)header.num_frames;i++)
3558 for (j = 0;j < (int)header.num_poses;j++, k++)
3560 float qx, qy, qz, qw;
3561 loadmodel->data_poses7s[k*7 + 0] = loadmodel->num_poseinvscale * (pose1[j].channeloffset[0] + (pose1[j].channelmask&1 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[0] : 0));
3562 loadmodel->data_poses7s[k*7 + 1] = loadmodel->num_poseinvscale * (pose1[j].channeloffset[1] + (pose1[j].channelmask&2 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[1] : 0));
3563 loadmodel->data_poses7s[k*7 + 2] = loadmodel->num_poseinvscale * (pose1[j].channeloffset[2] + (pose1[j].channelmask&4 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[2] : 0));
3564 qx = pose1[j].channeloffset[3] + (pose1[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[3] : 0);
3565 qy = pose1[j].channeloffset[4] + (pose1[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[4] : 0);
3566 qz = pose1[j].channeloffset[5] + (pose1[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[5] : 0);
3567 qw = 1.0f - (qx*qx + qy*qy + qz*qz);
3568 qw = qw > 0.0f ? -sqrt(qw) : 0.0f;
3569 loadmodel->data_poses7s[k*7 + 3] = 32767.0f * qx;
3570 loadmodel->data_poses7s[k*7 + 4] = 32767.0f * qy;
3571 loadmodel->data_poses7s[k*7 + 5] = 32767.0f * qz;
3572 loadmodel->data_poses7s[k*7 + 6] = 32767.0f * qw;
3573 // skip scale data for now
3574 if(pose1[j].channelmask&64) framedata++;
3575 if(pose1[j].channelmask&128) framedata++;
3576 if(pose1[j].channelmask&256) framedata++;
3579 if (header.num_frames <= 0)
3581 for (i = 0;i < loadmodel->num_bones;i++)
3583 float qx, qy, qz, qw;
3584 loadmodel->data_poses7s[i*7 + 0] = loadmodel->num_poseinvscale * joint1[i].origin[0];
3585 loadmodel->data_poses7s[i*7 + 1] = loadmodel->num_poseinvscale * joint1[i].origin[1];
3586 loadmodel->data_poses7s[i*7 + 2] = loadmodel->num_poseinvscale * joint1[i].origin[2];
3587 qx = joint1[i].rotation[0];
3588 qy = joint1[i].rotation[1];
3589 qz = joint1[i].rotation[2];
3590 qw = 1.0f - (qx*qx + qy*qy + qz*qz);
3591 qw = qw > 0.0f ? -sqrt(qw) : 0.0f;
3592 loadmodel->data_poses7s[i*7 + 3] = 32767.0f * qx;
3593 loadmodel->data_poses7s[i*7 + 4] = 32767.0f * qy;
3594 loadmodel->data_poses7s[i*7 + 5] = 32767.0f * qz;
3595 loadmodel->data_poses7s[i*7 + 6] = 32767.0f * qw;
3601 for (i = 0, k = 0;i < (int)header.num_frames;i++)
3603 for (j = 0;j < (int)header.num_poses;j++, k++)
3606 loadmodel->data_poses7s[k*7 + 0] = loadmodel->num_poseinvscale * (pose[j].channeloffset[0] + (pose[j].channelmask&1 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[0] : 0));
3607 loadmodel->data_poses7s[k*7 + 1] = loadmodel->num_poseinvscale * (pose[j].channeloffset[1] + (pose[j].channelmask&2 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[1] : 0));
3608 loadmodel->data_poses7s[k*7 + 2] = loadmodel->num_poseinvscale * (pose[j].channeloffset[2] + (pose[j].channelmask&4 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[2] : 0));
3609 rot[0] = pose[j].channeloffset[3] + (pose[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[3] : 0);
3610 rot[1] = pose[j].channeloffset[4] + (pose[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[4] : 0);
3611 rot[2] = pose[j].channeloffset[5] + (pose[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[5] : 0);
3612 rot[3] = pose[j].channeloffset[6] + (pose[j].channelmask&64 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[6] : 0);
3614 Vector4Negate(rot, rot);
3615 Vector4Normalize2(rot, rot);
3616 loadmodel->data_poses7s[k*7 + 3] = 32767.0f * rot[0];
3617 loadmodel->data_poses7s[k*7 + 4] = 32767.0f * rot[1];
3618 loadmodel->data_poses7s[k*7 + 5] = 32767.0f * rot[2];
3619 loadmodel->data_poses7s[k*7 + 6] = 32767.0f * rot[3];
3620 // skip scale data for now
3621 if(pose[j].channelmask&128) framedata++;
3622 if(pose[j].channelmask&256) framedata++;
3623 if(pose[j].channelmask&512) framedata++;
3626 if (header.num_frames <= 0)
3628 for (i = 0;i < loadmodel->num_bones;i++)
3630 loadmodel->data_poses7s[i*7 + 0] = loadmodel->num_poseinvscale * joint[i].origin[0];
3631 loadmodel->data_poses7s[i*7 + 1] = loadmodel->num_poseinvscale * joint[i].origin[1];
3632 loadmodel->data_poses7s[i*7 + 2] = loadmodel->num_poseinvscale * joint[i].origin[2];
3633 loadmodel->data_poses7s[i*7 + 3] = 32767.0f * joint[i].rotation[0];
3634 loadmodel->data_poses7s[i*7 + 4] = 32767.0f * joint[i].rotation[1];
3635 loadmodel->data_poses7s[i*7 + 5] = 32767.0f * joint[i].rotation[2];
3636 loadmodel->data_poses7s[i*7 + 6] = 32767.0f * joint[i].rotation[3];
3641 // load bounding box data
3642 if (header.ofs_bounds)
3644 float xyradius = 0, radius = 0;
3645 VectorClear(loadmodel->normalmins);
3646 VectorClear(loadmodel->normalmaxs);
3647 for (i = 0; i < (int)header.num_frames;i++)
3650 bound.mins[0] = LittleFloat(bounds[i].mins[0]);
3651 bound.mins[1] = LittleFloat(bounds[i].mins[1]);
3652 bound.mins[2] = LittleFloat(bounds[i].mins[2]);
3653 bound.maxs[0] = LittleFloat(bounds[i].maxs[0]);
3654 bound.maxs[1] = LittleFloat(bounds[i].maxs[1]);
3655 bound.maxs[2] = LittleFloat(bounds[i].maxs[2]);
3656 bound.xyradius = LittleFloat(bounds[i].xyradius);
3657 bound.radius = LittleFloat(bounds[i].radius);
3660 VectorCopy(bound.mins, loadmodel->normalmins);
3661 VectorCopy(bound.maxs, loadmodel->normalmaxs);
3665 if (loadmodel->normalmins[0] > bound.mins[0]) loadmodel->normalmins[0] = bound.mins[0];
3666 if (loadmodel->normalmins[1] > bound.mins[1]) loadmodel->normalmins[1] = bound.mins[1];
3667 if (loadmodel->normalmins[2] > bound.mins[2]) loadmodel->normalmins[2] = bound.mins[2];
3668 if (loadmodel->normalmaxs[0] < bound.maxs[0]) loadmodel->normalmaxs[0] = bound.maxs[0];
3669 if (loadmodel->normalmaxs[1] < bound.maxs[1]) loadmodel->normalmaxs[1] = bound.maxs[1];
3670 if (loadmodel->normalmaxs[2] < bound.maxs[2]) loadmodel->normalmaxs[2] = bound.maxs[2];
3672 if (bound.xyradius > xyradius)
3673 xyradius = bound.xyradius;
3674 if (bound.radius > radius)
3675 radius = bound.radius;
3677 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -xyradius;
3678 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = xyradius;
3679 loadmodel->yawmins[2] = loadmodel->normalmins[2];
3680 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
3681 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
3682 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
3683 loadmodel->radius = radius;
3684 loadmodel->radius2 = radius * radius;
3687 // load triangle data
3688 // this unaligned memory access is safe (LittleLong reads as bytes)
3689 inelements = (const unsigned int *)(pbase + header.ofs_triangles);
3690 outelements = loadmodel->surfmesh.data_element3i;
3691 for (i = 0;i < (int)header.num_triangles;i++)
3693 outelements[0] = LittleLong(inelements[0]);
3694 outelements[1] = LittleLong(inelements[1]);
3695 outelements[2] = LittleLong(inelements[2]);
3699 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, header.num_vertexes, __FILE__, __LINE__);
3701 if (header.ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
3703 // this unaligned memory access is safe (LittleLong reads as bytes)
3704 inneighbors = (const int *)(pbase + header.ofs_neighbors);
3705 outneighbors = loadmodel->surfmesh.data_neighbor3i;
3706 for (i = 0;i < (int)header.num_triangles;i++)
3708 outneighbors[0] = LittleLong(inneighbors[0]);
3709 outneighbors[1] = LittleLong(inneighbors[1]);
3710 outneighbors[2] = LittleLong(inneighbors[2]);
3717 // this unaligned memory access is safe (LittleFloat reads as bytes)
3718 outvertex = loadmodel->surfmesh.data_vertex3f;
3719 for (i = 0;i < (int)header.num_vertexes;i++)
3721 outvertex[0] = LittleFloat(vposition[0]);
3722 outvertex[1] = LittleFloat(vposition[1]);
3723 outvertex[2] = LittleFloat(vposition[2]);
3728 outtexcoord = loadmodel->surfmesh.data_texcoordtexture2f;
3729 // this unaligned memory access is safe (LittleFloat reads as bytes)
3730 for (i = 0;i < (int)header.num_vertexes;i++)
3732 outtexcoord[0] = LittleFloat(vtexcoord[0]);
3733 outtexcoord[1] = LittleFloat(vtexcoord[1]);
3738 // this unaligned memory access is safe (LittleFloat reads as bytes)
3741 outnormal = loadmodel->surfmesh.data_normal3f;
3742 for (i = 0;i < (int)header.num_vertexes;i++)
3744 outnormal[0] = LittleFloat(vnormal[0]);
3745 outnormal[1] = LittleFloat(vnormal[1]);
3746 outnormal[2] = LittleFloat(vnormal[2]);
3752 // this unaligned memory access is safe (LittleFloat reads as bytes)
3753 if(vnormal && vtangent)
3755 outnormal = loadmodel->surfmesh.data_normal3f;
3756 outsvector = loadmodel->surfmesh.data_svector3f;
3757 outtvector = loadmodel->surfmesh.data_tvector3f;
3758 for (i = 0;i < (int)header.num_vertexes;i++)
3760 outsvector[0] = LittleFloat(vtangent[0]);
3761 outsvector[1] = LittleFloat(vtangent[1]);
3762 outsvector[2] = LittleFloat(vtangent[2]);
3763 if(LittleFloat(vtangent[3]) < 0)
3764 CrossProduct(outsvector, outnormal, outtvector);
3766 CrossProduct(outnormal, outsvector, outtvector);
3774 // this unaligned memory access is safe (all bytes)
3775 if (vblendindexes && vblendweights)
3777 for (i = 0; i < (int)header.num_vertexes;i++)
3779 blendweights_t weights;
3780 memcpy(weights.index, vblendindexes + i*4, 4);
3781 memcpy(weights.influence, vblendweights + i*4, 4);
3782 loadmodel->surfmesh.blends[i] = Mod_Skeletal_AddBlend(loadmodel, &weights);
3788 outcolor = loadmodel->surfmesh.data_lightmapcolor4f;
3789 // this unaligned memory access is safe (LittleFloat reads as bytes)
3790 for (i = 0;i < (int)header.num_vertexes;i++)
3792 outcolor[0] = LittleFloat(vcolor4f[0]);
3793 outcolor[1] = LittleFloat(vcolor4f[1]);
3794 outcolor[2] = LittleFloat(vcolor4f[2]);
3795 outcolor[3] = LittleFloat(vcolor4f[3]);
3802 outcolor = loadmodel->surfmesh.data_lightmapcolor4f;
3803 // this unaligned memory access is safe (all bytes)
3804 for (i = 0;i < (int)header.num_vertexes;i++)
3806 outcolor[0] = vcolor4ub[0] * (1.0f / 255.0f);
3807 outcolor[1] = vcolor4ub[1] * (1.0f / 255.0f);
3808 outcolor[2] = vcolor4ub[2] * (1.0f / 255.0f);
3809 outcolor[3] = vcolor4ub[3] * (1.0f / 255.0f);
3816 for (i = 0;i < (int)header.num_meshes;i++)
3819 msurface_t *surface;
3821 mesh.name = LittleLong(meshes[i].name);
3822 mesh.material = LittleLong(meshes[i].material);
3823 mesh.first_vertex = LittleLong(meshes[i].first_vertex);
3824 mesh.num_vertexes = LittleLong(meshes[i].num_vertexes);
3825 mesh.first_triangle = LittleLong(meshes[i].first_triangle);
3826 mesh.num_triangles = LittleLong(meshes[i].num_triangles);
3828 loadmodel->sortedmodelsurfaces[i] = i;
3829 surface = loadmodel->data_surfaces + i;
3830 surface->texture = loadmodel->data_textures + i;
3831 surface->num_firsttriangle = mesh.first_triangle;
3832 surface->num_triangles = mesh.num_triangles;
3833 surface->num_firstvertex = mesh.first_vertex;
3834 surface->num_vertices = mesh.num_vertexes;
3836 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, &text[mesh.name], &text[mesh.material]);
3839 Mod_FreeSkinFiles(skinfiles);
3840 Mod_MakeSortedSurfaces(loadmodel);
3842 // compute all the mesh information that was not loaded from the file
3843 if (loadmodel->surfmesh.data_element3s)
3844 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3845 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3847 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);
3848 if (!vnormal || !vtangent)
3849 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);
3850 if (!header.ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
3851 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3852 if (!header.ofs_bounds)
3853 Mod_Alias_CalculateBoundingBox();
3855 if (!loadmodel->surfmesh.isanimated && loadmodel->surfmesh.num_triangles >= 1)
3857 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3858 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3859 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3860 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3861 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3862 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
3865 if (joint ) Mem_Free(joint );joint = NULL;
3866 if (joint1 ) Mem_Free(joint1 );joint1 = NULL;
3867 if (pose ) Mem_Free(pose );pose = NULL;
3868 if (pose1 ) Mem_Free(pose1 );pose1 = NULL;
3870 // because shaders can do somewhat unexpected things, check for unusual features now
3871 for (i = 0;i < loadmodel->num_textures;i++)
3873 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
3874 mod->DrawSky = R_Q1BSP_DrawSky;
3875 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
3876 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;