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 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 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 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 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 void Mod_MDL_AnimateVertices(const dp_model_t * RESTRICT model, const frameblend_t * RESTRICT frameblend, const skeleton_t *skeleton, float * RESTRICT vertex3f, float * RESTRICT normal3f, float * RESTRICT svector3f, float * RESTRICT tvector3f)
267 int i, numblends, blendnum;
268 int numverts = model->surfmesh.num_vertices;
270 VectorClear(translate);
272 // blend the frame translates to avoid redundantly doing so on each vertex
273 // (a bit of a brain twister but it works)
274 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
276 if (model->surfmesh.data_morphmd2framesize6f)
277 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6 + 3, translate);
279 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.num_morphmdlframetranslate, translate);
280 if (frameblend[blendnum].lerp > 0)
281 numblends = blendnum + 1;
283 // special case for the first blend because it avoids some adds and the need to memset the arrays first
284 for (blendnum = 0;blendnum < numblends;blendnum++)
286 const trivertx_t *verts = model->surfmesh.data_morphmdlvertex + numverts * frameblend[blendnum].subframe;
290 if (model->surfmesh.data_morphmd2framesize6f)
291 VectorScale(model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6, frameblend[blendnum].lerp, scale);
293 VectorScale(model->surfmesh.num_morphmdlframescale, frameblend[blendnum].lerp, scale);
296 for (i = 0;i < numverts;i++)
298 vertex3f[i * 3 + 0] = translate[0] + verts[i].v[0] * scale[0];
299 vertex3f[i * 3 + 1] = translate[1] + verts[i].v[1] * scale[1];
300 vertex3f[i * 3 + 2] = translate[2] + verts[i].v[2] * scale[2];
305 for (i = 0;i < numverts;i++)
307 vertex3f[i * 3 + 0] += verts[i].v[0] * scale[0];
308 vertex3f[i * 3 + 1] += verts[i].v[1] * scale[1];
309 vertex3f[i * 3 + 2] += verts[i].v[2] * scale[2];
313 // the vertex normals in mdl models are an index into a table of
314 // 162 unique values, this very crude quantization reduces the
315 // vertex normal to only one byte, which saves a lot of space but
316 // also makes lighting pretty coarse
319 float lerp = frameblend[blendnum].lerp;
322 for (i = 0;i < numverts;i++)
324 const float *vn = m_bytenormals[verts[i].lightnormalindex];
325 VectorScale(vn, lerp, normal3f + i*3);
330 for (i = 0;i < numverts;i++)
332 const float *vn = m_bytenormals[verts[i].lightnormalindex];
333 VectorMA(normal3f + i*3, lerp, vn, normal3f + i*3);
339 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
340 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
343 for (i = 0;i < numverts;i++, texvecvert++)
345 VectorScale(texvecvert->svec, f, svector3f + i*3);
346 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
351 for (i = 0;i < numverts;i++, texvecvert++)
353 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
354 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
361 int Mod_Alias_GetTagMatrix(const dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, int tagindex, matrix4x4_t *outmatrix)
364 matrix4x4_t parentbonematrix;
365 matrix4x4_t tempbonematrix;
366 matrix4x4_t bonematrix;
367 matrix4x4_t blendmatrix;
374 *outmatrix = identitymatrix;
375 if (skeleton && skeleton->relativetransforms)
377 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
379 *outmatrix = skeleton->relativetransforms[tagindex];
380 while ((tagindex = model->data_bones[tagindex].parent) >= 0)
383 Matrix4x4_Concat(outmatrix, &skeleton->relativetransforms[tagindex], &temp);
386 else if (model->num_bones)
388 if (tagindex < 0 || tagindex >= model->num_bones)
390 Matrix4x4_Clear(&blendmatrix);
391 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
393 lerp = frameblend[blendindex].lerp;
394 Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
395 parenttagindex = tagindex;
396 while ((parenttagindex = model->data_bones[parenttagindex].parent) >= 0)
398 Matrix4x4_FromBonePose6s(&parentbonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + parenttagindex));
399 tempbonematrix = bonematrix;
400 Matrix4x4_Concat(&bonematrix, &parentbonematrix, &tempbonematrix);
402 Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
404 *outmatrix = blendmatrix;
406 else if (model->num_tags)
408 if (tagindex < 0 || tagindex >= model->num_tags)
410 for (k = 0;k < 12;k++)
412 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
414 lerp = frameblend[blendindex].lerp;
415 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
416 for (k = 0;k < 12;k++)
417 blendtag[k] += input[k] * lerp;
419 Matrix4x4_FromArray12FloatGL(outmatrix, blendtag);
422 if(!mod_alias_supporttagscale.integer)
423 Matrix4x4_Normalize3(outmatrix, outmatrix);
428 int Mod_Alias_GetExtendedTagInfoForIndex(const dp_model_t *model, unsigned int skin, const frameblend_t *frameblend, const skeleton_t *skeleton, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
433 matrix4x4_t bonematrix;
434 matrix4x4_t blendmatrix;
438 if (skeleton && skeleton->relativetransforms)
440 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
442 *parentindex = skeleton->model->data_bones[tagindex].parent;
443 *tagname = skeleton->model->data_bones[tagindex].name;
444 *tag_localmatrix = skeleton->relativetransforms[tagindex];
447 else if (model->num_bones)
449 if (tagindex < 0 || tagindex >= model->num_bones)
451 *parentindex = model->data_bones[tagindex].parent;
452 *tagname = model->data_bones[tagindex].name;
453 Matrix4x4_Clear(&blendmatrix);
454 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
456 lerp = frameblend[blendindex].lerp;
457 Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
458 Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
460 *tag_localmatrix = blendmatrix;
463 else if (model->num_tags)
465 if (tagindex < 0 || tagindex >= model->num_tags)
468 *tagname = model->data_tags[tagindex].name;
469 for (k = 0;k < 12;k++)
471 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
473 lerp = frameblend[blendindex].lerp;
474 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
475 for (k = 0;k < 12;k++)
476 blendtag[k] += input[k] * lerp;
478 Matrix4x4_FromArray12FloatGL(tag_localmatrix, blendtag);
485 int Mod_Alias_GetTagIndexForName(const dp_model_t *model, unsigned int skin, const char *tagname)
488 if(skin >= (unsigned int)model->numskins)
490 if (model->num_bones)
491 for (i = 0;i < model->num_bones;i++)
492 if (!strcasecmp(tagname, model->data_bones[i].name))
495 for (i = 0;i < model->num_tags;i++)
496 if (!strcasecmp(tagname, model->data_tags[i].name))
501 static void Mod_BuildBaseBonePoses(void)
504 matrix4x4_t *basebonepose;
505 float *outinvmatrix = loadmodel->data_baseboneposeinverse;
506 matrix4x4_t bonematrix;
507 matrix4x4_t tempbonematrix;
508 if (!loadmodel->num_bones)
510 basebonepose = (matrix4x4_t *)Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(matrix4x4_t));
511 for (boneindex = 0;boneindex < loadmodel->num_bones;boneindex++)
513 Matrix4x4_FromBonePose6s(&bonematrix, loadmodel->num_posescale, loadmodel->data_poses6s + 6 * boneindex);
514 if (loadmodel->data_bones[boneindex].parent >= 0)
516 tempbonematrix = bonematrix;
517 Matrix4x4_Concat(&bonematrix, basebonepose + loadmodel->data_bones[boneindex].parent, &tempbonematrix);
519 basebonepose[boneindex] = bonematrix;
520 Matrix4x4_Invert_Simple(&tempbonematrix, basebonepose + boneindex);
521 Matrix4x4_ToArray12FloatD3D(&tempbonematrix, outinvmatrix + 12*boneindex);
523 Mem_Free(basebonepose);
526 static void Mod_Alias_CalculateBoundingBox(void)
529 qboolean firstvertex = true;
530 float dist, yawradius, radius;
532 VectorClear(loadmodel->normalmins);
533 VectorClear(loadmodel->normalmaxs);
536 if (loadmodel->AnimateVertices)
539 frameblend_t frameblend[MAX_FRAMEBLENDS];
540 memset(frameblend, 0, sizeof(frameblend));
541 frameblend[0].lerp = 1;
542 vertex3f = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
543 for (frameblend[0].subframe = 0;frameblend[0].subframe < loadmodel->num_poses;frameblend[0].subframe++)
545 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, vertex3f, NULL, NULL, NULL);
546 for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
551 VectorCopy(v, loadmodel->normalmins);
552 VectorCopy(v, loadmodel->normalmaxs);
556 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
557 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
558 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
559 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
560 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
561 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
563 dist = v[0] * v[0] + v[1] * v[1];
564 if (yawradius < dist)
576 for (vnum = 0, v = loadmodel->surfmesh.data_vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
581 VectorCopy(v, loadmodel->normalmins);
582 VectorCopy(v, loadmodel->normalmaxs);
586 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
587 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
588 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
589 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
590 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
591 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
593 dist = v[0] * v[0] + v[1] * v[1];
594 if (yawradius < dist)
601 radius = sqrt(radius);
602 yawradius = sqrt(yawradius);
603 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
604 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
605 loadmodel->yawmins[2] = loadmodel->normalmins[2];
606 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
607 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
608 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
609 loadmodel->radius = radius;
610 loadmodel->radius2 = radius * radius;
613 static void Mod_Alias_MorphMesh_CompileFrames(void)
616 frameblend_t frameblend[MAX_FRAMEBLENDS];
617 unsigned char *datapointer;
618 memset(frameblend, 0, sizeof(frameblend));
619 frameblend[0].lerp = 1;
620 datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
621 loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
622 loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
623 loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
624 loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
625 loadmodel->surfmesh.data_morphtexvecvertex = (texvecvertex_t *)datapointer;datapointer += loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices * sizeof(texvecvertex_t);
626 // this counts down from the last frame to the first so that the final data in surfmesh is for frame zero (which is what the renderer expects to be there)
627 for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
629 frameblend[0].subframe = i;
630 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
631 Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, r_smoothnormals_areaweighting.integer != 0);
632 // encode the svector and tvector in 3 byte format for permanent storage
633 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
635 VectorScaleCast(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
636 VectorScaleCast(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
641 static void Mod_MDLMD2MD3_TraceLine(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask)
644 float segmentmins[3], segmentmaxs[3];
646 static int maxvertices = 0;
647 static float *vertex3f = NULL;
648 memset(trace, 0, sizeof(*trace));
650 trace->realfraction = 1;
651 trace->hitsupercontentsmask = hitsupercontentsmask;
652 if (maxvertices < model->surfmesh.num_vertices)
656 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
657 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
659 segmentmins[0] = min(start[0], end[0]) - 1;
660 segmentmins[1] = min(start[1], end[1]) - 1;
661 segmentmins[2] = min(start[2], end[2]) - 1;
662 segmentmaxs[0] = max(start[0], end[0]) + 1;
663 segmentmaxs[1] = max(start[1], end[1]) + 1;
664 segmentmaxs[2] = max(start[2], end[2]) + 1;
665 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
666 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
667 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);
670 static int maxvertices = 0;
671 static float *vertex3f = NULL;
673 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)
676 vec3_t shiftstart, shiftend;
677 float segmentmins[3], segmentmaxs[3];
679 colboxbrushf_t thisbrush_start, thisbrush_end;
680 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
682 if (VectorCompare(boxmins, boxmaxs))
684 VectorAdd(start, boxmins, shiftstart);
685 VectorAdd(end, boxmins, shiftend);
686 Mod_MDLMD2MD3_TraceLine(model, frameblend, skeleton, trace, shiftstart, shiftend, hitsupercontentsmask);
687 VectorSubtract(trace->endpos, boxmins, trace->endpos);
691 // box trace, performed as brush trace
692 memset(trace, 0, sizeof(*trace));
694 trace->realfraction = 1;
695 trace->hitsupercontentsmask = hitsupercontentsmask;
696 if (maxvertices < model->surfmesh.num_vertices)
700 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
701 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
703 segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
704 segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
705 segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
706 segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
707 segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
708 segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
709 VectorAdd(start, boxmins, boxstartmins);
710 VectorAdd(start, boxmaxs, boxstartmaxs);
711 VectorAdd(end, boxmins, boxendmins);
712 VectorAdd(end, boxmaxs, boxendmaxs);
713 Collision_BrushForBox(&thisbrush_start, boxstartmins, boxstartmaxs, 0, 0, NULL);
714 Collision_BrushForBox(&thisbrush_end, boxendmins, boxendmaxs, 0, 0, NULL);
715 if (maxvertices < model->surfmesh.num_vertices)
719 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
720 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
722 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
723 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
724 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);
727 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
730 for (i = 0;i < inverts;i++)
732 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
734 j = vertremap[i]; // not onseam
737 j = vertremap[i+inverts]; // onseam
743 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
745 int i, f, pose, groupframes;
747 daliasframetype_t *pframetype;
748 daliasframe_t *pinframe;
749 daliasgroup_t *group;
750 daliasinterval_t *intervals;
753 scene = loadmodel->animscenes;
754 for (f = 0;f < loadmodel->numframes;f++)
756 pframetype = (daliasframetype_t *)datapointer;
757 datapointer += sizeof(daliasframetype_t);
758 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
760 // a single frame is still treated as a group
767 group = (daliasgroup_t *)datapointer;
768 datapointer += sizeof(daliasgroup_t);
769 groupframes = LittleLong (group->numframes);
771 // intervals (time per frame)
772 intervals = (daliasinterval_t *)datapointer;
773 datapointer += sizeof(daliasinterval_t) * groupframes;
775 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
776 if (interval < 0.01f)
778 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
783 // get scene name from first frame
784 pinframe = (daliasframe_t *)datapointer;
786 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
787 scene->firstframe = pose;
788 scene->framecount = groupframes;
789 scene->framerate = 1.0f / interval;
794 for (i = 0;i < groupframes;i++)
796 pinframe = (daliasframe_t *)datapointer;
797 datapointer += sizeof(daliasframe_t);
798 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
799 datapointer += sizeof(trivertx_t) * inverts;
805 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
807 if (cls.state == ca_dedicated)
811 skinframe = R_SkinFrame_LoadMissing();
812 memset(texture, 0, sizeof(*texture));
813 texture->currentframe = texture;
814 //texture->animated = false;
815 texture->numskinframes = 1;
816 texture->skinframerate = 1;
817 texture->skinframes[0] = skinframe;
818 texture->currentskinframe = skinframe;
819 //texture->backgroundnumskinframes = 0;
820 //texture->customblendfunc[0] = 0;
821 //texture->customblendfunc[1] = 0;
822 //texture->surfaceflags = 0;
823 //texture->supercontents = 0;
824 //texture->surfaceparms = 0;
825 //texture->textureflags = 0;
827 texture->basematerialflags = MATERIALFLAG_WALL;
828 if (texture->currentskinframe->hasalpha)
829 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
830 texture->currentmaterialflags = texture->basematerialflags;
831 texture->offsetmapping = OFFSETMAPPING_DEFAULT;
832 texture->offsetscale = 1;
833 texture->offsetbias = 0;
834 texture->specularscalemod = 1;
835 texture->specularpowermod = 1;
836 texture->surfaceflags = 0;
837 texture->supercontents = SUPERCONTENTS_SOLID;
838 if (!(texture->basematerialflags & MATERIALFLAG_BLENDED))
839 texture->supercontents |= SUPERCONTENTS_OPAQUE;
842 void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
845 static char stripbuf[MAX_QPATH];
846 skinfileitem_t *skinfileitem;
847 if(developer_extra.integer)
848 Con_DPrintf("Looking up texture for %s (default: %s)\n", meshname, shadername);
851 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
852 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
854 memset(skin, 0, sizeof(*skin));
856 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
858 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
859 if (!strcmp(skinfileitem->name, meshname))
861 Image_StripImageExtension(skinfileitem->replacement, stripbuf, sizeof(stripbuf));
862 if(developer_extra.integer)
863 Con_DPrintf("--> got %s from skin file\n", stripbuf);
864 Mod_LoadTextureFromQ3Shader(skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
870 // don't render unmentioned meshes
871 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
872 if(developer_extra.integer)
873 Con_DPrintf("--> skipping\n");
874 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
880 if(developer_extra.integer)
881 Con_DPrintf("--> using default\n");
882 Image_StripImageExtension(shadername, stripbuf, sizeof(stripbuf));
883 Mod_LoadTextureFromQ3Shader(skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
887 #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);
888 #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);
889 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
891 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
892 float scales, scalet, interval;
896 stvert_t *pinstverts;
897 dtriangle_t *pintriangles;
898 daliasskintype_t *pinskintype;
899 daliasskingroup_t *pinskingroup;
900 daliasskininterval_t *pinskinintervals;
901 daliasframetype_t *pinframetype;
902 daliasgroup_t *pinframegroup;
903 unsigned char *datapointer, *startframes, *startskins;
904 char name[MAX_QPATH];
905 skinframe_t *tempskinframe;
906 animscene_t *tempskinscenes;
907 texture_t *tempaliasskins;
909 int *vertonseam, *vertremap;
910 skinfile_t *skinfiles;
912 datapointer = (unsigned char *)buffer;
913 pinmodel = (mdl_t *)datapointer;
914 datapointer += sizeof(mdl_t);
916 version = LittleLong (pinmodel->version);
917 if (version != ALIAS_VERSION)
918 Host_Error ("%s has wrong version number (%i should be %i)",
919 loadmodel->name, version, ALIAS_VERSION);
921 loadmodel->modeldatatypestring = "MDL";
923 loadmodel->type = mod_alias;
924 loadmodel->DrawSky = NULL;
925 loadmodel->DrawAddWaterPlanes = NULL;
926 loadmodel->Draw = R_Q1BSP_Draw;
927 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
928 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
929 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
930 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
931 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
932 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
933 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
934 loadmodel->DrawLight = R_Q1BSP_DrawLight;
935 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
936 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
937 // FIXME add TraceBrush!
938 loadmodel->PointSuperContents = NULL;
940 loadmodel->num_surfaces = 1;
941 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
942 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
943 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
944 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
945 loadmodel->sortedmodelsurfaces[0] = 0;
947 loadmodel->numskins = LittleLong(pinmodel->numskins);
948 BOUNDI(loadmodel->numskins,0,65536);
949 skinwidth = LittleLong (pinmodel->skinwidth);
950 BOUNDI(skinwidth,0,65536);
951 skinheight = LittleLong (pinmodel->skinheight);
952 BOUNDI(skinheight,0,65536);
953 numverts = LittleLong(pinmodel->numverts);
954 BOUNDI(numverts,0,65536);
955 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
956 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
957 loadmodel->numframes = LittleLong(pinmodel->numframes);
958 BOUNDI(loadmodel->numframes,0,65536);
959 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
960 BOUNDI((int)loadmodel->synctype,0,2);
961 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
962 i = LittleLong (pinmodel->flags);
963 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
965 for (i = 0;i < 3;i++)
967 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
968 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
971 startskins = datapointer;
973 for (i = 0;i < loadmodel->numskins;i++)
975 pinskintype = (daliasskintype_t *)datapointer;
976 datapointer += sizeof(daliasskintype_t);
977 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
981 pinskingroup = (daliasskingroup_t *)datapointer;
982 datapointer += sizeof(daliasskingroup_t);
983 groupskins = LittleLong(pinskingroup->numskins);
984 datapointer += sizeof(daliasskininterval_t) * groupskins;
987 for (j = 0;j < groupskins;j++)
989 datapointer += skinwidth * skinheight;
994 pinstverts = (stvert_t *)datapointer;
995 datapointer += sizeof(stvert_t) * numverts;
997 pintriangles = (dtriangle_t *)datapointer;
998 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
1000 startframes = datapointer;
1001 loadmodel->surfmesh.num_morphframes = 0;
1002 for (i = 0;i < loadmodel->numframes;i++)
1004 pinframetype = (daliasframetype_t *)datapointer;
1005 datapointer += sizeof(daliasframetype_t);
1006 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
1010 pinframegroup = (daliasgroup_t *)datapointer;
1011 datapointer += sizeof(daliasgroup_t);
1012 groupframes = LittleLong(pinframegroup->numframes);
1013 datapointer += sizeof(daliasinterval_t) * groupframes;
1016 for (j = 0;j < groupframes;j++)
1018 datapointer += sizeof(daliasframe_t);
1019 datapointer += sizeof(trivertx_t) * numverts;
1020 loadmodel->surfmesh.num_morphframes++;
1023 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1025 // store texture coordinates into temporary array, they will be stored
1026 // after usage is determined (triangle data)
1027 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
1028 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
1029 vertonseam = vertremap + numverts * 2;
1031 scales = 1.0 / skinwidth;
1032 scalet = 1.0 / skinheight;
1033 for (i = 0;i < numverts;i++)
1035 vertonseam[i] = LittleLong(pinstverts[i].onseam);
1036 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
1037 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
1038 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
1039 vertst[(i+numverts)*2+1] = vertst[i*2+1];
1042 // load triangle data
1043 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1045 // read the triangle elements
1046 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1047 for (j = 0;j < 3;j++)
1048 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1049 // validate (note numverts is used because this is the original data)
1050 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1051 // now butcher the elements according to vertonseam and tri->facesfront
1052 // and then compact the vertex set to remove duplicates
1053 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1054 if (!LittleLong(pintriangles[i].facesfront)) // backface
1055 for (j = 0;j < 3;j++)
1056 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1057 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1059 // (this uses vertremap to count usage to save some memory)
1060 for (i = 0;i < numverts*2;i++)
1062 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1063 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1064 // build remapping table and compact array
1065 loadmodel->surfmesh.num_vertices = 0;
1066 for (i = 0;i < numverts*2;i++)
1070 vertremap[i] = loadmodel->surfmesh.num_vertices;
1071 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1072 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1073 loadmodel->surfmesh.num_vertices++;
1076 vertremap[i] = -1; // not used at all
1078 // remap the elements to the new vertex set
1079 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1080 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1081 // store the texture coordinates
1082 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1083 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1085 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1086 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1089 // generate ushort elements array if possible
1090 if (loadmodel->surfmesh.num_vertices <= 65536)
1091 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1092 if (loadmodel->surfmesh.data_element3s)
1093 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1094 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1097 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1098 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1099 if (r_enableshadowvolumes.integer)
1101 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1103 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1104 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices; // needed during loading, may be cleared by code later in this function
1105 if (loadmodel->surfmesh.data_neighbor3i)
1106 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1107 Mod_Alias_CalculateBoundingBox();
1108 Mod_Alias_MorphMesh_CompileFrames();
1109 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_MDL_AnimateVertices : NULL;
1112 Mem_Free(vertremap);
1115 skinfiles = Mod_LoadSkinFiles();
1118 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1119 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1120 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1121 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1122 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1123 Mod_FreeSkinFiles(skinfiles);
1124 for (i = 0;i < loadmodel->numskins;i++)
1126 loadmodel->skinscenes[i].firstframe = i;
1127 loadmodel->skinscenes[i].framecount = 1;
1128 loadmodel->skinscenes[i].loop = true;
1129 loadmodel->skinscenes[i].framerate = 10;
1134 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1135 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1136 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1137 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1139 datapointer = startskins;
1140 for (i = 0;i < loadmodel->numskins;i++)
1142 pinskintype = (daliasskintype_t *)datapointer;
1143 datapointer += sizeof(daliasskintype_t);
1145 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1152 pinskingroup = (daliasskingroup_t *)datapointer;
1153 datapointer += sizeof(daliasskingroup_t);
1155 groupskins = LittleLong (pinskingroup->numskins);
1157 pinskinintervals = (daliasskininterval_t *)datapointer;
1158 datapointer += sizeof(daliasskininterval_t) * groupskins;
1160 interval = LittleFloat(pinskinintervals[0].interval);
1161 if (interval < 0.01f)
1163 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1168 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1169 loadmodel->skinscenes[i].firstframe = totalskins;
1170 loadmodel->skinscenes[i].framecount = groupskins;
1171 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1172 loadmodel->skinscenes[i].loop = true;
1174 for (j = 0;j < groupskins;j++)
1177 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1179 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1180 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))
1181 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));
1182 datapointer += skinwidth * skinheight;
1186 // check for skins that don't exist in the model, but do exist as external images
1187 // (this was added because yummyluv kept pestering me about support for it)
1188 // TODO: support shaders here?
1189 while ((tempskinframe = R_SkinFrame_LoadExternal(va("%s_%i", loadmodel->name, loadmodel->numskins), (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS, false)))
1191 // expand the arrays to make room
1192 tempskinscenes = loadmodel->skinscenes;
1193 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1194 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1195 Mem_Free(tempskinscenes);
1197 tempaliasskins = loadmodel->data_textures;
1198 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1199 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1200 Mem_Free(tempaliasskins);
1202 // store the info about the new skin
1203 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1204 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1205 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1206 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1207 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1208 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1210 //increase skin counts
1211 loadmodel->numskins++;
1214 // fix up the pointers since they are pointing at the old textures array
1215 // FIXME: this is a hack!
1216 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1217 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1221 surface = loadmodel->data_surfaces;
1222 surface->texture = loadmodel->data_textures;
1223 surface->num_firsttriangle = 0;
1224 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1225 surface->num_firstvertex = 0;
1226 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1228 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1229 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_MDL_AnimateVertices : NULL;
1231 if (!loadmodel->surfmesh.isanimated)
1233 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1234 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1235 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1236 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1237 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1238 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1241 // because shaders can do somewhat unexpected things, check for unusual features now
1242 for (i = 0;i < loadmodel->num_textures;i++)
1244 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
1245 mod->DrawSky = R_Q1BSP_DrawSky;
1246 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
1247 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
1251 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1253 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1254 float iskinwidth, iskinheight;
1255 unsigned char *data;
1256 msurface_t *surface;
1258 unsigned char *base, *datapointer;
1259 md2frame_t *pinframe;
1261 md2triangle_t *intri;
1262 unsigned short *inst;
1263 struct md2verthash_s
1265 struct md2verthash_s *next;
1269 *hash, **md2verthash, *md2verthashdata;
1270 skinfile_t *skinfiles;
1272 pinmodel = (md2_t *)buffer;
1273 base = (unsigned char *)buffer;
1275 version = LittleLong (pinmodel->version);
1276 if (version != MD2ALIAS_VERSION)
1277 Host_Error ("%s has wrong version number (%i should be %i)",
1278 loadmodel->name, version, MD2ALIAS_VERSION);
1280 loadmodel->modeldatatypestring = "MD2";
1282 loadmodel->type = mod_alias;
1283 loadmodel->DrawSky = NULL;
1284 loadmodel->DrawAddWaterPlanes = NULL;
1285 loadmodel->Draw = R_Q1BSP_Draw;
1286 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1287 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1288 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1289 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1290 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1291 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1292 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1293 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1294 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1295 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1296 loadmodel->PointSuperContents = NULL;
1298 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1299 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1300 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1301 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1302 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1303 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1304 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1305 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1307 end = LittleLong(pinmodel->ofs_end);
1308 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1309 Host_Error ("%s is not a valid model", loadmodel->name);
1310 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1311 Host_Error ("%s is not a valid model", loadmodel->name);
1312 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1313 Host_Error ("%s is not a valid model", loadmodel->name);
1314 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1315 Host_Error ("%s is not a valid model", loadmodel->name);
1316 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1317 Host_Error ("%s is not a valid model", loadmodel->name);
1319 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1320 numxyz = LittleLong(pinmodel->num_xyz);
1321 numst = LittleLong(pinmodel->num_st);
1322 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1323 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1324 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1325 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1326 skinwidth = LittleLong(pinmodel->skinwidth);
1327 skinheight = LittleLong(pinmodel->skinheight);
1328 iskinwidth = 1.0f / skinwidth;
1329 iskinheight = 1.0f / skinheight;
1331 loadmodel->num_surfaces = 1;
1332 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1333 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));
1334 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1335 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1336 loadmodel->sortedmodelsurfaces[0] = 0;
1337 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1338 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1339 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1340 if (r_enableshadowvolumes.integer)
1342 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1345 loadmodel->synctype = ST_RAND;
1348 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1349 skinfiles = Mod_LoadSkinFiles();
1352 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1353 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1354 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1355 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1356 Mod_FreeSkinFiles(skinfiles);
1358 else if (loadmodel->numskins)
1360 // skins found (most likely not a player model)
1361 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1362 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1363 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1364 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1365 Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
1369 // no skins (most likely a player model)
1370 loadmodel->numskins = 1;
1371 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1372 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1373 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1374 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1377 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1378 for (i = 0;i < loadmodel->numskins;i++)
1380 loadmodel->skinscenes[i].firstframe = i;
1381 loadmodel->skinscenes[i].framecount = 1;
1382 loadmodel->skinscenes[i].loop = true;
1383 loadmodel->skinscenes[i].framerate = 10;
1386 // load the triangles and stvert data
1387 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1388 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1389 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1390 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1391 // swap the triangle list
1392 loadmodel->surfmesh.num_vertices = 0;
1393 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1395 for (j = 0;j < 3;j++)
1397 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1398 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1401 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1406 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1409 hashindex = (xyz * 256 + st) & 65535;
1410 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1411 if (hash->xyz == xyz && hash->st == st)
1415 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1418 hash->next = md2verthash[hashindex];
1419 md2verthash[hashindex] = hash;
1421 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1425 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1426 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));
1427 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1428 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1429 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1432 hash = md2verthashdata + i;
1433 vertremap[i] = hash->xyz;
1434 sts = LittleShort(inst[hash->st*2+0]);
1435 stt = LittleShort(inst[hash->st*2+1]);
1436 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1438 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1442 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1443 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1446 Mem_Free(md2verthash);
1447 Mem_Free(md2verthashdata);
1449 // generate ushort elements array if possible
1450 if (loadmodel->surfmesh.num_vertices <= 65536)
1451 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1452 if (loadmodel->surfmesh.data_element3s)
1453 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1454 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1457 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1458 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1463 pinframe = (md2frame_t *)datapointer;
1464 datapointer += sizeof(md2frame_t);
1465 // store the frame scale/translate into the appropriate array
1466 for (j = 0;j < 3;j++)
1468 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1469 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1471 // convert the vertices
1472 v = (trivertx_t *)datapointer;
1473 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1474 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1475 out[k] = v[vertremap[k]];
1476 datapointer += numxyz * sizeof(trivertx_t);
1478 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1479 loadmodel->animscenes[i].firstframe = i;
1480 loadmodel->animscenes[i].framecount = 1;
1481 loadmodel->animscenes[i].framerate = 10;
1482 loadmodel->animscenes[i].loop = true;
1485 Mem_Free(vertremap);
1487 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1488 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices; // needed during loading, may be cleared by code later in this function
1489 if (loadmodel->surfmesh.data_neighbor3i)
1490 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1491 Mod_Alias_CalculateBoundingBox();
1492 Mod_Alias_MorphMesh_CompileFrames();
1493 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_MDL_AnimateVertices : NULL;
1495 surface = loadmodel->data_surfaces;
1496 surface->texture = loadmodel->data_textures;
1497 surface->num_firsttriangle = 0;
1498 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1499 surface->num_firstvertex = 0;
1500 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1502 if (!loadmodel->surfmesh.isanimated)
1504 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1505 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1506 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1507 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1508 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1509 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1512 // because shaders can do somewhat unexpected things, check for unusual features now
1513 for (i = 0;i < loadmodel->num_textures;i++)
1515 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
1516 mod->DrawSky = R_Q1BSP_DrawSky;
1517 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
1518 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
1522 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1524 int i, j, k, version, meshvertices, meshtriangles;
1525 unsigned char *data;
1526 msurface_t *surface;
1527 md3modelheader_t *pinmodel;
1528 md3frameinfo_t *pinframe;
1531 skinfile_t *skinfiles;
1533 pinmodel = (md3modelheader_t *)buffer;
1535 if (memcmp(pinmodel->identifier, "IDP3", 4))
1536 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1537 version = LittleLong (pinmodel->version);
1538 if (version != MD3VERSION)
1539 Host_Error ("%s has wrong version number (%i should be %i)",
1540 loadmodel->name, version, MD3VERSION);
1542 skinfiles = Mod_LoadSkinFiles();
1543 if (loadmodel->numskins < 1)
1544 loadmodel->numskins = 1;
1546 loadmodel->modeldatatypestring = "MD3";
1548 loadmodel->type = mod_alias;
1549 loadmodel->DrawSky = NULL;
1550 loadmodel->DrawAddWaterPlanes = NULL;
1551 loadmodel->Draw = R_Q1BSP_Draw;
1552 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1553 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1554 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1555 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1556 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1557 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1558 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1559 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1560 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1561 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1562 loadmodel->PointSuperContents = NULL;
1563 loadmodel->synctype = ST_RAND;
1564 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1565 i = LittleLong (pinmodel->flags);
1566 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1568 // set up some global info about the model
1569 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1570 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1572 // make skinscenes for the skins (no groups)
1573 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1574 for (i = 0;i < loadmodel->numskins;i++)
1576 loadmodel->skinscenes[i].firstframe = i;
1577 loadmodel->skinscenes[i].framecount = 1;
1578 loadmodel->skinscenes[i].loop = true;
1579 loadmodel->skinscenes[i].framerate = 10;
1583 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1584 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1586 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1587 loadmodel->animscenes[i].firstframe = i;
1588 loadmodel->animscenes[i].framecount = 1;
1589 loadmodel->animscenes[i].framerate = 10;
1590 loadmodel->animscenes[i].loop = true;
1594 loadmodel->num_tagframes = loadmodel->numframes;
1595 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1596 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1597 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1599 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1600 for (j = 0;j < 9;j++)
1601 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1602 for (j = 0;j < 3;j++)
1603 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1604 //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);
1610 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)))
1612 if (memcmp(pinmesh->identifier, "IDP3", 4))
1613 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1614 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1615 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1616 meshvertices += LittleLong(pinmesh->num_vertices);
1617 meshtriangles += LittleLong(pinmesh->num_triangles);
1620 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1621 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1622 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1623 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));
1624 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1625 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1626 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1627 loadmodel->surfmesh.num_vertices = meshvertices;
1628 loadmodel->surfmesh.num_triangles = meshtriangles;
1629 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1630 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1631 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1632 if (r_enableshadowvolumes.integer)
1634 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1636 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1637 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1638 if (meshvertices <= 65536)
1640 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1645 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)))
1647 if (memcmp(pinmesh->identifier, "IDP3", 4))
1648 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1649 loadmodel->sortedmodelsurfaces[i] = i;
1650 surface = loadmodel->data_surfaces + i;
1651 surface->texture = loadmodel->data_textures + i;
1652 surface->num_firsttriangle = meshtriangles;
1653 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1654 surface->num_firstvertex = meshvertices;
1655 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1656 meshvertices += surface->num_vertices;
1657 meshtriangles += surface->num_triangles;
1659 for (j = 0;j < surface->num_triangles * 3;j++)
1660 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1661 for (j = 0;j < surface->num_vertices;j++)
1663 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1664 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1666 for (j = 0;j < loadmodel->numframes;j++)
1668 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1669 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1670 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1672 out->origin[0] = LittleShort(in->origin[0]);
1673 out->origin[1] = LittleShort(in->origin[1]);
1674 out->origin[2] = LittleShort(in->origin[2]);
1675 out->pitch = in->pitch;
1680 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1682 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1684 if (loadmodel->surfmesh.data_element3s)
1685 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1686 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1687 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1688 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices; // needed during loading, may be cleared by code later in this function
1689 if (loadmodel->surfmesh.data_neighbor3i)
1690 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1691 Mod_Alias_MorphMesh_CompileFrames();
1692 Mod_Alias_CalculateBoundingBox();
1693 Mod_FreeSkinFiles(skinfiles);
1694 Mod_MakeSortedSurfaces(loadmodel);
1695 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_MD3_AnimateVertices : NULL;
1697 if (!loadmodel->surfmesh.isanimated)
1699 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1700 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1701 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1702 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1703 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1704 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1707 // because shaders can do somewhat unexpected things, check for unusual features now
1708 for (i = 0;i < loadmodel->num_textures;i++)
1710 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
1711 mod->DrawSky = R_Q1BSP_DrawSky;
1712 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
1713 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
1717 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1719 zymtype1header_t *pinmodel, *pheader;
1720 unsigned char *pbase;
1721 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1722 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose, f, biggestorigin, tempvec[3], modelscale;
1723 zymvertex_t *verts, *vertdata;
1727 skinfile_t *skinfiles;
1728 unsigned char *data;
1729 msurface_t *surface;
1731 pinmodel = (zymtype1header_t *)buffer;
1732 pbase = (unsigned char *)buffer;
1733 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1734 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1735 if (BigLong(pinmodel->type) != 1)
1736 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1738 loadmodel->modeldatatypestring = "ZYM";
1740 loadmodel->type = mod_alias;
1741 loadmodel->synctype = ST_RAND;
1745 pheader->type = BigLong(pinmodel->type);
1746 pheader->filesize = BigLong(pinmodel->filesize);
1747 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1748 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1749 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1750 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1751 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1752 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1753 pheader->radius = BigFloat(pinmodel->radius);
1754 pheader->numverts = BigLong(pinmodel->numverts);
1755 pheader->numtris = BigLong(pinmodel->numtris);
1756 pheader->numshaders = BigLong(pinmodel->numshaders);
1757 pheader->numbones = BigLong(pinmodel->numbones);
1758 pheader->numscenes = BigLong(pinmodel->numscenes);
1759 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1760 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1761 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1762 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1763 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1764 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1765 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1766 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1767 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1768 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1769 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1770 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1771 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1772 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1773 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1774 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1775 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1776 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1778 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1780 Con_Printf("%s has no geometry\n", loadmodel->name);
1783 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1785 Con_Printf("%s has no animations\n", loadmodel->name);
1789 loadmodel->DrawSky = NULL;
1790 loadmodel->DrawAddWaterPlanes = NULL;
1791 loadmodel->Draw = R_Q1BSP_Draw;
1792 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1793 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1794 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1795 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1796 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1797 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1798 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1799 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1800 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1801 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1802 loadmodel->PointSuperContents = NULL;
1804 loadmodel->numframes = pheader->numscenes;
1805 loadmodel->num_surfaces = pheader->numshaders;
1807 skinfiles = Mod_LoadSkinFiles();
1808 if (loadmodel->numskins < 1)
1809 loadmodel->numskins = 1;
1811 // make skinscenes for the skins (no groups)
1812 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1813 for (i = 0;i < loadmodel->numskins;i++)
1815 loadmodel->skinscenes[i].firstframe = i;
1816 loadmodel->skinscenes[i].framecount = 1;
1817 loadmodel->skinscenes[i].loop = true;
1818 loadmodel->skinscenes[i].framerate = 10;
1822 modelradius = pheader->radius;
1823 for (i = 0;i < 3;i++)
1825 loadmodel->normalmins[i] = pheader->mins[i];
1826 loadmodel->normalmaxs[i] = pheader->maxs[i];
1827 loadmodel->rotatedmins[i] = -modelradius;
1828 loadmodel->rotatedmaxs[i] = modelradius;
1830 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1831 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1832 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1833 if (loadmodel->yawmaxs[0] > modelradius)
1834 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1835 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1836 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1837 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1838 loadmodel->radius = modelradius;
1839 loadmodel->radius2 = modelradius * modelradius;
1841 // go through the lumps, swapping things
1843 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1844 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1845 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1846 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1847 for (i = 0;i < pheader->numscenes;i++)
1849 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1850 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1851 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1852 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1853 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1854 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1855 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1856 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1857 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1858 if (loadmodel->animscenes[i].framerate < 0)
1859 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1863 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1864 loadmodel->num_bones = pheader->numbones;
1865 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1866 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1867 for (i = 0;i < pheader->numbones;i++)
1869 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1870 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1871 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1872 if (loadmodel->data_bones[i].parent >= i)
1873 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1876 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1877 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1878 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1879 for (i = 0;i < pheader->numverts;i++)
1881 vertbonecounts[i] = BigLong(bonecount[i]);
1882 if (vertbonecounts[i] != 1)
1883 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1886 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1888 meshvertices = pheader->numverts;
1889 meshtriangles = pheader->numtris;
1891 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1892 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
1893 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1894 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1895 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1896 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (r_enableshadowvolumes.integer ? meshtriangles * sizeof(int[3]) : 0) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshvertices * sizeof(float[14]) + meshvertices * sizeof(unsigned short) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]) + loadmodel->num_bones * sizeof(float[12]));
1897 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1898 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1899 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1900 loadmodel->surfmesh.num_vertices = meshvertices;
1901 loadmodel->surfmesh.num_triangles = meshtriangles;
1902 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1903 if (r_enableshadowvolumes.integer)
1905 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1907 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1908 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1909 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1910 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1911 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1912 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1913 loadmodel->surfmesh.num_blends = 0;
1914 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
1915 if (loadmodel->surfmesh.num_vertices <= 65536)
1917 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1919 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
1920 loadmodel->surfmesh.data_blendweights = NULL;
1922 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1923 poses = (float *) (pheader->lump_poses.start + pbase);
1924 // figure out scale of model from root bone, for compatibility with old zmodel versions
1925 tempvec[0] = BigFloat(poses[0]);
1926 tempvec[1] = BigFloat(poses[1]);
1927 tempvec[2] = BigFloat(poses[2]);
1928 modelscale = VectorLength(tempvec);
1930 for (i = 0;i < loadmodel->num_bones * numposes * 12;i++)
1932 f = fabs(BigFloat(poses[i]));
1933 biggestorigin = max(biggestorigin, f);
1935 loadmodel->num_posescale = biggestorigin / 32767.0f;
1936 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
1937 for (i = 0;i < numposes;i++)
1939 const float *frameposes = (float *) (pheader->lump_poses.start + pbase) + 12*i*loadmodel->num_bones;
1940 for (j = 0;j < loadmodel->num_bones;j++)
1943 matrix4x4_t posematrix;
1944 for (k = 0;k < 12;k++)
1945 pose[k] = BigFloat(frameposes[j*12+k]);
1946 //if (j < loadmodel->num_bones)
1947 // Con_Printf("%s: bone %i = %f %f %f %f : %f %f %f %f : %f %f %f %f : scale = %f\n", loadmodel->name, j, pose[0], pose[1], pose[2], pose[3], pose[4], pose[5], pose[6], pose[7], pose[8], pose[9], pose[10], pose[11], VectorLength(pose));
1948 // scale child bones to match the root scale
1949 if (loadmodel->data_bones[j].parent >= 0)
1951 pose[3] *= modelscale;
1952 pose[7] *= modelscale;
1953 pose[11] *= modelscale;
1955 // normalize rotation matrix
1956 VectorNormalize(pose + 0);
1957 VectorNormalize(pose + 4);
1958 VectorNormalize(pose + 8);
1959 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
1960 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
1964 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1965 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1966 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1967 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1968 // (converting from weight-blending skeletal animation to
1969 // deformation-based skeletal animation)
1970 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1971 for (i = 0;i < loadmodel->num_bones;i++)
1974 for (k = 0;k < 12;k++)
1975 m[k] = BigFloat(poses[i*12+k]);
1976 if (loadmodel->data_bones[i].parent >= 0)
1977 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1979 for (k = 0;k < 12;k++)
1980 bonepose[12*i+k] = m[k];
1982 for (j = 0;j < pheader->numverts;j++)
1984 // this format really should have had a per vertexweight weight value...
1985 // but since it does not, the weighting is completely ignored and
1986 // only one weight is allowed per vertex
1987 int boneindex = BigLong(vertdata[j].bonenum);
1988 const float *m = bonepose + 12 * boneindex;
1989 float relativeorigin[3];
1990 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1991 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1992 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1993 // transform the vertex bone weight into the base mesh
1994 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1995 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1996 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1997 // store the weight as the primary weight on this vertex
1998 loadmodel->surfmesh.blends[j] = boneindex;
2001 // normals and tangents are calculated after elements are loaded
2003 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
2004 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
2005 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
2006 for (i = 0;i < pheader->numverts;i++)
2008 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
2009 // flip T coordinate for OpenGL
2010 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
2013 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
2014 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
2015 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
2017 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
2018 //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)
2019 // byteswap, validate, and swap winding order of tris
2020 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
2021 if (pheader->lump_render.length != count)
2022 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
2023 renderlist = (int *) (pheader->lump_render.start + pbase);
2024 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
2026 for (i = 0;i < loadmodel->num_surfaces;i++)
2028 int firstvertex, lastvertex;
2029 if (renderlist >= renderlistend)
2030 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2031 count = BigLong(*renderlist);renderlist++;
2032 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
2033 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2035 loadmodel->sortedmodelsurfaces[i] = i;
2036 surface = loadmodel->data_surfaces + i;
2037 surface->texture = loadmodel->data_textures + i;
2038 surface->num_firsttriangle = meshtriangles;
2039 surface->num_triangles = count;
2040 meshtriangles += surface->num_triangles;
2042 // load the elements
2043 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2044 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
2046 outelements[j*3+2] = BigLong(renderlist[0]);
2047 outelements[j*3+1] = BigLong(renderlist[1]);
2048 outelements[j*3+0] = BigLong(renderlist[2]);
2050 // validate the elements and find the used vertex range
2051 firstvertex = meshvertices;
2053 for (j = 0;j < surface->num_triangles * 3;j++)
2055 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
2056 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
2057 firstvertex = min(firstvertex, outelements[j]);
2058 lastvertex = max(lastvertex, outelements[j]);
2060 surface->num_firstvertex = firstvertex;
2061 surface->num_vertices = lastvertex + 1 - firstvertex;
2063 // since zym models do not have named sections, reuse their shader
2064 // name as the section name
2065 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
2066 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
2068 Mod_FreeSkinFiles(skinfiles);
2069 Mem_Free(vertbonecounts);
2071 Mod_MakeSortedSurfaces(loadmodel);
2073 // compute all the mesh information that was not loaded from the file
2074 if (loadmodel->surfmesh.data_element3s)
2075 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2076 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2077 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2078 Mod_BuildBaseBonePoses();
2079 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);
2080 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);
2081 if (loadmodel->surfmesh.data_neighbor3i)
2082 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2084 if (!loadmodel->surfmesh.isanimated)
2086 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2087 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2088 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2089 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2090 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2091 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2094 // because shaders can do somewhat unexpected things, check for unusual features now
2095 for (i = 0;i < loadmodel->num_textures;i++)
2097 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
2098 mod->DrawSky = R_Q1BSP_DrawSky;
2099 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
2100 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
2104 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2106 dpmheader_t *pheader;
2110 unsigned char *pbase;
2111 int i, j, k, meshvertices, meshtriangles;
2112 skinfile_t *skinfiles;
2113 unsigned char *data;
2115 float biggestorigin, tempvec[3], modelscale;
2119 pheader = (dpmheader_t *)buffer;
2120 pbase = (unsigned char *)buffer;
2121 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2122 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2123 if (BigLong(pheader->type) != 2)
2124 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2126 loadmodel->modeldatatypestring = "DPM";
2128 loadmodel->type = mod_alias;
2129 loadmodel->synctype = ST_RAND;
2132 pheader->type = BigLong(pheader->type);
2133 pheader->filesize = BigLong(pheader->filesize);
2134 pheader->mins[0] = BigFloat(pheader->mins[0]);
2135 pheader->mins[1] = BigFloat(pheader->mins[1]);
2136 pheader->mins[2] = BigFloat(pheader->mins[2]);
2137 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2138 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2139 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2140 pheader->yawradius = BigFloat(pheader->yawradius);
2141 pheader->allradius = BigFloat(pheader->allradius);
2142 pheader->num_bones = BigLong(pheader->num_bones);
2143 pheader->num_meshs = BigLong(pheader->num_meshs);
2144 pheader->num_frames = BigLong(pheader->num_frames);
2145 pheader->ofs_bones = BigLong(pheader->ofs_bones);
2146 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2147 pheader->ofs_frames = BigLong(pheader->ofs_frames);
2149 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2151 Con_Printf("%s has no geometry\n", loadmodel->name);
2154 if (pheader->num_frames < 1)
2156 Con_Printf("%s has no frames\n", loadmodel->name);
2160 loadmodel->DrawSky = NULL;
2161 loadmodel->DrawAddWaterPlanes = NULL;
2162 loadmodel->Draw = R_Q1BSP_Draw;
2163 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2164 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2165 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2166 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2167 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2168 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2169 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2170 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2171 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2172 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2173 loadmodel->PointSuperContents = NULL;
2176 for (i = 0;i < 3;i++)
2178 loadmodel->normalmins[i] = pheader->mins[i];
2179 loadmodel->normalmaxs[i] = pheader->maxs[i];
2180 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2181 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2182 loadmodel->rotatedmins[i] = -pheader->allradius;
2183 loadmodel->rotatedmaxs[i] = pheader->allradius;
2185 loadmodel->radius = pheader->allradius;
2186 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2188 // load external .skin files if present
2189 skinfiles = Mod_LoadSkinFiles();
2190 if (loadmodel->numskins < 1)
2191 loadmodel->numskins = 1;
2196 // gather combined statistics from the meshes
2197 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2198 for (i = 0;i < (int)pheader->num_meshs;i++)
2200 int numverts = BigLong(dpmmesh->num_verts);
2201 meshvertices += numverts;
2202 meshtriangles += BigLong(dpmmesh->num_tris);
2206 loadmodel->numframes = pheader->num_frames;
2207 loadmodel->num_bones = pheader->num_bones;
2208 loadmodel->num_poses = loadmodel->numframes;
2209 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2210 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2211 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2212 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
2213 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
2214 // do most allocations as one merged chunk
2215 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + (r_enableshadowvolumes.integer ? meshtriangles * sizeof(int[3]) : 0) + meshvertices * (sizeof(float[14]) + sizeof(unsigned short)) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
2216 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2217 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2218 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2219 loadmodel->surfmesh.num_vertices = meshvertices;
2220 loadmodel->surfmesh.num_triangles = meshtriangles;
2221 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2222 if (r_enableshadowvolumes.integer)
2224 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2226 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2227 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2228 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2229 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2230 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2231 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2232 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2233 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2234 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2235 loadmodel->surfmesh.num_blends = 0;
2236 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2237 if (meshvertices <= 65536)
2239 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2241 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2242 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
2244 for (i = 0;i < loadmodel->numskins;i++)
2246 loadmodel->skinscenes[i].firstframe = i;
2247 loadmodel->skinscenes[i].framecount = 1;
2248 loadmodel->skinscenes[i].loop = true;
2249 loadmodel->skinscenes[i].framerate = 10;
2252 // load the bone info
2253 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2254 for (i = 0;i < loadmodel->num_bones;i++)
2256 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2257 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2258 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2259 if (loadmodel->data_bones[i].parent >= i)
2260 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2264 frames = (dpmframe_t *) (pbase + pheader->ofs_frames);
2265 // figure out scale of model from root bone, for compatibility with old dpmodel versions
2266 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2267 tempvec[0] = BigFloat(poses[0]);
2268 tempvec[1] = BigFloat(poses[1]);
2269 tempvec[2] = BigFloat(poses[2]);
2270 modelscale = VectorLength(tempvec);
2272 for (i = 0;i < loadmodel->numframes;i++)
2274 memcpy(loadmodel->animscenes[i].name, frames[i].name, sizeof(frames[i].name));
2275 loadmodel->animscenes[i].firstframe = i;
2276 loadmodel->animscenes[i].framecount = 1;
2277 loadmodel->animscenes[i].loop = true;
2278 loadmodel->animscenes[i].framerate = 10;
2279 // load the bone poses for this frame
2280 poses = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2281 for (j = 0;j < loadmodel->num_bones*12;j++)
2283 f = fabs(BigFloat(poses[j]));
2284 biggestorigin = max(biggestorigin, f);
2286 // stuff not processed here: mins, maxs, yawradius, allradius
2288 loadmodel->num_posescale = biggestorigin / 32767.0f;
2289 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2290 for (i = 0;i < loadmodel->numframes;i++)
2292 const float *frameposes = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2293 for (j = 0;j < loadmodel->num_bones;j++)
2296 matrix4x4_t posematrix;
2297 for (k = 0;k < 12;k++)
2298 pose[k] = BigFloat(frameposes[j*12+k]);
2299 // scale child bones to match the root scale
2300 if (loadmodel->data_bones[j].parent >= 0)
2302 pose[3] *= modelscale;
2303 pose[7] *= modelscale;
2304 pose[11] *= modelscale;
2306 // normalize rotation matrix
2307 VectorNormalize(pose + 0);
2308 VectorNormalize(pose + 4);
2309 VectorNormalize(pose + 8);
2310 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2311 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
2315 // load the meshes now
2316 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2319 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2320 // (converting from weight-blending skeletal animation to
2321 // deformation-based skeletal animation)
2322 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2323 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2324 for (i = 0;i < loadmodel->num_bones;i++)
2327 for (k = 0;k < 12;k++)
2328 m[k] = BigFloat(poses[i*12+k]);
2329 if (loadmodel->data_bones[i].parent >= 0)
2330 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2332 for (k = 0;k < 12;k++)
2333 bonepose[12*i+k] = m[k];
2335 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2337 const int *inelements;
2339 const float *intexcoord;
2340 msurface_t *surface;
2342 loadmodel->sortedmodelsurfaces[i] = i;
2343 surface = loadmodel->data_surfaces + i;
2344 surface->texture = loadmodel->data_textures + i;
2345 surface->num_firsttriangle = meshtriangles;
2346 surface->num_triangles = BigLong(dpmmesh->num_tris);
2347 surface->num_firstvertex = meshvertices;
2348 surface->num_vertices = BigLong(dpmmesh->num_verts);
2349 meshvertices += surface->num_vertices;
2350 meshtriangles += surface->num_triangles;
2352 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2353 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2354 for (j = 0;j < surface->num_triangles;j++)
2356 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2357 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2358 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2359 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2364 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2365 for (j = 0;j < surface->num_vertices*2;j++)
2366 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2368 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2369 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2371 int weightindex[4] = { 0, 0, 0, 0 };
2372 float weightinfluence[4] = { 0, 0, 0, 0 };
2374 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2375 data += sizeof(dpmvertex_t);
2376 for (k = 0;k < numweights;k++)
2378 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2379 int boneindex = BigLong(vert->bonenum);
2380 const float *m = bonepose + 12 * boneindex;
2381 float influence = BigFloat(vert->influence);
2382 float relativeorigin[3], relativenormal[3];
2383 relativeorigin[0] = BigFloat(vert->origin[0]);
2384 relativeorigin[1] = BigFloat(vert->origin[1]);
2385 relativeorigin[2] = BigFloat(vert->origin[2]);
2386 relativenormal[0] = BigFloat(vert->normal[0]);
2387 relativenormal[1] = BigFloat(vert->normal[1]);
2388 relativenormal[2] = BigFloat(vert->normal[2]);
2389 // blend the vertex bone weights into the base mesh
2390 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2391 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2392 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2393 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2394 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2395 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2398 // store the first (and often only) weight
2399 weightinfluence[0] = influence;
2400 weightindex[0] = boneindex;
2404 // sort the new weight into this vertex's weight table
2405 // (which only accepts up to 4 bones per vertex)
2406 for (l = 0;l < 4;l++)
2408 if (weightinfluence[l] < influence)
2410 // move weaker influence weights out of the way first
2412 for (l2 = 3;l2 > l;l2--)
2414 weightinfluence[l2] = weightinfluence[l2-1];
2415 weightindex[l2] = weightindex[l2-1];
2417 // store the new weight
2418 weightinfluence[l] = influence;
2419 weightindex[l] = boneindex;
2424 data += sizeof(dpmbonevert_t);
2426 loadmodel->surfmesh.blends[j] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
2429 // since dpm models do not have named sections, reuse their shader name as the section name
2430 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2432 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2434 if (loadmodel->surfmesh.num_blends < meshvertices)
2435 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2437 Mod_FreeSkinFiles(skinfiles);
2438 Mod_MakeSortedSurfaces(loadmodel);
2440 // compute all the mesh information that was not loaded from the file
2441 if (loadmodel->surfmesh.data_element3s)
2442 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2443 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2444 Mod_BuildBaseBonePoses();
2445 Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, r_smoothnormals_areaweighting.integer != 0);
2446 if (loadmodel->surfmesh.data_neighbor3i)
2447 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2449 if (!loadmodel->surfmesh.isanimated)
2451 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2452 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2453 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2454 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2455 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2456 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2459 // because shaders can do somewhat unexpected things, check for unusual features now
2460 for (i = 0;i < loadmodel->num_textures;i++)
2462 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
2463 mod->DrawSky = R_Q1BSP_DrawSky;
2464 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
2465 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
2469 // no idea why PSK/PSA files contain weird quaternions but they do...
2470 #define PSKQUATNEGATIONS
2471 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2473 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2474 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2475 fs_offset_t filesize;
2480 pskboneinfo_t *bones;
2481 pskrawweights_t *rawweights;
2482 //pskboneinfo_t *animbones;
2483 pskaniminfo_t *anims;
2484 pskanimkeys_t *animkeys;
2485 void *animfilebuffer, *animbuffer, *animbufferend;
2486 unsigned char *data;
2488 skinfile_t *skinfiles;
2489 char animname[MAX_QPATH];
2491 float biggestorigin;
2493 pchunk = (pskchunk_t *)buffer;
2494 if (strcmp(pchunk->id, "ACTRHEAD"))
2495 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2497 loadmodel->modeldatatypestring = "PSK";
2499 loadmodel->type = mod_alias;
2500 loadmodel->DrawSky = NULL;
2501 loadmodel->DrawAddWaterPlanes = NULL;
2502 loadmodel->Draw = R_Q1BSP_Draw;
2503 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2504 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2505 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2506 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2507 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2508 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2509 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2510 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2511 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2512 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2513 loadmodel->PointSuperContents = NULL;
2514 loadmodel->synctype = ST_RAND;
2516 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2517 strlcat(animname, ".psa", sizeof(animname));
2518 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2519 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2521 animbufferend = animbuffer;
2540 while (buffer < bufferend)
2542 pchunk = (pskchunk_t *)buffer;
2543 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2544 version = LittleLong(pchunk->version);
2545 recordsize = LittleLong(pchunk->recordsize);
2546 numrecords = LittleLong(pchunk->numrecords);
2547 if (developer_extra.integer)
2548 Con_DPrintf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2549 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2550 Con_Printf ("%s: chunk %s has unknown version %x (0x1e83b9, 0x1e9179, 0x2e, 0x12f2bc, 0x12f2f0 are currently supported), trying to load anyway!\n", loadmodel->name, pchunk->id, version);
2551 if (!strcmp(pchunk->id, "ACTRHEAD"))
2555 else if (!strcmp(pchunk->id, "PNTS0000"))
2558 if (recordsize != sizeof(*p))
2559 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2560 // byteswap in place and keep the pointer
2561 numpnts = numrecords;
2562 pnts = (pskpnts_t *)buffer;
2563 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2565 p->origin[0] = LittleFloat(p->origin[0]);
2566 p->origin[1] = LittleFloat(p->origin[1]);
2567 p->origin[2] = LittleFloat(p->origin[2]);
2571 else if (!strcmp(pchunk->id, "VTXW0000"))
2574 if (recordsize != sizeof(*p))
2575 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2576 // byteswap in place and keep the pointer
2577 numvtxw = numrecords;
2578 vtxw = (pskvtxw_t *)buffer;
2579 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2581 p->pntsindex = LittleShort(p->pntsindex);
2582 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2583 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2584 if (p->pntsindex >= numpnts)
2586 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2592 else if (!strcmp(pchunk->id, "FACE0000"))
2595 if (recordsize != sizeof(*p))
2596 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2597 // byteswap in place and keep the pointer
2598 numfaces = numrecords;
2599 faces = (pskface_t *)buffer;
2600 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2602 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2603 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2604 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2605 p->group = LittleLong(p->group);
2606 if (p->vtxwindex[0] >= numvtxw)
2608 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2609 p->vtxwindex[0] = 0;
2611 if (p->vtxwindex[1] >= numvtxw)
2613 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2614 p->vtxwindex[1] = 0;
2616 if (p->vtxwindex[2] >= numvtxw)
2618 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2619 p->vtxwindex[2] = 0;
2624 else if (!strcmp(pchunk->id, "MATT0000"))
2627 if (recordsize != sizeof(*p))
2628 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2629 // byteswap in place and keep the pointer
2630 nummatts = numrecords;
2631 matts = (pskmatt_t *)buffer;
2632 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2638 else if (!strcmp(pchunk->id, "REFSKELT"))
2641 if (recordsize != sizeof(*p))
2642 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2643 // byteswap in place and keep the pointer
2644 numbones = numrecords;
2645 bones = (pskboneinfo_t *)buffer;
2646 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2648 p->numchildren = LittleLong(p->numchildren);
2649 p->parent = LittleLong(p->parent);
2650 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2651 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2652 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2653 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2654 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2655 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2656 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2657 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2658 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2659 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2660 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2661 #ifdef PSKQUATNEGATIONS
2664 p->basepose.quat[0] *= -1;
2665 p->basepose.quat[1] *= -1;
2666 p->basepose.quat[2] *= -1;
2670 p->basepose.quat[0] *= 1;
2671 p->basepose.quat[1] *= -1;
2672 p->basepose.quat[2] *= 1;
2675 if (p->parent < 0 || p->parent >= numbones)
2677 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2683 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2686 if (recordsize != sizeof(*p))
2687 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2688 // byteswap in place and keep the pointer
2689 numrawweights = numrecords;
2690 rawweights = (pskrawweights_t *)buffer;
2691 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2693 p->weight = LittleFloat(p->weight);
2694 p->pntsindex = LittleLong(p->pntsindex);
2695 p->boneindex = LittleLong(p->boneindex);
2696 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2698 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2701 if (p->boneindex < 0 || p->boneindex >= numbones)
2703 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2711 while (animbuffer < animbufferend)
2713 pchunk = (pskchunk_t *)animbuffer;
2714 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2715 version = LittleLong(pchunk->version);
2716 recordsize = LittleLong(pchunk->recordsize);
2717 numrecords = LittleLong(pchunk->numrecords);
2718 if (developer_extra.integer)
2719 Con_DPrintf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2720 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2721 Con_Printf ("%s: chunk %s has unknown version %x (0x1e83b9, 0x1e9179, 0x2e, 0x12f2bc, 0x12f2f0 are currently supported), trying to load anyway!\n", animname, pchunk->id, version);
2722 if (!strcmp(pchunk->id, "ANIMHEAD"))
2726 else if (!strcmp(pchunk->id, "BONENAMES"))
2729 if (recordsize != sizeof(*p))
2730 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2731 // byteswap in place and keep the pointer
2732 numanimbones = numrecords;
2733 //animbones = (pskboneinfo_t *)animbuffer;
2734 // NOTE: supposedly psa does not need to match the psk model, the
2735 // bones missing from the psa would simply use their base
2736 // positions from the psk, but this is hard for me to implement
2737 // and people can easily make animations that match.
2738 if (numanimbones != numbones)
2739 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2740 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2742 p->numchildren = LittleLong(p->numchildren);
2743 p->parent = LittleLong(p->parent);
2744 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2745 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2746 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2747 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2748 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2749 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2750 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2751 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2752 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2753 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2754 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2755 #ifdef PSKQUATNEGATIONS
2758 p->basepose.quat[0] *= -1;
2759 p->basepose.quat[1] *= -1;
2760 p->basepose.quat[2] *= -1;
2764 p->basepose.quat[0] *= 1;
2765 p->basepose.quat[1] *= -1;
2766 p->basepose.quat[2] *= 1;
2769 if (p->parent < 0 || p->parent >= numanimbones)
2771 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2774 // check that bones are the same as in the base
2775 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2776 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2780 else if (!strcmp(pchunk->id, "ANIMINFO"))
2783 if (recordsize != sizeof(*p))
2784 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2785 // byteswap in place and keep the pointer
2786 numanims = numrecords;
2787 anims = (pskaniminfo_t *)animbuffer;
2788 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2790 p->numbones = LittleLong(p->numbones);
2791 p->playtime = LittleFloat(p->playtime);
2792 p->fps = LittleFloat(p->fps);
2793 p->firstframe = LittleLong(p->firstframe);
2794 p->numframes = LittleLong(p->numframes);
2795 if (p->numbones != numbones)
2796 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2800 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2803 if (recordsize != sizeof(*p))
2804 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2805 numanimkeys = numrecords;
2806 animkeys = (pskanimkeys_t *)animbuffer;
2807 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2809 p->origin[0] = LittleFloat(p->origin[0]);
2810 p->origin[1] = LittleFloat(p->origin[1]);
2811 p->origin[2] = LittleFloat(p->origin[2]);
2812 p->quat[0] = LittleFloat(p->quat[0]);
2813 p->quat[1] = LittleFloat(p->quat[1]);
2814 p->quat[2] = LittleFloat(p->quat[2]);
2815 p->quat[3] = LittleFloat(p->quat[3]);
2816 p->frametime = LittleFloat(p->frametime);
2817 #ifdef PSKQUATNEGATIONS
2818 if (index % numbones)
2833 // TODO: allocate bonepose stuff
2836 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2839 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights)
2840 Host_Error("%s: missing required chunks", loadmodel->name);
2844 loadmodel->numframes = 0;
2845 for (index = 0;index < numanims;index++)
2846 loadmodel->numframes += anims[index].numframes;
2847 if (numanimkeys != numbones * loadmodel->numframes)
2848 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2851 loadmodel->numframes = loadmodel->num_poses = 1;
2853 meshvertices = numvtxw;
2854 meshtriangles = numfaces;
2856 // load external .skin files if present
2857 skinfiles = Mod_LoadSkinFiles();
2858 if (loadmodel->numskins < 1)
2859 loadmodel->numskins = 1;
2860 loadmodel->num_bones = numbones;
2861 loadmodel->num_poses = loadmodel->numframes;
2862 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2863 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2864 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2865 loadmodel->surfmesh.num_vertices = meshvertices;
2866 loadmodel->surfmesh.num_triangles = meshtriangles;
2867 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
2868 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
2869 // do most allocations as one merged chunk
2870 size = loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + loadmodel->surfmesh.num_triangles * sizeof(int[3]) + (r_enableshadowvolumes.integer ? loadmodel->surfmesh.num_triangles * sizeof(int[3]) : 0) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[2]) + loadmodel->surfmesh.num_vertices * sizeof(unsigned short) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t) + ((loadmodel->surfmesh.num_vertices <= 65536) ? (loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3])) : 0);
2871 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2872 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2873 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2874 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2875 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2876 if (r_enableshadowvolumes.integer)
2878 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2880 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2881 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2882 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2883 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2884 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2885 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2886 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2887 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2888 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2889 loadmodel->surfmesh.num_blends = 0;
2890 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2891 if (loadmodel->surfmesh.num_vertices <= 65536)
2893 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2895 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2896 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(blendweights_t));
2898 for (i = 0;i < loadmodel->numskins;i++)
2900 loadmodel->skinscenes[i].firstframe = i;
2901 loadmodel->skinscenes[i].framecount = 1;
2902 loadmodel->skinscenes[i].loop = true;
2903 loadmodel->skinscenes[i].framerate = 10;
2907 for (index = 0, i = 0;index < nummatts;index++)
2909 // since psk models do not have named sections, reuse their shader name as the section name
2910 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2911 loadmodel->sortedmodelsurfaces[index] = index;
2912 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2913 loadmodel->data_surfaces[index].num_firstvertex = 0;
2914 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2917 // copy over the vertex locations and texcoords
2918 for (index = 0;index < numvtxw;index++)
2920 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2921 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2922 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2923 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2924 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2927 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2928 for (index = 0;index < numfaces;index++)
2929 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2930 for (index = 0, i = 0;index < nummatts;index++)
2932 loadmodel->data_surfaces[index].num_firsttriangle = i;
2933 i += loadmodel->data_surfaces[index].num_triangles;
2934 loadmodel->data_surfaces[index].num_triangles = 0;
2936 for (index = 0;index < numfaces;index++)
2938 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2939 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2940 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2941 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2944 // copy over the bones
2945 for (index = 0;index < numbones;index++)
2947 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2948 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2949 if (loadmodel->data_bones[index].parent >= index)
2950 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2953 // convert the basepose data
2954 if (loadmodel->num_bones)
2957 matrix4x4_t *basebonepose;
2958 float *outinvmatrix = loadmodel->data_baseboneposeinverse;
2959 matrix4x4_t bonematrix;
2960 matrix4x4_t tempbonematrix;
2961 basebonepose = (matrix4x4_t *)Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(matrix4x4_t));
2962 for (boneindex = 0;boneindex < loadmodel->num_bones;boneindex++)
2964 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]);
2965 if (loadmodel->data_bones[boneindex].parent >= 0)
2967 tempbonematrix = bonematrix;
2968 Matrix4x4_Concat(&bonematrix, basebonepose + loadmodel->data_bones[boneindex].parent, &tempbonematrix);
2970 basebonepose[boneindex] = bonematrix;
2971 Matrix4x4_Invert_Simple(&tempbonematrix, basebonepose + boneindex);
2972 Matrix4x4_ToArray12FloatD3D(&tempbonematrix, outinvmatrix + 12*boneindex);
2974 Mem_Free(basebonepose);
2977 // sort the psk point weights into the vertex weight tables
2978 // (which only accept up to 4 bones per vertex)
2979 for (index = 0;index < numvtxw;index++)
2981 int weightindex[4] = { 0, 0, 0, 0 };
2982 float weightinfluence[4] = { 0, 0, 0, 0 };
2984 for (j = 0;j < numrawweights;j++)
2986 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2988 int boneindex = rawweights[j].boneindex;
2989 float influence = rawweights[j].weight;
2990 for (l = 0;l < 4;l++)
2992 if (weightinfluence[l] < influence)
2994 // move lower influence weights out of the way first
2996 for (l2 = 3;l2 > l;l2--)
2998 weightinfluence[l2] = weightinfluence[l2-1];
2999 weightindex[l2] = weightindex[l2-1];
3001 // store the new weight
3002 weightinfluence[l] = influence;
3003 weightindex[l] = boneindex;
3009 loadmodel->surfmesh.blends[index] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
3011 if (loadmodel->surfmesh.num_blends < loadmodel->surfmesh.num_vertices)
3012 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
3014 // set up the animscenes based on the anims
3017 for (index = 0, i = 0;index < numanims;index++)
3019 for (j = 0;j < anims[index].numframes;j++, i++)
3021 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
3022 loadmodel->animscenes[i].firstframe = i;
3023 loadmodel->animscenes[i].framecount = 1;
3024 loadmodel->animscenes[i].loop = true;
3025 loadmodel->animscenes[i].framerate = anims[index].fps;
3028 // calculate the scaling value for bone origins so they can be compressed to short
3030 for (index = 0;index < numanimkeys;index++)
3032 pskanimkeys_t *k = animkeys + index;
3033 biggestorigin = max(biggestorigin, fabs(k->origin[0]));
3034 biggestorigin = max(biggestorigin, fabs(k->origin[1]));
3035 biggestorigin = max(biggestorigin, fabs(k->origin[2]));
3037 loadmodel->num_posescale = biggestorigin / 32767.0f;
3038 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3040 // load the poses from the animkeys
3041 for (index = 0;index < numanimkeys;index++)
3043 pskanimkeys_t *k = animkeys + index;
3045 Vector4Copy(k->quat, quat);
3047 Vector4Negate(quat, quat);
3048 Vector4Normalize2(quat, quat);
3049 // compress poses to the short[6] format for longterm storage
3050 loadmodel->data_poses6s[index*6+0] = k->origin[0] * loadmodel->num_poseinvscale;
3051 loadmodel->data_poses6s[index*6+1] = k->origin[1] * loadmodel->num_poseinvscale;
3052 loadmodel->data_poses6s[index*6+2] = k->origin[2] * loadmodel->num_poseinvscale;
3053 loadmodel->data_poses6s[index*6+3] = quat[0] * 32767.0f;
3054 loadmodel->data_poses6s[index*6+4] = quat[1] * 32767.0f;
3055 loadmodel->data_poses6s[index*6+5] = quat[2] * 32767.0f;
3060 strlcpy(loadmodel->animscenes[0].name, "base", sizeof(loadmodel->animscenes[0].name));
3061 loadmodel->animscenes[0].firstframe = 0;
3062 loadmodel->animscenes[0].framecount = 1;
3063 loadmodel->animscenes[0].loop = true;
3064 loadmodel->animscenes[0].framerate = 10;
3066 // calculate the scaling value for bone origins so they can be compressed to short
3068 for (index = 0;index < numbones;index++)
3070 pskboneinfo_t *p = bones + index;
3071 biggestorigin = max(biggestorigin, fabs(p->basepose.origin[0]));
3072 biggestorigin = max(biggestorigin, fabs(p->basepose.origin[1]));
3073 biggestorigin = max(biggestorigin, fabs(p->basepose.origin[2]));
3075 loadmodel->num_posescale = biggestorigin / 32767.0f;
3076 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3078 // load the basepose as a frame
3079 for (index = 0;index < numbones;index++)
3081 pskboneinfo_t *p = bones + index;
3083 Vector4Copy(p->basepose.quat, quat);
3085 Vector4Negate(quat, quat);
3086 Vector4Normalize2(quat, quat);
3087 // compress poses to the short[6] format for longterm storage
3088 loadmodel->data_poses6s[index*6+0] = p->basepose.origin[0] * loadmodel->num_poseinvscale;
3089 loadmodel->data_poses6s[index*6+1] = p->basepose.origin[1] * loadmodel->num_poseinvscale;
3090 loadmodel->data_poses6s[index*6+2] = p->basepose.origin[2] * loadmodel->num_poseinvscale;
3091 loadmodel->data_poses6s[index*6+3] = quat[0] * 32767.0f;
3092 loadmodel->data_poses6s[index*6+4] = quat[1] * 32767.0f;
3093 loadmodel->data_poses6s[index*6+5] = quat[2] * 32767.0f;
3097 Mod_FreeSkinFiles(skinfiles);
3099 Mem_Free(animfilebuffer);
3100 Mod_MakeSortedSurfaces(loadmodel);
3102 // compute all the mesh information that was not loaded from the file
3103 // TODO: honor smoothing groups somehow?
3104 if (loadmodel->surfmesh.data_element3s)
3105 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3106 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3107 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
3108 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);
3109 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);
3110 if (loadmodel->surfmesh.data_neighbor3i)
3111 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3112 Mod_Alias_CalculateBoundingBox();
3114 if (!loadmodel->surfmesh.isanimated)
3116 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3117 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3118 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3119 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3120 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3121 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
3124 // because shaders can do somewhat unexpected things, check for unusual features now
3125 for (i = 0;i < loadmodel->num_textures;i++)
3127 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
3128 mod->DrawSky = R_Q1BSP_DrawSky;
3129 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
3130 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
3134 void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
3136 unsigned char *data;
3138 const unsigned char *pbase, *pend;
3140 skinfile_t *skinfiles;
3141 int i, j, k, meshvertices, meshtriangles;
3142 float biggestorigin;
3143 const unsigned int *inelements;
3145 const int *inneighbors;
3147 float *outvertex, *outnormal, *outtexcoord, *outsvector, *outtvector, *outcolor;
3148 // this pointers into the file data are read only through Little* functions so they can be unaligned memory
3149 const float *vnormal = NULL;
3150 const float *vposition = NULL;
3151 const float *vtangent = NULL;
3152 const float *vtexcoord = NULL;
3153 const float *vcolor4f = NULL;
3154 const unsigned char *vblendindexes = NULL;
3155 const unsigned char *vblendweights = NULL;
3156 const unsigned char *vcolor4ub = NULL;
3157 const unsigned short *framedata = NULL;
3158 // temporary memory allocations (because the data in the file may be misaligned)
3159 iqmanim_t *anims = NULL;
3160 iqmbounds_t *bounds = NULL;
3161 iqmjoint1_t *joint1 = NULL;
3162 iqmjoint_t *joint = NULL;
3163 iqmmesh_t *meshes = NULL;
3164 iqmpose1_t *pose1 = NULL;
3165 iqmpose_t *pose = NULL;
3166 iqmvertexarray_t *vas = NULL;
3168 pbase = (unsigned char *)buffer;
3169 pend = (unsigned char *)bufferend;
3171 if (pbase + sizeof(iqmheader_t) > pend)
3172 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model %d", loadmodel->name, (int)(pend - pbase));
3174 // copy struct (otherwise it may be misaligned)
3175 // LordHavoc: okay it's definitely not misaligned here, but for consistency...
3176 memcpy(&header, pbase, sizeof(iqmheader_t));
3178 if (memcmp(header.id, "INTERQUAKEMODEL", 16))
3179 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model", loadmodel->name);
3180 if (LittleLong(header.version) != 1 && LittleLong(header.version) != 2)
3181 Host_Error ("Mod_INTERQUAKEMODEL_Load: only version 1 and 2 models are currently supported (name = %s)", loadmodel->name);
3183 loadmodel->modeldatatypestring = "IQM";
3185 loadmodel->type = mod_alias;
3186 loadmodel->synctype = ST_RAND;
3189 header.version = LittleLong(header.version);
3190 header.filesize = LittleLong(header.filesize);
3191 header.flags = LittleLong(header.flags);
3192 header.num_text = LittleLong(header.num_text);
3193 header.ofs_text = LittleLong(header.ofs_text);
3194 header.num_meshes = LittleLong(header.num_meshes);
3195 header.ofs_meshes = LittleLong(header.ofs_meshes);
3196 header.num_vertexarrays = LittleLong(header.num_vertexarrays);
3197 header.num_vertexes = LittleLong(header.num_vertexes);
3198 header.ofs_vertexarrays = LittleLong(header.ofs_vertexarrays);
3199 header.num_triangles = LittleLong(header.num_triangles);
3200 header.ofs_triangles = LittleLong(header.ofs_triangles);
3201 header.ofs_neighbors = LittleLong(header.ofs_neighbors);
3202 header.num_joints = LittleLong(header.num_joints);
3203 header.ofs_joints = LittleLong(header.ofs_joints);
3204 header.num_poses = LittleLong(header.num_poses);
3205 header.ofs_poses = LittleLong(header.ofs_poses);
3206 header.num_anims = LittleLong(header.num_anims);
3207 header.ofs_anims = LittleLong(header.ofs_anims);
3208 header.num_frames = LittleLong(header.num_frames);
3209 header.num_framechannels = LittleLong(header.num_framechannels);
3210 header.ofs_frames = LittleLong(header.ofs_frames);
3211 header.ofs_bounds = LittleLong(header.ofs_bounds);
3212 header.num_comment = LittleLong(header.num_comment);
3213 header.ofs_comment = LittleLong(header.ofs_comment);
3214 header.num_extensions = LittleLong(header.num_extensions);
3215 header.ofs_extensions = LittleLong(header.ofs_extensions);
3217 if (header.version == 1)
3219 if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint1_t) > pend ||
3220 pbase + header.ofs_poses + header.num_poses*sizeof(iqmpose1_t) > pend)
3222 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3228 if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint_t) > pend ||
3229 pbase + header.ofs_poses + header.num_poses*sizeof(iqmpose_t) > pend)
3231 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3235 if (pbase + header.ofs_text + header.num_text > pend ||
3236 pbase + header.ofs_meshes + header.num_meshes*sizeof(iqmmesh_t) > pend ||
3237 pbase + header.ofs_vertexarrays + header.num_vertexarrays*sizeof(iqmvertexarray_t) > pend ||
3238 pbase + header.ofs_triangles + header.num_triangles*sizeof(int[3]) > pend ||
3239 (header.ofs_neighbors && pbase + header.ofs_neighbors + header.num_triangles*sizeof(int[3]) > pend) ||
3240 pbase + header.ofs_anims + header.num_anims*sizeof(iqmanim_t) > pend ||
3241 pbase + header.ofs_frames + header.num_frames*header.num_framechannels*sizeof(unsigned short) > pend ||
3242 (header.ofs_bounds && pbase + header.ofs_bounds + header.num_frames*sizeof(iqmbounds_t) > pend) ||
3243 pbase + header.ofs_comment + header.num_comment > pend)
3245 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3249 // copy structs to make them aligned in memory (otherwise we crash on Sparc and PowerPC and others)
3250 if (header.num_vertexarrays)
3251 vas = (iqmvertexarray_t *)(pbase + header.ofs_vertexarrays);
3252 if (header.num_anims)
3253 anims = (iqmanim_t *)(pbase + header.ofs_anims);
3254 if (header.ofs_bounds)
3255 bounds = (iqmbounds_t *)(pbase + header.ofs_bounds);
3256 if (header.num_meshes)
3257 meshes = (iqmmesh_t *)(pbase + header.ofs_meshes);
3259 for (i = 0;i < (int)header.num_vertexarrays;i++)
3261 iqmvertexarray_t va;
3263 va.type = LittleLong(vas[i].type);
3264 va.flags = LittleLong(vas[i].flags);
3265 va.format = LittleLong(vas[i].format);
3266 va.size = LittleLong(vas[i].size);
3267 va.offset = LittleLong(vas[i].offset);
3268 vsize = header.num_vertexes*va.size;
3271 case IQM_FLOAT: vsize *= sizeof(float); break;
3272 case IQM_UBYTE: vsize *= sizeof(unsigned char); break;
3275 if (pbase + va.offset + vsize > pend)
3277 // no need to copy the vertex data for alignment because LittleLong/LittleShort will be invoked on reading them, and the destination is aligned
3281 if (va.format == IQM_FLOAT && va.size == 3)
3282 vposition = (const float *)(pbase + va.offset);
3285 if (va.format == IQM_FLOAT && va.size == 2)
3286 vtexcoord = (const float *)(pbase + va.offset);
3289 if (va.format == IQM_FLOAT && va.size == 3)
3290 vnormal = (const float *)(pbase + va.offset);
3293 if (va.format == IQM_FLOAT && va.size == 4)
3294 vtangent = (const float *)(pbase + va.offset);
3296 case IQM_BLENDINDEXES:
3297 if (va.format == IQM_UBYTE && va.size == 4)
3298 vblendindexes = (const unsigned char *)(pbase + va.offset);
3300 case IQM_BLENDWEIGHTS:
3301 if (va.format == IQM_UBYTE && va.size == 4)
3302 vblendweights = (const unsigned char *)(pbase + va.offset);
3305 if (va.format == IQM_FLOAT && va.size == 4)
3306 vcolor4f = (const float *)(pbase + va.offset);
3307 if (va.format == IQM_UBYTE && va.size == 4)
3308 vcolor4ub = (const unsigned char *)(pbase + va.offset);
3312 if (header.num_vertexes > 0 && (!vposition || !vtexcoord || ((header.num_frames > 0 || header.num_anims > 0) && (!vblendindexes || !vblendweights))))
3314 Con_Printf("%s is missing vertex array data\n", loadmodel->name);
3318 text = header.num_text && header.ofs_text ? (const char *)(pbase + header.ofs_text) : "";
3320 loadmodel->DrawSky = NULL;
3321 loadmodel->DrawAddWaterPlanes = NULL;
3322 loadmodel->Draw = R_Q1BSP_Draw;
3323 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
3324 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
3325 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
3326 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
3327 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
3328 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
3329 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
3330 loadmodel->DrawLight = R_Q1BSP_DrawLight;
3331 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
3332 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
3333 loadmodel->PointSuperContents = NULL;
3335 // load external .skin files if present
3336 skinfiles = Mod_LoadSkinFiles();
3337 if (loadmodel->numskins < 1)
3338 loadmodel->numskins = 1;
3340 loadmodel->numframes = max(header.num_anims, 1);
3341 loadmodel->num_bones = header.num_joints;
3342 loadmodel->num_poses = max(header.num_frames, 1);
3343 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = header.num_meshes;
3344 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3345 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3346 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices; // updated later
3348 meshvertices = header.num_vertexes;
3349 meshtriangles = header.num_triangles;
3351 // do most allocations as one merged chunk
3352 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + (r_enableshadowvolumes.integer ? meshtriangles * sizeof(int[3]) : 0) + meshvertices * (sizeof(float[14]) + (vcolor4f || vcolor4ub ? sizeof(float[4]) : 0)) + (vblendindexes && vblendweights ? meshvertices * sizeof(unsigned short) : 0) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
3353 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
3354 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
3355 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
3356 loadmodel->surfmesh.num_vertices = meshvertices;
3357 loadmodel->surfmesh.num_triangles = meshtriangles;
3358 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3359 if (r_enableshadowvolumes.integer)
3361 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3363 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
3364 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3365 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3366 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
3367 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
3368 if (vcolor4f || vcolor4ub)
3370 loadmodel->surfmesh.data_lightmapcolor4f = (float *)data;data += meshvertices * sizeof(float[4]);
3372 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
3373 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
3374 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
3375 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
3376 if (vblendindexes && vblendweights)
3378 loadmodel->surfmesh.num_blends = 0;
3379 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
3381 if (meshvertices <= 65536)
3383 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
3385 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
3386 if (vblendindexes && vblendweights)
3387 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
3389 for (i = 0;i < loadmodel->numskins;i++)
3391 loadmodel->skinscenes[i].firstframe = i;
3392 loadmodel->skinscenes[i].framecount = 1;
3393 loadmodel->skinscenes[i].loop = true;
3394 loadmodel->skinscenes[i].framerate = 10;
3397 // load the bone info
3398 if (header.version == 1)
3400 iqmjoint1_t *injoint1 = (iqmjoint1_t *)(pbase + header.ofs_joints);
3401 if (loadmodel->num_bones)
3402 joint1 = (iqmjoint1_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(iqmjoint1_t));
3403 for (i = 0;i < loadmodel->num_bones;i++)
3405 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3406 joint1[i].name = LittleLong(injoint1[i].name);
3407 joint1[i].parent = LittleLong(injoint1[i].parent);
3408 for (j = 0;j < 3;j++)
3410 joint1[i].origin[j] = LittleFloat(injoint1[i].origin[j]);
3411 joint1[i].rotation[j] = LittleFloat(injoint1[i].rotation[j]);
3412 joint1[i].scale[j] = LittleFloat(injoint1[i].scale[j]);
3414 strlcpy(loadmodel->data_bones[i].name, &text[joint1[i].name], sizeof(loadmodel->data_bones[i].name));
3415 loadmodel->data_bones[i].parent = joint1[i].parent;
3416 if (loadmodel->data_bones[i].parent >= i)
3417 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3418 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]);
3419 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3420 if (loadmodel->data_bones[i].parent >= 0)
3422 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3423 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3424 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3426 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3431 iqmjoint_t *injoint = (iqmjoint_t *)(pbase + header.ofs_joints);
3432 if (header.num_joints)
3433 joint = (iqmjoint_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(iqmjoint_t));
3434 for (i = 0;i < loadmodel->num_bones;i++)
3436 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3437 joint[i].name = LittleLong(injoint[i].name);
3438 joint[i].parent = LittleLong(injoint[i].parent);
3439 for (j = 0;j < 3;j++)
3441 joint[i].origin[j] = LittleFloat(injoint[i].origin[j]);
3442 joint[i].rotation[j] = LittleFloat(injoint[i].rotation[j]);
3443 joint[i].scale[j] = LittleFloat(injoint[i].scale[j]);
3445 joint[i].rotation[3] = LittleFloat(injoint[i].rotation[3]);
3446 strlcpy(loadmodel->data_bones[i].name, &text[joint[i].name], sizeof(loadmodel->data_bones[i].name));
3447 loadmodel->data_bones[i].parent = joint[i].parent;
3448 if (loadmodel->data_bones[i].parent >= i)
3449 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3450 if (joint[i].rotation[3] > 0)
3451 Vector4Negate(joint[i].rotation, joint[i].rotation);
3452 Vector4Normalize2(joint[i].rotation, joint[i].rotation);
3453 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]);
3454 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3455 if (loadmodel->data_bones[i].parent >= 0)
3457 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3458 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3459 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3461 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3465 // set up the animscenes based on the anims
3466 for (i = 0;i < (int)header.num_anims;i++)
3469 anim.name = LittleLong(anims[i].name);
3470 anim.first_frame = LittleLong(anims[i].first_frame);
3471 anim.num_frames = LittleLong(anims[i].num_frames);
3472 anim.framerate = LittleFloat(anims[i].framerate);
3473 anim.flags = LittleLong(anims[i].flags);
3474 strlcpy(loadmodel->animscenes[i].name, &text[anim.name], sizeof(loadmodel->animscenes[i].name));
3475 loadmodel->animscenes[i].firstframe = anim.first_frame;
3476 loadmodel->animscenes[i].framecount = anim.num_frames;
3477 loadmodel->animscenes[i].loop = ((anim.flags & IQM_LOOP) != 0);
3478 loadmodel->animscenes[i].framerate = anim.framerate;
3480 if (header.num_anims <= 0)
3482 strlcpy(loadmodel->animscenes[0].name, "static", sizeof(loadmodel->animscenes[0].name));
3483 loadmodel->animscenes[0].firstframe = 0;
3484 loadmodel->animscenes[0].framecount = 1;
3485 loadmodel->animscenes[0].loop = true;
3486 loadmodel->animscenes[0].framerate = 10;
3489 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
3490 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
3493 if (header.version == 1)
3495 iqmpose1_t *inpose1 = (iqmpose1_t *)(pbase + header.ofs_poses);
3496 if (header.num_poses)
3497 pose1 = (iqmpose1_t *)Mem_Alloc(loadmodel->mempool, header.num_poses * sizeof(iqmpose1_t));
3498 for (i = 0;i < (int)header.num_poses;i++)
3501 pose1[i].parent = LittleLong(inpose1[i].parent);
3502 pose1[i].channelmask = LittleLong(inpose1[i].channelmask);
3503 for (j = 0;j < 9;j++)
3505 pose1[i].channeloffset[j] = LittleFloat(inpose1[i].channeloffset[j]);
3506 pose1[i].channelscale[j] = LittleFloat(inpose1[i].channelscale[j]);
3508 f = fabs(pose1[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3509 f = fabs(pose1[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3510 f = fabs(pose1[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3511 f = fabs(pose1[i].channeloffset[0] + 0xFFFF*pose1[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3512 f = fabs(pose1[i].channeloffset[1] + 0xFFFF*pose1[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3513 f = fabs(pose1[i].channeloffset[2] + 0xFFFF*pose1[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3515 if (header.num_frames <= 0)
3517 for (i = 0;i < loadmodel->num_bones;i++)
3520 f = fabs(joint1[i].origin[0]); biggestorigin = max(biggestorigin, f);
3521 f = fabs(joint1[i].origin[1]); biggestorigin = max(biggestorigin, f);
3522 f = fabs(joint1[i].origin[2]); biggestorigin = max(biggestorigin, f);
3528 iqmpose_t *inpose = (iqmpose_t *)(pbase + header.ofs_poses);
3529 if (header.num_poses)
3530 pose = (iqmpose_t *)Mem_Alloc(loadmodel->mempool, header.num_poses * sizeof(iqmpose_t));
3531 for (i = 0;i < (int)header.num_poses;i++)
3534 pose[i].parent = LittleLong(inpose[i].parent);
3535 pose[i].channelmask = LittleLong(inpose[i].channelmask);
3536 for (j = 0;j < 10;j++)
3538 pose[i].channeloffset[j] = LittleFloat(inpose[i].channeloffset[j]);
3539 pose[i].channelscale[j] = LittleFloat(inpose[i].channelscale[j]);
3541 f = fabs(pose[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3542 f = fabs(pose[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3543 f = fabs(pose[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3544 f = fabs(pose[i].channeloffset[0] + 0xFFFF*pose[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3545 f = fabs(pose[i].channeloffset[1] + 0xFFFF*pose[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3546 f = fabs(pose[i].channeloffset[2] + 0xFFFF*pose[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3548 if (header.num_frames <= 0)
3550 for (i = 0;i < loadmodel->num_bones;i++)
3553 f = fabs(joint[i].origin[0]); biggestorigin = max(biggestorigin, f);
3554 f = fabs(joint[i].origin[1]); biggestorigin = max(biggestorigin, f);
3555 f = fabs(joint[i].origin[2]); biggestorigin = max(biggestorigin, f);
3559 loadmodel->num_posescale = biggestorigin / 32767.0f;
3560 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3562 // load the pose data
3563 // this unaligned memory access is safe (LittleShort reads as bytes)
3564 framedata = (const unsigned short *)(pbase + header.ofs_frames);
3565 if (header.version == 1)
3567 for (i = 0, k = 0;i < (int)header.num_frames;i++)
3569 for (j = 0;j < (int)header.num_poses;j++, k++)
3571 loadmodel->data_poses6s[k*6 + 0] = loadmodel->num_poseinvscale * (pose1[j].channeloffset[0] + (pose1[j].channelmask&1 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[0] : 0));
3572 loadmodel->data_poses6s[k*6 + 1] = loadmodel->num_poseinvscale * (pose1[j].channeloffset[1] + (pose1[j].channelmask&2 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[1] : 0));
3573 loadmodel->data_poses6s[k*6 + 2] = loadmodel->num_poseinvscale * (pose1[j].channeloffset[2] + (pose1[j].channelmask&4 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[2] : 0));
3574 loadmodel->data_poses6s[k*6 + 3] = 32767.0f * (pose1[j].channeloffset[3] + (pose1[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[3] : 0));
3575 loadmodel->data_poses6s[k*6 + 4] = 32767.0f * (pose1[j].channeloffset[4] + (pose1[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[4] : 0));
3576 loadmodel->data_poses6s[k*6 + 5] = 32767.0f * (pose1[j].channeloffset[5] + (pose1[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[5] : 0));
3577 // skip scale data for now
3578 if(pose1[j].channelmask&64) framedata++;
3579 if(pose1[j].channelmask&128) framedata++;
3580 if(pose1[j].channelmask&256) framedata++;
3583 if (header.num_frames <= 0)
3585 for (i = 0;i < loadmodel->num_bones;i++)
3587 loadmodel->data_poses6s[i*6 + 0] = loadmodel->num_poseinvscale * joint1[i].origin[0];
3588 loadmodel->data_poses6s[i*6 + 1] = loadmodel->num_poseinvscale * joint1[i].origin[1];
3589 loadmodel->data_poses6s[i*6 + 2] = loadmodel->num_poseinvscale * joint1[i].origin[2];
3590 loadmodel->data_poses6s[i*6 + 3] = 32767.0f * joint1[i].rotation[0];
3591 loadmodel->data_poses6s[i*6 + 4] = 32767.0f * joint1[i].rotation[1];
3592 loadmodel->data_poses6s[i*6 + 5] = 32767.0f * joint1[i].rotation[2];
3598 for (i = 0, k = 0;i < (int)header.num_frames;i++)
3600 for (j = 0;j < (int)header.num_poses;j++, k++)
3603 loadmodel->data_poses6s[k*6 + 0] = loadmodel->num_poseinvscale * (pose[j].channeloffset[0] + (pose[j].channelmask&1 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[0] : 0));
3604 loadmodel->data_poses6s[k*6 + 1] = loadmodel->num_poseinvscale * (pose[j].channeloffset[1] + (pose[j].channelmask&2 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[1] : 0));
3605 loadmodel->data_poses6s[k*6 + 2] = loadmodel->num_poseinvscale * (pose[j].channeloffset[2] + (pose[j].channelmask&4 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[2] : 0));
3606 rot[0] = pose[j].channeloffset[3] + (pose[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[3] : 0);
3607 rot[1] = pose[j].channeloffset[4] + (pose[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[4] : 0);
3608 rot[2] = pose[j].channeloffset[5] + (pose[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[5] : 0);
3609 rot[3] = pose[j].channeloffset[6] + (pose[j].channelmask&64 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[6] : 0);
3611 Vector4Negate(rot, rot);
3612 Vector4Normalize2(rot, rot);
3613 loadmodel->data_poses6s[k*6 + 3] = 32767.0f * rot[0];
3614 loadmodel->data_poses6s[k*6 + 4] = 32767.0f * rot[1];
3615 loadmodel->data_poses6s[k*6 + 5] = 32767.0f * rot[2];
3616 // skip scale data for now
3617 if(pose[j].channelmask&128) framedata++;
3618 if(pose[j].channelmask&256) framedata++;
3619 if(pose[j].channelmask&512) framedata++;
3622 if (header.num_frames <= 0)
3624 for (i = 0;i < loadmodel->num_bones;i++)
3626 loadmodel->data_poses6s[i*6 + 0] = loadmodel->num_poseinvscale * joint[i].origin[0];
3627 loadmodel->data_poses6s[i*6 + 1] = loadmodel->num_poseinvscale * joint[i].origin[1];
3628 loadmodel->data_poses6s[i*6 + 2] = loadmodel->num_poseinvscale * joint[i].origin[2];
3629 loadmodel->data_poses6s[i*6 + 3] = 32767.0f * joint[i].rotation[0];
3630 loadmodel->data_poses6s[i*6 + 4] = 32767.0f * joint[i].rotation[1];
3631 loadmodel->data_poses6s[i*6 + 5] = 32767.0f * joint[i].rotation[2];
3636 // load bounding box data
3637 if (header.ofs_bounds)
3639 float xyradius = 0, radius = 0;
3640 VectorClear(loadmodel->normalmins);
3641 VectorClear(loadmodel->normalmaxs);
3642 for (i = 0; i < (int)header.num_frames;i++)
3645 bound.mins[0] = LittleFloat(bounds[i].mins[0]);
3646 bound.mins[1] = LittleFloat(bounds[i].mins[1]);
3647 bound.mins[2] = LittleFloat(bounds[i].mins[2]);
3648 bound.maxs[0] = LittleFloat(bounds[i].maxs[0]);
3649 bound.maxs[1] = LittleFloat(bounds[i].maxs[1]);
3650 bound.maxs[2] = LittleFloat(bounds[i].maxs[2]);
3651 bound.xyradius = LittleFloat(bounds[i].xyradius);
3652 bound.radius = LittleFloat(bounds[i].radius);
3655 VectorCopy(bound.mins, loadmodel->normalmins);
3656 VectorCopy(bound.maxs, loadmodel->normalmaxs);
3660 if (loadmodel->normalmins[0] > bound.mins[0]) loadmodel->normalmins[0] = bound.mins[0];
3661 if (loadmodel->normalmins[1] > bound.mins[1]) loadmodel->normalmins[1] = bound.mins[1];
3662 if (loadmodel->normalmins[2] > bound.mins[2]) loadmodel->normalmins[2] = bound.mins[2];
3663 if (loadmodel->normalmaxs[0] < bound.maxs[0]) loadmodel->normalmaxs[0] = bound.maxs[0];
3664 if (loadmodel->normalmaxs[1] < bound.maxs[1]) loadmodel->normalmaxs[1] = bound.maxs[1];
3665 if (loadmodel->normalmaxs[2] < bound.maxs[2]) loadmodel->normalmaxs[2] = bound.maxs[2];
3667 if (bound.xyradius > xyradius)
3668 xyradius = bound.xyradius;
3669 if (bound.radius > radius)
3670 radius = bound.radius;
3672 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -xyradius;
3673 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = xyradius;
3674 loadmodel->yawmins[2] = loadmodel->normalmins[2];
3675 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
3676 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
3677 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
3678 loadmodel->radius = radius;
3679 loadmodel->radius2 = radius * radius;
3682 // load triangle data
3683 // this unaligned memory access is safe (LittleLong reads as bytes)
3684 inelements = (const unsigned int *)(pbase + header.ofs_triangles);
3685 outelements = loadmodel->surfmesh.data_element3i;
3686 for (i = 0;i < (int)header.num_triangles;i++)
3688 outelements[0] = LittleLong(inelements[0]);
3689 outelements[1] = LittleLong(inelements[1]);
3690 outelements[2] = LittleLong(inelements[2]);
3694 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, header.num_vertexes, __FILE__, __LINE__);
3696 if (header.ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
3698 // this unaligned memory access is safe (LittleLong reads as bytes)
3699 inneighbors = (const int *)(pbase + header.ofs_neighbors);
3700 outneighbors = loadmodel->surfmesh.data_neighbor3i;
3701 for (i = 0;i < (int)header.num_triangles;i++)
3703 outneighbors[0] = LittleLong(inneighbors[0]);
3704 outneighbors[1] = LittleLong(inneighbors[1]);
3705 outneighbors[2] = LittleLong(inneighbors[2]);
3712 // this unaligned memory access is safe (LittleFloat reads as bytes)
3713 outvertex = loadmodel->surfmesh.data_vertex3f;
3714 for (i = 0;i < (int)header.num_vertexes;i++)
3716 outvertex[0] = LittleFloat(vposition[0]);
3717 outvertex[1] = LittleFloat(vposition[1]);
3718 outvertex[2] = LittleFloat(vposition[2]);
3723 outtexcoord = loadmodel->surfmesh.data_texcoordtexture2f;
3724 // this unaligned memory access is safe (LittleFloat reads as bytes)
3725 for (i = 0;i < (int)header.num_vertexes;i++)
3727 outtexcoord[0] = LittleFloat(vtexcoord[0]);
3728 outtexcoord[1] = LittleFloat(vtexcoord[1]);
3733 // this unaligned memory access is safe (LittleFloat reads as bytes)
3736 outnormal = loadmodel->surfmesh.data_normal3f;
3737 for (i = 0;i < (int)header.num_vertexes;i++)
3739 outnormal[0] = LittleFloat(vnormal[0]);
3740 outnormal[1] = LittleFloat(vnormal[1]);
3741 outnormal[2] = LittleFloat(vnormal[2]);
3747 // this unaligned memory access is safe (LittleFloat reads as bytes)
3748 if(vnormal && vtangent)
3750 outnormal = loadmodel->surfmesh.data_normal3f;
3751 outsvector = loadmodel->surfmesh.data_svector3f;
3752 outtvector = loadmodel->surfmesh.data_tvector3f;
3753 for (i = 0;i < (int)header.num_vertexes;i++)
3755 outsvector[0] = LittleFloat(vtangent[0]);
3756 outsvector[1] = LittleFloat(vtangent[1]);
3757 outsvector[2] = LittleFloat(vtangent[2]);
3758 if(LittleFloat(vtangent[3]) < 0)
3759 CrossProduct(outsvector, outnormal, outtvector);
3761 CrossProduct(outnormal, outsvector, outtvector);
3769 // this unaligned memory access is safe (all bytes)
3770 if (vblendindexes && vblendweights)
3772 for (i = 0; i < (int)header.num_vertexes;i++)
3774 blendweights_t weights;
3775 memcpy(weights.index, vblendindexes + i*4, 4);
3776 memcpy(weights.influence, vblendweights + i*4, 4);
3777 loadmodel->surfmesh.blends[i] = Mod_Skeletal_AddBlend(loadmodel, &weights);
3783 outcolor = loadmodel->surfmesh.data_lightmapcolor4f;
3784 // this unaligned memory access is safe (LittleFloat reads as bytes)
3785 for (i = 0;i < (int)header.num_vertexes;i++)
3787 outcolor[0] = LittleFloat(vcolor4f[0]);
3788 outcolor[1] = LittleFloat(vcolor4f[1]);
3789 outcolor[2] = LittleFloat(vcolor4f[2]);
3790 outcolor[3] = LittleFloat(vcolor4f[3]);
3797 outcolor = loadmodel->surfmesh.data_lightmapcolor4f;
3798 // this unaligned memory access is safe (all bytes)
3799 for (i = 0;i < (int)header.num_vertexes;i++)
3801 outcolor[0] = vcolor4ub[0] * (1.0f / 255.0f);
3802 outcolor[1] = vcolor4ub[1] * (1.0f / 255.0f);
3803 outcolor[2] = vcolor4ub[2] * (1.0f / 255.0f);
3804 outcolor[3] = vcolor4ub[3] * (1.0f / 255.0f);
3811 for (i = 0;i < (int)header.num_meshes;i++)
3814 msurface_t *surface;
3816 mesh.name = LittleLong(meshes[i].name);
3817 mesh.material = LittleLong(meshes[i].material);
3818 mesh.first_vertex = LittleLong(meshes[i].first_vertex);
3819 mesh.num_vertexes = LittleLong(meshes[i].num_vertexes);
3820 mesh.first_triangle = LittleLong(meshes[i].first_triangle);
3821 mesh.num_triangles = LittleLong(meshes[i].num_triangles);
3823 loadmodel->sortedmodelsurfaces[i] = i;
3824 surface = loadmodel->data_surfaces + i;
3825 surface->texture = loadmodel->data_textures + i;
3826 surface->num_firsttriangle = mesh.first_triangle;
3827 surface->num_triangles = mesh.num_triangles;
3828 surface->num_firstvertex = mesh.first_vertex;
3829 surface->num_vertices = mesh.num_vertexes;
3831 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, &text[mesh.name], &text[mesh.material]);
3834 Mod_FreeSkinFiles(skinfiles);
3835 Mod_MakeSortedSurfaces(loadmodel);
3837 // compute all the mesh information that was not loaded from the file
3838 if (loadmodel->surfmesh.data_element3s)
3839 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3840 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3842 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);
3843 if (!vnormal || !vtangent)
3844 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);
3845 if (!header.ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
3846 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3847 if (!header.ofs_bounds)
3848 Mod_Alias_CalculateBoundingBox();
3850 if (!loadmodel->surfmesh.isanimated && loadmodel->surfmesh.num_triangles >= 1)
3852 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3853 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3854 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3855 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3856 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3857 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
3860 if (joint ) Mem_Free(joint );joint = NULL;
3861 if (joint1 ) Mem_Free(joint1 );joint1 = NULL;
3862 if (pose ) Mem_Free(pose );pose = NULL;
3863 if (pose1 ) Mem_Free(pose1 );pose1 = NULL;
3865 // because shaders can do somewhat unexpected things, check for unusual features now
3866 for (i = 0;i < loadmodel->num_textures;i++)
3868 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
3869 mod->DrawSky = R_Q1BSP_DrawSky;
3870 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
3871 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;