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->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1105 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices; // needed during loading, may be cleared by code later in this function
1106 if (loadmodel->surfmesh.data_neighbor3i)
1107 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1108 Mod_Alias_CalculateBoundingBox();
1109 Mod_Alias_MorphMesh_CompileFrames();
1110 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_MDL_AnimateVertices : NULL;
1113 Mem_Free(vertremap);
1116 skinfiles = Mod_LoadSkinFiles();
1119 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1120 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1121 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1122 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1123 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1124 Mod_FreeSkinFiles(skinfiles);
1125 for (i = 0;i < loadmodel->numskins;i++)
1127 loadmodel->skinscenes[i].firstframe = i;
1128 loadmodel->skinscenes[i].framecount = 1;
1129 loadmodel->skinscenes[i].loop = true;
1130 loadmodel->skinscenes[i].framerate = 10;
1135 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1136 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1137 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1138 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1140 datapointer = startskins;
1141 for (i = 0;i < loadmodel->numskins;i++)
1143 pinskintype = (daliasskintype_t *)datapointer;
1144 datapointer += sizeof(daliasskintype_t);
1146 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1153 pinskingroup = (daliasskingroup_t *)datapointer;
1154 datapointer += sizeof(daliasskingroup_t);
1156 groupskins = LittleLong (pinskingroup->numskins);
1158 pinskinintervals = (daliasskininterval_t *)datapointer;
1159 datapointer += sizeof(daliasskininterval_t) * groupskins;
1161 interval = LittleFloat(pinskinintervals[0].interval);
1162 if (interval < 0.01f)
1164 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1169 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1170 loadmodel->skinscenes[i].firstframe = totalskins;
1171 loadmodel->skinscenes[i].framecount = groupskins;
1172 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1173 loadmodel->skinscenes[i].loop = true;
1175 for (j = 0;j < groupskins;j++)
1178 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1180 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1181 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))
1182 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));
1183 datapointer += skinwidth * skinheight;
1187 // check for skins that don't exist in the model, but do exist as external images
1188 // (this was added because yummyluv kept pestering me about support for it)
1189 // TODO: support shaders here?
1190 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)))
1192 // expand the arrays to make room
1193 tempskinscenes = loadmodel->skinscenes;
1194 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1195 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1196 Mem_Free(tempskinscenes);
1198 tempaliasskins = loadmodel->data_textures;
1199 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1200 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1201 Mem_Free(tempaliasskins);
1203 // store the info about the new skin
1204 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1205 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1206 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1207 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1208 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1209 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1211 //increase skin counts
1212 loadmodel->numskins++;
1215 // fix up the pointers since they are pointing at the old textures array
1216 // FIXME: this is a hack!
1217 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1218 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1222 surface = loadmodel->data_surfaces;
1223 surface->texture = loadmodel->data_textures;
1224 surface->num_firsttriangle = 0;
1225 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1226 surface->num_firstvertex = 0;
1227 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1229 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1230 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_MDL_AnimateVertices : NULL;
1232 if (!loadmodel->surfmesh.isanimated)
1234 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1235 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1236 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1237 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1238 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1239 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1242 // because shaders can do somewhat unexpected things, check for unusual features now
1243 for (i = 0;i < loadmodel->num_textures;i++)
1245 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
1246 mod->DrawSky = R_Q1BSP_DrawSky;
1247 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
1248 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
1252 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1254 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1255 float iskinwidth, iskinheight;
1256 unsigned char *data;
1257 msurface_t *surface;
1259 unsigned char *base, *datapointer;
1260 md2frame_t *pinframe;
1262 md2triangle_t *intri;
1263 unsigned short *inst;
1264 struct md2verthash_s
1266 struct md2verthash_s *next;
1270 *hash, **md2verthash, *md2verthashdata;
1271 skinfile_t *skinfiles;
1273 pinmodel = (md2_t *)buffer;
1274 base = (unsigned char *)buffer;
1276 version = LittleLong (pinmodel->version);
1277 if (version != MD2ALIAS_VERSION)
1278 Host_Error ("%s has wrong version number (%i should be %i)",
1279 loadmodel->name, version, MD2ALIAS_VERSION);
1281 loadmodel->modeldatatypestring = "MD2";
1283 loadmodel->type = mod_alias;
1284 loadmodel->DrawSky = NULL;
1285 loadmodel->DrawAddWaterPlanes = NULL;
1286 loadmodel->Draw = R_Q1BSP_Draw;
1287 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1288 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1289 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1290 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1291 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1292 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1293 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1294 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1295 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1296 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1297 loadmodel->PointSuperContents = NULL;
1299 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1300 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1301 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1302 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1303 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1304 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1305 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1306 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1308 end = LittleLong(pinmodel->ofs_end);
1309 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1310 Host_Error ("%s is not a valid model", loadmodel->name);
1311 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1312 Host_Error ("%s is not a valid model", loadmodel->name);
1313 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1314 Host_Error ("%s is not a valid model", loadmodel->name);
1315 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1316 Host_Error ("%s is not a valid model", loadmodel->name);
1317 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1318 Host_Error ("%s is not a valid model", loadmodel->name);
1320 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1321 numxyz = LittleLong(pinmodel->num_xyz);
1322 numst = LittleLong(pinmodel->num_st);
1323 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1324 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1325 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1326 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1327 skinwidth = LittleLong(pinmodel->skinwidth);
1328 skinheight = LittleLong(pinmodel->skinheight);
1329 iskinwidth = 1.0f / skinwidth;
1330 iskinheight = 1.0f / skinheight;
1332 loadmodel->num_surfaces = 1;
1333 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1334 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));
1335 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1336 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1337 loadmodel->sortedmodelsurfaces[0] = 0;
1338 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1339 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1340 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1341 if (r_enableshadowvolumes.integer)
1343 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1346 loadmodel->synctype = ST_RAND;
1349 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1350 skinfiles = Mod_LoadSkinFiles();
1353 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1354 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1355 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1356 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1357 Mod_FreeSkinFiles(skinfiles);
1359 else if (loadmodel->numskins)
1361 // skins found (most likely not a player model)
1362 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1363 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1364 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1365 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1366 Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
1370 // no skins (most likely a player model)
1371 loadmodel->numskins = 1;
1372 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1373 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1374 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1375 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1378 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1379 for (i = 0;i < loadmodel->numskins;i++)
1381 loadmodel->skinscenes[i].firstframe = i;
1382 loadmodel->skinscenes[i].framecount = 1;
1383 loadmodel->skinscenes[i].loop = true;
1384 loadmodel->skinscenes[i].framerate = 10;
1387 // load the triangles and stvert data
1388 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1389 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1390 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1391 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1392 // swap the triangle list
1393 loadmodel->surfmesh.num_vertices = 0;
1394 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1396 for (j = 0;j < 3;j++)
1398 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1399 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1402 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1407 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1410 hashindex = (xyz * 256 + st) & 65535;
1411 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1412 if (hash->xyz == xyz && hash->st == st)
1416 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1419 hash->next = md2verthash[hashindex];
1420 md2verthash[hashindex] = hash;
1422 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1426 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1427 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));
1428 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1429 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1430 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1433 hash = md2verthashdata + i;
1434 vertremap[i] = hash->xyz;
1435 sts = LittleShort(inst[hash->st*2+0]);
1436 stt = LittleShort(inst[hash->st*2+1]);
1437 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1439 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1443 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1444 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1447 Mem_Free(md2verthash);
1448 Mem_Free(md2verthashdata);
1450 // generate ushort elements array if possible
1451 if (loadmodel->surfmesh.num_vertices <= 65536)
1452 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1453 if (loadmodel->surfmesh.data_element3s)
1454 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1455 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1458 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1459 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1464 pinframe = (md2frame_t *)datapointer;
1465 datapointer += sizeof(md2frame_t);
1466 // store the frame scale/translate into the appropriate array
1467 for (j = 0;j < 3;j++)
1469 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1470 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1472 // convert the vertices
1473 v = (trivertx_t *)datapointer;
1474 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1475 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1476 out[k] = v[vertremap[k]];
1477 datapointer += numxyz * sizeof(trivertx_t);
1479 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1480 loadmodel->animscenes[i].firstframe = i;
1481 loadmodel->animscenes[i].framecount = 1;
1482 loadmodel->animscenes[i].framerate = 10;
1483 loadmodel->animscenes[i].loop = true;
1486 Mem_Free(vertremap);
1488 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1489 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices; // needed during loading, may be cleared by code later in this function
1490 if (loadmodel->surfmesh.data_neighbor3i)
1491 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1492 Mod_Alias_CalculateBoundingBox();
1493 Mod_Alias_MorphMesh_CompileFrames();
1494 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_MDL_AnimateVertices : NULL;
1496 surface = loadmodel->data_surfaces;
1497 surface->texture = loadmodel->data_textures;
1498 surface->num_firsttriangle = 0;
1499 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1500 surface->num_firstvertex = 0;
1501 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1503 if (!loadmodel->surfmesh.isanimated)
1505 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1506 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1507 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1508 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1509 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1510 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1513 // because shaders can do somewhat unexpected things, check for unusual features now
1514 for (i = 0;i < loadmodel->num_textures;i++)
1516 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
1517 mod->DrawSky = R_Q1BSP_DrawSky;
1518 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
1519 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
1523 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1525 int i, j, k, version, meshvertices, meshtriangles;
1526 unsigned char *data;
1527 msurface_t *surface;
1528 md3modelheader_t *pinmodel;
1529 md3frameinfo_t *pinframe;
1532 skinfile_t *skinfiles;
1534 pinmodel = (md3modelheader_t *)buffer;
1536 if (memcmp(pinmodel->identifier, "IDP3", 4))
1537 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1538 version = LittleLong (pinmodel->version);
1539 if (version != MD3VERSION)
1540 Host_Error ("%s has wrong version number (%i should be %i)",
1541 loadmodel->name, version, MD3VERSION);
1543 skinfiles = Mod_LoadSkinFiles();
1544 if (loadmodel->numskins < 1)
1545 loadmodel->numskins = 1;
1547 loadmodel->modeldatatypestring = "MD3";
1549 loadmodel->type = mod_alias;
1550 loadmodel->DrawSky = NULL;
1551 loadmodel->DrawAddWaterPlanes = NULL;
1552 loadmodel->Draw = R_Q1BSP_Draw;
1553 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1554 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1555 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1556 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1557 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1558 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1559 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1560 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1561 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1562 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1563 loadmodel->PointSuperContents = NULL;
1564 loadmodel->synctype = ST_RAND;
1565 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1566 i = LittleLong (pinmodel->flags);
1567 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1569 // set up some global info about the model
1570 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1571 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1573 // make skinscenes for the skins (no groups)
1574 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1575 for (i = 0;i < loadmodel->numskins;i++)
1577 loadmodel->skinscenes[i].firstframe = i;
1578 loadmodel->skinscenes[i].framecount = 1;
1579 loadmodel->skinscenes[i].loop = true;
1580 loadmodel->skinscenes[i].framerate = 10;
1584 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1585 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1587 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1588 loadmodel->animscenes[i].firstframe = i;
1589 loadmodel->animscenes[i].framecount = 1;
1590 loadmodel->animscenes[i].framerate = 10;
1591 loadmodel->animscenes[i].loop = true;
1595 loadmodel->num_tagframes = loadmodel->numframes;
1596 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1597 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1598 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1600 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1601 for (j = 0;j < 9;j++)
1602 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1603 for (j = 0;j < 3;j++)
1604 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1605 //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);
1611 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)))
1613 if (memcmp(pinmesh->identifier, "IDP3", 4))
1614 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1615 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1616 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1617 meshvertices += LittleLong(pinmesh->num_vertices);
1618 meshtriangles += LittleLong(pinmesh->num_triangles);
1621 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1622 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1623 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1624 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));
1625 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1626 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1627 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1628 loadmodel->surfmesh.num_vertices = meshvertices;
1629 loadmodel->surfmesh.num_triangles = meshtriangles;
1630 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1631 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1632 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1633 if (r_enableshadowvolumes.integer)
1635 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1637 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1638 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1639 if (meshvertices <= 65536)
1641 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1646 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)))
1648 if (memcmp(pinmesh->identifier, "IDP3", 4))
1649 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1650 loadmodel->sortedmodelsurfaces[i] = i;
1651 surface = loadmodel->data_surfaces + i;
1652 surface->texture = loadmodel->data_textures + i;
1653 surface->num_firsttriangle = meshtriangles;
1654 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1655 surface->num_firstvertex = meshvertices;
1656 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1657 meshvertices += surface->num_vertices;
1658 meshtriangles += surface->num_triangles;
1660 for (j = 0;j < surface->num_triangles * 3;j++)
1661 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1662 for (j = 0;j < surface->num_vertices;j++)
1664 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1665 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1667 for (j = 0;j < loadmodel->numframes;j++)
1669 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1670 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1671 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1673 out->origin[0] = LittleShort(in->origin[0]);
1674 out->origin[1] = LittleShort(in->origin[1]);
1675 out->origin[2] = LittleShort(in->origin[2]);
1676 out->pitch = in->pitch;
1681 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1683 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1685 if (loadmodel->surfmesh.data_element3s)
1686 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1687 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1688 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1689 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices; // needed during loading, may be cleared by code later in this function
1690 if (loadmodel->surfmesh.data_neighbor3i)
1691 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1692 Mod_Alias_MorphMesh_CompileFrames();
1693 Mod_Alias_CalculateBoundingBox();
1694 Mod_FreeSkinFiles(skinfiles);
1695 Mod_MakeSortedSurfaces(loadmodel);
1696 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_MD3_AnimateVertices : NULL;
1698 if (!loadmodel->surfmesh.isanimated)
1700 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1701 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1702 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1703 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1704 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1705 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1708 // because shaders can do somewhat unexpected things, check for unusual features now
1709 for (i = 0;i < loadmodel->num_textures;i++)
1711 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
1712 mod->DrawSky = R_Q1BSP_DrawSky;
1713 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
1714 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
1718 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1720 zymtype1header_t *pinmodel, *pheader;
1721 unsigned char *pbase;
1722 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1723 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose, f, biggestorigin, tempvec[3], modelscale;
1724 zymvertex_t *verts, *vertdata;
1728 skinfile_t *skinfiles;
1729 unsigned char *data;
1730 msurface_t *surface;
1732 pinmodel = (zymtype1header_t *)buffer;
1733 pbase = (unsigned char *)buffer;
1734 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1735 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1736 if (BigLong(pinmodel->type) != 1)
1737 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1739 loadmodel->modeldatatypestring = "ZYM";
1741 loadmodel->type = mod_alias;
1742 loadmodel->synctype = ST_RAND;
1746 pheader->type = BigLong(pinmodel->type);
1747 pheader->filesize = BigLong(pinmodel->filesize);
1748 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1749 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1750 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1751 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1752 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1753 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1754 pheader->radius = BigFloat(pinmodel->radius);
1755 pheader->numverts = BigLong(pinmodel->numverts);
1756 pheader->numtris = BigLong(pinmodel->numtris);
1757 pheader->numshaders = BigLong(pinmodel->numshaders);
1758 pheader->numbones = BigLong(pinmodel->numbones);
1759 pheader->numscenes = BigLong(pinmodel->numscenes);
1760 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1761 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1762 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1763 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1764 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1765 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1766 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1767 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1768 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1769 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1770 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1771 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1772 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1773 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1774 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1775 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1776 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1777 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1779 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1781 Con_Printf("%s has no geometry\n", loadmodel->name);
1784 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1786 Con_Printf("%s has no animations\n", loadmodel->name);
1790 loadmodel->DrawSky = NULL;
1791 loadmodel->DrawAddWaterPlanes = NULL;
1792 loadmodel->Draw = R_Q1BSP_Draw;
1793 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1794 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1795 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1796 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1797 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1798 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1799 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1800 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1801 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1802 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1803 loadmodel->PointSuperContents = NULL;
1805 loadmodel->numframes = pheader->numscenes;
1806 loadmodel->num_surfaces = pheader->numshaders;
1808 skinfiles = Mod_LoadSkinFiles();
1809 if (loadmodel->numskins < 1)
1810 loadmodel->numskins = 1;
1812 // make skinscenes for the skins (no groups)
1813 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1814 for (i = 0;i < loadmodel->numskins;i++)
1816 loadmodel->skinscenes[i].firstframe = i;
1817 loadmodel->skinscenes[i].framecount = 1;
1818 loadmodel->skinscenes[i].loop = true;
1819 loadmodel->skinscenes[i].framerate = 10;
1823 modelradius = pheader->radius;
1824 for (i = 0;i < 3;i++)
1826 loadmodel->normalmins[i] = pheader->mins[i];
1827 loadmodel->normalmaxs[i] = pheader->maxs[i];
1828 loadmodel->rotatedmins[i] = -modelradius;
1829 loadmodel->rotatedmaxs[i] = modelradius;
1831 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1832 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1833 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1834 if (loadmodel->yawmaxs[0] > modelradius)
1835 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1836 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1837 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1838 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1839 loadmodel->radius = modelradius;
1840 loadmodel->radius2 = modelradius * modelradius;
1842 // go through the lumps, swapping things
1844 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1845 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1846 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1847 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1848 for (i = 0;i < pheader->numscenes;i++)
1850 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1851 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1852 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1853 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1854 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1855 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1856 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1857 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1858 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1859 if (loadmodel->animscenes[i].framerate < 0)
1860 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1864 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1865 loadmodel->num_bones = pheader->numbones;
1866 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1867 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1868 for (i = 0;i < pheader->numbones;i++)
1870 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1871 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1872 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1873 if (loadmodel->data_bones[i].parent >= i)
1874 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1877 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1878 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1879 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1880 for (i = 0;i < pheader->numverts;i++)
1882 vertbonecounts[i] = BigLong(bonecount[i]);
1883 if (vertbonecounts[i] != 1)
1884 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1887 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1889 meshvertices = pheader->numverts;
1890 meshtriangles = pheader->numtris;
1892 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1893 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
1894 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1895 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1896 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1897 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]));
1898 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1899 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1900 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1901 loadmodel->surfmesh.num_vertices = meshvertices;
1902 loadmodel->surfmesh.num_triangles = meshtriangles;
1903 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1904 if (r_enableshadowvolumes.integer)
1906 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1908 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1909 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1910 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1911 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1912 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1913 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1914 loadmodel->surfmesh.num_blends = 0;
1915 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
1916 if (loadmodel->surfmesh.num_vertices <= 65536)
1918 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1920 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
1921 loadmodel->surfmesh.data_blendweights = NULL;
1923 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1924 poses = (float *) (pheader->lump_poses.start + pbase);
1925 // figure out scale of model from root bone, for compatibility with old zmodel versions
1926 tempvec[0] = BigFloat(poses[0]);
1927 tempvec[1] = BigFloat(poses[1]);
1928 tempvec[2] = BigFloat(poses[2]);
1929 modelscale = VectorLength(tempvec);
1931 for (i = 0;i < loadmodel->num_bones * numposes * 12;i++)
1933 f = fabs(BigFloat(poses[i]));
1934 biggestorigin = max(biggestorigin, f);
1936 loadmodel->num_posescale = biggestorigin / 32767.0f;
1937 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
1938 for (i = 0;i < numposes;i++)
1940 const float *frameposes = (float *) (pheader->lump_poses.start + pbase) + 12*i*loadmodel->num_bones;
1941 for (j = 0;j < loadmodel->num_bones;j++)
1944 matrix4x4_t posematrix;
1945 for (k = 0;k < 12;k++)
1946 pose[k] = BigFloat(frameposes[j*12+k]);
1947 //if (j < loadmodel->num_bones)
1948 // 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));
1949 // scale child bones to match the root scale
1950 if (loadmodel->data_bones[j].parent >= 0)
1952 pose[3] *= modelscale;
1953 pose[7] *= modelscale;
1954 pose[11] *= modelscale;
1956 // normalize rotation matrix
1957 VectorNormalize(pose + 0);
1958 VectorNormalize(pose + 4);
1959 VectorNormalize(pose + 8);
1960 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
1961 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
1965 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1966 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1967 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1968 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1969 // (converting from weight-blending skeletal animation to
1970 // deformation-based skeletal animation)
1971 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1972 for (i = 0;i < loadmodel->num_bones;i++)
1975 for (k = 0;k < 12;k++)
1976 m[k] = BigFloat(poses[i*12+k]);
1977 if (loadmodel->data_bones[i].parent >= 0)
1978 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1980 for (k = 0;k < 12;k++)
1981 bonepose[12*i+k] = m[k];
1983 for (j = 0;j < pheader->numverts;j++)
1985 // this format really should have had a per vertexweight weight value...
1986 // but since it does not, the weighting is completely ignored and
1987 // only one weight is allowed per vertex
1988 int boneindex = BigLong(vertdata[j].bonenum);
1989 const float *m = bonepose + 12 * boneindex;
1990 float relativeorigin[3];
1991 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1992 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1993 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1994 // transform the vertex bone weight into the base mesh
1995 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1996 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1997 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1998 // store the weight as the primary weight on this vertex
1999 loadmodel->surfmesh.blends[j] = boneindex;
2002 // normals and tangents are calculated after elements are loaded
2004 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
2005 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
2006 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
2007 for (i = 0;i < pheader->numverts;i++)
2009 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
2010 // flip T coordinate for OpenGL
2011 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
2014 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
2015 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
2016 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
2018 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
2019 //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)
2020 // byteswap, validate, and swap winding order of tris
2021 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
2022 if (pheader->lump_render.length != count)
2023 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
2024 renderlist = (int *) (pheader->lump_render.start + pbase);
2025 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
2027 for (i = 0;i < loadmodel->num_surfaces;i++)
2029 int firstvertex, lastvertex;
2030 if (renderlist >= renderlistend)
2031 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2032 count = BigLong(*renderlist);renderlist++;
2033 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
2034 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2036 loadmodel->sortedmodelsurfaces[i] = i;
2037 surface = loadmodel->data_surfaces + i;
2038 surface->texture = loadmodel->data_textures + i;
2039 surface->num_firsttriangle = meshtriangles;
2040 surface->num_triangles = count;
2041 meshtriangles += surface->num_triangles;
2043 // load the elements
2044 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2045 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
2047 outelements[j*3+2] = BigLong(renderlist[0]);
2048 outelements[j*3+1] = BigLong(renderlist[1]);
2049 outelements[j*3+0] = BigLong(renderlist[2]);
2051 // validate the elements and find the used vertex range
2052 firstvertex = meshvertices;
2054 for (j = 0;j < surface->num_triangles * 3;j++)
2056 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
2057 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
2058 firstvertex = min(firstvertex, outelements[j]);
2059 lastvertex = max(lastvertex, outelements[j]);
2061 surface->num_firstvertex = firstvertex;
2062 surface->num_vertices = lastvertex + 1 - firstvertex;
2064 // since zym models do not have named sections, reuse their shader
2065 // name as the section name
2066 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
2067 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
2069 Mod_FreeSkinFiles(skinfiles);
2070 Mem_Free(vertbonecounts);
2072 Mod_MakeSortedSurfaces(loadmodel);
2074 // compute all the mesh information that was not loaded from the file
2075 if (loadmodel->surfmesh.data_element3s)
2076 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2077 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2078 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2079 Mod_BuildBaseBonePoses();
2080 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);
2081 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);
2082 if (loadmodel->surfmesh.data_neighbor3i)
2083 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2085 if (!loadmodel->surfmesh.isanimated)
2087 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2088 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2089 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2090 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2091 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2092 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2095 // because shaders can do somewhat unexpected things, check for unusual features now
2096 for (i = 0;i < loadmodel->num_textures;i++)
2098 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
2099 mod->DrawSky = R_Q1BSP_DrawSky;
2100 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
2101 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
2105 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2107 dpmheader_t *pheader;
2111 unsigned char *pbase;
2112 int i, j, k, meshvertices, meshtriangles;
2113 skinfile_t *skinfiles;
2114 unsigned char *data;
2116 float biggestorigin, tempvec[3], modelscale;
2120 pheader = (dpmheader_t *)buffer;
2121 pbase = (unsigned char *)buffer;
2122 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2123 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2124 if (BigLong(pheader->type) != 2)
2125 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2127 loadmodel->modeldatatypestring = "DPM";
2129 loadmodel->type = mod_alias;
2130 loadmodel->synctype = ST_RAND;
2133 pheader->type = BigLong(pheader->type);
2134 pheader->filesize = BigLong(pheader->filesize);
2135 pheader->mins[0] = BigFloat(pheader->mins[0]);
2136 pheader->mins[1] = BigFloat(pheader->mins[1]);
2137 pheader->mins[2] = BigFloat(pheader->mins[2]);
2138 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2139 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2140 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2141 pheader->yawradius = BigFloat(pheader->yawradius);
2142 pheader->allradius = BigFloat(pheader->allradius);
2143 pheader->num_bones = BigLong(pheader->num_bones);
2144 pheader->num_meshs = BigLong(pheader->num_meshs);
2145 pheader->num_frames = BigLong(pheader->num_frames);
2146 pheader->ofs_bones = BigLong(pheader->ofs_bones);
2147 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2148 pheader->ofs_frames = BigLong(pheader->ofs_frames);
2150 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2152 Con_Printf("%s has no geometry\n", loadmodel->name);
2155 if (pheader->num_frames < 1)
2157 Con_Printf("%s has no frames\n", loadmodel->name);
2161 loadmodel->DrawSky = NULL;
2162 loadmodel->DrawAddWaterPlanes = NULL;
2163 loadmodel->Draw = R_Q1BSP_Draw;
2164 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2165 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2166 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2167 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2168 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2169 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2170 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2171 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2172 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2173 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2174 loadmodel->PointSuperContents = NULL;
2177 for (i = 0;i < 3;i++)
2179 loadmodel->normalmins[i] = pheader->mins[i];
2180 loadmodel->normalmaxs[i] = pheader->maxs[i];
2181 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2182 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2183 loadmodel->rotatedmins[i] = -pheader->allradius;
2184 loadmodel->rotatedmaxs[i] = pheader->allradius;
2186 loadmodel->radius = pheader->allradius;
2187 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2189 // load external .skin files if present
2190 skinfiles = Mod_LoadSkinFiles();
2191 if (loadmodel->numskins < 1)
2192 loadmodel->numskins = 1;
2197 // gather combined statistics from the meshes
2198 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2199 for (i = 0;i < (int)pheader->num_meshs;i++)
2201 int numverts = BigLong(dpmmesh->num_verts);
2202 meshvertices += numverts;
2203 meshtriangles += BigLong(dpmmesh->num_tris);
2207 loadmodel->numframes = pheader->num_frames;
2208 loadmodel->num_bones = pheader->num_bones;
2209 loadmodel->num_poses = loadmodel->numframes;
2210 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2211 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2212 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2213 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2214 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
2215 // do most allocations as one merged chunk
2216 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));
2217 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2218 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2219 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2220 loadmodel->surfmesh.num_vertices = meshvertices;
2221 loadmodel->surfmesh.num_triangles = meshtriangles;
2222 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2223 if (r_enableshadowvolumes.integer)
2225 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2227 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2228 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2229 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2230 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2231 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2232 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2233 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2234 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2235 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2236 loadmodel->surfmesh.num_blends = 0;
2237 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2238 if (meshvertices <= 65536)
2240 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2242 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2243 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
2245 for (i = 0;i < loadmodel->numskins;i++)
2247 loadmodel->skinscenes[i].firstframe = i;
2248 loadmodel->skinscenes[i].framecount = 1;
2249 loadmodel->skinscenes[i].loop = true;
2250 loadmodel->skinscenes[i].framerate = 10;
2253 // load the bone info
2254 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2255 for (i = 0;i < loadmodel->num_bones;i++)
2257 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2258 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2259 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2260 if (loadmodel->data_bones[i].parent >= i)
2261 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2265 frames = (dpmframe_t *) (pbase + pheader->ofs_frames);
2266 // figure out scale of model from root bone, for compatibility with old dpmodel versions
2267 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2268 tempvec[0] = BigFloat(poses[0]);
2269 tempvec[1] = BigFloat(poses[1]);
2270 tempvec[2] = BigFloat(poses[2]);
2271 modelscale = VectorLength(tempvec);
2273 for (i = 0;i < loadmodel->numframes;i++)
2275 memcpy(loadmodel->animscenes[i].name, frames[i].name, sizeof(frames[i].name));
2276 loadmodel->animscenes[i].firstframe = i;
2277 loadmodel->animscenes[i].framecount = 1;
2278 loadmodel->animscenes[i].loop = true;
2279 loadmodel->animscenes[i].framerate = 10;
2280 // load the bone poses for this frame
2281 poses = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2282 for (j = 0;j < loadmodel->num_bones*12;j++)
2284 f = fabs(BigFloat(poses[j]));
2285 biggestorigin = max(biggestorigin, f);
2287 // stuff not processed here: mins, maxs, yawradius, allradius
2289 loadmodel->num_posescale = biggestorigin / 32767.0f;
2290 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2291 for (i = 0;i < loadmodel->numframes;i++)
2293 const float *frameposes = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2294 for (j = 0;j < loadmodel->num_bones;j++)
2297 matrix4x4_t posematrix;
2298 for (k = 0;k < 12;k++)
2299 pose[k] = BigFloat(frameposes[j*12+k]);
2300 // scale child bones to match the root scale
2301 if (loadmodel->data_bones[j].parent >= 0)
2303 pose[3] *= modelscale;
2304 pose[7] *= modelscale;
2305 pose[11] *= modelscale;
2307 // normalize rotation matrix
2308 VectorNormalize(pose + 0);
2309 VectorNormalize(pose + 4);
2310 VectorNormalize(pose + 8);
2311 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2312 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
2316 // load the meshes now
2317 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2320 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2321 // (converting from weight-blending skeletal animation to
2322 // deformation-based skeletal animation)
2323 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2324 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2325 for (i = 0;i < loadmodel->num_bones;i++)
2328 for (k = 0;k < 12;k++)
2329 m[k] = BigFloat(poses[i*12+k]);
2330 if (loadmodel->data_bones[i].parent >= 0)
2331 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2333 for (k = 0;k < 12;k++)
2334 bonepose[12*i+k] = m[k];
2336 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2338 const int *inelements;
2340 const float *intexcoord;
2341 msurface_t *surface;
2343 loadmodel->sortedmodelsurfaces[i] = i;
2344 surface = loadmodel->data_surfaces + i;
2345 surface->texture = loadmodel->data_textures + i;
2346 surface->num_firsttriangle = meshtriangles;
2347 surface->num_triangles = BigLong(dpmmesh->num_tris);
2348 surface->num_firstvertex = meshvertices;
2349 surface->num_vertices = BigLong(dpmmesh->num_verts);
2350 meshvertices += surface->num_vertices;
2351 meshtriangles += surface->num_triangles;
2353 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2354 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2355 for (j = 0;j < surface->num_triangles;j++)
2357 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2358 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2359 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2360 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2365 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2366 for (j = 0;j < surface->num_vertices*2;j++)
2367 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2369 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2370 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2372 int weightindex[4] = { 0, 0, 0, 0 };
2373 float weightinfluence[4] = { 0, 0, 0, 0 };
2375 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2376 data += sizeof(dpmvertex_t);
2377 for (k = 0;k < numweights;k++)
2379 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2380 int boneindex = BigLong(vert->bonenum);
2381 const float *m = bonepose + 12 * boneindex;
2382 float influence = BigFloat(vert->influence);
2383 float relativeorigin[3], relativenormal[3];
2384 relativeorigin[0] = BigFloat(vert->origin[0]);
2385 relativeorigin[1] = BigFloat(vert->origin[1]);
2386 relativeorigin[2] = BigFloat(vert->origin[2]);
2387 relativenormal[0] = BigFloat(vert->normal[0]);
2388 relativenormal[1] = BigFloat(vert->normal[1]);
2389 relativenormal[2] = BigFloat(vert->normal[2]);
2390 // blend the vertex bone weights into the base mesh
2391 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2392 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2393 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2394 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2395 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2396 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2399 // store the first (and often only) weight
2400 weightinfluence[0] = influence;
2401 weightindex[0] = boneindex;
2405 // sort the new weight into this vertex's weight table
2406 // (which only accepts up to 4 bones per vertex)
2407 for (l = 0;l < 4;l++)
2409 if (weightinfluence[l] < influence)
2411 // move weaker influence weights out of the way first
2413 for (l2 = 3;l2 > l;l2--)
2415 weightinfluence[l2] = weightinfluence[l2-1];
2416 weightindex[l2] = weightindex[l2-1];
2418 // store the new weight
2419 weightinfluence[l] = influence;
2420 weightindex[l] = boneindex;
2425 data += sizeof(dpmbonevert_t);
2427 loadmodel->surfmesh.blends[j] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
2430 // since dpm models do not have named sections, reuse their shader name as the section name
2431 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2433 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2435 if (loadmodel->surfmesh.num_blends < meshvertices)
2436 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2438 Mod_FreeSkinFiles(skinfiles);
2439 Mod_MakeSortedSurfaces(loadmodel);
2441 // compute all the mesh information that was not loaded from the file
2442 if (loadmodel->surfmesh.data_element3s)
2443 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2444 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2445 Mod_BuildBaseBonePoses();
2446 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);
2447 if (loadmodel->surfmesh.data_neighbor3i)
2448 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2450 if (!loadmodel->surfmesh.isanimated)
2452 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2453 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2454 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2455 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2456 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2457 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2460 // because shaders can do somewhat unexpected things, check for unusual features now
2461 for (i = 0;i < loadmodel->num_textures;i++)
2463 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
2464 mod->DrawSky = R_Q1BSP_DrawSky;
2465 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
2466 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
2470 // no idea why PSK/PSA files contain weird quaternions but they do...
2471 #define PSKQUATNEGATIONS
2472 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2474 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2475 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2476 fs_offset_t filesize;
2481 pskboneinfo_t *bones;
2482 pskrawweights_t *rawweights;
2483 //pskboneinfo_t *animbones;
2484 pskaniminfo_t *anims;
2485 pskanimkeys_t *animkeys;
2486 void *animfilebuffer, *animbuffer, *animbufferend;
2487 unsigned char *data;
2489 skinfile_t *skinfiles;
2490 char animname[MAX_QPATH];
2492 float biggestorigin;
2494 pchunk = (pskchunk_t *)buffer;
2495 if (strcmp(pchunk->id, "ACTRHEAD"))
2496 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2498 loadmodel->modeldatatypestring = "PSK";
2500 loadmodel->type = mod_alias;
2501 loadmodel->DrawSky = NULL;
2502 loadmodel->DrawAddWaterPlanes = NULL;
2503 loadmodel->Draw = R_Q1BSP_Draw;
2504 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2505 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2506 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2507 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2508 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2509 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2510 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2511 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2512 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2513 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2514 loadmodel->PointSuperContents = NULL;
2515 loadmodel->synctype = ST_RAND;
2517 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2518 strlcat(animname, ".psa", sizeof(animname));
2519 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2520 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2521 if (animbuffer == NULL)
2522 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2541 while (buffer < bufferend)
2543 pchunk = (pskchunk_t *)buffer;
2544 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2545 version = LittleLong(pchunk->version);
2546 recordsize = LittleLong(pchunk->recordsize);
2547 numrecords = LittleLong(pchunk->numrecords);
2548 if (developer_extra.integer)
2549 Con_DPrintf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2550 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2551 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);
2552 if (!strcmp(pchunk->id, "ACTRHEAD"))
2556 else if (!strcmp(pchunk->id, "PNTS0000"))
2559 if (recordsize != sizeof(*p))
2560 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2561 // byteswap in place and keep the pointer
2562 numpnts = numrecords;
2563 pnts = (pskpnts_t *)buffer;
2564 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2566 p->origin[0] = LittleFloat(p->origin[0]);
2567 p->origin[1] = LittleFloat(p->origin[1]);
2568 p->origin[2] = LittleFloat(p->origin[2]);
2572 else if (!strcmp(pchunk->id, "VTXW0000"))
2575 if (recordsize != sizeof(*p))
2576 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2577 // byteswap in place and keep the pointer
2578 numvtxw = numrecords;
2579 vtxw = (pskvtxw_t *)buffer;
2580 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2582 p->pntsindex = LittleShort(p->pntsindex);
2583 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2584 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2585 if (p->pntsindex >= numpnts)
2587 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2593 else if (!strcmp(pchunk->id, "FACE0000"))
2596 if (recordsize != sizeof(*p))
2597 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2598 // byteswap in place and keep the pointer
2599 numfaces = numrecords;
2600 faces = (pskface_t *)buffer;
2601 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2603 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2604 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2605 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2606 p->group = LittleLong(p->group);
2607 if (p->vtxwindex[0] >= numvtxw)
2609 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2610 p->vtxwindex[0] = 0;
2612 if (p->vtxwindex[1] >= numvtxw)
2614 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2615 p->vtxwindex[1] = 0;
2617 if (p->vtxwindex[2] >= numvtxw)
2619 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2620 p->vtxwindex[2] = 0;
2625 else if (!strcmp(pchunk->id, "MATT0000"))
2628 if (recordsize != sizeof(*p))
2629 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2630 // byteswap in place and keep the pointer
2631 nummatts = numrecords;
2632 matts = (pskmatt_t *)buffer;
2633 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2639 else if (!strcmp(pchunk->id, "REFSKELT"))
2642 if (recordsize != sizeof(*p))
2643 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2644 // byteswap in place and keep the pointer
2645 numbones = numrecords;
2646 bones = (pskboneinfo_t *)buffer;
2647 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2649 p->numchildren = LittleLong(p->numchildren);
2650 p->parent = LittleLong(p->parent);
2651 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2652 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2653 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2654 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2655 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2656 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2657 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2658 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2659 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2660 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2661 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2662 #ifdef PSKQUATNEGATIONS
2665 p->basepose.quat[0] *= -1;
2666 p->basepose.quat[1] *= -1;
2667 p->basepose.quat[2] *= -1;
2671 p->basepose.quat[0] *= 1;
2672 p->basepose.quat[1] *= -1;
2673 p->basepose.quat[2] *= 1;
2676 if (p->parent < 0 || p->parent >= numbones)
2678 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2684 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2687 if (recordsize != sizeof(*p))
2688 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2689 // byteswap in place and keep the pointer
2690 numrawweights = numrecords;
2691 rawweights = (pskrawweights_t *)buffer;
2692 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2694 p->weight = LittleFloat(p->weight);
2695 p->pntsindex = LittleLong(p->pntsindex);
2696 p->boneindex = LittleLong(p->boneindex);
2697 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2699 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2702 if (p->boneindex < 0 || p->boneindex >= numbones)
2704 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2712 while (animbuffer < animbufferend)
2714 pchunk = (pskchunk_t *)animbuffer;
2715 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2716 version = LittleLong(pchunk->version);
2717 recordsize = LittleLong(pchunk->recordsize);
2718 numrecords = LittleLong(pchunk->numrecords);
2719 if (developer_extra.integer)
2720 Con_DPrintf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2721 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2722 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);
2723 if (!strcmp(pchunk->id, "ANIMHEAD"))
2727 else if (!strcmp(pchunk->id, "BONENAMES"))
2730 if (recordsize != sizeof(*p))
2731 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2732 // byteswap in place and keep the pointer
2733 numanimbones = numrecords;
2734 //animbones = (pskboneinfo_t *)animbuffer;
2735 // NOTE: supposedly psa does not need to match the psk model, the
2736 // bones missing from the psa would simply use their base
2737 // positions from the psk, but this is hard for me to implement
2738 // and people can easily make animations that match.
2739 if (numanimbones != numbones)
2740 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2741 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2743 p->numchildren = LittleLong(p->numchildren);
2744 p->parent = LittleLong(p->parent);
2745 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2746 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2747 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2748 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2749 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2750 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2751 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2752 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2753 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2754 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2755 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2756 #ifdef PSKQUATNEGATIONS
2759 p->basepose.quat[0] *= -1;
2760 p->basepose.quat[1] *= -1;
2761 p->basepose.quat[2] *= -1;
2765 p->basepose.quat[0] *= 1;
2766 p->basepose.quat[1] *= -1;
2767 p->basepose.quat[2] *= 1;
2770 if (p->parent < 0 || p->parent >= numanimbones)
2772 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2775 // check that bones are the same as in the base
2776 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2777 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2781 else if (!strcmp(pchunk->id, "ANIMINFO"))
2784 if (recordsize != sizeof(*p))
2785 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2786 // byteswap in place and keep the pointer
2787 numanims = numrecords;
2788 anims = (pskaniminfo_t *)animbuffer;
2789 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2791 p->numbones = LittleLong(p->numbones);
2792 p->playtime = LittleFloat(p->playtime);
2793 p->fps = LittleFloat(p->fps);
2794 p->firstframe = LittleLong(p->firstframe);
2795 p->numframes = LittleLong(p->numframes);
2796 if (p->numbones != numbones)
2797 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2801 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2804 if (recordsize != sizeof(*p))
2805 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2806 numanimkeys = numrecords;
2807 animkeys = (pskanimkeys_t *)animbuffer;
2808 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2810 p->origin[0] = LittleFloat(p->origin[0]);
2811 p->origin[1] = LittleFloat(p->origin[1]);
2812 p->origin[2] = LittleFloat(p->origin[2]);
2813 p->quat[0] = LittleFloat(p->quat[0]);
2814 p->quat[1] = LittleFloat(p->quat[1]);
2815 p->quat[2] = LittleFloat(p->quat[2]);
2816 p->quat[3] = LittleFloat(p->quat[3]);
2817 p->frametime = LittleFloat(p->frametime);
2818 #ifdef PSKQUATNEGATIONS
2819 if (index % numbones)
2834 // TODO: allocate bonepose stuff
2837 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2840 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2841 Host_Error("%s: missing required chunks", loadmodel->name);
2843 loadmodel->numframes = 0;
2844 for (index = 0;index < numanims;index++)
2845 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);
2850 meshvertices = numvtxw;
2851 meshtriangles = numfaces;
2853 // load external .skin files if present
2854 skinfiles = Mod_LoadSkinFiles();
2855 if (loadmodel->numskins < 1)
2856 loadmodel->numskins = 1;
2857 loadmodel->num_bones = numbones;
2858 loadmodel->num_poses = loadmodel->numframes;
2859 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2860 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2861 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2862 loadmodel->surfmesh.num_vertices = meshvertices;
2863 loadmodel->surfmesh.num_triangles = meshtriangles;
2864 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2865 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
2866 // do most allocations as one merged chunk
2867 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);
2868 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2869 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2870 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2871 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2872 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2873 if (r_enableshadowvolumes.integer)
2875 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2877 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2878 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2879 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2880 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2881 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2882 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2883 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2884 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2885 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2886 loadmodel->surfmesh.num_blends = 0;
2887 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2888 if (loadmodel->surfmesh.num_vertices <= 65536)
2890 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2892 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2893 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(blendweights_t));
2895 for (i = 0;i < loadmodel->numskins;i++)
2897 loadmodel->skinscenes[i].firstframe = i;
2898 loadmodel->skinscenes[i].framecount = 1;
2899 loadmodel->skinscenes[i].loop = true;
2900 loadmodel->skinscenes[i].framerate = 10;
2904 for (index = 0, i = 0;index < nummatts;index++)
2906 // since psk models do not have named sections, reuse their shader name as the section name
2907 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2908 loadmodel->sortedmodelsurfaces[index] = index;
2909 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2910 loadmodel->data_surfaces[index].num_firstvertex = 0;
2911 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2914 // copy over the vertex locations and texcoords
2915 for (index = 0;index < numvtxw;index++)
2917 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2918 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2919 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2920 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2921 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2924 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2925 for (index = 0;index < numfaces;index++)
2926 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2927 for (index = 0, i = 0;index < nummatts;index++)
2929 loadmodel->data_surfaces[index].num_firsttriangle = i;
2930 i += loadmodel->data_surfaces[index].num_triangles;
2931 loadmodel->data_surfaces[index].num_triangles = 0;
2933 for (index = 0;index < numfaces;index++)
2935 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2936 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2937 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2938 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2941 // copy over the bones
2942 for (index = 0;index < numbones;index++)
2944 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2945 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2946 if (loadmodel->data_bones[index].parent >= index)
2947 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2950 // sort the psk point weights into the vertex weight tables
2951 // (which only accept up to 4 bones per vertex)
2952 for (index = 0;index < numvtxw;index++)
2954 int weightindex[4] = { 0, 0, 0, 0 };
2955 float weightinfluence[4] = { 0, 0, 0, 0 };
2957 for (j = 0;j < numrawweights;j++)
2959 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2961 int boneindex = rawweights[j].boneindex;
2962 float influence = rawweights[j].weight;
2963 for (l = 0;l < 4;l++)
2965 if (weightinfluence[l] < influence)
2967 // move lower influence weights out of the way first
2969 for (l2 = 3;l2 > l;l2--)
2971 weightinfluence[l2] = weightinfluence[l2-1];
2972 weightindex[l2] = weightindex[l2-1];
2974 // store the new weight
2975 weightinfluence[l] = influence;
2976 weightindex[l] = boneindex;
2982 loadmodel->surfmesh.blends[index] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
2984 if (loadmodel->surfmesh.num_blends < loadmodel->surfmesh.num_vertices)
2985 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2987 // set up the animscenes based on the anims
2988 for (index = 0, i = 0;index < numanims;index++)
2990 for (j = 0;j < anims[index].numframes;j++, i++)
2992 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2993 loadmodel->animscenes[i].firstframe = i;
2994 loadmodel->animscenes[i].framecount = 1;
2995 loadmodel->animscenes[i].loop = true;
2996 loadmodel->animscenes[i].framerate = anims[index].fps;
3000 // calculate the scaling value for bone origins so they can be compressed to short
3002 for (index = 0;index < numanimkeys;index++)
3004 pskanimkeys_t *k = animkeys + index;
3005 biggestorigin = max(biggestorigin, fabs(k->origin[0]));
3006 biggestorigin = max(biggestorigin, fabs(k->origin[1]));
3007 biggestorigin = max(biggestorigin, fabs(k->origin[2]));
3009 loadmodel->num_posescale = biggestorigin / 32767.0f;
3010 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3012 // load the poses from the animkeys
3013 for (index = 0;index < numanimkeys;index++)
3015 pskanimkeys_t *k = animkeys + index;
3017 Vector4Copy(k->quat, quat);
3019 Vector4Negate(quat, quat);
3020 Vector4Normalize2(quat, quat);
3021 // compress poses to the short[6] format for longterm storage
3022 loadmodel->data_poses6s[index*6+0] = k->origin[0] * loadmodel->num_poseinvscale;
3023 loadmodel->data_poses6s[index*6+1] = k->origin[1] * loadmodel->num_poseinvscale;
3024 loadmodel->data_poses6s[index*6+2] = k->origin[2] * loadmodel->num_poseinvscale;
3025 loadmodel->data_poses6s[index*6+3] = quat[0] * 32767.0f;
3026 loadmodel->data_poses6s[index*6+4] = quat[1] * 32767.0f;
3027 loadmodel->data_poses6s[index*6+5] = quat[2] * 32767.0f;
3029 Mod_FreeSkinFiles(skinfiles);
3030 Mem_Free(animfilebuffer);
3031 Mod_MakeSortedSurfaces(loadmodel);
3033 // compute all the mesh information that was not loaded from the file
3034 // TODO: honor smoothing groups somehow?
3035 if (loadmodel->surfmesh.data_element3s)
3036 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3037 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3038 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
3039 Mod_BuildBaseBonePoses();
3040 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);
3041 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);
3042 if (loadmodel->surfmesh.data_neighbor3i)
3043 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3044 Mod_Alias_CalculateBoundingBox();
3046 if (!loadmodel->surfmesh.isanimated)
3048 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3049 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3050 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3051 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3052 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3053 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
3056 // because shaders can do somewhat unexpected things, check for unusual features now
3057 for (i = 0;i < loadmodel->num_textures;i++)
3059 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
3060 mod->DrawSky = R_Q1BSP_DrawSky;
3061 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
3062 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
3066 void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
3068 unsigned char *data;
3070 const unsigned char *pbase, *pend;
3072 skinfile_t *skinfiles;
3073 int i, j, k, meshvertices, meshtriangles;
3074 float biggestorigin;
3075 const unsigned int *inelements;
3077 const int *inneighbors;
3079 float *outvertex, *outnormal, *outtexcoord, *outsvector, *outtvector, *outcolor;
3080 // this pointers into the file data are read only through Little* functions so they can be unaligned memory
3081 const float *vnormal = NULL;
3082 const float *vposition = NULL;
3083 const float *vtangent = NULL;
3084 const float *vtexcoord = NULL;
3085 const float *vcolor4f = NULL;
3086 const unsigned char *vblendindexes = NULL;
3087 const unsigned char *vblendweights = NULL;
3088 const unsigned char *vcolor4ub = NULL;
3089 const unsigned short *framedata = NULL;
3090 // temporary memory allocations (because the data in the file may be misaligned)
3091 iqmanim_t *anims = NULL;
3092 iqmbounds_t *bounds = NULL;
3093 iqmjoint1_t *joint1 = NULL;
3094 iqmjoint_t *joint = NULL;
3095 iqmmesh_t *meshes = NULL;
3096 iqmpose1_t *pose1 = NULL;
3097 iqmpose_t *pose = NULL;
3098 iqmvertexarray_t *vas = NULL;
3100 pbase = (unsigned char *)buffer;
3101 pend = (unsigned char *)bufferend;
3103 if (pbase + sizeof(iqmheader_t) > pend)
3104 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model %d", loadmodel->name, (int)(pend - pbase));
3106 // copy struct (otherwise it may be misaligned)
3107 // LordHavoc: okay it's definitely not misaligned here, but for consistency...
3108 memcpy(&header, pbase, sizeof(iqmheader_t));
3110 if (memcmp(header.id, "INTERQUAKEMODEL", 16))
3111 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model", loadmodel->name);
3112 if (LittleLong(header.version) != 1 && LittleLong(header.version) != 2)
3113 Host_Error ("Mod_INTERQUAKEMODEL_Load: only version 1 and 2 models are currently supported (name = %s)", loadmodel->name);
3115 loadmodel->modeldatatypestring = "IQM";
3117 loadmodel->type = mod_alias;
3118 loadmodel->synctype = ST_RAND;
3121 header.version = LittleLong(header.version);
3122 header.filesize = LittleLong(header.filesize);
3123 header.flags = LittleLong(header.flags);
3124 header.num_text = LittleLong(header.num_text);
3125 header.ofs_text = LittleLong(header.ofs_text);
3126 header.num_meshes = LittleLong(header.num_meshes);
3127 header.ofs_meshes = LittleLong(header.ofs_meshes);
3128 header.num_vertexarrays = LittleLong(header.num_vertexarrays);
3129 header.num_vertexes = LittleLong(header.num_vertexes);
3130 header.ofs_vertexarrays = LittleLong(header.ofs_vertexarrays);
3131 header.num_triangles = LittleLong(header.num_triangles);
3132 header.ofs_triangles = LittleLong(header.ofs_triangles);
3133 header.ofs_neighbors = LittleLong(header.ofs_neighbors);
3134 header.num_joints = LittleLong(header.num_joints);
3135 header.ofs_joints = LittleLong(header.ofs_joints);
3136 header.num_poses = LittleLong(header.num_poses);
3137 header.ofs_poses = LittleLong(header.ofs_poses);
3138 header.num_anims = LittleLong(header.num_anims);
3139 header.ofs_anims = LittleLong(header.ofs_anims);
3140 header.num_frames = LittleLong(header.num_frames);
3141 header.num_framechannels = LittleLong(header.num_framechannels);
3142 header.ofs_frames = LittleLong(header.ofs_frames);
3143 header.ofs_bounds = LittleLong(header.ofs_bounds);
3144 header.num_comment = LittleLong(header.num_comment);
3145 header.ofs_comment = LittleLong(header.ofs_comment);
3146 header.num_extensions = LittleLong(header.num_extensions);
3147 header.ofs_extensions = LittleLong(header.ofs_extensions);
3149 if (header.version == 1)
3151 if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint1_t) > pend ||
3152 pbase + header.ofs_poses + header.num_poses*sizeof(iqmpose1_t) > pend)
3154 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3160 if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint_t) > pend ||
3161 pbase + header.ofs_poses + header.num_poses*sizeof(iqmpose_t) > pend)
3163 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3167 if (pbase + header.ofs_text + header.num_text > pend ||
3168 pbase + header.ofs_meshes + header.num_meshes*sizeof(iqmmesh_t) > pend ||
3169 pbase + header.ofs_vertexarrays + header.num_vertexarrays*sizeof(iqmvertexarray_t) > pend ||
3170 pbase + header.ofs_triangles + header.num_triangles*sizeof(int[3]) > pend ||
3171 (header.ofs_neighbors && pbase + header.ofs_neighbors + header.num_triangles*sizeof(int[3]) > pend) ||
3172 pbase + header.ofs_anims + header.num_anims*sizeof(iqmanim_t) > pend ||
3173 pbase + header.ofs_frames + header.num_frames*header.num_framechannels*sizeof(unsigned short) > pend ||
3174 (header.ofs_bounds && pbase + header.ofs_bounds + header.num_frames*sizeof(iqmbounds_t) > pend) ||
3175 pbase + header.ofs_comment + header.num_comment > pend)
3177 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3181 // copy structs to make them aligned in memory (otherwise we crash on Sparc and PowerPC and others)
3182 if (header.num_vertexarrays)
3183 vas = (iqmvertexarray_t *)(pbase + header.ofs_vertexarrays);
3184 if (header.num_anims)
3185 anims = (iqmanim_t *)(pbase + header.ofs_anims);
3186 if (header.ofs_bounds)
3187 bounds = (iqmbounds_t *)(pbase + header.ofs_bounds);
3188 if (header.num_meshes)
3189 meshes = (iqmmesh_t *)(pbase + header.ofs_meshes);
3191 for (i = 0;i < (int)header.num_vertexarrays;i++)
3193 iqmvertexarray_t va;
3195 va.type = LittleLong(vas[i].type);
3196 va.flags = LittleLong(vas[i].flags);
3197 va.format = LittleLong(vas[i].format);
3198 va.size = LittleLong(vas[i].size);
3199 va.offset = LittleLong(vas[i].offset);
3200 vsize = header.num_vertexes*va.size;
3203 case IQM_FLOAT: vsize *= sizeof(float); break;
3204 case IQM_UBYTE: vsize *= sizeof(unsigned char); break;
3207 if (pbase + va.offset + vsize > pend)
3209 // no need to copy the vertex data for alignment because LittleLong/LittleShort will be invoked on reading them, and the destination is aligned
3213 if (va.format == IQM_FLOAT && va.size == 3)
3214 vposition = (const float *)(pbase + va.offset);
3217 if (va.format == IQM_FLOAT && va.size == 2)
3218 vtexcoord = (const float *)(pbase + va.offset);
3221 if (va.format == IQM_FLOAT && va.size == 3)
3222 vnormal = (const float *)(pbase + va.offset);
3225 if (va.format == IQM_FLOAT && va.size == 4)
3226 vtangent = (const float *)(pbase + va.offset);
3228 case IQM_BLENDINDEXES:
3229 if (va.format == IQM_UBYTE && va.size == 4)
3230 vblendindexes = (const unsigned char *)(pbase + va.offset);
3232 case IQM_BLENDWEIGHTS:
3233 if (va.format == IQM_UBYTE && va.size == 4)
3234 vblendweights = (const unsigned char *)(pbase + va.offset);
3237 if (va.format == IQM_FLOAT && va.size == 4)
3238 vcolor4f = (const float *)(pbase + va.offset);
3239 if (va.format == IQM_UBYTE && va.size == 4)
3240 vcolor4ub = (const unsigned char *)(pbase + va.offset);
3244 if (header.num_vertexes > 0 && (!vposition || !vtexcoord || ((header.num_frames > 0 || header.num_anims > 0) && (!vblendindexes || !vblendweights))))
3246 Con_Printf("%s is missing vertex array data\n", loadmodel->name);
3250 text = header.num_text && header.ofs_text ? (const char *)(pbase + header.ofs_text) : "";
3252 loadmodel->DrawSky = NULL;
3253 loadmodel->DrawAddWaterPlanes = NULL;
3254 loadmodel->Draw = R_Q1BSP_Draw;
3255 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
3256 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
3257 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
3258 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
3259 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
3260 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
3261 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
3262 loadmodel->DrawLight = R_Q1BSP_DrawLight;
3263 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
3264 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
3265 loadmodel->PointSuperContents = NULL;
3267 // load external .skin files if present
3268 skinfiles = Mod_LoadSkinFiles();
3269 if (loadmodel->numskins < 1)
3270 loadmodel->numskins = 1;
3272 loadmodel->numframes = max(header.num_anims, 1);
3273 loadmodel->num_bones = header.num_joints;
3274 loadmodel->num_poses = max(header.num_frames, 1);
3275 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = header.num_meshes;
3276 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3277 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3278 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices; // updated later
3280 meshvertices = header.num_vertexes;
3281 meshtriangles = header.num_triangles;
3283 // do most allocations as one merged chunk
3284 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));
3285 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
3286 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
3287 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
3288 loadmodel->surfmesh.num_vertices = meshvertices;
3289 loadmodel->surfmesh.num_triangles = meshtriangles;
3290 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3291 if (r_enableshadowvolumes.integer)
3293 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3295 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
3296 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3297 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3298 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
3299 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
3300 if (vcolor4f || vcolor4ub)
3302 loadmodel->surfmesh.data_lightmapcolor4f = (float *)data;data += meshvertices * sizeof(float[4]);
3304 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
3305 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
3306 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
3307 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
3308 if (vblendindexes && vblendweights)
3310 loadmodel->surfmesh.num_blends = 0;
3311 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
3313 if (meshvertices <= 65536)
3315 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
3317 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
3318 if (vblendindexes && vblendweights)
3319 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
3321 for (i = 0;i < loadmodel->numskins;i++)
3323 loadmodel->skinscenes[i].firstframe = i;
3324 loadmodel->skinscenes[i].framecount = 1;
3325 loadmodel->skinscenes[i].loop = true;
3326 loadmodel->skinscenes[i].framerate = 10;
3329 // load the bone info
3330 if (header.version == 1)
3332 iqmjoint1_t *injoint1 = (iqmjoint1_t *)(pbase + header.ofs_joints);
3333 if (loadmodel->num_bones)
3334 joint1 = (iqmjoint1_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(iqmjoint1_t));
3335 for (i = 0;i < loadmodel->num_bones;i++)
3337 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3338 joint1[i].name = LittleLong(injoint1[i].name);
3339 joint1[i].parent = LittleLong(injoint1[i].parent);
3340 for (j = 0;j < 3;j++)
3342 joint1[i].origin[j] = LittleFloat(injoint1[i].origin[j]);
3343 joint1[i].rotation[j] = LittleFloat(injoint1[i].rotation[j]);
3344 joint1[i].scale[j] = LittleFloat(injoint1[i].scale[j]);
3346 strlcpy(loadmodel->data_bones[i].name, &text[joint1[i].name], sizeof(loadmodel->data_bones[i].name));
3347 loadmodel->data_bones[i].parent = joint1[i].parent;
3348 if (loadmodel->data_bones[i].parent >= i)
3349 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3350 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]);
3351 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3352 if (loadmodel->data_bones[i].parent >= 0)
3354 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3355 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3356 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3358 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3363 iqmjoint_t *injoint = (iqmjoint_t *)(pbase + header.ofs_joints);
3364 if (header.num_joints)
3365 joint = (iqmjoint_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(iqmjoint_t));
3366 for (i = 0;i < loadmodel->num_bones;i++)
3368 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3369 joint[i].name = LittleLong(injoint[i].name);
3370 joint[i].parent = LittleLong(injoint[i].parent);
3371 for (j = 0;j < 3;j++)
3373 joint[i].origin[j] = LittleFloat(injoint[i].origin[j]);
3374 joint[i].rotation[j] = LittleFloat(injoint[i].rotation[j]);
3375 joint[i].scale[j] = LittleFloat(injoint[i].scale[j]);
3377 joint[i].rotation[3] = LittleFloat(injoint[i].rotation[3]);
3378 strlcpy(loadmodel->data_bones[i].name, &text[joint[i].name], sizeof(loadmodel->data_bones[i].name));
3379 loadmodel->data_bones[i].parent = joint[i].parent;
3380 if (loadmodel->data_bones[i].parent >= i)
3381 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3382 if (joint[i].rotation[3] > 0)
3383 Vector4Negate(joint[i].rotation, joint[i].rotation);
3384 Vector4Normalize2(joint[i].rotation, joint[i].rotation);
3385 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]);
3386 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3387 if (loadmodel->data_bones[i].parent >= 0)
3389 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3390 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3391 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3393 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3397 // set up the animscenes based on the anims
3398 for (i = 0;i < (int)header.num_anims;i++)
3401 anim.name = LittleLong(anims[i].name);
3402 anim.first_frame = LittleLong(anims[i].first_frame);
3403 anim.num_frames = LittleLong(anims[i].num_frames);
3404 anim.framerate = LittleFloat(anims[i].framerate);
3405 anim.flags = LittleLong(anims[i].flags);
3406 strlcpy(loadmodel->animscenes[i].name, &text[anim.name], sizeof(loadmodel->animscenes[i].name));
3407 loadmodel->animscenes[i].firstframe = anim.first_frame;
3408 loadmodel->animscenes[i].framecount = anim.num_frames;
3409 loadmodel->animscenes[i].loop = ((anim.flags & IQM_LOOP) != 0);
3410 loadmodel->animscenes[i].framerate = anim.framerate;
3412 if (header.num_anims <= 0)
3414 strlcpy(loadmodel->animscenes[0].name, "static", sizeof(loadmodel->animscenes[0].name));
3415 loadmodel->animscenes[0].firstframe = 0;
3416 loadmodel->animscenes[0].framecount = 1;
3417 loadmodel->animscenes[0].loop = true;
3418 loadmodel->animscenes[0].framerate = 10;
3421 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
3422 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
3425 if (header.version == 1)
3427 iqmpose1_t *inpose1 = (iqmpose1_t *)(pbase + header.ofs_poses);
3428 if (header.num_poses)
3429 pose1 = (iqmpose1_t *)Mem_Alloc(loadmodel->mempool, header.num_poses * sizeof(iqmpose1_t));
3430 for (i = 0;i < (int)header.num_poses;i++)
3433 pose1[i].parent = LittleLong(inpose1[i].parent);
3434 pose1[i].channelmask = LittleLong(inpose1[i].channelmask);
3435 for (j = 0;j < 9;j++)
3437 pose1[i].channeloffset[j] = LittleFloat(inpose1[i].channeloffset[j]);
3438 pose1[i].channelscale[j] = LittleFloat(inpose1[i].channelscale[j]);
3440 f = fabs(pose1[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3441 f = fabs(pose1[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3442 f = fabs(pose1[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3443 f = fabs(pose1[i].channeloffset[0] + 0xFFFF*pose1[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3444 f = fabs(pose1[i].channeloffset[1] + 0xFFFF*pose1[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3445 f = fabs(pose1[i].channeloffset[2] + 0xFFFF*pose1[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3447 if (header.num_frames <= 0)
3449 for (i = 0;i < loadmodel->num_bones;i++)
3452 f = fabs(joint1[i].origin[0]); biggestorigin = max(biggestorigin, f);
3453 f = fabs(joint1[i].origin[1]); biggestorigin = max(biggestorigin, f);
3454 f = fabs(joint1[i].origin[2]); biggestorigin = max(biggestorigin, f);
3460 iqmpose_t *inpose = (iqmpose_t *)(pbase + header.ofs_poses);
3461 if (header.num_poses)
3462 pose = (iqmpose_t *)Mem_Alloc(loadmodel->mempool, header.num_poses * sizeof(iqmpose_t));
3463 for (i = 0;i < (int)header.num_poses;i++)
3466 pose[i].parent = LittleLong(inpose[i].parent);
3467 pose[i].channelmask = LittleLong(inpose[i].channelmask);
3468 for (j = 0;j < 10;j++)
3470 pose[i].channeloffset[j] = LittleFloat(inpose[i].channeloffset[j]);
3471 pose[i].channelscale[j] = LittleFloat(inpose[i].channelscale[j]);
3473 f = fabs(pose[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3474 f = fabs(pose[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3475 f = fabs(pose[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3476 f = fabs(pose[i].channeloffset[0] + 0xFFFF*pose[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3477 f = fabs(pose[i].channeloffset[1] + 0xFFFF*pose[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3478 f = fabs(pose[i].channeloffset[2] + 0xFFFF*pose[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3480 if (header.num_frames <= 0)
3482 for (i = 0;i < loadmodel->num_bones;i++)
3485 f = fabs(joint[i].origin[0]); biggestorigin = max(biggestorigin, f);
3486 f = fabs(joint[i].origin[1]); biggestorigin = max(biggestorigin, f);
3487 f = fabs(joint[i].origin[2]); biggestorigin = max(biggestorigin, f);
3491 loadmodel->num_posescale = biggestorigin / 32767.0f;
3492 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3494 // load the pose data
3495 // this unaligned memory access is safe (LittleShort reads as bytes)
3496 framedata = (const unsigned short *)(pbase + header.ofs_frames);
3497 if (header.version == 1)
3499 for (i = 0, k = 0;i < (int)header.num_frames;i++)
3501 for (j = 0;j < (int)header.num_poses;j++, k++)
3503 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));
3504 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));
3505 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));
3506 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));
3507 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));
3508 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));
3509 // skip scale data for now
3510 if(pose1[j].channelmask&64) framedata++;
3511 if(pose1[j].channelmask&128) framedata++;
3512 if(pose1[j].channelmask&256) framedata++;
3515 if (header.num_frames <= 0)
3517 for (i = 0;i < loadmodel->num_bones;i++)
3519 loadmodel->data_poses6s[i*6 + 0] = loadmodel->num_poseinvscale * joint1[i].origin[0];
3520 loadmodel->data_poses6s[i*6 + 1] = loadmodel->num_poseinvscale * joint1[i].origin[1];
3521 loadmodel->data_poses6s[i*6 + 2] = loadmodel->num_poseinvscale * joint1[i].origin[2];
3522 loadmodel->data_poses6s[i*6 + 3] = 32767.0f * joint1[i].rotation[0];
3523 loadmodel->data_poses6s[i*6 + 4] = 32767.0f * joint1[i].rotation[1];
3524 loadmodel->data_poses6s[i*6 + 5] = 32767.0f * joint1[i].rotation[2];
3530 for (i = 0, k = 0;i < (int)header.num_frames;i++)
3532 for (j = 0;j < (int)header.num_poses;j++, k++)
3535 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));
3536 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));
3537 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));
3538 rot[0] = pose[j].channeloffset[3] + (pose[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[3] : 0);
3539 rot[1] = pose[j].channeloffset[4] + (pose[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[4] : 0);
3540 rot[2] = pose[j].channeloffset[5] + (pose[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[5] : 0);
3541 rot[3] = pose[j].channeloffset[6] + (pose[j].channelmask&64 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[6] : 0);
3543 Vector4Negate(rot, rot);
3544 Vector4Normalize2(rot, rot);
3545 loadmodel->data_poses6s[k*6 + 3] = 32767.0f * rot[0];
3546 loadmodel->data_poses6s[k*6 + 4] = 32767.0f * rot[1];
3547 loadmodel->data_poses6s[k*6 + 5] = 32767.0f * rot[2];
3548 // skip scale data for now
3549 if(pose[j].channelmask&128) framedata++;
3550 if(pose[j].channelmask&256) framedata++;
3551 if(pose[j].channelmask&512) framedata++;
3554 if (header.num_frames <= 0)
3556 for (i = 0;i < loadmodel->num_bones;i++)
3558 loadmodel->data_poses6s[i*6 + 0] = loadmodel->num_poseinvscale * joint[i].origin[0];
3559 loadmodel->data_poses6s[i*6 + 1] = loadmodel->num_poseinvscale * joint[i].origin[1];
3560 loadmodel->data_poses6s[i*6 + 2] = loadmodel->num_poseinvscale * joint[i].origin[2];
3561 loadmodel->data_poses6s[i*6 + 3] = 32767.0f * joint[i].rotation[0];
3562 loadmodel->data_poses6s[i*6 + 4] = 32767.0f * joint[i].rotation[1];
3563 loadmodel->data_poses6s[i*6 + 5] = 32767.0f * joint[i].rotation[2];
3568 // load bounding box data
3569 if (header.ofs_bounds)
3571 float xyradius = 0, radius = 0;
3572 VectorClear(loadmodel->normalmins);
3573 VectorClear(loadmodel->normalmaxs);
3574 for (i = 0; i < (int)header.num_frames;i++)
3577 bound.mins[0] = LittleFloat(bounds[i].mins[0]);
3578 bound.mins[1] = LittleFloat(bounds[i].mins[1]);
3579 bound.mins[2] = LittleFloat(bounds[i].mins[2]);
3580 bound.maxs[0] = LittleFloat(bounds[i].maxs[0]);
3581 bound.maxs[1] = LittleFloat(bounds[i].maxs[1]);
3582 bound.maxs[2] = LittleFloat(bounds[i].maxs[2]);
3583 bound.xyradius = LittleFloat(bounds[i].xyradius);
3584 bound.radius = LittleFloat(bounds[i].radius);
3587 VectorCopy(bound.mins, loadmodel->normalmins);
3588 VectorCopy(bound.maxs, loadmodel->normalmaxs);
3592 if (loadmodel->normalmins[0] > bound.mins[0]) loadmodel->normalmins[0] = bound.mins[0];
3593 if (loadmodel->normalmins[1] > bound.mins[1]) loadmodel->normalmins[1] = bound.mins[1];
3594 if (loadmodel->normalmins[2] > bound.mins[2]) loadmodel->normalmins[2] = bound.mins[2];
3595 if (loadmodel->normalmaxs[0] < bound.maxs[0]) loadmodel->normalmaxs[0] = bound.maxs[0];
3596 if (loadmodel->normalmaxs[1] < bound.maxs[1]) loadmodel->normalmaxs[1] = bound.maxs[1];
3597 if (loadmodel->normalmaxs[2] < bound.maxs[2]) loadmodel->normalmaxs[2] = bound.maxs[2];
3599 if (bound.xyradius > xyradius)
3600 xyradius = bound.xyradius;
3601 if (bound.radius > radius)
3602 radius = bound.radius;
3604 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -xyradius;
3605 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = xyradius;
3606 loadmodel->yawmins[2] = loadmodel->normalmins[2];
3607 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
3608 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
3609 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
3610 loadmodel->radius = radius;
3611 loadmodel->radius2 = radius * radius;
3614 // load triangle data
3615 // this unaligned memory access is safe (LittleLong reads as bytes)
3616 inelements = (const unsigned int *)(pbase + header.ofs_triangles);
3617 outelements = loadmodel->surfmesh.data_element3i;
3618 for (i = 0;i < (int)header.num_triangles;i++)
3620 outelements[0] = LittleLong(inelements[0]);
3621 outelements[1] = LittleLong(inelements[1]);
3622 outelements[2] = LittleLong(inelements[2]);
3626 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, header.num_vertexes, __FILE__, __LINE__);
3628 if (header.ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
3630 // this unaligned memory access is safe (LittleLong reads as bytes)
3631 inneighbors = (const int *)(pbase + header.ofs_neighbors);
3632 outneighbors = loadmodel->surfmesh.data_neighbor3i;
3633 for (i = 0;i < (int)header.num_triangles;i++)
3635 outneighbors[0] = LittleLong(inneighbors[0]);
3636 outneighbors[1] = LittleLong(inneighbors[1]);
3637 outneighbors[2] = LittleLong(inneighbors[2]);
3644 // this unaligned memory access is safe (LittleFloat reads as bytes)
3645 outvertex = loadmodel->surfmesh.data_vertex3f;
3646 for (i = 0;i < (int)header.num_vertexes;i++)
3648 outvertex[0] = LittleFloat(vposition[0]);
3649 outvertex[1] = LittleFloat(vposition[1]);
3650 outvertex[2] = LittleFloat(vposition[2]);
3655 outtexcoord = loadmodel->surfmesh.data_texcoordtexture2f;
3656 // this unaligned memory access is safe (LittleFloat reads as bytes)
3657 for (i = 0;i < (int)header.num_vertexes;i++)
3659 outtexcoord[0] = LittleFloat(vtexcoord[0]);
3660 outtexcoord[1] = LittleFloat(vtexcoord[1]);
3665 // this unaligned memory access is safe (LittleFloat reads as bytes)
3668 outnormal = loadmodel->surfmesh.data_normal3f;
3669 for (i = 0;i < (int)header.num_vertexes;i++)
3671 outnormal[0] = LittleFloat(vnormal[0]);
3672 outnormal[1] = LittleFloat(vnormal[1]);
3673 outnormal[2] = LittleFloat(vnormal[2]);
3679 // this unaligned memory access is safe (LittleFloat reads as bytes)
3680 if(vnormal && vtangent)
3682 outnormal = loadmodel->surfmesh.data_normal3f;
3683 outsvector = loadmodel->surfmesh.data_svector3f;
3684 outtvector = loadmodel->surfmesh.data_tvector3f;
3685 for (i = 0;i < (int)header.num_vertexes;i++)
3687 outsvector[0] = LittleFloat(vtangent[0]);
3688 outsvector[1] = LittleFloat(vtangent[1]);
3689 outsvector[2] = LittleFloat(vtangent[2]);
3690 if(LittleFloat(vtangent[3]) < 0)
3691 CrossProduct(outsvector, outnormal, outtvector);
3693 CrossProduct(outnormal, outsvector, outtvector);
3701 // this unaligned memory access is safe (all bytes)
3702 if (vblendindexes && vblendweights)
3704 for (i = 0; i < (int)header.num_vertexes;i++)
3706 blendweights_t weights;
3707 memcpy(weights.index, vblendindexes + i*4, 4);
3708 memcpy(weights.influence, vblendweights + i*4, 4);
3709 loadmodel->surfmesh.blends[i] = Mod_Skeletal_AddBlend(loadmodel, &weights);
3715 outcolor = loadmodel->surfmesh.data_lightmapcolor4f;
3716 // this unaligned memory access is safe (LittleFloat reads as bytes)
3717 for (i = 0;i < (int)header.num_vertexes;i++)
3719 outcolor[0] = LittleFloat(vcolor4f[0]);
3720 outcolor[1] = LittleFloat(vcolor4f[1]);
3721 outcolor[2] = LittleFloat(vcolor4f[2]);
3722 outcolor[3] = LittleFloat(vcolor4f[3]);
3729 outcolor = loadmodel->surfmesh.data_lightmapcolor4f;
3730 // this unaligned memory access is safe (all bytes)
3731 for (i = 0;i < (int)header.num_vertexes;i++)
3733 outcolor[0] = vcolor4ub[0] * (1.0f / 128.0f);
3734 outcolor[1] = vcolor4ub[1] * (1.0f / 128.0f);
3735 outcolor[2] = vcolor4ub[2] * (1.0f / 128.0f);
3736 outcolor[3] = vcolor4ub[3] * (1.0f / 128.0f);
3743 for (i = 0;i < (int)header.num_meshes;i++)
3746 msurface_t *surface;
3748 mesh.name = LittleLong(meshes[i].name);
3749 mesh.material = LittleLong(meshes[i].material);
3750 mesh.first_vertex = LittleLong(meshes[i].first_vertex);
3751 mesh.num_vertexes = LittleLong(meshes[i].num_vertexes);
3752 mesh.first_triangle = LittleLong(meshes[i].first_triangle);
3753 mesh.num_triangles = LittleLong(meshes[i].num_triangles);
3755 loadmodel->sortedmodelsurfaces[i] = i;
3756 surface = loadmodel->data_surfaces + i;
3757 surface->texture = loadmodel->data_textures + i;
3758 surface->num_firsttriangle = mesh.first_triangle;
3759 surface->num_triangles = mesh.num_triangles;
3760 surface->num_firstvertex = mesh.first_vertex;
3761 surface->num_vertices = mesh.num_vertexes;
3763 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, &text[mesh.name], &text[mesh.material]);
3766 Mod_FreeSkinFiles(skinfiles);
3767 Mod_MakeSortedSurfaces(loadmodel);
3769 // compute all the mesh information that was not loaded from the file
3770 if (loadmodel->surfmesh.data_element3s)
3771 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3772 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3774 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);
3775 if (!vnormal || !vtangent)
3776 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);
3777 if (!header.ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
3778 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3779 if (!header.ofs_bounds)
3780 Mod_Alias_CalculateBoundingBox();
3782 if (!loadmodel->surfmesh.isanimated && loadmodel->surfmesh.num_triangles >= 1)
3784 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3785 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3786 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3787 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3788 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3789 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
3792 if (joint ) Mem_Free(joint );joint = NULL;
3793 if (joint1 ) Mem_Free(joint1 );joint1 = NULL;
3794 if (pose ) Mem_Free(pose );pose = NULL;
3795 if (pose1 ) Mem_Free(pose1 );pose1 = NULL;
3797 // because shaders can do somewhat unexpected things, check for unusual features now
3798 for (i = 0;i < loadmodel->num_textures;i++)
3800 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
3801 mod->DrawSky = R_Q1BSP_DrawSky;
3802 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
3803 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;