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_Skeltal_AnimateVertices_maxbonepose = 0;
44 static void *Mod_Skeltal_AnimateVertices_bonepose = NULL;
45 void Mod_Skeletal_FreeBuffers(void)
47 if(Mod_Skeltal_AnimateVertices_bonepose)
48 Mem_Free(Mod_Skeltal_AnimateVertices_bonepose);
49 Mod_Skeltal_AnimateVertices_maxbonepose = 0;
50 Mod_Skeltal_AnimateVertices_bonepose = NULL;
52 void *Mod_Skeletal_AnimateVertices_AllocBuffers(size_t nbytes)
54 if(Mod_Skeltal_AnimateVertices_maxbonepose < nbytes)
56 Mem_Free(Mod_Skeltal_AnimateVertices_bonepose);
57 Mod_Skeltal_AnimateVertices_bonepose = Z_Malloc(nbytes);
58 Mod_Skeltal_AnimateVertices_maxbonepose = nbytes;
60 return Mod_Skeltal_AnimateVertices_bonepose;
63 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)
66 if(r_skeletal_use_sse_defined)
67 if(r_skeletal_use_sse.integer)
69 Mod_Skeletal_AnimateVertices_SSE(model, frameblend, skeleton, vertex3f, normal3f, svector3f, tvector3f);
73 Mod_Skeletal_AnimateVertices_Generic(model, frameblend, skeleton, vertex3f, normal3f, svector3f, tvector3f);
78 // code from SDL, shortened as we can expect CPUID to work
79 static int CPUID_Features(void)
82 # if defined(__GNUC__) && defined(__i386__)
85 " xorl %%eax,%%eax \n"
87 " cpuid # Get family/model/stepping/features\n"
92 : "%eax", "%ecx", "%edx", "%edi"
94 # elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
98 cpuid ; Get family/model/stepping/features
102 # error SSE_POSSIBLE set but no CPUID implementation
107 static qboolean Have_SSE(void)
109 // COMMANDLINEOPTION: SSE: -nosse disables SSE support and detection
110 if(COM_CheckParm("-nosse"))
112 // COMMANDLINEOPTION: SSE: -forcesse enables SSE support and disables detection
116 if(COM_CheckParm("-forcesse"))
118 if(CPUID_Features() & (1 << 25))
125 void Mod_AliasInit (void)
128 Cvar_RegisterVariable(&r_skeletal_debugbone);
129 Cvar_RegisterVariable(&r_skeletal_debugbonecomponent);
130 Cvar_RegisterVariable(&r_skeletal_debugbonevalue);
131 Cvar_RegisterVariable(&r_skeletal_debugtranslatex);
132 Cvar_RegisterVariable(&r_skeletal_debugtranslatey);
133 Cvar_RegisterVariable(&r_skeletal_debugtranslatez);
134 Cvar_RegisterVariable(&mod_alias_supporttagscale);
135 for (i = 0;i < 320;i++)
136 mod_md3_sin[i] = sin(i * M_PI * 2.0f / 256.0);
141 Con_Printf("Skeletal animation uses SSE code path\n");
142 r_skeletal_use_sse_defined = true;
143 Cvar_RegisterVariable(&r_skeletal_use_sse);
146 Con_Printf("Skeletal animation uses generic code path (SSE disabled or not detected)\n");
149 Con_Printf("Skeletal animation uses generic code path (SSE not compiled in)\n");
153 int Mod_Skeletal_AddBlend(dp_model_t *model, const blendweights_t *newweights)
156 blendweights_t *weights;
157 if(!newweights->influence[1])
158 return newweights->index[0];
159 weights = model->surfmesh.data_blendweights;
160 for (i = 0;i < model->surfmesh.num_blends;i++, weights++)
162 if (!memcmp(weights, newweights, sizeof(blendweights_t)))
163 return model->num_bones + i;
165 model->surfmesh.num_blends++;
166 memcpy(weights, newweights, sizeof(blendweights_t));
167 return model->num_bones + i;
170 int Mod_Skeletal_CompressBlend(dp_model_t *model, const int *newindex, const float *newinfluence)
174 blendweights_t newweights;
178 for (i = 0;i < 4;i++)
179 scale += newinfluence[i];
180 scale = 255.0f / scale;
182 for (i = 0;i < 4;i++)
184 newweights.index[i] = newindex[i];
185 newweights.influence[i] = (unsigned char)(newinfluence[i] * scale);
186 total += newweights.influence[i];
190 for (i = 0;i < 4;i++)
192 if(newweights.influence[i] > 0 && total > 255)
194 newweights.influence[i]--;
201 for (i = 0; i < 4;i++)
203 if(newweights.influence[i] < 255 && total < 255)
205 newweights.influence[i]++;
210 return Mod_Skeletal_AddBlend(model, &newweights);
213 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)
216 int i, numblends, blendnum;
217 int numverts = model->surfmesh.num_vertices;
219 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
221 //VectorMA(translate, model->surfmesh.num_morphmdlframetranslate, frameblend[blendnum].lerp, translate);
222 if (frameblend[blendnum].lerp > 0)
223 numblends = blendnum + 1;
225 // special case for the first blend because it avoids some adds and the need to memset the arrays first
226 for (blendnum = 0;blendnum < numblends;blendnum++)
228 const md3vertex_t *verts = model->surfmesh.data_morphmd3vertex + numverts * frameblend[blendnum].subframe;
231 float scale = frameblend[blendnum].lerp * (1.0f / 64.0f);
234 for (i = 0;i < numverts;i++)
236 vertex3f[i * 3 + 0] = verts[i].origin[0] * scale;
237 vertex3f[i * 3 + 1] = verts[i].origin[1] * scale;
238 vertex3f[i * 3 + 2] = verts[i].origin[2] * scale;
243 for (i = 0;i < numverts;i++)
245 vertex3f[i * 3 + 0] += verts[i].origin[0] * scale;
246 vertex3f[i * 3 + 1] += verts[i].origin[1] * scale;
247 vertex3f[i * 3 + 2] += verts[i].origin[2] * scale;
251 // the yaw and pitch stored in md3 models are 8bit quantized angles
252 // (0-255), and as such a lookup table is very well suited to
253 // decoding them, and since cosine is equivilant to sine with an
254 // extra 45 degree rotation, this uses one lookup table for both
255 // sine and cosine with a +64 bias to get cosine.
258 float lerp = frameblend[blendnum].lerp;
261 for (i = 0;i < numverts;i++)
263 normal3f[i * 3 + 0] = mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
264 normal3f[i * 3 + 1] = mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
265 normal3f[i * 3 + 2] = mod_md3_sin[verts[i].pitch + 64] * lerp;
270 for (i = 0;i < numverts;i++)
272 normal3f[i * 3 + 0] += mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
273 normal3f[i * 3 + 1] += mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
274 normal3f[i * 3 + 2] += mod_md3_sin[verts[i].pitch + 64] * lerp;
280 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
281 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
284 for (i = 0;i < numverts;i++, texvecvert++)
286 VectorScale(texvecvert->svec, f, svector3f + i*3);
287 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
292 for (i = 0;i < numverts;i++, texvecvert++)
294 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
295 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
301 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)
304 int i, numblends, blendnum;
305 int numverts = model->surfmesh.num_vertices;
307 VectorClear(translate);
309 // blend the frame translates to avoid redundantly doing so on each vertex
310 // (a bit of a brain twister but it works)
311 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
313 if (model->surfmesh.data_morphmd2framesize6f)
314 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6 + 3, translate);
316 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.num_morphmdlframetranslate, translate);
317 if (frameblend[blendnum].lerp > 0)
318 numblends = blendnum + 1;
320 // special case for the first blend because it avoids some adds and the need to memset the arrays first
321 for (blendnum = 0;blendnum < numblends;blendnum++)
323 const trivertx_t *verts = model->surfmesh.data_morphmdlvertex + numverts * frameblend[blendnum].subframe;
327 if (model->surfmesh.data_morphmd2framesize6f)
328 VectorScale(model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6, frameblend[blendnum].lerp, scale);
330 VectorScale(model->surfmesh.num_morphmdlframescale, frameblend[blendnum].lerp, scale);
333 for (i = 0;i < numverts;i++)
335 vertex3f[i * 3 + 0] = translate[0] + verts[i].v[0] * scale[0];
336 vertex3f[i * 3 + 1] = translate[1] + verts[i].v[1] * scale[1];
337 vertex3f[i * 3 + 2] = translate[2] + verts[i].v[2] * scale[2];
342 for (i = 0;i < numverts;i++)
344 vertex3f[i * 3 + 0] += verts[i].v[0] * scale[0];
345 vertex3f[i * 3 + 1] += verts[i].v[1] * scale[1];
346 vertex3f[i * 3 + 2] += verts[i].v[2] * scale[2];
350 // the vertex normals in mdl models are an index into a table of
351 // 162 unique values, this very crude quantization reduces the
352 // vertex normal to only one byte, which saves a lot of space but
353 // also makes lighting pretty coarse
356 float lerp = frameblend[blendnum].lerp;
359 for (i = 0;i < numverts;i++)
361 const float *vn = m_bytenormals[verts[i].lightnormalindex];
362 VectorScale(vn, lerp, normal3f + i*3);
367 for (i = 0;i < numverts;i++)
369 const float *vn = m_bytenormals[verts[i].lightnormalindex];
370 VectorMA(normal3f + i*3, lerp, vn, normal3f + i*3);
376 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
377 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
380 for (i = 0;i < numverts;i++, texvecvert++)
382 VectorScale(texvecvert->svec, f, svector3f + i*3);
383 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
388 for (i = 0;i < numverts;i++, texvecvert++)
390 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
391 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
398 int Mod_Alias_GetTagMatrix(const dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, int tagindex, matrix4x4_t *outmatrix)
401 matrix4x4_t parentbonematrix;
402 matrix4x4_t tempbonematrix;
403 matrix4x4_t bonematrix;
404 matrix4x4_t blendmatrix;
411 *outmatrix = identitymatrix;
412 if (skeleton && skeleton->relativetransforms)
414 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
416 *outmatrix = skeleton->relativetransforms[tagindex];
417 while ((tagindex = model->data_bones[tagindex].parent) >= 0)
420 Matrix4x4_Concat(outmatrix, &skeleton->relativetransforms[tagindex], &temp);
423 else if (model->num_bones)
425 if (tagindex < 0 || tagindex >= model->num_bones)
427 Matrix4x4_Clear(&blendmatrix);
428 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
430 lerp = frameblend[blendindex].lerp;
431 Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
432 parenttagindex = tagindex;
433 while ((parenttagindex = model->data_bones[parenttagindex].parent) >= 0)
435 Matrix4x4_FromBonePose6s(&parentbonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + parenttagindex));
436 tempbonematrix = bonematrix;
437 Matrix4x4_Concat(&bonematrix, &parentbonematrix, &tempbonematrix);
439 Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
441 *outmatrix = blendmatrix;
443 else if (model->num_tags)
445 if (tagindex < 0 || tagindex >= model->num_tags)
447 for (k = 0;k < 12;k++)
449 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
451 lerp = frameblend[blendindex].lerp;
452 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
453 for (k = 0;k < 12;k++)
454 blendtag[k] += input[k] * lerp;
456 Matrix4x4_FromArray12FloatGL(outmatrix, blendtag);
459 if(!mod_alias_supporttagscale.integer)
460 Matrix4x4_Normalize3(outmatrix, outmatrix);
465 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)
470 matrix4x4_t bonematrix;
471 matrix4x4_t blendmatrix;
475 if (skeleton && skeleton->relativetransforms)
477 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
479 *parentindex = skeleton->model->data_bones[tagindex].parent;
480 *tagname = skeleton->model->data_bones[tagindex].name;
481 *tag_localmatrix = skeleton->relativetransforms[tagindex];
484 else if (model->num_bones)
486 if (tagindex < 0 || tagindex >= model->num_bones)
488 *parentindex = model->data_bones[tagindex].parent;
489 *tagname = model->data_bones[tagindex].name;
490 Matrix4x4_Clear(&blendmatrix);
491 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
493 lerp = frameblend[blendindex].lerp;
494 Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
495 Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
497 *tag_localmatrix = blendmatrix;
500 else if (model->num_tags)
502 if (tagindex < 0 || tagindex >= model->num_tags)
505 *tagname = model->data_tags[tagindex].name;
506 for (k = 0;k < 12;k++)
508 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
510 lerp = frameblend[blendindex].lerp;
511 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
512 for (k = 0;k < 12;k++)
513 blendtag[k] += input[k] * lerp;
515 Matrix4x4_FromArray12FloatGL(tag_localmatrix, blendtag);
522 int Mod_Alias_GetTagIndexForName(const dp_model_t *model, unsigned int skin, const char *tagname)
525 if(skin >= (unsigned int)model->numskins)
527 if (model->num_bones)
528 for (i = 0;i < model->num_bones;i++)
529 if (!strcasecmp(tagname, model->data_bones[i].name))
532 for (i = 0;i < model->num_tags;i++)
533 if (!strcasecmp(tagname, model->data_tags[i].name))
538 static void Mod_BuildBaseBonePoses(void)
541 matrix4x4_t *basebonepose;
542 float *outinvmatrix = loadmodel->data_baseboneposeinverse;
543 matrix4x4_t bonematrix;
544 matrix4x4_t tempbonematrix;
545 if (!loadmodel->num_bones)
547 basebonepose = (matrix4x4_t *)Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(matrix4x4_t));
548 for (boneindex = 0;boneindex < loadmodel->num_bones;boneindex++)
550 Matrix4x4_FromBonePose6s(&bonematrix, loadmodel->num_posescale, loadmodel->data_poses6s + 6 * boneindex);
551 if (loadmodel->data_bones[boneindex].parent >= 0)
553 tempbonematrix = bonematrix;
554 Matrix4x4_Concat(&bonematrix, basebonepose + loadmodel->data_bones[boneindex].parent, &tempbonematrix);
556 basebonepose[boneindex] = bonematrix;
557 Matrix4x4_Invert_Simple(&tempbonematrix, basebonepose + boneindex);
558 Matrix4x4_ToArray12FloatD3D(&tempbonematrix, outinvmatrix + 12*boneindex);
560 Mem_Free(basebonepose);
563 static void Mod_Alias_CalculateBoundingBox(void)
566 qboolean firstvertex = true;
567 float dist, yawradius, radius;
570 frameblend_t frameblend[MAX_FRAMEBLENDS];
571 memset(frameblend, 0, sizeof(frameblend));
572 frameblend[0].lerp = 1;
573 vertex3f = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
574 VectorClear(loadmodel->normalmins);
575 VectorClear(loadmodel->normalmaxs);
578 for (frameblend[0].subframe = 0;frameblend[0].subframe < loadmodel->num_poses;frameblend[0].subframe++)
580 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, vertex3f, NULL, NULL, NULL);
581 for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
586 VectorCopy(v, loadmodel->normalmins);
587 VectorCopy(v, loadmodel->normalmaxs);
591 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
592 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
593 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
594 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
595 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
596 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
598 dist = v[0] * v[0] + v[1] * v[1];
599 if (yawradius < dist)
608 radius = sqrt(radius);
609 yawradius = sqrt(yawradius);
610 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
611 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
612 loadmodel->yawmins[2] = loadmodel->normalmins[2];
613 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
614 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
615 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
616 loadmodel->radius = radius;
617 loadmodel->radius2 = radius * radius;
620 static void Mod_Alias_MorphMesh_CompileFrames(void)
623 frameblend_t frameblend[MAX_FRAMEBLENDS];
624 unsigned char *datapointer;
625 memset(frameblend, 0, sizeof(frameblend));
626 frameblend[0].lerp = 1;
627 datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
628 loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
629 loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
630 loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
631 loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
632 loadmodel->surfmesh.data_morphtexvecvertex = (texvecvertex_t *)datapointer;datapointer += loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices * sizeof(texvecvertex_t);
633 // 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)
634 for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
636 frameblend[0].subframe = i;
637 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
638 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);
639 // encode the svector and tvector in 3 byte format for permanent storage
640 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
642 VectorScaleCast(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
643 VectorScaleCast(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
648 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)
651 float segmentmins[3], segmentmaxs[3];
653 static int maxvertices = 0;
654 static float *vertex3f = NULL;
655 memset(trace, 0, sizeof(*trace));
657 trace->realfraction = 1;
658 trace->hitsupercontentsmask = hitsupercontentsmask;
659 if (maxvertices < model->surfmesh.num_vertices)
663 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
664 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
666 segmentmins[0] = min(start[0], end[0]) - 1;
667 segmentmins[1] = min(start[1], end[1]) - 1;
668 segmentmins[2] = min(start[2], end[2]) - 1;
669 segmentmaxs[0] = max(start[0], end[0]) + 1;
670 segmentmaxs[1] = max(start[1], end[1]) + 1;
671 segmentmaxs[2] = max(start[2], end[2]) + 1;
672 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
673 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
674 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);
677 static int maxvertices = 0;
678 static float *vertex3f = NULL;
680 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)
683 vec3_t shiftstart, shiftend;
684 float segmentmins[3], segmentmaxs[3];
686 colboxbrushf_t thisbrush_start, thisbrush_end;
687 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
689 if (VectorCompare(boxmins, boxmaxs))
691 VectorAdd(start, boxmins, shiftstart);
692 VectorAdd(end, boxmins, shiftend);
693 Mod_MDLMD2MD3_TraceLine(model, frameblend, skeleton, trace, shiftstart, shiftend, hitsupercontentsmask);
694 VectorSubtract(trace->endpos, boxmins, trace->endpos);
698 // box trace, performed as brush trace
699 memset(trace, 0, sizeof(*trace));
701 trace->realfraction = 1;
702 trace->hitsupercontentsmask = hitsupercontentsmask;
703 if (maxvertices < model->surfmesh.num_vertices)
707 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
708 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
710 segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
711 segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
712 segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
713 segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
714 segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
715 segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
716 VectorAdd(start, boxmins, boxstartmins);
717 VectorAdd(start, boxmaxs, boxstartmaxs);
718 VectorAdd(end, boxmins, boxendmins);
719 VectorAdd(end, boxmaxs, boxendmaxs);
720 Collision_BrushForBox(&thisbrush_start, boxstartmins, boxstartmaxs, 0, 0, NULL);
721 Collision_BrushForBox(&thisbrush_end, boxendmins, boxendmaxs, 0, 0, NULL);
722 if (maxvertices < model->surfmesh.num_vertices)
726 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
727 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
729 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
730 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
731 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);
734 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
737 for (i = 0;i < inverts;i++)
739 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
741 j = vertremap[i]; // not onseam
744 j = vertremap[i+inverts]; // onseam
750 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
752 int i, f, pose, groupframes;
754 daliasframetype_t *pframetype;
755 daliasframe_t *pinframe;
756 daliasgroup_t *group;
757 daliasinterval_t *intervals;
760 scene = loadmodel->animscenes;
761 for (f = 0;f < loadmodel->numframes;f++)
763 pframetype = (daliasframetype_t *)datapointer;
764 datapointer += sizeof(daliasframetype_t);
765 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
767 // a single frame is still treated as a group
774 group = (daliasgroup_t *)datapointer;
775 datapointer += sizeof(daliasgroup_t);
776 groupframes = LittleLong (group->numframes);
778 // intervals (time per frame)
779 intervals = (daliasinterval_t *)datapointer;
780 datapointer += sizeof(daliasinterval_t) * groupframes;
782 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
783 if (interval < 0.01f)
785 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
790 // get scene name from first frame
791 pinframe = (daliasframe_t *)datapointer;
793 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
794 scene->firstframe = pose;
795 scene->framecount = groupframes;
796 scene->framerate = 1.0f / interval;
801 for (i = 0;i < groupframes;i++)
803 pinframe = (daliasframe_t *)datapointer;
804 datapointer += sizeof(daliasframe_t);
805 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
806 datapointer += sizeof(trivertx_t) * inverts;
812 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
814 if (cls.state == ca_dedicated)
818 skinframe = R_SkinFrame_LoadMissing();
819 memset(texture, 0, sizeof(*texture));
820 texture->currentframe = texture;
821 //texture->animated = false;
822 texture->numskinframes = 1;
823 texture->skinframerate = 1;
824 texture->skinframes[0] = skinframe;
825 texture->currentskinframe = skinframe;
826 //texture->backgroundnumskinframes = 0;
827 //texture->customblendfunc[0] = 0;
828 //texture->customblendfunc[1] = 0;
829 //texture->surfaceflags = 0;
830 //texture->supercontents = 0;
831 //texture->surfaceparms = 0;
832 //texture->textureflags = 0;
834 texture->basematerialflags = MATERIALFLAG_WALL;
835 if (texture->currentskinframe->hasalpha)
836 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
837 texture->currentmaterialflags = texture->basematerialflags;
838 texture->offsetmapping = OFFSETMAPPING_OFF;
839 texture->offsetscale = 1;
840 texture->specularscalemod = 1;
841 texture->specularpowermod = 1;
842 texture->surfaceflags = 0;
843 texture->supercontents = SUPERCONTENTS_SOLID;
844 if (!(texture->basematerialflags & MATERIALFLAG_BLENDED))
845 texture->supercontents |= SUPERCONTENTS_OPAQUE;
848 void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
851 static char stripbuf[MAX_QPATH];
852 skinfileitem_t *skinfileitem;
855 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
856 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
858 memset(skin, 0, sizeof(*skin));
860 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
862 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
863 if (!strcmp(skinfileitem->name, meshname))
865 Image_StripImageExtension(skinfileitem->replacement, stripbuf, sizeof(stripbuf));
866 Mod_LoadTextureFromQ3Shader(skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
872 // don't render unmentioned meshes
873 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
874 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
880 Image_StripImageExtension(shadername, stripbuf, sizeof(stripbuf));
881 Mod_LoadTextureFromQ3Shader(skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
885 #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);
886 #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);
887 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
889 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
890 float scales, scalet, interval;
894 stvert_t *pinstverts;
895 dtriangle_t *pintriangles;
896 daliasskintype_t *pinskintype;
897 daliasskingroup_t *pinskingroup;
898 daliasskininterval_t *pinskinintervals;
899 daliasframetype_t *pinframetype;
900 daliasgroup_t *pinframegroup;
901 unsigned char *datapointer, *startframes, *startskins;
902 char name[MAX_QPATH];
903 skinframe_t *tempskinframe;
904 animscene_t *tempskinscenes;
905 texture_t *tempaliasskins;
907 int *vertonseam, *vertremap;
908 skinfile_t *skinfiles;
910 datapointer = (unsigned char *)buffer;
911 pinmodel = (mdl_t *)datapointer;
912 datapointer += sizeof(mdl_t);
914 version = LittleLong (pinmodel->version);
915 if (version != ALIAS_VERSION)
916 Host_Error ("%s has wrong version number (%i should be %i)",
917 loadmodel->name, version, ALIAS_VERSION);
919 loadmodel->modeldatatypestring = "MDL";
921 loadmodel->type = mod_alias;
922 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
923 loadmodel->DrawSky = NULL;
924 loadmodel->DrawAddWaterPlanes = NULL;
925 loadmodel->Draw = R_Q1BSP_Draw;
926 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
927 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
928 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
929 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
930 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
931 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
932 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
933 loadmodel->DrawLight = R_Q1BSP_DrawLight;
934 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
935 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
936 // FIXME add TraceBrush!
937 loadmodel->PointSuperContents = NULL;
939 loadmodel->num_surfaces = 1;
940 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
941 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
942 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
943 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
944 loadmodel->sortedmodelsurfaces[0] = 0;
946 loadmodel->numskins = LittleLong(pinmodel->numskins);
947 BOUNDI(loadmodel->numskins,0,65536);
948 skinwidth = LittleLong (pinmodel->skinwidth);
949 BOUNDI(skinwidth,0,65536);
950 skinheight = LittleLong (pinmodel->skinheight);
951 BOUNDI(skinheight,0,65536);
952 numverts = LittleLong(pinmodel->numverts);
953 BOUNDI(numverts,0,65536);
954 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
955 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
956 loadmodel->numframes = LittleLong(pinmodel->numframes);
957 BOUNDI(loadmodel->numframes,0,65536);
958 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
959 BOUNDI((int)loadmodel->synctype,0,2);
960 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
961 i = LittleLong (pinmodel->flags);
962 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
964 for (i = 0;i < 3;i++)
966 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
967 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
970 startskins = datapointer;
972 for (i = 0;i < loadmodel->numskins;i++)
974 pinskintype = (daliasskintype_t *)datapointer;
975 datapointer += sizeof(daliasskintype_t);
976 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
980 pinskingroup = (daliasskingroup_t *)datapointer;
981 datapointer += sizeof(daliasskingroup_t);
982 groupskins = LittleLong(pinskingroup->numskins);
983 datapointer += sizeof(daliasskininterval_t) * groupskins;
986 for (j = 0;j < groupskins;j++)
988 datapointer += skinwidth * skinheight;
993 pinstverts = (stvert_t *)datapointer;
994 datapointer += sizeof(stvert_t) * numverts;
996 pintriangles = (dtriangle_t *)datapointer;
997 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
999 startframes = datapointer;
1000 loadmodel->surfmesh.num_morphframes = 0;
1001 for (i = 0;i < loadmodel->numframes;i++)
1003 pinframetype = (daliasframetype_t *)datapointer;
1004 datapointer += sizeof(daliasframetype_t);
1005 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
1009 pinframegroup = (daliasgroup_t *)datapointer;
1010 datapointer += sizeof(daliasgroup_t);
1011 groupframes = LittleLong(pinframegroup->numframes);
1012 datapointer += sizeof(daliasinterval_t) * groupframes;
1015 for (j = 0;j < groupframes;j++)
1017 datapointer += sizeof(daliasframe_t);
1018 datapointer += sizeof(trivertx_t) * numverts;
1019 loadmodel->surfmesh.num_morphframes++;
1022 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1024 // store texture coordinates into temporary array, they will be stored
1025 // after usage is determined (triangle data)
1026 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
1027 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
1028 vertonseam = vertremap + numverts * 2;
1030 scales = 1.0 / skinwidth;
1031 scalet = 1.0 / skinheight;
1032 for (i = 0;i < numverts;i++)
1034 vertonseam[i] = LittleLong(pinstverts[i].onseam);
1035 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
1036 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
1037 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
1038 vertst[(i+numverts)*2+1] = vertst[i*2+1];
1041 // load triangle data
1042 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1044 // read the triangle elements
1045 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1046 for (j = 0;j < 3;j++)
1047 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1048 // validate (note numverts is used because this is the original data)
1049 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1050 // now butcher the elements according to vertonseam and tri->facesfront
1051 // and then compact the vertex set to remove duplicates
1052 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1053 if (!LittleLong(pintriangles[i].facesfront)) // backface
1054 for (j = 0;j < 3;j++)
1055 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1056 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1058 // (this uses vertremap to count usage to save some memory)
1059 for (i = 0;i < numverts*2;i++)
1061 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1062 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1063 // build remapping table and compact array
1064 loadmodel->surfmesh.num_vertices = 0;
1065 for (i = 0;i < numverts*2;i++)
1069 vertremap[i] = loadmodel->surfmesh.num_vertices;
1070 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1071 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1072 loadmodel->surfmesh.num_vertices++;
1075 vertremap[i] = -1; // not used at all
1077 // remap the elements to the new vertex set
1078 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1079 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1080 // store the texture coordinates
1081 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1082 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1084 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1085 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1088 // generate ushort elements array if possible
1089 if (loadmodel->surfmesh.num_vertices <= 65536)
1090 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1091 if (loadmodel->surfmesh.data_element3s)
1092 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1093 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1096 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1097 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1098 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1099 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1100 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1101 Mod_Alias_CalculateBoundingBox();
1102 Mod_Alias_MorphMesh_CompileFrames();
1105 Mem_Free(vertremap);
1108 skinfiles = Mod_LoadSkinFiles();
1111 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1112 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1113 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1114 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1115 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1116 Mod_FreeSkinFiles(skinfiles);
1117 for (i = 0;i < loadmodel->numskins;i++)
1119 loadmodel->skinscenes[i].firstframe = i;
1120 loadmodel->skinscenes[i].framecount = 1;
1121 loadmodel->skinscenes[i].loop = true;
1122 loadmodel->skinscenes[i].framerate = 10;
1127 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1128 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1129 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1130 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1132 datapointer = startskins;
1133 for (i = 0;i < loadmodel->numskins;i++)
1135 pinskintype = (daliasskintype_t *)datapointer;
1136 datapointer += sizeof(daliasskintype_t);
1138 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1145 pinskingroup = (daliasskingroup_t *)datapointer;
1146 datapointer += sizeof(daliasskingroup_t);
1148 groupskins = LittleLong (pinskingroup->numskins);
1150 pinskinintervals = (daliasskininterval_t *)datapointer;
1151 datapointer += sizeof(daliasskininterval_t) * groupskins;
1153 interval = LittleFloat(pinskinintervals[0].interval);
1154 if (interval < 0.01f)
1156 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1161 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1162 loadmodel->skinscenes[i].firstframe = totalskins;
1163 loadmodel->skinscenes[i].framecount = groupskins;
1164 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1165 loadmodel->skinscenes[i].loop = true;
1167 for (j = 0;j < groupskins;j++)
1170 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1172 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1173 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))
1174 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));
1175 datapointer += skinwidth * skinheight;
1179 // check for skins that don't exist in the model, but do exist as external images
1180 // (this was added because yummyluv kept pestering me about support for it)
1181 // TODO: support shaders here?
1182 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)))
1184 // expand the arrays to make room
1185 tempskinscenes = loadmodel->skinscenes;
1186 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1187 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1188 Mem_Free(tempskinscenes);
1190 tempaliasskins = loadmodel->data_textures;
1191 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1192 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1193 Mem_Free(tempaliasskins);
1195 // store the info about the new skin
1196 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1197 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1198 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1199 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1200 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1201 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1203 //increase skin counts
1204 loadmodel->numskins++;
1207 // fix up the pointers since they are pointing at the old textures array
1208 // FIXME: this is a hack!
1209 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1210 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1214 surface = loadmodel->data_surfaces;
1215 surface->texture = loadmodel->data_textures;
1216 surface->num_firsttriangle = 0;
1217 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1218 surface->num_firstvertex = 0;
1219 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1221 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1223 if (!loadmodel->surfmesh.isanimated)
1225 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1226 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1227 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1228 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1229 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1230 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1234 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1236 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1237 float iskinwidth, iskinheight;
1238 unsigned char *data;
1239 msurface_t *surface;
1241 unsigned char *base, *datapointer;
1242 md2frame_t *pinframe;
1244 md2triangle_t *intri;
1245 unsigned short *inst;
1246 struct md2verthash_s
1248 struct md2verthash_s *next;
1252 *hash, **md2verthash, *md2verthashdata;
1253 skinfile_t *skinfiles;
1255 pinmodel = (md2_t *)buffer;
1256 base = (unsigned char *)buffer;
1258 version = LittleLong (pinmodel->version);
1259 if (version != MD2ALIAS_VERSION)
1260 Host_Error ("%s has wrong version number (%i should be %i)",
1261 loadmodel->name, version, MD2ALIAS_VERSION);
1263 loadmodel->modeldatatypestring = "MD2";
1265 loadmodel->type = mod_alias;
1266 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1267 loadmodel->DrawSky = NULL;
1268 loadmodel->DrawAddWaterPlanes = NULL;
1269 loadmodel->Draw = R_Q1BSP_Draw;
1270 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1271 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1272 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1273 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1274 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1275 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1276 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1277 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1278 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1279 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1280 loadmodel->PointSuperContents = NULL;
1282 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1283 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1284 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1285 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1286 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1287 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1288 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1289 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1291 end = LittleLong(pinmodel->ofs_end);
1292 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1293 Host_Error ("%s is not a valid model", loadmodel->name);
1294 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1295 Host_Error ("%s is not a valid model", loadmodel->name);
1296 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1297 Host_Error ("%s is not a valid model", loadmodel->name);
1298 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1299 Host_Error ("%s is not a valid model", loadmodel->name);
1300 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1301 Host_Error ("%s is not a valid model", loadmodel->name);
1303 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1304 numxyz = LittleLong(pinmodel->num_xyz);
1305 numst = LittleLong(pinmodel->num_st);
1306 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1307 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1308 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1309 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1310 skinwidth = LittleLong(pinmodel->skinwidth);
1311 skinheight = LittleLong(pinmodel->skinheight);
1312 iskinwidth = 1.0f / skinwidth;
1313 iskinheight = 1.0f / skinheight;
1315 loadmodel->num_surfaces = 1;
1316 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1317 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]) + loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1318 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1319 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1320 loadmodel->sortedmodelsurfaces[0] = 0;
1321 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1322 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1323 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1324 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1326 loadmodel->synctype = ST_RAND;
1329 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1330 skinfiles = Mod_LoadSkinFiles();
1333 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1334 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1335 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1336 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1337 Mod_FreeSkinFiles(skinfiles);
1339 else if (loadmodel->numskins)
1341 // skins found (most likely not a player model)
1342 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1343 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1344 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1345 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1346 Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
1350 // no skins (most likely a player model)
1351 loadmodel->numskins = 1;
1352 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1353 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1354 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1355 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1358 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1359 for (i = 0;i < loadmodel->numskins;i++)
1361 loadmodel->skinscenes[i].firstframe = i;
1362 loadmodel->skinscenes[i].framecount = 1;
1363 loadmodel->skinscenes[i].loop = true;
1364 loadmodel->skinscenes[i].framerate = 10;
1367 // load the triangles and stvert data
1368 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1369 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1370 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1371 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1372 // swap the triangle list
1373 loadmodel->surfmesh.num_vertices = 0;
1374 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1376 for (j = 0;j < 3;j++)
1378 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1379 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1382 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1387 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1390 hashindex = (xyz * 256 + st) & 65535;
1391 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1392 if (hash->xyz == xyz && hash->st == st)
1396 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1399 hash->next = md2verthash[hashindex];
1400 md2verthash[hashindex] = hash;
1402 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1406 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1407 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));
1408 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1409 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1410 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1413 hash = md2verthashdata + i;
1414 vertremap[i] = hash->xyz;
1415 sts = LittleShort(inst[hash->st*2+0]);
1416 stt = LittleShort(inst[hash->st*2+1]);
1417 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1419 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1423 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1424 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1427 Mem_Free(md2verthash);
1428 Mem_Free(md2verthashdata);
1430 // generate ushort elements array if possible
1431 if (loadmodel->surfmesh.num_vertices <= 65536)
1432 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1433 if (loadmodel->surfmesh.data_element3s)
1434 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1435 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1438 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1439 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1444 pinframe = (md2frame_t *)datapointer;
1445 datapointer += sizeof(md2frame_t);
1446 // store the frame scale/translate into the appropriate array
1447 for (j = 0;j < 3;j++)
1449 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1450 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1452 // convert the vertices
1453 v = (trivertx_t *)datapointer;
1454 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1455 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1456 out[k] = v[vertremap[k]];
1457 datapointer += numxyz * sizeof(trivertx_t);
1459 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1460 loadmodel->animscenes[i].firstframe = i;
1461 loadmodel->animscenes[i].framecount = 1;
1462 loadmodel->animscenes[i].framerate = 10;
1463 loadmodel->animscenes[i].loop = true;
1466 Mem_Free(vertremap);
1468 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1469 Mod_Alias_CalculateBoundingBox();
1470 Mod_Alias_MorphMesh_CompileFrames();
1472 surface = loadmodel->data_surfaces;
1473 surface->texture = loadmodel->data_textures;
1474 surface->num_firsttriangle = 0;
1475 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1476 surface->num_firstvertex = 0;
1477 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1479 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1481 if (!loadmodel->surfmesh.isanimated)
1483 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1484 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1485 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1486 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1487 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1488 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1492 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1494 int i, j, k, version, meshvertices, meshtriangles;
1495 unsigned char *data;
1496 msurface_t *surface;
1497 md3modelheader_t *pinmodel;
1498 md3frameinfo_t *pinframe;
1501 skinfile_t *skinfiles;
1503 pinmodel = (md3modelheader_t *)buffer;
1505 if (memcmp(pinmodel->identifier, "IDP3", 4))
1506 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1507 version = LittleLong (pinmodel->version);
1508 if (version != MD3VERSION)
1509 Host_Error ("%s has wrong version number (%i should be %i)",
1510 loadmodel->name, version, MD3VERSION);
1512 skinfiles = Mod_LoadSkinFiles();
1513 if (loadmodel->numskins < 1)
1514 loadmodel->numskins = 1;
1516 loadmodel->modeldatatypestring = "MD3";
1518 loadmodel->type = mod_alias;
1519 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1520 loadmodel->DrawSky = NULL;
1521 loadmodel->DrawAddWaterPlanes = NULL;
1522 loadmodel->Draw = R_Q1BSP_Draw;
1523 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1524 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1525 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1526 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1527 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1528 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1529 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1530 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1531 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1532 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1533 loadmodel->PointSuperContents = NULL;
1534 loadmodel->synctype = ST_RAND;
1535 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1536 i = LittleLong (pinmodel->flags);
1537 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1539 // set up some global info about the model
1540 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1541 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1543 // make skinscenes for the skins (no groups)
1544 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1545 for (i = 0;i < loadmodel->numskins;i++)
1547 loadmodel->skinscenes[i].firstframe = i;
1548 loadmodel->skinscenes[i].framecount = 1;
1549 loadmodel->skinscenes[i].loop = true;
1550 loadmodel->skinscenes[i].framerate = 10;
1554 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1555 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1557 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1558 loadmodel->animscenes[i].firstframe = i;
1559 loadmodel->animscenes[i].framecount = 1;
1560 loadmodel->animscenes[i].framerate = 10;
1561 loadmodel->animscenes[i].loop = true;
1565 loadmodel->num_tagframes = loadmodel->numframes;
1566 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1567 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1568 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1570 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1571 for (j = 0;j < 9;j++)
1572 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1573 for (j = 0;j < 3;j++)
1574 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1575 //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);
1581 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)))
1583 if (memcmp(pinmesh->identifier, "IDP3", 4))
1584 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1585 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1586 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1587 meshvertices += LittleLong(pinmesh->num_vertices);
1588 meshtriangles += LittleLong(pinmesh->num_triangles);
1591 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1592 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1593 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1594 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]) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshvertices * sizeof(float[2]) + meshvertices * loadmodel->numframes * sizeof(md3vertex_t));
1595 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1596 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1597 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1598 loadmodel->surfmesh.num_vertices = meshvertices;
1599 loadmodel->surfmesh.num_triangles = meshtriangles;
1600 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1601 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1602 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1603 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1604 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1605 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1606 if (meshvertices <= 65536)
1607 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
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 loadmodel->sortedmodelsurfaces[i] = i;
1616 surface = loadmodel->data_surfaces + i;
1617 surface->texture = loadmodel->data_textures + i;
1618 surface->num_firsttriangle = meshtriangles;
1619 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1620 surface->num_firstvertex = meshvertices;
1621 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1622 meshvertices += surface->num_vertices;
1623 meshtriangles += surface->num_triangles;
1625 for (j = 0;j < surface->num_triangles * 3;j++)
1626 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1627 for (j = 0;j < surface->num_vertices;j++)
1629 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1630 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1632 for (j = 0;j < loadmodel->numframes;j++)
1634 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1635 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1636 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1638 out->origin[0] = LittleShort(in->origin[0]);
1639 out->origin[1] = LittleShort(in->origin[1]);
1640 out->origin[2] = LittleShort(in->origin[2]);
1641 out->pitch = in->pitch;
1646 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1648 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1650 if (loadmodel->surfmesh.data_element3s)
1651 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1652 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1653 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1654 Mod_Alias_MorphMesh_CompileFrames();
1655 Mod_Alias_CalculateBoundingBox();
1656 Mod_FreeSkinFiles(skinfiles);
1657 Mod_MakeSortedSurfaces(loadmodel);
1659 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1660 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1662 if (!loadmodel->surfmesh.isanimated)
1664 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1665 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1666 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1667 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1668 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1669 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1673 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1675 zymtype1header_t *pinmodel, *pheader;
1676 unsigned char *pbase;
1677 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1678 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose, f, biggestorigin, tempvec[3], modelscale;
1679 zymvertex_t *verts, *vertdata;
1683 skinfile_t *skinfiles;
1684 unsigned char *data;
1685 msurface_t *surface;
1687 pinmodel = (zymtype1header_t *)buffer;
1688 pbase = (unsigned char *)buffer;
1689 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1690 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1691 if (BigLong(pinmodel->type) != 1)
1692 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1694 loadmodel->modeldatatypestring = "ZYM";
1696 loadmodel->type = mod_alias;
1697 loadmodel->synctype = ST_RAND;
1701 pheader->type = BigLong(pinmodel->type);
1702 pheader->filesize = BigLong(pinmodel->filesize);
1703 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1704 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1705 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1706 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1707 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1708 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1709 pheader->radius = BigFloat(pinmodel->radius);
1710 pheader->numverts = BigLong(pinmodel->numverts);
1711 pheader->numtris = BigLong(pinmodel->numtris);
1712 pheader->numshaders = BigLong(pinmodel->numshaders);
1713 pheader->numbones = BigLong(pinmodel->numbones);
1714 pheader->numscenes = BigLong(pinmodel->numscenes);
1715 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1716 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1717 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1718 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1719 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1720 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1721 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1722 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1723 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1724 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1725 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1726 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1727 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1728 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1729 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1730 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1731 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1732 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1734 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1736 Con_Printf("%s has no geometry\n", loadmodel->name);
1739 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1741 Con_Printf("%s has no animations\n", loadmodel->name);
1745 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1746 loadmodel->DrawSky = NULL;
1747 loadmodel->DrawAddWaterPlanes = NULL;
1748 loadmodel->Draw = R_Q1BSP_Draw;
1749 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1750 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1751 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1752 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1753 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1754 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1755 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1756 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1757 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1758 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1759 loadmodel->PointSuperContents = NULL;
1761 loadmodel->numframes = pheader->numscenes;
1762 loadmodel->num_surfaces = pheader->numshaders;
1764 skinfiles = Mod_LoadSkinFiles();
1765 if (loadmodel->numskins < 1)
1766 loadmodel->numskins = 1;
1768 // make skinscenes for the skins (no groups)
1769 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1770 for (i = 0;i < loadmodel->numskins;i++)
1772 loadmodel->skinscenes[i].firstframe = i;
1773 loadmodel->skinscenes[i].framecount = 1;
1774 loadmodel->skinscenes[i].loop = true;
1775 loadmodel->skinscenes[i].framerate = 10;
1779 modelradius = pheader->radius;
1780 for (i = 0;i < 3;i++)
1782 loadmodel->normalmins[i] = pheader->mins[i];
1783 loadmodel->normalmaxs[i] = pheader->maxs[i];
1784 loadmodel->rotatedmins[i] = -modelradius;
1785 loadmodel->rotatedmaxs[i] = modelradius;
1787 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1788 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1789 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1790 if (loadmodel->yawmaxs[0] > modelradius)
1791 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1792 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1793 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1794 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1795 loadmodel->radius = modelradius;
1796 loadmodel->radius2 = modelradius * modelradius;
1798 // go through the lumps, swapping things
1800 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1801 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1802 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1803 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1804 for (i = 0;i < pheader->numscenes;i++)
1806 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1807 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1808 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1809 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1810 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1811 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1812 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1813 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1814 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1815 if (loadmodel->animscenes[i].framerate < 0)
1816 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1820 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1821 loadmodel->num_bones = pheader->numbones;
1822 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1823 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1824 for (i = 0;i < pheader->numbones;i++)
1826 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1827 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1828 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1829 if (loadmodel->data_bones[i].parent >= i)
1830 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1833 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1834 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1835 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1836 for (i = 0;i < pheader->numverts;i++)
1838 vertbonecounts[i] = BigLong(bonecount[i]);
1839 if (vertbonecounts[i] != 1)
1840 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1843 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1845 meshvertices = pheader->numverts;
1846 meshtriangles = pheader->numtris;
1848 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1849 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1850 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1851 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]) + meshtriangles * sizeof(int[3]) + (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]));
1852 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1853 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1854 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1855 loadmodel->surfmesh.num_vertices = meshvertices;
1856 loadmodel->surfmesh.num_triangles = meshtriangles;
1857 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1858 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1859 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1860 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1861 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1862 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1863 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1864 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1865 loadmodel->surfmesh.num_blends = 0;
1866 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
1867 if (loadmodel->surfmesh.num_vertices <= 65536)
1868 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1869 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
1870 loadmodel->surfmesh.data_blendweights = NULL;
1872 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1873 poses = (float *) (pheader->lump_poses.start + pbase);
1874 // figure out scale of model from root bone, for compatibility with old zmodel versions
1875 tempvec[0] = BigFloat(poses[0]);
1876 tempvec[1] = BigFloat(poses[1]);
1877 tempvec[2] = BigFloat(poses[2]);
1878 modelscale = VectorLength(tempvec);
1880 for (i = 0;i < loadmodel->num_bones * numposes * 12;i++)
1882 f = fabs(BigFloat(poses[i]));
1883 biggestorigin = max(biggestorigin, f);
1885 loadmodel->num_posescale = biggestorigin / 32767.0f;
1886 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
1887 for (i = 0;i < numposes;i++)
1889 const float *frameposes = (float *) (pheader->lump_poses.start + pbase) + 12*i*loadmodel->num_bones;
1890 for (j = 0;j < loadmodel->num_bones;j++)
1893 matrix4x4_t posematrix;
1894 for (k = 0;k < 12;k++)
1895 pose[k] = BigFloat(frameposes[j*12+k]);
1896 //if (j < loadmodel->num_bones)
1897 // 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));
1898 // scale child bones to match the root scale
1899 if (loadmodel->data_bones[j].parent >= 0)
1901 pose[3] *= modelscale;
1902 pose[7] *= modelscale;
1903 pose[11] *= modelscale;
1905 // normalize rotation matrix
1906 VectorNormalize(pose + 0);
1907 VectorNormalize(pose + 4);
1908 VectorNormalize(pose + 8);
1909 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
1910 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
1914 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1915 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1916 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1917 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1918 // (converting from weight-blending skeletal animation to
1919 // deformation-based skeletal animation)
1920 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1921 for (i = 0;i < loadmodel->num_bones;i++)
1924 for (k = 0;k < 12;k++)
1925 m[k] = BigFloat(poses[i*12+k]);
1926 if (loadmodel->data_bones[i].parent >= 0)
1927 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1929 for (k = 0;k < 12;k++)
1930 bonepose[12*i+k] = m[k];
1932 for (j = 0;j < pheader->numverts;j++)
1934 // this format really should have had a per vertexweight weight value...
1935 // but since it does not, the weighting is completely ignored and
1936 // only one weight is allowed per vertex
1937 int boneindex = BigLong(vertdata[j].bonenum);
1938 const float *m = bonepose + 12 * boneindex;
1939 float relativeorigin[3];
1940 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1941 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1942 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1943 // transform the vertex bone weight into the base mesh
1944 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1945 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1946 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1947 // store the weight as the primary weight on this vertex
1948 loadmodel->surfmesh.blends[j] = boneindex;
1951 // normals and tangents are calculated after elements are loaded
1953 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1954 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1955 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1956 for (i = 0;i < pheader->numverts;i++)
1958 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1959 // flip T coordinate for OpenGL
1960 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1963 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1964 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1965 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1967 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1968 //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)
1969 // byteswap, validate, and swap winding order of tris
1970 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1971 if (pheader->lump_render.length != count)
1972 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1973 renderlist = (int *) (pheader->lump_render.start + pbase);
1974 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1976 for (i = 0;i < loadmodel->num_surfaces;i++)
1978 int firstvertex, lastvertex;
1979 if (renderlist >= renderlistend)
1980 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1981 count = BigLong(*renderlist);renderlist++;
1982 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1983 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1985 loadmodel->sortedmodelsurfaces[i] = i;
1986 surface = loadmodel->data_surfaces + i;
1987 surface->texture = loadmodel->data_textures + i;
1988 surface->num_firsttriangle = meshtriangles;
1989 surface->num_triangles = count;
1990 meshtriangles += surface->num_triangles;
1992 // load the elements
1993 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
1994 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
1996 outelements[j*3+2] = BigLong(renderlist[0]);
1997 outelements[j*3+1] = BigLong(renderlist[1]);
1998 outelements[j*3+0] = BigLong(renderlist[2]);
2000 // validate the elements and find the used vertex range
2001 firstvertex = meshvertices;
2003 for (j = 0;j < surface->num_triangles * 3;j++)
2005 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
2006 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
2007 firstvertex = min(firstvertex, outelements[j]);
2008 lastvertex = max(lastvertex, outelements[j]);
2010 surface->num_firstvertex = firstvertex;
2011 surface->num_vertices = lastvertex + 1 - firstvertex;
2013 // since zym models do not have named sections, reuse their shader
2014 // name as the section name
2015 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
2016 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
2018 Mod_FreeSkinFiles(skinfiles);
2019 Mem_Free(vertbonecounts);
2021 Mod_MakeSortedSurfaces(loadmodel);
2023 // compute all the mesh information that was not loaded from the file
2024 if (loadmodel->surfmesh.data_element3s)
2025 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2026 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2027 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2028 Mod_BuildBaseBonePoses();
2029 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2030 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, true);
2031 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2033 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2035 if (!loadmodel->surfmesh.isanimated)
2037 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2038 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2039 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2040 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2041 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2042 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2046 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2048 dpmheader_t *pheader;
2052 unsigned char *pbase;
2053 int i, j, k, meshvertices, meshtriangles;
2054 skinfile_t *skinfiles;
2055 unsigned char *data;
2057 float biggestorigin, tempvec[3], modelscale;
2061 pheader = (dpmheader_t *)buffer;
2062 pbase = (unsigned char *)buffer;
2063 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2064 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2065 if (BigLong(pheader->type) != 2)
2066 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2068 loadmodel->modeldatatypestring = "DPM";
2070 loadmodel->type = mod_alias;
2071 loadmodel->synctype = ST_RAND;
2074 pheader->type = BigLong(pheader->type);
2075 pheader->filesize = BigLong(pheader->filesize);
2076 pheader->mins[0] = BigFloat(pheader->mins[0]);
2077 pheader->mins[1] = BigFloat(pheader->mins[1]);
2078 pheader->mins[2] = BigFloat(pheader->mins[2]);
2079 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2080 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2081 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2082 pheader->yawradius = BigFloat(pheader->yawradius);
2083 pheader->allradius = BigFloat(pheader->allradius);
2084 pheader->num_bones = BigLong(pheader->num_bones);
2085 pheader->num_meshs = BigLong(pheader->num_meshs);
2086 pheader->num_frames = BigLong(pheader->num_frames);
2087 pheader->ofs_bones = BigLong(pheader->ofs_bones);
2088 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2089 pheader->ofs_frames = BigLong(pheader->ofs_frames);
2091 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2093 Con_Printf("%s has no geometry\n", loadmodel->name);
2096 if (pheader->num_frames < 1)
2098 Con_Printf("%s has no frames\n", loadmodel->name);
2102 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2103 loadmodel->DrawSky = NULL;
2104 loadmodel->DrawAddWaterPlanes = NULL;
2105 loadmodel->Draw = R_Q1BSP_Draw;
2106 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2107 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2108 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2109 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2110 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2111 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2112 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2113 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2114 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2115 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2116 loadmodel->PointSuperContents = NULL;
2119 for (i = 0;i < 3;i++)
2121 loadmodel->normalmins[i] = pheader->mins[i];
2122 loadmodel->normalmaxs[i] = pheader->maxs[i];
2123 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2124 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2125 loadmodel->rotatedmins[i] = -pheader->allradius;
2126 loadmodel->rotatedmaxs[i] = pheader->allradius;
2128 loadmodel->radius = pheader->allradius;
2129 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2131 // load external .skin files if present
2132 skinfiles = Mod_LoadSkinFiles();
2133 if (loadmodel->numskins < 1)
2134 loadmodel->numskins = 1;
2139 // gather combined statistics from the meshes
2140 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2141 for (i = 0;i < (int)pheader->num_meshs;i++)
2143 int numverts = BigLong(dpmmesh->num_verts);
2144 meshvertices += numverts;
2145 meshtriangles += BigLong(dpmmesh->num_tris);
2149 loadmodel->numframes = pheader->num_frames;
2150 loadmodel->num_bones = pheader->num_bones;
2151 loadmodel->num_poses = loadmodel->numframes;
2152 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2153 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2154 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2155 // do most allocations as one merged chunk
2156 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) + meshtriangles * sizeof(int[3]) + 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));
2157 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2158 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2159 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2160 loadmodel->surfmesh.num_vertices = meshvertices;
2161 loadmodel->surfmesh.num_triangles = meshtriangles;
2162 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2163 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2164 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2165 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2166 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2167 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2168 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2169 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2170 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2171 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2172 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2173 loadmodel->surfmesh.num_blends = 0;
2174 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2175 if (meshvertices <= 65536)
2176 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2177 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2178 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
2180 for (i = 0;i < loadmodel->numskins;i++)
2182 loadmodel->skinscenes[i].firstframe = i;
2183 loadmodel->skinscenes[i].framecount = 1;
2184 loadmodel->skinscenes[i].loop = true;
2185 loadmodel->skinscenes[i].framerate = 10;
2188 // load the bone info
2189 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2190 for (i = 0;i < loadmodel->num_bones;i++)
2192 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2193 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2194 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2195 if (loadmodel->data_bones[i].parent >= i)
2196 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2200 frames = (dpmframe_t *) (pbase + pheader->ofs_frames);
2201 // figure out scale of model from root bone, for compatibility with old dpmodel versions
2202 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2203 tempvec[0] = BigFloat(poses[0]);
2204 tempvec[1] = BigFloat(poses[1]);
2205 tempvec[2] = BigFloat(poses[2]);
2206 modelscale = VectorLength(tempvec);
2208 for (i = 0;i < loadmodel->numframes;i++)
2210 memcpy(loadmodel->animscenes[i].name, frames[i].name, sizeof(frames[i].name));
2211 loadmodel->animscenes[i].firstframe = i;
2212 loadmodel->animscenes[i].framecount = 1;
2213 loadmodel->animscenes[i].loop = true;
2214 loadmodel->animscenes[i].framerate = 10;
2215 // load the bone poses for this frame
2216 poses = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2217 for (j = 0;j < loadmodel->num_bones*12;j++)
2219 f = fabs(BigFloat(poses[j]));
2220 biggestorigin = max(biggestorigin, f);
2222 // stuff not processed here: mins, maxs, yawradius, allradius
2224 loadmodel->num_posescale = biggestorigin / 32767.0f;
2225 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2226 for (i = 0;i < loadmodel->numframes;i++)
2228 const float *frameposes = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2229 for (j = 0;j < loadmodel->num_bones;j++)
2232 matrix4x4_t posematrix;
2233 for (k = 0;k < 12;k++)
2234 pose[k] = BigFloat(frameposes[j*12+k]);
2235 // scale child bones to match the root scale
2236 if (loadmodel->data_bones[j].parent >= 0)
2238 pose[3] *= modelscale;
2239 pose[7] *= modelscale;
2240 pose[11] *= modelscale;
2242 // normalize rotation matrix
2243 VectorNormalize(pose + 0);
2244 VectorNormalize(pose + 4);
2245 VectorNormalize(pose + 8);
2246 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2247 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
2251 // load the meshes now
2252 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2255 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2256 // (converting from weight-blending skeletal animation to
2257 // deformation-based skeletal animation)
2258 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2259 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2260 for (i = 0;i < loadmodel->num_bones;i++)
2263 for (k = 0;k < 12;k++)
2264 m[k] = BigFloat(poses[i*12+k]);
2265 if (loadmodel->data_bones[i].parent >= 0)
2266 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2268 for (k = 0;k < 12;k++)
2269 bonepose[12*i+k] = m[k];
2271 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2273 const int *inelements;
2275 const float *intexcoord;
2276 msurface_t *surface;
2278 loadmodel->sortedmodelsurfaces[i] = i;
2279 surface = loadmodel->data_surfaces + i;
2280 surface->texture = loadmodel->data_textures + i;
2281 surface->num_firsttriangle = meshtriangles;
2282 surface->num_triangles = BigLong(dpmmesh->num_tris);
2283 surface->num_firstvertex = meshvertices;
2284 surface->num_vertices = BigLong(dpmmesh->num_verts);
2285 meshvertices += surface->num_vertices;
2286 meshtriangles += surface->num_triangles;
2288 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2289 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2290 for (j = 0;j < surface->num_triangles;j++)
2292 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2293 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2294 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2295 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2300 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2301 for (j = 0;j < surface->num_vertices*2;j++)
2302 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2304 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2305 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2307 int weightindex[4] = { 0, 0, 0, 0 };
2308 float weightinfluence[4] = { 0, 0, 0, 0 };
2310 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2311 data += sizeof(dpmvertex_t);
2312 for (k = 0;k < numweights;k++)
2314 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2315 int boneindex = BigLong(vert->bonenum);
2316 const float *m = bonepose + 12 * boneindex;
2317 float influence = BigFloat(vert->influence);
2318 float relativeorigin[3], relativenormal[3];
2319 relativeorigin[0] = BigFloat(vert->origin[0]);
2320 relativeorigin[1] = BigFloat(vert->origin[1]);
2321 relativeorigin[2] = BigFloat(vert->origin[2]);
2322 relativenormal[0] = BigFloat(vert->normal[0]);
2323 relativenormal[1] = BigFloat(vert->normal[1]);
2324 relativenormal[2] = BigFloat(vert->normal[2]);
2325 // blend the vertex bone weights into the base mesh
2326 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2327 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2328 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2329 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2330 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2331 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2334 // store the first (and often only) weight
2335 weightinfluence[0] = influence;
2336 weightindex[0] = boneindex;
2340 // sort the new weight into this vertex's weight table
2341 // (which only accepts up to 4 bones per vertex)
2342 for (l = 0;l < 4;l++)
2344 if (weightinfluence[l] < influence)
2346 // move weaker influence weights out of the way first
2348 for (l2 = 3;l2 > l;l2--)
2350 weightinfluence[l2] = weightinfluence[l2-1];
2351 weightindex[l2] = weightindex[l2-1];
2353 // store the new weight
2354 weightinfluence[l] = influence;
2355 weightindex[l] = boneindex;
2360 data += sizeof(dpmbonevert_t);
2362 loadmodel->surfmesh.blends[j] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
2365 // since dpm models do not have named sections, reuse their shader name as the section name
2366 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2368 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2370 if (loadmodel->surfmesh.num_blends < meshvertices)
2371 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2373 Mod_FreeSkinFiles(skinfiles);
2374 Mod_MakeSortedSurfaces(loadmodel);
2376 // compute all the mesh information that was not loaded from the file
2377 if (loadmodel->surfmesh.data_element3s)
2378 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2379 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2380 Mod_BuildBaseBonePoses();
2381 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, true);
2382 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2384 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2386 if (!loadmodel->surfmesh.isanimated)
2388 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2389 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2390 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2391 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2392 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2393 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2397 // no idea why PSK/PSA files contain weird quaternions but they do...
2398 #define PSKQUATNEGATIONS
2399 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2401 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2402 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2403 fs_offset_t filesize;
2408 pskboneinfo_t *bones;
2409 pskrawweights_t *rawweights;
2410 //pskboneinfo_t *animbones;
2411 pskaniminfo_t *anims;
2412 pskanimkeys_t *animkeys;
2413 void *animfilebuffer, *animbuffer, *animbufferend;
2414 unsigned char *data;
2416 skinfile_t *skinfiles;
2417 char animname[MAX_QPATH];
2419 float biggestorigin;
2421 pchunk = (pskchunk_t *)buffer;
2422 if (strcmp(pchunk->id, "ACTRHEAD"))
2423 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2425 loadmodel->modeldatatypestring = "PSK";
2427 loadmodel->type = mod_alias;
2428 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2429 loadmodel->DrawSky = NULL;
2430 loadmodel->DrawAddWaterPlanes = NULL;
2431 loadmodel->Draw = R_Q1BSP_Draw;
2432 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2433 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2434 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2435 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2436 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2437 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2438 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2439 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2440 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2441 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2442 loadmodel->PointSuperContents = NULL;
2443 loadmodel->synctype = ST_RAND;
2445 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2446 strlcat(animname, ".psa", sizeof(animname));
2447 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2448 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2449 if (animbuffer == NULL)
2450 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2469 while (buffer < bufferend)
2471 pchunk = (pskchunk_t *)buffer;
2472 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2473 version = LittleLong(pchunk->version);
2474 recordsize = LittleLong(pchunk->recordsize);
2475 numrecords = LittleLong(pchunk->numrecords);
2476 if (developer_extra.integer)
2477 Con_DPrintf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2478 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2479 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);
2480 if (!strcmp(pchunk->id, "ACTRHEAD"))
2484 else if (!strcmp(pchunk->id, "PNTS0000"))
2487 if (recordsize != sizeof(*p))
2488 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2489 // byteswap in place and keep the pointer
2490 numpnts = numrecords;
2491 pnts = (pskpnts_t *)buffer;
2492 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2494 p->origin[0] = LittleFloat(p->origin[0]);
2495 p->origin[1] = LittleFloat(p->origin[1]);
2496 p->origin[2] = LittleFloat(p->origin[2]);
2500 else if (!strcmp(pchunk->id, "VTXW0000"))
2503 if (recordsize != sizeof(*p))
2504 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2505 // byteswap in place and keep the pointer
2506 numvtxw = numrecords;
2507 vtxw = (pskvtxw_t *)buffer;
2508 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2510 p->pntsindex = LittleShort(p->pntsindex);
2511 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2512 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2513 if (p->pntsindex >= numpnts)
2515 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2521 else if (!strcmp(pchunk->id, "FACE0000"))
2524 if (recordsize != sizeof(*p))
2525 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2526 // byteswap in place and keep the pointer
2527 numfaces = numrecords;
2528 faces = (pskface_t *)buffer;
2529 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2531 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2532 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2533 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2534 p->group = LittleLong(p->group);
2535 if (p->vtxwindex[0] >= numvtxw)
2537 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2538 p->vtxwindex[0] = 0;
2540 if (p->vtxwindex[1] >= numvtxw)
2542 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2543 p->vtxwindex[1] = 0;
2545 if (p->vtxwindex[2] >= numvtxw)
2547 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2548 p->vtxwindex[2] = 0;
2553 else if (!strcmp(pchunk->id, "MATT0000"))
2556 if (recordsize != sizeof(*p))
2557 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2558 // byteswap in place and keep the pointer
2559 nummatts = numrecords;
2560 matts = (pskmatt_t *)buffer;
2561 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2567 else if (!strcmp(pchunk->id, "REFSKELT"))
2570 if (recordsize != sizeof(*p))
2571 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2572 // byteswap in place and keep the pointer
2573 numbones = numrecords;
2574 bones = (pskboneinfo_t *)buffer;
2575 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2577 p->numchildren = LittleLong(p->numchildren);
2578 p->parent = LittleLong(p->parent);
2579 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2580 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2581 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2582 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2583 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2584 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2585 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2586 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2587 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2588 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2589 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2590 #ifdef PSKQUATNEGATIONS
2593 p->basepose.quat[0] *= -1;
2594 p->basepose.quat[1] *= -1;
2595 p->basepose.quat[2] *= -1;
2599 p->basepose.quat[0] *= 1;
2600 p->basepose.quat[1] *= -1;
2601 p->basepose.quat[2] *= 1;
2604 if (p->parent < 0 || p->parent >= numbones)
2606 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2612 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2615 if (recordsize != sizeof(*p))
2616 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2617 // byteswap in place and keep the pointer
2618 numrawweights = numrecords;
2619 rawweights = (pskrawweights_t *)buffer;
2620 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2622 p->weight = LittleFloat(p->weight);
2623 p->pntsindex = LittleLong(p->pntsindex);
2624 p->boneindex = LittleLong(p->boneindex);
2625 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2627 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2630 if (p->boneindex < 0 || p->boneindex >= numbones)
2632 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2640 while (animbuffer < animbufferend)
2642 pchunk = (pskchunk_t *)animbuffer;
2643 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2644 version = LittleLong(pchunk->version);
2645 recordsize = LittleLong(pchunk->recordsize);
2646 numrecords = LittleLong(pchunk->numrecords);
2647 if (developer_extra.integer)
2648 Con_DPrintf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2649 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2650 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);
2651 if (!strcmp(pchunk->id, "ANIMHEAD"))
2655 else if (!strcmp(pchunk->id, "BONENAMES"))
2658 if (recordsize != sizeof(*p))
2659 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2660 // byteswap in place and keep the pointer
2661 numanimbones = numrecords;
2662 //animbones = (pskboneinfo_t *)animbuffer;
2663 // NOTE: supposedly psa does not need to match the psk model, the
2664 // bones missing from the psa would simply use their base
2665 // positions from the psk, but this is hard for me to implement
2666 // and people can easily make animations that match.
2667 if (numanimbones != numbones)
2668 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2669 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2671 p->numchildren = LittleLong(p->numchildren);
2672 p->parent = LittleLong(p->parent);
2673 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2674 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2675 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2676 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2677 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2678 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2679 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2680 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2681 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2682 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2683 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2684 #ifdef PSKQUATNEGATIONS
2687 p->basepose.quat[0] *= -1;
2688 p->basepose.quat[1] *= -1;
2689 p->basepose.quat[2] *= -1;
2693 p->basepose.quat[0] *= 1;
2694 p->basepose.quat[1] *= -1;
2695 p->basepose.quat[2] *= 1;
2698 if (p->parent < 0 || p->parent >= numanimbones)
2700 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2703 // check that bones are the same as in the base
2704 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2705 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2709 else if (!strcmp(pchunk->id, "ANIMINFO"))
2712 if (recordsize != sizeof(*p))
2713 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2714 // byteswap in place and keep the pointer
2715 numanims = numrecords;
2716 anims = (pskaniminfo_t *)animbuffer;
2717 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2719 p->numbones = LittleLong(p->numbones);
2720 p->playtime = LittleFloat(p->playtime);
2721 p->fps = LittleFloat(p->fps);
2722 p->firstframe = LittleLong(p->firstframe);
2723 p->numframes = LittleLong(p->numframes);
2724 if (p->numbones != numbones)
2725 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2729 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2732 if (recordsize != sizeof(*p))
2733 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2734 numanimkeys = numrecords;
2735 animkeys = (pskanimkeys_t *)animbuffer;
2736 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2738 p->origin[0] = LittleFloat(p->origin[0]);
2739 p->origin[1] = LittleFloat(p->origin[1]);
2740 p->origin[2] = LittleFloat(p->origin[2]);
2741 p->quat[0] = LittleFloat(p->quat[0]);
2742 p->quat[1] = LittleFloat(p->quat[1]);
2743 p->quat[2] = LittleFloat(p->quat[2]);
2744 p->quat[3] = LittleFloat(p->quat[3]);
2745 p->frametime = LittleFloat(p->frametime);
2746 #ifdef PSKQUATNEGATIONS
2747 if (index % numbones)
2762 // TODO: allocate bonepose stuff
2765 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2768 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2769 Host_Error("%s: missing required chunks", loadmodel->name);
2771 loadmodel->numframes = 0;
2772 for (index = 0;index < numanims;index++)
2773 loadmodel->numframes += anims[index].numframes;
2775 if (numanimkeys != numbones * loadmodel->numframes)
2776 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2778 meshvertices = numvtxw;
2779 meshtriangles = numfaces;
2781 // load external .skin files if present
2782 skinfiles = Mod_LoadSkinFiles();
2783 if (loadmodel->numskins < 1)
2784 loadmodel->numskins = 1;
2785 loadmodel->num_bones = numbones;
2786 loadmodel->num_poses = loadmodel->numframes;
2787 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2788 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2789 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2790 loadmodel->surfmesh.num_vertices = meshvertices;
2791 loadmodel->surfmesh.num_triangles = meshtriangles;
2792 // do most allocations as one merged chunk
2793 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]) + loadmodel->surfmesh.num_triangles * sizeof(int[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[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);
2794 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2795 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2796 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2797 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2798 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2799 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2800 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2801 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2802 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2803 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2804 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2805 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2806 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2807 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2808 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2809 loadmodel->surfmesh.num_blends = 0;
2810 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2811 if (loadmodel->surfmesh.num_vertices <= 65536)
2812 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2813 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2814 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(blendweights_t));
2816 for (i = 0;i < loadmodel->numskins;i++)
2818 loadmodel->skinscenes[i].firstframe = i;
2819 loadmodel->skinscenes[i].framecount = 1;
2820 loadmodel->skinscenes[i].loop = true;
2821 loadmodel->skinscenes[i].framerate = 10;
2825 for (index = 0, i = 0;index < nummatts;index++)
2827 // since psk models do not have named sections, reuse their shader name as the section name
2828 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2829 loadmodel->sortedmodelsurfaces[index] = index;
2830 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2831 loadmodel->data_surfaces[index].num_firstvertex = 0;
2832 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2835 // copy over the vertex locations and texcoords
2836 for (index = 0;index < numvtxw;index++)
2838 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2839 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2840 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2841 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2842 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2845 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2846 for (index = 0;index < numfaces;index++)
2847 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2848 for (index = 0, i = 0;index < nummatts;index++)
2850 loadmodel->data_surfaces[index].num_firsttriangle = i;
2851 i += loadmodel->data_surfaces[index].num_triangles;
2852 loadmodel->data_surfaces[index].num_triangles = 0;
2854 for (index = 0;index < numfaces;index++)
2856 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2857 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2858 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2859 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2862 // copy over the bones
2863 for (index = 0;index < numbones;index++)
2865 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2866 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2867 if (loadmodel->data_bones[index].parent >= index)
2868 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2871 // sort the psk point weights into the vertex weight tables
2872 // (which only accept up to 4 bones per vertex)
2873 for (index = 0;index < numvtxw;index++)
2875 int weightindex[4] = { 0, 0, 0, 0 };
2876 float weightinfluence[4] = { 0, 0, 0, 0 };
2878 for (j = 0;j < numrawweights;j++)
2880 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2882 int boneindex = rawweights[j].boneindex;
2883 float influence = rawweights[j].weight;
2884 for (l = 0;l < 4;l++)
2886 if (weightinfluence[l] < influence)
2888 // move lower influence weights out of the way first
2890 for (l2 = 3;l2 > l;l2--)
2892 weightinfluence[l2] = weightinfluence[l2-1];
2893 weightindex[l2] = weightindex[l2-1];
2895 // store the new weight
2896 weightinfluence[l] = influence;
2897 weightindex[l] = boneindex;
2903 loadmodel->surfmesh.blends[index] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
2905 if (loadmodel->surfmesh.num_blends < loadmodel->surfmesh.num_vertices)
2906 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2908 // set up the animscenes based on the anims
2909 for (index = 0, i = 0;index < numanims;index++)
2911 for (j = 0;j < anims[index].numframes;j++, i++)
2913 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2914 loadmodel->animscenes[i].firstframe = i;
2915 loadmodel->animscenes[i].framecount = 1;
2916 loadmodel->animscenes[i].loop = true;
2917 loadmodel->animscenes[i].framerate = anims[index].fps;
2921 // calculate the scaling value for bone origins so they can be compressed to short
2923 for (index = 0;index < numanimkeys;index++)
2925 pskanimkeys_t *k = animkeys + index;
2926 biggestorigin = max(biggestorigin, fabs(k->origin[0]));
2927 biggestorigin = max(biggestorigin, fabs(k->origin[1]));
2928 biggestorigin = max(biggestorigin, fabs(k->origin[2]));
2930 loadmodel->num_posescale = biggestorigin / 32767.0f;
2931 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2933 // load the poses from the animkeys
2934 for (index = 0;index < numanimkeys;index++)
2936 pskanimkeys_t *k = animkeys + index;
2938 Vector4Copy(k->quat, quat);
2940 Vector4Negate(quat, quat);
2941 Vector4Normalize2(quat, quat);
2942 // compress poses to the short[6] format for longterm storage
2943 loadmodel->data_poses6s[index*6+0] = k->origin[0] * loadmodel->num_poseinvscale;
2944 loadmodel->data_poses6s[index*6+1] = k->origin[1] * loadmodel->num_poseinvscale;
2945 loadmodel->data_poses6s[index*6+2] = k->origin[2] * loadmodel->num_poseinvscale;
2946 loadmodel->data_poses6s[index*6+3] = quat[0] * 32767.0f;
2947 loadmodel->data_poses6s[index*6+4] = quat[1] * 32767.0f;
2948 loadmodel->data_poses6s[index*6+5] = quat[2] * 32767.0f;
2950 Mod_FreeSkinFiles(skinfiles);
2951 Mem_Free(animfilebuffer);
2952 Mod_MakeSortedSurfaces(loadmodel);
2954 // compute all the mesh information that was not loaded from the file
2955 // TODO: honor smoothing groups somehow?
2956 if (loadmodel->surfmesh.data_element3s)
2957 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2958 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2959 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2960 Mod_BuildBaseBonePoses();
2961 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2962 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, true);
2963 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2964 Mod_Alias_CalculateBoundingBox();
2966 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2968 if (!loadmodel->surfmesh.isanimated)
2970 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2971 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2972 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2973 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2974 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2975 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2979 void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2981 unsigned char *data;
2983 unsigned char *pbase, *pend;
2984 iqmheader_t *header;
2985 skinfile_t *skinfiles;
2986 int i, j, k, meshvertices, meshtriangles;
2987 float *vposition = NULL, *vtexcoord = NULL, *vnormal = NULL, *vtangent = NULL;
2988 unsigned char *vblendindexes = NULL, *vblendweights = NULL;
2993 iqmbounds_t *bounds;
2994 iqmvertexarray_t *va;
2995 unsigned short *framedata;
2996 float biggestorigin;
2997 const int *inelements;
2999 float *outvertex, *outnormal, *outtexcoord, *outsvector, *outtvector;
3001 pbase = (unsigned char *)buffer;
3002 pend = (unsigned char *)bufferend;
3003 header = (iqmheader_t *)buffer;
3004 if (memcmp(header->id, "INTERQUAKEMODEL", 16))
3005 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model", loadmodel->name);
3006 if (LittleLong(header->version) != 1)
3007 Host_Error ("Mod_INTERQUAKEMODEL_Load: only version 1 models are currently supported (name = %s)", loadmodel->name);
3009 loadmodel->modeldatatypestring = "IQM";
3011 loadmodel->type = mod_alias;
3012 loadmodel->synctype = ST_RAND;
3015 header->version = LittleLong(header->version);
3016 header->filesize = LittleLong(header->filesize);
3017 header->flags = LittleLong(header->flags);
3018 header->num_text = LittleLong(header->num_text);
3019 header->ofs_text = LittleLong(header->ofs_text);
3020 header->num_meshes = LittleLong(header->num_meshes);
3021 header->ofs_meshes = LittleLong(header->ofs_meshes);
3022 header->num_vertexarrays = LittleLong(header->num_vertexarrays);
3023 header->num_vertexes = LittleLong(header->num_vertexes);
3024 header->ofs_vertexarrays = LittleLong(header->ofs_vertexarrays);
3025 header->num_triangles = LittleLong(header->num_triangles);
3026 header->ofs_triangles = LittleLong(header->ofs_triangles);
3027 header->ofs_neighbors = LittleLong(header->ofs_neighbors);
3028 header->num_joints = LittleLong(header->num_joints);
3029 header->ofs_joints = LittleLong(header->ofs_joints);
3030 header->num_poses = LittleLong(header->num_poses);
3031 header->ofs_poses = LittleLong(header->ofs_poses);
3032 header->num_anims = LittleLong(header->num_anims);
3033 header->ofs_anims = LittleLong(header->ofs_anims);
3034 header->num_frames = LittleLong(header->num_frames);
3035 header->num_framechannels = LittleLong(header->num_framechannels);
3036 header->ofs_frames = LittleLong(header->ofs_frames);
3037 header->ofs_bounds = LittleLong(header->ofs_bounds);
3038 header->num_comment = LittleLong(header->num_comment);
3039 header->ofs_comment = LittleLong(header->ofs_comment);
3040 header->num_extensions = LittleLong(header->num_extensions);
3041 header->ofs_extensions = LittleLong(header->ofs_extensions);
3043 if (header->num_triangles < 1 || header->num_vertexes < 3 || header->num_vertexarrays < 1 || header->num_meshes < 1)
3045 Con_Printf("%s has no geometry\n", loadmodel->name);
3048 if (header->num_frames < 1 || header->num_anims < 1)
3050 Con_Printf("%s has no animations\n", loadmodel->name);
3054 if (pbase + header->ofs_text + header->num_text > pend ||
3055 pbase + header->ofs_meshes + header->num_meshes*sizeof(iqmmesh_t) > pend ||
3056 pbase + header->ofs_vertexarrays + header->num_vertexarrays*sizeof(iqmvertexarray_t) > pend ||
3057 pbase + header->ofs_triangles + header->num_triangles*sizeof(int[3]) > pend ||
3058 (header->ofs_neighbors && pbase + header->ofs_neighbors + header->num_triangles*sizeof(int[3]) > pend) ||
3059 pbase + header->ofs_joints + header->num_joints*sizeof(iqmjoint_t) > pend ||
3060 pbase + header->ofs_poses + header->num_poses*sizeof(iqmpose_t) > pend ||
3061 pbase + header->ofs_anims + header->num_anims*sizeof(iqmanim_t) > pend ||
3062 pbase + header->ofs_frames + header->num_frames*header->num_framechannels*sizeof(unsigned short) > pend ||
3063 (header->ofs_bounds && pbase + header->ofs_bounds + header->num_frames*sizeof(iqmbounds_t) > pend) ||
3064 pbase + header->ofs_comment + header->num_comment > pend)
3066 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3070 va = (iqmvertexarray_t *)(pbase + header->ofs_vertexarrays);
3071 for (i = 0;i < (int)header->num_vertexarrays;i++)
3074 va[i].type = LittleLong(va[i].type);
3075 va[i].flags = LittleLong(va[i].flags);
3076 va[i].format = LittleLong(va[i].format);
3077 va[i].size = LittleLong(va[i].size);
3078 va[i].offset = LittleLong(va[i].offset);
3079 vsize = header->num_vertexes*va[i].size;
3080 switch (va[i].format)
3082 case IQM_FLOAT: vsize *= sizeof(float); break;
3083 case IQM_UBYTE: vsize *= sizeof(unsigned char); break;
3086 if (pbase + va[i].offset + vsize > pend)
3091 if (va[i].format == IQM_FLOAT && va[i].size == 3)
3092 vposition = (float *)(pbase + va[i].offset);
3095 if (va[i].format == IQM_FLOAT && va[i].size == 2)
3096 vtexcoord = (float *)(pbase + va[i].offset);
3099 if (va[i].format == IQM_FLOAT && va[i].size == 3)
3100 vnormal = (float *)(pbase + va[i].offset);
3103 if (va[i].format == IQM_FLOAT && va[i].size == 4)
3104 vtangent = (float *)(pbase + va[i].offset);
3106 case IQM_BLENDINDEXES:
3107 if (va[i].format == IQM_UBYTE && va[i].size == 4)
3108 vblendindexes = (unsigned char *)(pbase + va[i].offset);
3110 case IQM_BLENDWEIGHTS:
3111 if (va[i].format == IQM_UBYTE && va[i].size == 4)
3112 vblendweights = (unsigned char *)(pbase + va[i].offset);
3116 if (!vposition || !vtexcoord || !vblendindexes || !vblendweights)
3118 Con_Printf("%s is missing vertex array data\n", loadmodel->name);
3122 text = header->num_text && header->ofs_text ? (const char *)(pbase + header->ofs_text) : "";
3124 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
3125 loadmodel->DrawSky = NULL;
3126 loadmodel->DrawAddWaterPlanes = NULL;
3127 loadmodel->Draw = R_Q1BSP_Draw;
3128 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
3129 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
3130 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
3131 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
3132 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
3133 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
3134 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
3135 loadmodel->DrawLight = R_Q1BSP_DrawLight;
3136 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
3137 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
3138 loadmodel->PointSuperContents = NULL;
3140 // load external .skin files if present
3141 skinfiles = Mod_LoadSkinFiles();
3142 if (loadmodel->numskins < 1)
3143 loadmodel->numskins = 1;
3145 loadmodel->numframes = header->num_anims;
3146 loadmodel->num_bones = header->num_joints;
3147 loadmodel->num_poses = header->num_frames;
3148 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = header->num_meshes;
3149 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3150 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3152 meshvertices = header->num_vertexes;
3153 meshtriangles = header->num_triangles;
3155 // do most allocations as one merged chunk
3156 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) + meshtriangles * sizeof(int[3]) + 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));
3157 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
3158 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
3159 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
3160 loadmodel->surfmesh.num_vertices = meshvertices;
3161 loadmodel->surfmesh.num_triangles = meshtriangles;
3162 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3163 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3164 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
3165 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3166 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3167 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
3168 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
3169 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
3170 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
3171 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
3172 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
3173 loadmodel->surfmesh.num_blends = 0;
3174 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
3175 if (meshvertices <= 65536)
3176 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
3177 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
3178 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
3180 for (i = 0;i < loadmodel->numskins;i++)
3182 loadmodel->skinscenes[i].firstframe = i;
3183 loadmodel->skinscenes[i].framecount = 1;
3184 loadmodel->skinscenes[i].loop = true;
3185 loadmodel->skinscenes[i].framerate = 10;
3188 // load the bone info
3189 joint = (iqmjoint_t *) (pbase + header->ofs_joints);
3190 for (i = 0;i < loadmodel->num_bones;i++)
3192 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3193 joint[i].name = LittleLong(joint[i].name);
3194 joint[i].parent = LittleLong(joint[i].parent);
3195 for (j = 0;j < 3;j++)
3197 joint[i].origin[j] = LittleFloat(joint[i].origin[j]);
3198 joint[i].rotation[j] = LittleFloat(joint[i].rotation[j]);
3199 joint[i].scale[j] = LittleFloat(joint[i].scale[j]);
3201 strlcpy(loadmodel->data_bones[i].name, &text[joint[i].name], sizeof(loadmodel->data_bones[i].name));
3202 loadmodel->data_bones[i].parent = joint[i].parent;
3203 if (loadmodel->data_bones[i].parent >= i)
3204 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3205 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]);
3206 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3207 if (loadmodel->data_bones[i].parent >= 0)
3209 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3210 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3211 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3213 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3216 // set up the animscenes based on the anims
3217 anim = (iqmanim_t *) (pbase + header->ofs_anims);
3218 for (i = 0;i < (int)header->num_anims;i++)
3220 anim[i].name = LittleLong(anim[i].name);
3221 anim[i].first_frame = LittleLong(anim[i].first_frame);
3222 anim[i].num_frames = LittleLong(anim[i].num_frames);
3223 anim[i].framerate = LittleFloat(anim[i].framerate);
3224 anim[i].flags = LittleLong(anim[i].flags);
3225 strlcpy(loadmodel->animscenes[i].name, &text[anim[i].name], sizeof(loadmodel->animscenes[i].name));
3226 loadmodel->animscenes[i].firstframe = anim[i].first_frame;
3227 loadmodel->animscenes[i].framecount = anim[i].num_frames;
3228 loadmodel->animscenes[i].loop = ((anim[i].flags & IQM_LOOP) != 0);
3229 loadmodel->animscenes[i].framerate = anim[i].framerate;
3232 pose = (iqmpose_t *) (pbase + header->ofs_poses);
3234 for (i = 0;i < (int)header->num_poses;i++)
3237 pose[i].parent = LittleLong(pose[i].parent);
3238 pose[i].channelmask = LittleLong(pose[i].channelmask);
3239 pose[i].channeloffset[0] = LittleFloat(pose[i].channeloffset[0]);
3240 pose[i].channeloffset[1] = LittleFloat(pose[i].channeloffset[1]);
3241 pose[i].channeloffset[2] = LittleFloat(pose[i].channeloffset[2]);
3242 pose[i].channeloffset[3] = LittleFloat(pose[i].channeloffset[3]);
3243 pose[i].channeloffset[4] = LittleFloat(pose[i].channeloffset[4]);
3244 pose[i].channeloffset[5] = LittleFloat(pose[i].channeloffset[5]);
3245 pose[i].channeloffset[6] = LittleFloat(pose[i].channeloffset[6]);
3246 pose[i].channeloffset[7] = LittleFloat(pose[i].channeloffset[7]);
3247 pose[i].channeloffset[8] = LittleFloat(pose[i].channeloffset[8]);
3248 pose[i].channelscale[0] = LittleFloat(pose[i].channelscale[0]);
3249 pose[i].channelscale[1] = LittleFloat(pose[i].channelscale[1]);
3250 pose[i].channelscale[2] = LittleFloat(pose[i].channelscale[2]);
3251 pose[i].channelscale[3] = LittleFloat(pose[i].channelscale[3]);
3252 pose[i].channelscale[4] = LittleFloat(pose[i].channelscale[4]);
3253 pose[i].channelscale[5] = LittleFloat(pose[i].channelscale[5]);
3254 pose[i].channelscale[6] = LittleFloat(pose[i].channelscale[6]);
3255 pose[i].channelscale[7] = LittleFloat(pose[i].channelscale[7]);
3256 pose[i].channelscale[8] = LittleFloat(pose[i].channelscale[8]);
3257 f = fabs(pose[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3258 f = fabs(pose[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3259 f = fabs(pose[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3260 f = fabs(pose[i].channeloffset[0] + 0xFFFF*pose[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3261 f = fabs(pose[i].channeloffset[1] + 0xFFFF*pose[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3262 f = fabs(pose[i].channeloffset[2] + 0xFFFF*pose[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3264 loadmodel->num_posescale = biggestorigin / 32767.0f;
3265 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3267 // load the pose data
3268 framedata = (unsigned short *) (pbase + header->ofs_frames);
3269 for (i = 0, k = 0;i < (int)header->num_frames;i++)
3271 for (j = 0;j < (int)header->num_poses;j++, k++)
3273 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));
3274 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));
3275 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));
3276 loadmodel->data_poses6s[k*6 + 3] = 32767.0f * (pose[j].channeloffset[3] + (pose[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[3] : 0));
3277 loadmodel->data_poses6s[k*6 + 4] = 32767.0f * (pose[j].channeloffset[4] + (pose[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[4] : 0));
3278 loadmodel->data_poses6s[k*6 + 5] = 32767.0f * (pose[j].channeloffset[5] + (pose[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[5] : 0));
3279 // skip scale data for now
3280 if(pose[j].channelmask&64) framedata++;
3281 if(pose[j].channelmask&128) framedata++;
3282 if(pose[j].channelmask&256) framedata++;
3286 // load bounding box data
3287 if (header->ofs_bounds)
3289 float xyradius = 0, radius = 0;
3290 bounds = (iqmbounds_t *) (pbase + header->ofs_bounds);
3291 VectorClear(loadmodel->normalmins);
3292 VectorClear(loadmodel->normalmaxs);
3293 for (i = 0; i < (int)header->num_frames;i++)
3295 bounds[i].mins[0] = LittleFloat(bounds[i].mins[0]);
3296 bounds[i].mins[1] = LittleFloat(bounds[i].mins[1]);
3297 bounds[i].mins[2] = LittleFloat(bounds[i].mins[2]);
3298 bounds[i].maxs[0] = LittleFloat(bounds[i].maxs[0]);
3299 bounds[i].maxs[1] = LittleFloat(bounds[i].maxs[1]);
3300 bounds[i].maxs[2] = LittleFloat(bounds[i].maxs[2]);
3301 bounds[i].xyradius = LittleFloat(bounds[i].xyradius);
3302 bounds[i].radius = LittleFloat(bounds[i].radius);
3305 VectorCopy(bounds[i].mins, loadmodel->normalmins);
3306 VectorCopy(bounds[i].maxs, loadmodel->normalmaxs);
3310 if (loadmodel->normalmins[0] > bounds[i].mins[0]) loadmodel->normalmins[0] = bounds[i].mins[0];
3311 if (loadmodel->normalmins[1] > bounds[i].mins[1]) loadmodel->normalmins[1] = bounds[i].mins[1];
3312 if (loadmodel->normalmins[2] > bounds[i].mins[2]) loadmodel->normalmins[2] = bounds[i].mins[2];
3313 if (loadmodel->normalmaxs[0] < bounds[i].maxs[0]) loadmodel->normalmaxs[0] = bounds[i].maxs[0];
3314 if (loadmodel->normalmaxs[1] < bounds[i].maxs[1]) loadmodel->normalmaxs[1] = bounds[i].maxs[1];
3315 if (loadmodel->normalmaxs[2] < bounds[i].maxs[2]) loadmodel->normalmaxs[2] = bounds[i].maxs[2];
3317 if (bounds[i].xyradius > xyradius)
3318 xyradius = bounds[i].xyradius;
3319 if (bounds[i].radius > radius)
3320 radius = bounds[i].radius;
3322 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -xyradius;
3323 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = xyradius;
3324 loadmodel->yawmins[2] = loadmodel->normalmins[2];
3325 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
3326 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
3327 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
3328 loadmodel->radius = radius;
3329 loadmodel->radius2 = radius * radius;
3332 // load triangle data
3333 inelements = (const int *) (pbase + header->ofs_triangles);
3334 outelements = loadmodel->surfmesh.data_element3i;
3335 for (i = 0;i < (int)header->num_triangles;i++)
3337 outelements[0] = LittleLong(inelements[0]);
3338 outelements[1] = LittleLong(inelements[1]);
3339 outelements[2] = LittleLong(inelements[2]);
3343 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, header->num_vertexes, __FILE__, __LINE__);
3345 if (header->ofs_neighbors)
3347 inelements = (const int *) (pbase + header->ofs_neighbors);
3348 outelements = loadmodel->surfmesh.data_neighbor3i;
3349 for (i = 0;i < (int)header->num_triangles;i++)
3351 outelements[0] = LittleLong(inelements[0]);
3352 outelements[1] = LittleLong(inelements[1]);
3353 outelements[2] = LittleLong(inelements[2]);
3360 outvertex = loadmodel->surfmesh.data_vertex3f;
3361 for (i = 0;i < (int)header->num_vertexes;i++)
3363 outvertex[0] = LittleFloat(vposition[0]);
3364 outvertex[1] = LittleFloat(vposition[1]);
3365 outvertex[2] = LittleFloat(vposition[2]);
3370 outtexcoord = loadmodel->surfmesh.data_texcoordtexture2f;
3371 for (i = 0;i < (int)header->num_vertexes;i++)
3373 outtexcoord[0] = LittleFloat(vtexcoord[0]);
3374 outtexcoord[1] = LittleFloat(vtexcoord[1]);
3381 outnormal = loadmodel->surfmesh.data_normal3f;
3382 for (i = 0;i < (int)header->num_vertexes;i++)
3384 outnormal[0] = LittleFloat(vnormal[0]);
3385 outnormal[1] = LittleFloat(vnormal[1]);
3386 outnormal[2] = LittleFloat(vnormal[2]);
3392 if(vnormal && vtangent)
3394 outnormal = loadmodel->surfmesh.data_normal3f;
3395 outsvector = loadmodel->surfmesh.data_svector3f;
3396 outtvector = loadmodel->surfmesh.data_tvector3f;
3397 for (i = 0;i < (int)header->num_vertexes;i++)
3399 outsvector[0] = LittleFloat(vtangent[0]);
3400 outsvector[1] = LittleFloat(vtangent[1]);
3401 outsvector[2] = LittleFloat(vtangent[2]);
3402 if(LittleFloat(vtangent[3]) < 0)
3403 CrossProduct(outsvector, outnormal, outtvector);
3405 CrossProduct(outnormal, outsvector, outtvector);
3413 for (i = 0; i < (int)header->num_vertexes;i++)
3415 blendweights_t weights;
3416 memcpy(weights.index, vblendindexes + i*4, 4);
3417 memcpy(weights.influence, vblendweights + i*4, 4);
3418 loadmodel->surfmesh.blends[i] = Mod_Skeletal_AddBlend(loadmodel, &weights);
3422 mesh = (iqmmesh_t *) (pbase + header->ofs_meshes);
3423 for (i = 0;i < (int)header->num_meshes;i++)
3425 msurface_t *surface;
3427 mesh[i].name = LittleLong(mesh[i].name);
3428 mesh[i].material = LittleLong(mesh[i].material);
3429 mesh[i].first_vertex = LittleLong(mesh[i].first_vertex);
3430 mesh[i].num_vertexes = LittleLong(mesh[i].num_vertexes);
3431 mesh[i].first_triangle = LittleLong(mesh[i].first_triangle);
3432 mesh[i].num_triangles = LittleLong(mesh[i].num_triangles);
3434 loadmodel->sortedmodelsurfaces[i] = i;
3435 surface = loadmodel->data_surfaces + i;
3436 surface->texture = loadmodel->data_textures + i;
3437 surface->num_firsttriangle = mesh[i].first_triangle;
3438 surface->num_triangles = mesh[i].num_triangles;
3439 surface->num_firstvertex = mesh[i].first_vertex;
3440 surface->num_vertices = mesh[i].num_vertexes;
3442 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, &text[mesh[i].name], &text[mesh[i].material]);
3445 Mod_FreeSkinFiles(skinfiles);
3446 Mod_MakeSortedSurfaces(loadmodel);
3448 // compute all the mesh information that was not loaded from the file
3449 if (loadmodel->surfmesh.data_element3s)
3450 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3451 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3453 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
3454 if (!vnormal || !vtangent)
3455 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, true);
3456 if (!header->ofs_neighbors)
3457 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3458 if (!header->ofs_bounds)
3459 Mod_Alias_CalculateBoundingBox();
3461 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
3463 if (!loadmodel->surfmesh.isanimated)
3465 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3466 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3467 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3468 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3469 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3470 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;