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 if(Mod_Skeltal_AnimateVertices_bonepose)
57 Mem_Free(Mod_Skeltal_AnimateVertices_bonepose);
58 Mod_Skeltal_AnimateVertices_bonepose = Z_Malloc(nbytes);
59 Mod_Skeltal_AnimateVertices_maxbonepose = nbytes;
61 return Mod_Skeltal_AnimateVertices_bonepose;
64 void Mod_Skeletal_AnimateVertices(const dp_model_t * RESTRICT model, const frameblend_t * RESTRICT frameblend, const skeleton_t *skeleton, float * RESTRICT vertex3f, float * RESTRICT normal3f, float * RESTRICT svector3f, float * RESTRICT tvector3f)
67 if(r_skeletal_use_sse_defined)
68 if(r_skeletal_use_sse.integer)
70 Mod_Skeletal_AnimateVertices_SSE(model, frameblend, skeleton, vertex3f, normal3f, svector3f, tvector3f);
74 Mod_Skeletal_AnimateVertices_Generic(model, frameblend, skeleton, vertex3f, normal3f, svector3f, tvector3f);
77 void Mod_AliasInit (void)
80 Cvar_RegisterVariable(&r_skeletal_debugbone);
81 Cvar_RegisterVariable(&r_skeletal_debugbonecomponent);
82 Cvar_RegisterVariable(&r_skeletal_debugbonevalue);
83 Cvar_RegisterVariable(&r_skeletal_debugtranslatex);
84 Cvar_RegisterVariable(&r_skeletal_debugtranslatey);
85 Cvar_RegisterVariable(&r_skeletal_debugtranslatez);
86 Cvar_RegisterVariable(&mod_alias_supporttagscale);
87 for (i = 0;i < 320;i++)
88 mod_md3_sin[i] = sin(i * M_PI * 2.0f / 256.0);
92 Con_Printf("Skeletal animation uses SSE code path\n");
93 r_skeletal_use_sse_defined = true;
94 Cvar_RegisterVariable(&r_skeletal_use_sse);
97 Con_Printf("Skeletal animation uses generic code path (SSE disabled or not detected)\n");
99 Con_Printf("Skeletal animation uses generic code path (SSE not compiled in)\n");
103 int Mod_Skeletal_AddBlend(dp_model_t *model, const blendweights_t *newweights)
106 blendweights_t *weights;
107 if(!newweights->influence[1])
108 return newweights->index[0];
109 weights = model->surfmesh.data_blendweights;
110 for (i = 0;i < model->surfmesh.num_blends;i++, weights++)
112 if (!memcmp(weights, newweights, sizeof(blendweights_t)))
113 return model->num_bones + i;
115 model->surfmesh.num_blends++;
116 memcpy(weights, newweights, sizeof(blendweights_t));
117 return model->num_bones + i;
120 int Mod_Skeletal_CompressBlend(dp_model_t *model, const int *newindex, const float *newinfluence)
124 blendweights_t newweights;
128 for (i = 0;i < 4;i++)
129 scale += newinfluence[i];
130 scale = 255.0f / scale;
132 for (i = 0;i < 4;i++)
134 newweights.index[i] = newindex[i];
135 newweights.influence[i] = (unsigned char)(newinfluence[i] * scale);
136 total += newweights.influence[i];
140 for (i = 0;i < 4;i++)
142 if(newweights.influence[i] > 0 && total > 255)
144 newweights.influence[i]--;
151 for (i = 0; i < 4;i++)
153 if(newweights.influence[i] < 255 && total < 255)
155 newweights.influence[i]++;
160 return Mod_Skeletal_AddBlend(model, &newweights);
163 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)
166 int i, numblends, blendnum;
167 int numverts = model->surfmesh.num_vertices;
169 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
171 //VectorMA(translate, model->surfmesh.num_morphmdlframetranslate, frameblend[blendnum].lerp, translate);
172 if (frameblend[blendnum].lerp > 0)
173 numblends = blendnum + 1;
175 // special case for the first blend because it avoids some adds and the need to memset the arrays first
176 for (blendnum = 0;blendnum < numblends;blendnum++)
178 const md3vertex_t *verts = model->surfmesh.data_morphmd3vertex + numverts * frameblend[blendnum].subframe;
181 float scale = frameblend[blendnum].lerp * (1.0f / 64.0f);
184 for (i = 0;i < numverts;i++)
186 vertex3f[i * 3 + 0] = verts[i].origin[0] * scale;
187 vertex3f[i * 3 + 1] = verts[i].origin[1] * scale;
188 vertex3f[i * 3 + 2] = verts[i].origin[2] * scale;
193 for (i = 0;i < numverts;i++)
195 vertex3f[i * 3 + 0] += verts[i].origin[0] * scale;
196 vertex3f[i * 3 + 1] += verts[i].origin[1] * scale;
197 vertex3f[i * 3 + 2] += verts[i].origin[2] * scale;
201 // the yaw and pitch stored in md3 models are 8bit quantized angles
202 // (0-255), and as such a lookup table is very well suited to
203 // decoding them, and since cosine is equivalent to sine with an
204 // extra 45 degree rotation, this uses one lookup table for both
205 // sine and cosine with a +64 bias to get cosine.
208 float lerp = frameblend[blendnum].lerp;
211 for (i = 0;i < numverts;i++)
213 normal3f[i * 3 + 0] = mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
214 normal3f[i * 3 + 1] = mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
215 normal3f[i * 3 + 2] = mod_md3_sin[verts[i].pitch + 64] * lerp;
220 for (i = 0;i < numverts;i++)
222 normal3f[i * 3 + 0] += mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
223 normal3f[i * 3 + 1] += mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
224 normal3f[i * 3 + 2] += mod_md3_sin[verts[i].pitch + 64] * lerp;
230 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
231 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
234 for (i = 0;i < numverts;i++, texvecvert++)
236 VectorScale(texvecvert->svec, f, svector3f + i*3);
237 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
242 for (i = 0;i < numverts;i++, texvecvert++)
244 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
245 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
251 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)
254 int i, numblends, blendnum;
255 int numverts = model->surfmesh.num_vertices;
257 VectorClear(translate);
259 // blend the frame translates to avoid redundantly doing so on each vertex
260 // (a bit of a brain twister but it works)
261 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
263 if (model->surfmesh.data_morphmd2framesize6f)
264 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6 + 3, translate);
266 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.num_morphmdlframetranslate, translate);
267 if (frameblend[blendnum].lerp > 0)
268 numblends = blendnum + 1;
270 // special case for the first blend because it avoids some adds and the need to memset the arrays first
271 for (blendnum = 0;blendnum < numblends;blendnum++)
273 const trivertx_t *verts = model->surfmesh.data_morphmdlvertex + numverts * frameblend[blendnum].subframe;
277 if (model->surfmesh.data_morphmd2framesize6f)
278 VectorScale(model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6, frameblend[blendnum].lerp, scale);
280 VectorScale(model->surfmesh.num_morphmdlframescale, frameblend[blendnum].lerp, scale);
283 for (i = 0;i < numverts;i++)
285 vertex3f[i * 3 + 0] = translate[0] + verts[i].v[0] * scale[0];
286 vertex3f[i * 3 + 1] = translate[1] + verts[i].v[1] * scale[1];
287 vertex3f[i * 3 + 2] = translate[2] + verts[i].v[2] * scale[2];
292 for (i = 0;i < numverts;i++)
294 vertex3f[i * 3 + 0] += verts[i].v[0] * scale[0];
295 vertex3f[i * 3 + 1] += verts[i].v[1] * scale[1];
296 vertex3f[i * 3 + 2] += verts[i].v[2] * scale[2];
300 // the vertex normals in mdl models are an index into a table of
301 // 162 unique values, this very crude quantization reduces the
302 // vertex normal to only one byte, which saves a lot of space but
303 // also makes lighting pretty coarse
306 float lerp = frameblend[blendnum].lerp;
309 for (i = 0;i < numverts;i++)
311 const float *vn = m_bytenormals[verts[i].lightnormalindex];
312 VectorScale(vn, lerp, normal3f + i*3);
317 for (i = 0;i < numverts;i++)
319 const float *vn = m_bytenormals[verts[i].lightnormalindex];
320 VectorMA(normal3f + i*3, lerp, vn, normal3f + i*3);
326 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
327 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
330 for (i = 0;i < numverts;i++, texvecvert++)
332 VectorScale(texvecvert->svec, f, svector3f + i*3);
333 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
338 for (i = 0;i < numverts;i++, texvecvert++)
340 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
341 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
348 int Mod_Alias_GetTagMatrix(const dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, int tagindex, matrix4x4_t *outmatrix)
351 matrix4x4_t parentbonematrix;
352 matrix4x4_t tempbonematrix;
353 matrix4x4_t bonematrix;
354 matrix4x4_t blendmatrix;
361 *outmatrix = identitymatrix;
362 if (skeleton && skeleton->relativetransforms)
364 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
366 *outmatrix = skeleton->relativetransforms[tagindex];
367 while ((tagindex = model->data_bones[tagindex].parent) >= 0)
370 Matrix4x4_Concat(outmatrix, &skeleton->relativetransforms[tagindex], &temp);
373 else if (model->num_bones)
375 if (tagindex < 0 || tagindex >= model->num_bones)
377 Matrix4x4_Clear(&blendmatrix);
378 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
380 lerp = frameblend[blendindex].lerp;
381 Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
382 parenttagindex = tagindex;
383 while ((parenttagindex = model->data_bones[parenttagindex].parent) >= 0)
385 Matrix4x4_FromBonePose6s(&parentbonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + parenttagindex));
386 tempbonematrix = bonematrix;
387 Matrix4x4_Concat(&bonematrix, &parentbonematrix, &tempbonematrix);
389 Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
391 *outmatrix = blendmatrix;
393 else if (model->num_tags)
395 if (tagindex < 0 || tagindex >= model->num_tags)
397 for (k = 0;k < 12;k++)
399 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
401 lerp = frameblend[blendindex].lerp;
402 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
403 for (k = 0;k < 12;k++)
404 blendtag[k] += input[k] * lerp;
406 Matrix4x4_FromArray12FloatGL(outmatrix, blendtag);
409 if(!mod_alias_supporttagscale.integer)
410 Matrix4x4_Normalize3(outmatrix, outmatrix);
415 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)
420 matrix4x4_t bonematrix;
421 matrix4x4_t blendmatrix;
425 if (skeleton && skeleton->relativetransforms)
427 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
429 *parentindex = skeleton->model->data_bones[tagindex].parent;
430 *tagname = skeleton->model->data_bones[tagindex].name;
431 *tag_localmatrix = skeleton->relativetransforms[tagindex];
434 else if (model->num_bones)
436 if (tagindex < 0 || tagindex >= model->num_bones)
438 *parentindex = model->data_bones[tagindex].parent;
439 *tagname = model->data_bones[tagindex].name;
440 Matrix4x4_Clear(&blendmatrix);
441 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
443 lerp = frameblend[blendindex].lerp;
444 Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
445 Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
447 *tag_localmatrix = blendmatrix;
450 else if (model->num_tags)
452 if (tagindex < 0 || tagindex >= model->num_tags)
455 *tagname = model->data_tags[tagindex].name;
456 for (k = 0;k < 12;k++)
458 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
460 lerp = frameblend[blendindex].lerp;
461 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
462 for (k = 0;k < 12;k++)
463 blendtag[k] += input[k] * lerp;
465 Matrix4x4_FromArray12FloatGL(tag_localmatrix, blendtag);
472 int Mod_Alias_GetTagIndexForName(const dp_model_t *model, unsigned int skin, const char *tagname)
475 if(skin >= (unsigned int)model->numskins)
477 if (model->num_bones)
478 for (i = 0;i < model->num_bones;i++)
479 if (!strcasecmp(tagname, model->data_bones[i].name))
482 for (i = 0;i < model->num_tags;i++)
483 if (!strcasecmp(tagname, model->data_tags[i].name))
488 static void Mod_BuildBaseBonePoses(void)
491 matrix4x4_t *basebonepose;
492 float *outinvmatrix = loadmodel->data_baseboneposeinverse;
493 matrix4x4_t bonematrix;
494 matrix4x4_t tempbonematrix;
495 if (!loadmodel->num_bones)
497 basebonepose = (matrix4x4_t *)Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(matrix4x4_t));
498 for (boneindex = 0;boneindex < loadmodel->num_bones;boneindex++)
500 Matrix4x4_FromBonePose6s(&bonematrix, loadmodel->num_posescale, loadmodel->data_poses6s + 6 * boneindex);
501 if (loadmodel->data_bones[boneindex].parent >= 0)
503 tempbonematrix = bonematrix;
504 Matrix4x4_Concat(&bonematrix, basebonepose + loadmodel->data_bones[boneindex].parent, &tempbonematrix);
506 basebonepose[boneindex] = bonematrix;
507 Matrix4x4_Invert_Simple(&tempbonematrix, basebonepose + boneindex);
508 Matrix4x4_ToArray12FloatD3D(&tempbonematrix, outinvmatrix + 12*boneindex);
510 Mem_Free(basebonepose);
513 static void Mod_Alias_CalculateBoundingBox(void)
516 qboolean firstvertex = true;
517 float dist, yawradius, radius;
520 frameblend_t frameblend[MAX_FRAMEBLENDS];
521 memset(frameblend, 0, sizeof(frameblend));
522 frameblend[0].lerp = 1;
523 vertex3f = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
524 VectorClear(loadmodel->normalmins);
525 VectorClear(loadmodel->normalmaxs);
528 for (frameblend[0].subframe = 0;frameblend[0].subframe < loadmodel->num_poses;frameblend[0].subframe++)
530 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, vertex3f, NULL, NULL, NULL);
531 for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
536 VectorCopy(v, loadmodel->normalmins);
537 VectorCopy(v, loadmodel->normalmaxs);
541 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
542 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
543 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
544 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
545 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
546 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
548 dist = v[0] * v[0] + v[1] * v[1];
549 if (yawradius < dist)
558 radius = sqrt(radius);
559 yawradius = sqrt(yawradius);
560 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
561 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
562 loadmodel->yawmins[2] = loadmodel->normalmins[2];
563 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
564 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
565 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
566 loadmodel->radius = radius;
567 loadmodel->radius2 = radius * radius;
570 static void Mod_Alias_MorphMesh_CompileFrames(void)
573 frameblend_t frameblend[MAX_FRAMEBLENDS];
574 unsigned char *datapointer;
575 memset(frameblend, 0, sizeof(frameblend));
576 frameblend[0].lerp = 1;
577 datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
578 loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
579 loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
580 loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
581 loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
582 loadmodel->surfmesh.data_morphtexvecvertex = (texvecvertex_t *)datapointer;datapointer += loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices * sizeof(texvecvertex_t);
583 // 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)
584 for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
586 frameblend[0].subframe = i;
587 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
588 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);
589 // encode the svector and tvector in 3 byte format for permanent storage
590 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
592 VectorScaleCast(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
593 VectorScaleCast(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
598 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)
601 float segmentmins[3], segmentmaxs[3];
603 static int maxvertices = 0;
604 static float *vertex3f = NULL;
605 memset(trace, 0, sizeof(*trace));
607 trace->realfraction = 1;
608 trace->hitsupercontentsmask = hitsupercontentsmask;
609 if (maxvertices < model->surfmesh.num_vertices)
613 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
614 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
616 segmentmins[0] = min(start[0], end[0]) - 1;
617 segmentmins[1] = min(start[1], end[1]) - 1;
618 segmentmins[2] = min(start[2], end[2]) - 1;
619 segmentmaxs[0] = max(start[0], end[0]) + 1;
620 segmentmaxs[1] = max(start[1], end[1]) + 1;
621 segmentmaxs[2] = max(start[2], end[2]) + 1;
622 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
623 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
624 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);
627 static int maxvertices = 0;
628 static float *vertex3f = NULL;
630 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)
633 vec3_t shiftstart, shiftend;
634 float segmentmins[3], segmentmaxs[3];
636 colboxbrushf_t thisbrush_start, thisbrush_end;
637 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
639 if (VectorCompare(boxmins, boxmaxs))
641 VectorAdd(start, boxmins, shiftstart);
642 VectorAdd(end, boxmins, shiftend);
643 Mod_MDLMD2MD3_TraceLine(model, frameblend, skeleton, trace, shiftstart, shiftend, hitsupercontentsmask);
644 VectorSubtract(trace->endpos, boxmins, trace->endpos);
648 // box trace, performed as brush trace
649 memset(trace, 0, sizeof(*trace));
651 trace->realfraction = 1;
652 trace->hitsupercontentsmask = hitsupercontentsmask;
653 if (maxvertices < model->surfmesh.num_vertices)
657 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
658 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
660 segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
661 segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
662 segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
663 segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
664 segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
665 segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
666 VectorAdd(start, boxmins, boxstartmins);
667 VectorAdd(start, boxmaxs, boxstartmaxs);
668 VectorAdd(end, boxmins, boxendmins);
669 VectorAdd(end, boxmaxs, boxendmaxs);
670 Collision_BrushForBox(&thisbrush_start, boxstartmins, boxstartmaxs, 0, 0, NULL);
671 Collision_BrushForBox(&thisbrush_end, boxendmins, boxendmaxs, 0, 0, NULL);
672 if (maxvertices < model->surfmesh.num_vertices)
676 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
677 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
679 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
680 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
681 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);
684 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
687 for (i = 0;i < inverts;i++)
689 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
691 j = vertremap[i]; // not onseam
694 j = vertremap[i+inverts]; // onseam
700 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
702 int i, f, pose, groupframes;
704 daliasframetype_t *pframetype;
705 daliasframe_t *pinframe;
706 daliasgroup_t *group;
707 daliasinterval_t *intervals;
710 scene = loadmodel->animscenes;
711 for (f = 0;f < loadmodel->numframes;f++)
713 pframetype = (daliasframetype_t *)datapointer;
714 datapointer += sizeof(daliasframetype_t);
715 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
717 // a single frame is still treated as a group
724 group = (daliasgroup_t *)datapointer;
725 datapointer += sizeof(daliasgroup_t);
726 groupframes = LittleLong (group->numframes);
728 // intervals (time per frame)
729 intervals = (daliasinterval_t *)datapointer;
730 datapointer += sizeof(daliasinterval_t) * groupframes;
732 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
733 if (interval < 0.01f)
735 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
740 // get scene name from first frame
741 pinframe = (daliasframe_t *)datapointer;
743 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
744 scene->firstframe = pose;
745 scene->framecount = groupframes;
746 scene->framerate = 1.0f / interval;
751 for (i = 0;i < groupframes;i++)
753 pinframe = (daliasframe_t *)datapointer;
754 datapointer += sizeof(daliasframe_t);
755 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
756 datapointer += sizeof(trivertx_t) * inverts;
762 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
764 if (cls.state == ca_dedicated)
768 skinframe = R_SkinFrame_LoadMissing();
769 memset(texture, 0, sizeof(*texture));
770 texture->currentframe = texture;
771 //texture->animated = false;
772 texture->numskinframes = 1;
773 texture->skinframerate = 1;
774 texture->skinframes[0] = skinframe;
775 texture->currentskinframe = skinframe;
776 //texture->backgroundnumskinframes = 0;
777 //texture->customblendfunc[0] = 0;
778 //texture->customblendfunc[1] = 0;
779 //texture->surfaceflags = 0;
780 //texture->supercontents = 0;
781 //texture->surfaceparms = 0;
782 //texture->textureflags = 0;
784 texture->basematerialflags = MATERIALFLAG_WALL;
785 if (texture->currentskinframe->hasalpha)
786 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
787 texture->currentmaterialflags = texture->basematerialflags;
788 texture->offsetmapping = OFFSETMAPPING_DEFAULT;
789 texture->offsetscale = 1;
790 texture->offsetbias = 0;
791 texture->specularscalemod = 1;
792 texture->specularpowermod = 1;
793 texture->surfaceflags = 0;
794 texture->supercontents = SUPERCONTENTS_SOLID;
795 if (!(texture->basematerialflags & MATERIALFLAG_BLENDED))
796 texture->supercontents |= SUPERCONTENTS_OPAQUE;
799 void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
802 static char stripbuf[MAX_QPATH];
803 skinfileitem_t *skinfileitem;
804 if(developer_extra.integer)
805 Con_DPrintf("Looking up texture for %s (default: %s)\n", meshname, shadername);
808 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
809 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
811 memset(skin, 0, sizeof(*skin));
813 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
815 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
816 if (!strcmp(skinfileitem->name, meshname))
818 Image_StripImageExtension(skinfileitem->replacement, stripbuf, sizeof(stripbuf));
819 if(developer_extra.integer)
820 Con_DPrintf("--> got %s from skin file\n", stripbuf);
821 Mod_LoadTextureFromQ3Shader(skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
827 // don't render unmentioned meshes
828 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
829 if(developer_extra.integer)
830 Con_DPrintf("--> skipping\n");
831 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
837 if(developer_extra.integer)
838 Con_DPrintf("--> using default\n");
839 Image_StripImageExtension(shadername, stripbuf, sizeof(stripbuf));
840 Mod_LoadTextureFromQ3Shader(skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
844 #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);
845 #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);
846 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
848 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
849 float scales, scalet, interval;
853 stvert_t *pinstverts;
854 dtriangle_t *pintriangles;
855 daliasskintype_t *pinskintype;
856 daliasskingroup_t *pinskingroup;
857 daliasskininterval_t *pinskinintervals;
858 daliasframetype_t *pinframetype;
859 daliasgroup_t *pinframegroup;
860 unsigned char *datapointer, *startframes, *startskins;
861 char name[MAX_QPATH];
862 skinframe_t *tempskinframe;
863 animscene_t *tempskinscenes;
864 texture_t *tempaliasskins;
866 int *vertonseam, *vertremap;
867 skinfile_t *skinfiles;
869 datapointer = (unsigned char *)buffer;
870 pinmodel = (mdl_t *)datapointer;
871 datapointer += sizeof(mdl_t);
873 version = LittleLong (pinmodel->version);
874 if (version != ALIAS_VERSION)
875 Host_Error ("%s has wrong version number (%i should be %i)",
876 loadmodel->name, version, ALIAS_VERSION);
878 loadmodel->modeldatatypestring = "MDL";
880 loadmodel->type = mod_alias;
881 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
882 loadmodel->DrawSky = NULL;
883 loadmodel->DrawAddWaterPlanes = NULL;
884 loadmodel->Draw = R_Q1BSP_Draw;
885 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
886 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
887 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
888 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
889 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
890 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
891 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
892 loadmodel->DrawLight = R_Q1BSP_DrawLight;
893 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
894 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
895 // FIXME add TraceBrush!
896 loadmodel->PointSuperContents = NULL;
898 loadmodel->num_surfaces = 1;
899 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
900 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
901 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
902 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
903 loadmodel->sortedmodelsurfaces[0] = 0;
905 loadmodel->numskins = LittleLong(pinmodel->numskins);
906 BOUNDI(loadmodel->numskins,0,65536);
907 skinwidth = LittleLong (pinmodel->skinwidth);
908 BOUNDI(skinwidth,0,65536);
909 skinheight = LittleLong (pinmodel->skinheight);
910 BOUNDI(skinheight,0,65536);
911 numverts = LittleLong(pinmodel->numverts);
912 BOUNDI(numverts,0,65536);
913 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
914 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
915 loadmodel->numframes = LittleLong(pinmodel->numframes);
916 BOUNDI(loadmodel->numframes,0,65536);
917 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
918 BOUNDI((int)loadmodel->synctype,0,2);
919 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
920 i = LittleLong (pinmodel->flags);
921 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
923 for (i = 0;i < 3;i++)
925 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
926 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
929 startskins = datapointer;
931 for (i = 0;i < loadmodel->numskins;i++)
933 pinskintype = (daliasskintype_t *)datapointer;
934 datapointer += sizeof(daliasskintype_t);
935 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
939 pinskingroup = (daliasskingroup_t *)datapointer;
940 datapointer += sizeof(daliasskingroup_t);
941 groupskins = LittleLong(pinskingroup->numskins);
942 datapointer += sizeof(daliasskininterval_t) * groupskins;
945 for (j = 0;j < groupskins;j++)
947 datapointer += skinwidth * skinheight;
952 pinstverts = (stvert_t *)datapointer;
953 datapointer += sizeof(stvert_t) * numverts;
955 pintriangles = (dtriangle_t *)datapointer;
956 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
958 startframes = datapointer;
959 loadmodel->surfmesh.num_morphframes = 0;
960 for (i = 0;i < loadmodel->numframes;i++)
962 pinframetype = (daliasframetype_t *)datapointer;
963 datapointer += sizeof(daliasframetype_t);
964 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
968 pinframegroup = (daliasgroup_t *)datapointer;
969 datapointer += sizeof(daliasgroup_t);
970 groupframes = LittleLong(pinframegroup->numframes);
971 datapointer += sizeof(daliasinterval_t) * groupframes;
974 for (j = 0;j < groupframes;j++)
976 datapointer += sizeof(daliasframe_t);
977 datapointer += sizeof(trivertx_t) * numverts;
978 loadmodel->surfmesh.num_morphframes++;
981 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
983 // store texture coordinates into temporary array, they will be stored
984 // after usage is determined (triangle data)
985 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
986 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
987 vertonseam = vertremap + numverts * 2;
989 scales = 1.0 / skinwidth;
990 scalet = 1.0 / skinheight;
991 for (i = 0;i < numverts;i++)
993 vertonseam[i] = LittleLong(pinstverts[i].onseam);
994 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
995 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
996 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
997 vertst[(i+numverts)*2+1] = vertst[i*2+1];
1000 // load triangle data
1001 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1003 // read the triangle elements
1004 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1005 for (j = 0;j < 3;j++)
1006 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1007 // validate (note numverts is used because this is the original data)
1008 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1009 // now butcher the elements according to vertonseam and tri->facesfront
1010 // and then compact the vertex set to remove duplicates
1011 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1012 if (!LittleLong(pintriangles[i].facesfront)) // backface
1013 for (j = 0;j < 3;j++)
1014 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1015 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1017 // (this uses vertremap to count usage to save some memory)
1018 for (i = 0;i < numverts*2;i++)
1020 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1021 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1022 // build remapping table and compact array
1023 loadmodel->surfmesh.num_vertices = 0;
1024 for (i = 0;i < numverts*2;i++)
1028 vertremap[i] = loadmodel->surfmesh.num_vertices;
1029 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1030 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1031 loadmodel->surfmesh.num_vertices++;
1034 vertremap[i] = -1; // not used at all
1036 // remap the elements to the new vertex set
1037 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1038 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1039 // store the texture coordinates
1040 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1041 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1043 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1044 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1047 // generate ushort elements array if possible
1048 if (loadmodel->surfmesh.num_vertices <= 65536)
1049 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1050 if (loadmodel->surfmesh.data_element3s)
1051 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1052 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1055 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1056 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1057 if (r_enableshadowvolumes.integer)
1059 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1061 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1062 if (loadmodel->surfmesh.data_neighbor3i)
1063 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1064 Mod_Alias_CalculateBoundingBox();
1065 Mod_Alias_MorphMesh_CompileFrames();
1068 Mem_Free(vertremap);
1071 skinfiles = Mod_LoadSkinFiles();
1074 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1075 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1076 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1077 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1078 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1079 Mod_FreeSkinFiles(skinfiles);
1080 for (i = 0;i < loadmodel->numskins;i++)
1082 loadmodel->skinscenes[i].firstframe = i;
1083 loadmodel->skinscenes[i].framecount = 1;
1084 loadmodel->skinscenes[i].loop = true;
1085 loadmodel->skinscenes[i].framerate = 10;
1090 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1091 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1092 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1093 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1095 datapointer = startskins;
1096 for (i = 0;i < loadmodel->numskins;i++)
1098 pinskintype = (daliasskintype_t *)datapointer;
1099 datapointer += sizeof(daliasskintype_t);
1101 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1108 pinskingroup = (daliasskingroup_t *)datapointer;
1109 datapointer += sizeof(daliasskingroup_t);
1111 groupskins = LittleLong (pinskingroup->numskins);
1113 pinskinintervals = (daliasskininterval_t *)datapointer;
1114 datapointer += sizeof(daliasskininterval_t) * groupskins;
1116 interval = LittleFloat(pinskinintervals[0].interval);
1117 if (interval < 0.01f)
1119 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1124 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1125 loadmodel->skinscenes[i].firstframe = totalskins;
1126 loadmodel->skinscenes[i].framecount = groupskins;
1127 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1128 loadmodel->skinscenes[i].loop = true;
1130 for (j = 0;j < groupskins;j++)
1133 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1135 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1136 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))
1137 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));
1138 datapointer += skinwidth * skinheight;
1142 // check for skins that don't exist in the model, but do exist as external images
1143 // (this was added because yummyluv kept pestering me about support for it)
1144 // TODO: support shaders here?
1145 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)))
1147 // expand the arrays to make room
1148 tempskinscenes = loadmodel->skinscenes;
1149 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1150 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1151 Mem_Free(tempskinscenes);
1153 tempaliasskins = loadmodel->data_textures;
1154 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1155 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1156 Mem_Free(tempaliasskins);
1158 // store the info about the new skin
1159 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1160 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1161 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1162 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1163 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1164 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1166 //increase skin counts
1167 loadmodel->numskins++;
1170 // fix up the pointers since they are pointing at the old textures array
1171 // FIXME: this is a hack!
1172 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1173 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1177 surface = loadmodel->data_surfaces;
1178 surface->texture = loadmodel->data_textures;
1179 surface->num_firsttriangle = 0;
1180 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1181 surface->num_firstvertex = 0;
1182 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1184 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1186 if (!loadmodel->surfmesh.isanimated)
1188 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1189 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1190 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1191 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1192 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1193 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1197 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1199 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1200 float iskinwidth, iskinheight;
1201 unsigned char *data;
1202 msurface_t *surface;
1204 unsigned char *base, *datapointer;
1205 md2frame_t *pinframe;
1207 md2triangle_t *intri;
1208 unsigned short *inst;
1209 struct md2verthash_s
1211 struct md2verthash_s *next;
1215 *hash, **md2verthash, *md2verthashdata;
1216 skinfile_t *skinfiles;
1218 pinmodel = (md2_t *)buffer;
1219 base = (unsigned char *)buffer;
1221 version = LittleLong (pinmodel->version);
1222 if (version != MD2ALIAS_VERSION)
1223 Host_Error ("%s has wrong version number (%i should be %i)",
1224 loadmodel->name, version, MD2ALIAS_VERSION);
1226 loadmodel->modeldatatypestring = "MD2";
1228 loadmodel->type = mod_alias;
1229 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1230 loadmodel->DrawSky = NULL;
1231 loadmodel->DrawAddWaterPlanes = NULL;
1232 loadmodel->Draw = R_Q1BSP_Draw;
1233 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1234 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1235 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1236 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1237 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1238 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1239 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1240 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1241 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1242 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1243 loadmodel->PointSuperContents = NULL;
1245 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1246 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1247 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1248 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1249 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1250 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1251 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1252 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1254 end = LittleLong(pinmodel->ofs_end);
1255 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1256 Host_Error ("%s is not a valid model", loadmodel->name);
1257 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1258 Host_Error ("%s is not a valid model", loadmodel->name);
1259 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1260 Host_Error ("%s is not a valid model", loadmodel->name);
1261 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1262 Host_Error ("%s is not a valid model", loadmodel->name);
1263 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1264 Host_Error ("%s is not a valid model", loadmodel->name);
1266 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1267 numxyz = LittleLong(pinmodel->num_xyz);
1268 numst = LittleLong(pinmodel->num_st);
1269 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1270 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1271 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1272 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1273 skinwidth = LittleLong(pinmodel->skinwidth);
1274 skinheight = LittleLong(pinmodel->skinheight);
1275 iskinwidth = 1.0f / skinwidth;
1276 iskinheight = 1.0f / skinheight;
1278 loadmodel->num_surfaces = 1;
1279 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1280 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->numframes * sizeof(animscene_t) + loadmodel->numframes * sizeof(float[6]) + loadmodel->surfmesh.num_triangles * sizeof(int[3]) + (r_enableshadowvolumes.integer ? loadmodel->surfmesh.num_triangles * sizeof(int[3]) : 0));
1281 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1282 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1283 loadmodel->sortedmodelsurfaces[0] = 0;
1284 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1285 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1286 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1287 if (r_enableshadowvolumes.integer)
1289 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1292 loadmodel->synctype = ST_RAND;
1295 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1296 skinfiles = Mod_LoadSkinFiles();
1299 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1300 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1301 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1302 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1303 Mod_FreeSkinFiles(skinfiles);
1305 else if (loadmodel->numskins)
1307 // skins found (most likely not a player model)
1308 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1309 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1310 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1311 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1312 Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
1316 // no skins (most likely a player model)
1317 loadmodel->numskins = 1;
1318 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1319 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1320 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1321 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1324 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1325 for (i = 0;i < loadmodel->numskins;i++)
1327 loadmodel->skinscenes[i].firstframe = i;
1328 loadmodel->skinscenes[i].framecount = 1;
1329 loadmodel->skinscenes[i].loop = true;
1330 loadmodel->skinscenes[i].framerate = 10;
1333 // load the triangles and stvert data
1334 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1335 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1336 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1337 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1338 // swap the triangle list
1339 loadmodel->surfmesh.num_vertices = 0;
1340 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1342 for (j = 0;j < 3;j++)
1344 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1345 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1348 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1353 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1356 hashindex = (xyz * 256 + st) & 65535;
1357 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1358 if (hash->xyz == xyz && hash->st == st)
1362 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1365 hash->next = md2verthash[hashindex];
1366 md2verthash[hashindex] = hash;
1368 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1372 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1373 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));
1374 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1375 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1376 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1379 hash = md2verthashdata + i;
1380 vertremap[i] = hash->xyz;
1381 sts = LittleShort(inst[hash->st*2+0]);
1382 stt = LittleShort(inst[hash->st*2+1]);
1383 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1385 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1389 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1390 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1393 Mem_Free(md2verthash);
1394 Mem_Free(md2verthashdata);
1396 // generate ushort elements array if possible
1397 if (loadmodel->surfmesh.num_vertices <= 65536)
1398 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1399 if (loadmodel->surfmesh.data_element3s)
1400 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1401 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1404 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1405 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1410 pinframe = (md2frame_t *)datapointer;
1411 datapointer += sizeof(md2frame_t);
1412 // store the frame scale/translate into the appropriate array
1413 for (j = 0;j < 3;j++)
1415 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1416 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1418 // convert the vertices
1419 v = (trivertx_t *)datapointer;
1420 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1421 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1422 out[k] = v[vertremap[k]];
1423 datapointer += numxyz * sizeof(trivertx_t);
1425 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1426 loadmodel->animscenes[i].firstframe = i;
1427 loadmodel->animscenes[i].framecount = 1;
1428 loadmodel->animscenes[i].framerate = 10;
1429 loadmodel->animscenes[i].loop = true;
1432 Mem_Free(vertremap);
1434 if (loadmodel->surfmesh.data_neighbor3i)
1435 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1436 Mod_Alias_CalculateBoundingBox();
1437 Mod_Alias_MorphMesh_CompileFrames();
1439 surface = loadmodel->data_surfaces;
1440 surface->texture = loadmodel->data_textures;
1441 surface->num_firsttriangle = 0;
1442 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1443 surface->num_firstvertex = 0;
1444 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1446 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1448 if (!loadmodel->surfmesh.isanimated)
1450 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1451 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1452 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1453 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1454 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1455 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1459 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1461 int i, j, k, version, meshvertices, meshtriangles;
1462 unsigned char *data;
1463 msurface_t *surface;
1464 md3modelheader_t *pinmodel;
1465 md3frameinfo_t *pinframe;
1468 skinfile_t *skinfiles;
1470 pinmodel = (md3modelheader_t *)buffer;
1472 if (memcmp(pinmodel->identifier, "IDP3", 4))
1473 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1474 version = LittleLong (pinmodel->version);
1475 if (version != MD3VERSION)
1476 Host_Error ("%s has wrong version number (%i should be %i)",
1477 loadmodel->name, version, MD3VERSION);
1479 skinfiles = Mod_LoadSkinFiles();
1480 if (loadmodel->numskins < 1)
1481 loadmodel->numskins = 1;
1483 loadmodel->modeldatatypestring = "MD3";
1485 loadmodel->type = mod_alias;
1486 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1487 loadmodel->DrawSky = NULL;
1488 loadmodel->DrawAddWaterPlanes = NULL;
1489 loadmodel->Draw = R_Q1BSP_Draw;
1490 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1491 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1492 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1493 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1494 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1495 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1496 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1497 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1498 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1499 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1500 loadmodel->PointSuperContents = NULL;
1501 loadmodel->synctype = ST_RAND;
1502 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1503 i = LittleLong (pinmodel->flags);
1504 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1506 // set up some global info about the model
1507 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1508 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1510 // make skinscenes for the skins (no groups)
1511 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1512 for (i = 0;i < loadmodel->numskins;i++)
1514 loadmodel->skinscenes[i].firstframe = i;
1515 loadmodel->skinscenes[i].framecount = 1;
1516 loadmodel->skinscenes[i].loop = true;
1517 loadmodel->skinscenes[i].framerate = 10;
1521 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1522 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1524 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1525 loadmodel->animscenes[i].firstframe = i;
1526 loadmodel->animscenes[i].framecount = 1;
1527 loadmodel->animscenes[i].framerate = 10;
1528 loadmodel->animscenes[i].loop = true;
1532 loadmodel->num_tagframes = loadmodel->numframes;
1533 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1534 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1535 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1537 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1538 for (j = 0;j < 9;j++)
1539 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1540 for (j = 0;j < 3;j++)
1541 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1542 //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);
1548 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)))
1550 if (memcmp(pinmesh->identifier, "IDP3", 4))
1551 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1552 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1553 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1554 meshvertices += LittleLong(pinmesh->num_vertices);
1555 meshtriangles += LittleLong(pinmesh->num_triangles);
1558 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1559 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1560 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1561 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (r_enableshadowvolumes.integer ? meshtriangles * sizeof(int[3]) : 0) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshvertices * sizeof(float[2]) + meshvertices * loadmodel->numframes * sizeof(md3vertex_t));
1562 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1563 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1564 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1565 loadmodel->surfmesh.num_vertices = meshvertices;
1566 loadmodel->surfmesh.num_triangles = meshtriangles;
1567 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1568 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1569 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1570 if (r_enableshadowvolumes.integer)
1572 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1574 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1575 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1576 if (meshvertices <= 65536)
1578 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1583 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)))
1585 if (memcmp(pinmesh->identifier, "IDP3", 4))
1586 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1587 loadmodel->sortedmodelsurfaces[i] = i;
1588 surface = loadmodel->data_surfaces + i;
1589 surface->texture = loadmodel->data_textures + i;
1590 surface->num_firsttriangle = meshtriangles;
1591 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1592 surface->num_firstvertex = meshvertices;
1593 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1594 meshvertices += surface->num_vertices;
1595 meshtriangles += surface->num_triangles;
1597 for (j = 0;j < surface->num_triangles * 3;j++)
1598 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1599 for (j = 0;j < surface->num_vertices;j++)
1601 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1602 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1604 for (j = 0;j < loadmodel->numframes;j++)
1606 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1607 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1608 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1610 out->origin[0] = LittleShort(in->origin[0]);
1611 out->origin[1] = LittleShort(in->origin[1]);
1612 out->origin[2] = LittleShort(in->origin[2]);
1613 out->pitch = in->pitch;
1618 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1620 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1622 if (loadmodel->surfmesh.data_element3s)
1623 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1624 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1625 if (loadmodel->surfmesh.data_neighbor3i)
1626 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1627 Mod_Alias_MorphMesh_CompileFrames();
1628 Mod_Alias_CalculateBoundingBox();
1629 Mod_FreeSkinFiles(skinfiles);
1630 Mod_MakeSortedSurfaces(loadmodel);
1632 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1633 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1635 if (!loadmodel->surfmesh.isanimated)
1637 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1638 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1639 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1640 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1641 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1642 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1646 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1648 zymtype1header_t *pinmodel, *pheader;
1649 unsigned char *pbase;
1650 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1651 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose, f, biggestorigin, tempvec[3], modelscale;
1652 zymvertex_t *verts, *vertdata;
1656 skinfile_t *skinfiles;
1657 unsigned char *data;
1658 msurface_t *surface;
1660 pinmodel = (zymtype1header_t *)buffer;
1661 pbase = (unsigned char *)buffer;
1662 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1663 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1664 if (BigLong(pinmodel->type) != 1)
1665 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1667 loadmodel->modeldatatypestring = "ZYM";
1669 loadmodel->type = mod_alias;
1670 loadmodel->synctype = ST_RAND;
1674 pheader->type = BigLong(pinmodel->type);
1675 pheader->filesize = BigLong(pinmodel->filesize);
1676 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1677 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1678 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1679 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1680 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1681 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1682 pheader->radius = BigFloat(pinmodel->radius);
1683 pheader->numverts = BigLong(pinmodel->numverts);
1684 pheader->numtris = BigLong(pinmodel->numtris);
1685 pheader->numshaders = BigLong(pinmodel->numshaders);
1686 pheader->numbones = BigLong(pinmodel->numbones);
1687 pheader->numscenes = BigLong(pinmodel->numscenes);
1688 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1689 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1690 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1691 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1692 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1693 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1694 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1695 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1696 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1697 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1698 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1699 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1700 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1701 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1702 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1703 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1704 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1705 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1707 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1709 Con_Printf("%s has no geometry\n", loadmodel->name);
1712 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1714 Con_Printf("%s has no animations\n", loadmodel->name);
1718 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1719 loadmodel->DrawSky = NULL;
1720 loadmodel->DrawAddWaterPlanes = NULL;
1721 loadmodel->Draw = R_Q1BSP_Draw;
1722 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1723 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1724 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1725 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1726 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1727 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1728 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1729 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1730 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1731 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1732 loadmodel->PointSuperContents = NULL;
1734 loadmodel->numframes = pheader->numscenes;
1735 loadmodel->num_surfaces = pheader->numshaders;
1737 skinfiles = Mod_LoadSkinFiles();
1738 if (loadmodel->numskins < 1)
1739 loadmodel->numskins = 1;
1741 // make skinscenes for the skins (no groups)
1742 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1743 for (i = 0;i < loadmodel->numskins;i++)
1745 loadmodel->skinscenes[i].firstframe = i;
1746 loadmodel->skinscenes[i].framecount = 1;
1747 loadmodel->skinscenes[i].loop = true;
1748 loadmodel->skinscenes[i].framerate = 10;
1752 modelradius = pheader->radius;
1753 for (i = 0;i < 3;i++)
1755 loadmodel->normalmins[i] = pheader->mins[i];
1756 loadmodel->normalmaxs[i] = pheader->maxs[i];
1757 loadmodel->rotatedmins[i] = -modelradius;
1758 loadmodel->rotatedmaxs[i] = modelradius;
1760 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1761 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1762 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1763 if (loadmodel->yawmaxs[0] > modelradius)
1764 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1765 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1766 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1767 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1768 loadmodel->radius = modelradius;
1769 loadmodel->radius2 = modelradius * modelradius;
1771 // go through the lumps, swapping things
1773 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1774 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1775 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1776 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1777 for (i = 0;i < pheader->numscenes;i++)
1779 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1780 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1781 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1782 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1783 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1784 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1785 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1786 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1787 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1788 if (loadmodel->animscenes[i].framerate < 0)
1789 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1793 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1794 loadmodel->num_bones = pheader->numbones;
1795 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1796 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1797 for (i = 0;i < pheader->numbones;i++)
1799 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1800 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1801 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1802 if (loadmodel->data_bones[i].parent >= i)
1803 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1806 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1807 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1808 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1809 for (i = 0;i < pheader->numverts;i++)
1811 vertbonecounts[i] = BigLong(bonecount[i]);
1812 if (vertbonecounts[i] != 1)
1813 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1816 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1818 meshvertices = pheader->numverts;
1819 meshtriangles = pheader->numtris;
1821 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1822 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1823 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1824 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (r_enableshadowvolumes.integer ? meshtriangles * sizeof(int[3]) : 0) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshvertices * sizeof(float[14]) + meshvertices * sizeof(unsigned short) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]) + loadmodel->num_bones * sizeof(float[12]));
1825 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1826 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1827 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1828 loadmodel->surfmesh.num_vertices = meshvertices;
1829 loadmodel->surfmesh.num_triangles = meshtriangles;
1830 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1831 if (r_enableshadowvolumes.integer)
1833 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1835 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1836 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1837 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1838 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1839 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1840 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1841 loadmodel->surfmesh.num_blends = 0;
1842 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
1843 if (loadmodel->surfmesh.num_vertices <= 65536)
1845 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1847 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
1848 loadmodel->surfmesh.data_blendweights = NULL;
1850 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1851 poses = (float *) (pheader->lump_poses.start + pbase);
1852 // figure out scale of model from root bone, for compatibility with old zmodel versions
1853 tempvec[0] = BigFloat(poses[0]);
1854 tempvec[1] = BigFloat(poses[1]);
1855 tempvec[2] = BigFloat(poses[2]);
1856 modelscale = VectorLength(tempvec);
1858 for (i = 0;i < loadmodel->num_bones * numposes * 12;i++)
1860 f = fabs(BigFloat(poses[i]));
1861 biggestorigin = max(biggestorigin, f);
1863 loadmodel->num_posescale = biggestorigin / 32767.0f;
1864 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
1865 for (i = 0;i < numposes;i++)
1867 const float *frameposes = (float *) (pheader->lump_poses.start + pbase) + 12*i*loadmodel->num_bones;
1868 for (j = 0;j < loadmodel->num_bones;j++)
1871 matrix4x4_t posematrix;
1872 for (k = 0;k < 12;k++)
1873 pose[k] = BigFloat(frameposes[j*12+k]);
1874 //if (j < loadmodel->num_bones)
1875 // 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));
1876 // scale child bones to match the root scale
1877 if (loadmodel->data_bones[j].parent >= 0)
1879 pose[3] *= modelscale;
1880 pose[7] *= modelscale;
1881 pose[11] *= modelscale;
1883 // normalize rotation matrix
1884 VectorNormalize(pose + 0);
1885 VectorNormalize(pose + 4);
1886 VectorNormalize(pose + 8);
1887 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
1888 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
1892 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1893 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1894 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1895 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1896 // (converting from weight-blending skeletal animation to
1897 // deformation-based skeletal animation)
1898 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1899 for (i = 0;i < loadmodel->num_bones;i++)
1902 for (k = 0;k < 12;k++)
1903 m[k] = BigFloat(poses[i*12+k]);
1904 if (loadmodel->data_bones[i].parent >= 0)
1905 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1907 for (k = 0;k < 12;k++)
1908 bonepose[12*i+k] = m[k];
1910 for (j = 0;j < pheader->numverts;j++)
1912 // this format really should have had a per vertexweight weight value...
1913 // but since it does not, the weighting is completely ignored and
1914 // only one weight is allowed per vertex
1915 int boneindex = BigLong(vertdata[j].bonenum);
1916 const float *m = bonepose + 12 * boneindex;
1917 float relativeorigin[3];
1918 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1919 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1920 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1921 // transform the vertex bone weight into the base mesh
1922 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1923 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1924 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1925 // store the weight as the primary weight on this vertex
1926 loadmodel->surfmesh.blends[j] = boneindex;
1929 // normals and tangents are calculated after elements are loaded
1931 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1932 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1933 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1934 for (i = 0;i < pheader->numverts;i++)
1936 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1937 // flip T coordinate for OpenGL
1938 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1941 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1942 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1943 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1945 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1946 //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)
1947 // byteswap, validate, and swap winding order of tris
1948 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1949 if (pheader->lump_render.length != count)
1950 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1951 renderlist = (int *) (pheader->lump_render.start + pbase);
1952 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1954 for (i = 0;i < loadmodel->num_surfaces;i++)
1956 int firstvertex, lastvertex;
1957 if (renderlist >= renderlistend)
1958 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1959 count = BigLong(*renderlist);renderlist++;
1960 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1961 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1963 loadmodel->sortedmodelsurfaces[i] = i;
1964 surface = loadmodel->data_surfaces + i;
1965 surface->texture = loadmodel->data_textures + i;
1966 surface->num_firsttriangle = meshtriangles;
1967 surface->num_triangles = count;
1968 meshtriangles += surface->num_triangles;
1970 // load the elements
1971 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
1972 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
1974 outelements[j*3+2] = BigLong(renderlist[0]);
1975 outelements[j*3+1] = BigLong(renderlist[1]);
1976 outelements[j*3+0] = BigLong(renderlist[2]);
1978 // validate the elements and find the used vertex range
1979 firstvertex = meshvertices;
1981 for (j = 0;j < surface->num_triangles * 3;j++)
1983 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
1984 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
1985 firstvertex = min(firstvertex, outelements[j]);
1986 lastvertex = max(lastvertex, outelements[j]);
1988 surface->num_firstvertex = firstvertex;
1989 surface->num_vertices = lastvertex + 1 - firstvertex;
1991 // since zym models do not have named sections, reuse their shader
1992 // name as the section name
1993 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
1994 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
1996 Mod_FreeSkinFiles(skinfiles);
1997 Mem_Free(vertbonecounts);
1999 Mod_MakeSortedSurfaces(loadmodel);
2001 // compute all the mesh information that was not loaded from the file
2002 if (loadmodel->surfmesh.data_element3s)
2003 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2004 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2005 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2006 Mod_BuildBaseBonePoses();
2007 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, r_smoothnormals_areaweighting.integer != 0);
2008 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);
2009 if (loadmodel->surfmesh.data_neighbor3i)
2010 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2012 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2014 if (!loadmodel->surfmesh.isanimated)
2016 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2017 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2018 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2019 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2020 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2021 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2025 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2027 dpmheader_t *pheader;
2031 unsigned char *pbase;
2032 int i, j, k, meshvertices, meshtriangles;
2033 skinfile_t *skinfiles;
2034 unsigned char *data;
2036 float biggestorigin, tempvec[3], modelscale;
2040 pheader = (dpmheader_t *)buffer;
2041 pbase = (unsigned char *)buffer;
2042 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2043 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2044 if (BigLong(pheader->type) != 2)
2045 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2047 loadmodel->modeldatatypestring = "DPM";
2049 loadmodel->type = mod_alias;
2050 loadmodel->synctype = ST_RAND;
2053 pheader->type = BigLong(pheader->type);
2054 pheader->filesize = BigLong(pheader->filesize);
2055 pheader->mins[0] = BigFloat(pheader->mins[0]);
2056 pheader->mins[1] = BigFloat(pheader->mins[1]);
2057 pheader->mins[2] = BigFloat(pheader->mins[2]);
2058 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2059 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2060 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2061 pheader->yawradius = BigFloat(pheader->yawradius);
2062 pheader->allradius = BigFloat(pheader->allradius);
2063 pheader->num_bones = BigLong(pheader->num_bones);
2064 pheader->num_meshs = BigLong(pheader->num_meshs);
2065 pheader->num_frames = BigLong(pheader->num_frames);
2066 pheader->ofs_bones = BigLong(pheader->ofs_bones);
2067 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2068 pheader->ofs_frames = BigLong(pheader->ofs_frames);
2070 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2072 Con_Printf("%s has no geometry\n", loadmodel->name);
2075 if (pheader->num_frames < 1)
2077 Con_Printf("%s has no frames\n", loadmodel->name);
2081 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2082 loadmodel->DrawSky = NULL;
2083 loadmodel->DrawAddWaterPlanes = NULL;
2084 loadmodel->Draw = R_Q1BSP_Draw;
2085 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2086 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2087 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2088 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2089 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2090 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2091 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2092 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2093 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2094 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2095 loadmodel->PointSuperContents = NULL;
2098 for (i = 0;i < 3;i++)
2100 loadmodel->normalmins[i] = pheader->mins[i];
2101 loadmodel->normalmaxs[i] = pheader->maxs[i];
2102 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2103 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2104 loadmodel->rotatedmins[i] = -pheader->allradius;
2105 loadmodel->rotatedmaxs[i] = pheader->allradius;
2107 loadmodel->radius = pheader->allradius;
2108 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2110 // load external .skin files if present
2111 skinfiles = Mod_LoadSkinFiles();
2112 if (loadmodel->numskins < 1)
2113 loadmodel->numskins = 1;
2118 // gather combined statistics from the meshes
2119 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2120 for (i = 0;i < (int)pheader->num_meshs;i++)
2122 int numverts = BigLong(dpmmesh->num_verts);
2123 meshvertices += numverts;
2124 meshtriangles += BigLong(dpmmesh->num_tris);
2128 loadmodel->numframes = pheader->num_frames;
2129 loadmodel->num_bones = pheader->num_bones;
2130 loadmodel->num_poses = loadmodel->numframes;
2131 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2132 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2133 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2134 // do most allocations as one merged chunk
2135 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + (r_enableshadowvolumes.integer ? meshtriangles * sizeof(int[3]) : 0) + meshvertices * (sizeof(float[14]) + sizeof(unsigned short)) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
2136 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2137 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2138 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2139 loadmodel->surfmesh.num_vertices = meshvertices;
2140 loadmodel->surfmesh.num_triangles = meshtriangles;
2141 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2142 if (r_enableshadowvolumes.integer)
2144 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2146 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2147 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2148 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2149 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2150 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2151 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2152 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2153 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2154 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2155 loadmodel->surfmesh.num_blends = 0;
2156 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2157 if (meshvertices <= 65536)
2159 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2161 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2162 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
2164 for (i = 0;i < loadmodel->numskins;i++)
2166 loadmodel->skinscenes[i].firstframe = i;
2167 loadmodel->skinscenes[i].framecount = 1;
2168 loadmodel->skinscenes[i].loop = true;
2169 loadmodel->skinscenes[i].framerate = 10;
2172 // load the bone info
2173 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2174 for (i = 0;i < loadmodel->num_bones;i++)
2176 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2177 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2178 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2179 if (loadmodel->data_bones[i].parent >= i)
2180 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2184 frames = (dpmframe_t *) (pbase + pheader->ofs_frames);
2185 // figure out scale of model from root bone, for compatibility with old dpmodel versions
2186 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2187 tempvec[0] = BigFloat(poses[0]);
2188 tempvec[1] = BigFloat(poses[1]);
2189 tempvec[2] = BigFloat(poses[2]);
2190 modelscale = VectorLength(tempvec);
2192 for (i = 0;i < loadmodel->numframes;i++)
2194 memcpy(loadmodel->animscenes[i].name, frames[i].name, sizeof(frames[i].name));
2195 loadmodel->animscenes[i].firstframe = i;
2196 loadmodel->animscenes[i].framecount = 1;
2197 loadmodel->animscenes[i].loop = true;
2198 loadmodel->animscenes[i].framerate = 10;
2199 // load the bone poses for this frame
2200 poses = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2201 for (j = 0;j < loadmodel->num_bones*12;j++)
2203 f = fabs(BigFloat(poses[j]));
2204 biggestorigin = max(biggestorigin, f);
2206 // stuff not processed here: mins, maxs, yawradius, allradius
2208 loadmodel->num_posescale = biggestorigin / 32767.0f;
2209 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2210 for (i = 0;i < loadmodel->numframes;i++)
2212 const float *frameposes = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2213 for (j = 0;j < loadmodel->num_bones;j++)
2216 matrix4x4_t posematrix;
2217 for (k = 0;k < 12;k++)
2218 pose[k] = BigFloat(frameposes[j*12+k]);
2219 // scale child bones to match the root scale
2220 if (loadmodel->data_bones[j].parent >= 0)
2222 pose[3] *= modelscale;
2223 pose[7] *= modelscale;
2224 pose[11] *= modelscale;
2226 // normalize rotation matrix
2227 VectorNormalize(pose + 0);
2228 VectorNormalize(pose + 4);
2229 VectorNormalize(pose + 8);
2230 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2231 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
2235 // load the meshes now
2236 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2239 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2240 // (converting from weight-blending skeletal animation to
2241 // deformation-based skeletal animation)
2242 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2243 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2244 for (i = 0;i < loadmodel->num_bones;i++)
2247 for (k = 0;k < 12;k++)
2248 m[k] = BigFloat(poses[i*12+k]);
2249 if (loadmodel->data_bones[i].parent >= 0)
2250 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2252 for (k = 0;k < 12;k++)
2253 bonepose[12*i+k] = m[k];
2255 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2257 const int *inelements;
2259 const float *intexcoord;
2260 msurface_t *surface;
2262 loadmodel->sortedmodelsurfaces[i] = i;
2263 surface = loadmodel->data_surfaces + i;
2264 surface->texture = loadmodel->data_textures + i;
2265 surface->num_firsttriangle = meshtriangles;
2266 surface->num_triangles = BigLong(dpmmesh->num_tris);
2267 surface->num_firstvertex = meshvertices;
2268 surface->num_vertices = BigLong(dpmmesh->num_verts);
2269 meshvertices += surface->num_vertices;
2270 meshtriangles += surface->num_triangles;
2272 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2273 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2274 for (j = 0;j < surface->num_triangles;j++)
2276 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2277 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2278 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2279 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2284 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2285 for (j = 0;j < surface->num_vertices*2;j++)
2286 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2288 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2289 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2291 int weightindex[4] = { 0, 0, 0, 0 };
2292 float weightinfluence[4] = { 0, 0, 0, 0 };
2294 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2295 data += sizeof(dpmvertex_t);
2296 for (k = 0;k < numweights;k++)
2298 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2299 int boneindex = BigLong(vert->bonenum);
2300 const float *m = bonepose + 12 * boneindex;
2301 float influence = BigFloat(vert->influence);
2302 float relativeorigin[3], relativenormal[3];
2303 relativeorigin[0] = BigFloat(vert->origin[0]);
2304 relativeorigin[1] = BigFloat(vert->origin[1]);
2305 relativeorigin[2] = BigFloat(vert->origin[2]);
2306 relativenormal[0] = BigFloat(vert->normal[0]);
2307 relativenormal[1] = BigFloat(vert->normal[1]);
2308 relativenormal[2] = BigFloat(vert->normal[2]);
2309 // blend the vertex bone weights into the base mesh
2310 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2311 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2312 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2313 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2314 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2315 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2318 // store the first (and often only) weight
2319 weightinfluence[0] = influence;
2320 weightindex[0] = boneindex;
2324 // sort the new weight into this vertex's weight table
2325 // (which only accepts up to 4 bones per vertex)
2326 for (l = 0;l < 4;l++)
2328 if (weightinfluence[l] < influence)
2330 // move weaker influence weights out of the way first
2332 for (l2 = 3;l2 > l;l2--)
2334 weightinfluence[l2] = weightinfluence[l2-1];
2335 weightindex[l2] = weightindex[l2-1];
2337 // store the new weight
2338 weightinfluence[l] = influence;
2339 weightindex[l] = boneindex;
2344 data += sizeof(dpmbonevert_t);
2346 loadmodel->surfmesh.blends[j] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
2349 // since dpm models do not have named sections, reuse their shader name as the section name
2350 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2352 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2354 if (loadmodel->surfmesh.num_blends < meshvertices)
2355 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2357 Mod_FreeSkinFiles(skinfiles);
2358 Mod_MakeSortedSurfaces(loadmodel);
2360 // compute all the mesh information that was not loaded from the file
2361 if (loadmodel->surfmesh.data_element3s)
2362 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2363 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2364 Mod_BuildBaseBonePoses();
2365 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);
2366 if (loadmodel->surfmesh.data_neighbor3i)
2367 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2369 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2371 if (!loadmodel->surfmesh.isanimated)
2373 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2374 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2375 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2376 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2377 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2378 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2382 // no idea why PSK/PSA files contain weird quaternions but they do...
2383 #define PSKQUATNEGATIONS
2384 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2386 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2387 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2388 fs_offset_t filesize;
2393 pskboneinfo_t *bones;
2394 pskrawweights_t *rawweights;
2395 //pskboneinfo_t *animbones;
2396 pskaniminfo_t *anims;
2397 pskanimkeys_t *animkeys;
2398 void *animfilebuffer, *animbuffer, *animbufferend;
2399 unsigned char *data;
2401 skinfile_t *skinfiles;
2402 char animname[MAX_QPATH];
2404 float biggestorigin;
2406 pchunk = (pskchunk_t *)buffer;
2407 if (strcmp(pchunk->id, "ACTRHEAD"))
2408 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2410 loadmodel->modeldatatypestring = "PSK";
2412 loadmodel->type = mod_alias;
2413 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2414 loadmodel->DrawSky = NULL;
2415 loadmodel->DrawAddWaterPlanes = NULL;
2416 loadmodel->Draw = R_Q1BSP_Draw;
2417 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2418 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2419 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2420 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2421 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2422 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2423 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2424 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2425 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2426 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2427 loadmodel->PointSuperContents = NULL;
2428 loadmodel->synctype = ST_RAND;
2430 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2431 strlcat(animname, ".psa", sizeof(animname));
2432 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2433 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2434 if (animbuffer == NULL)
2435 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2454 while (buffer < bufferend)
2456 pchunk = (pskchunk_t *)buffer;
2457 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2458 version = LittleLong(pchunk->version);
2459 recordsize = LittleLong(pchunk->recordsize);
2460 numrecords = LittleLong(pchunk->numrecords);
2461 if (developer_extra.integer)
2462 Con_DPrintf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2463 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2464 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);
2465 if (!strcmp(pchunk->id, "ACTRHEAD"))
2469 else if (!strcmp(pchunk->id, "PNTS0000"))
2472 if (recordsize != sizeof(*p))
2473 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2474 // byteswap in place and keep the pointer
2475 numpnts = numrecords;
2476 pnts = (pskpnts_t *)buffer;
2477 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2479 p->origin[0] = LittleFloat(p->origin[0]);
2480 p->origin[1] = LittleFloat(p->origin[1]);
2481 p->origin[2] = LittleFloat(p->origin[2]);
2485 else if (!strcmp(pchunk->id, "VTXW0000"))
2488 if (recordsize != sizeof(*p))
2489 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2490 // byteswap in place and keep the pointer
2491 numvtxw = numrecords;
2492 vtxw = (pskvtxw_t *)buffer;
2493 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2495 p->pntsindex = LittleShort(p->pntsindex);
2496 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2497 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2498 if (p->pntsindex >= numpnts)
2500 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2506 else if (!strcmp(pchunk->id, "FACE0000"))
2509 if (recordsize != sizeof(*p))
2510 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2511 // byteswap in place and keep the pointer
2512 numfaces = numrecords;
2513 faces = (pskface_t *)buffer;
2514 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2516 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2517 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2518 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2519 p->group = LittleLong(p->group);
2520 if (p->vtxwindex[0] >= numvtxw)
2522 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2523 p->vtxwindex[0] = 0;
2525 if (p->vtxwindex[1] >= numvtxw)
2527 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2528 p->vtxwindex[1] = 0;
2530 if (p->vtxwindex[2] >= numvtxw)
2532 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2533 p->vtxwindex[2] = 0;
2538 else if (!strcmp(pchunk->id, "MATT0000"))
2541 if (recordsize != sizeof(*p))
2542 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2543 // byteswap in place and keep the pointer
2544 nummatts = numrecords;
2545 matts = (pskmatt_t *)buffer;
2546 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2552 else if (!strcmp(pchunk->id, "REFSKELT"))
2555 if (recordsize != sizeof(*p))
2556 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2557 // byteswap in place and keep the pointer
2558 numbones = numrecords;
2559 bones = (pskboneinfo_t *)buffer;
2560 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2562 p->numchildren = LittleLong(p->numchildren);
2563 p->parent = LittleLong(p->parent);
2564 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2565 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2566 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2567 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2568 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2569 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2570 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2571 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2572 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2573 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2574 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2575 #ifdef PSKQUATNEGATIONS
2578 p->basepose.quat[0] *= -1;
2579 p->basepose.quat[1] *= -1;
2580 p->basepose.quat[2] *= -1;
2584 p->basepose.quat[0] *= 1;
2585 p->basepose.quat[1] *= -1;
2586 p->basepose.quat[2] *= 1;
2589 if (p->parent < 0 || p->parent >= numbones)
2591 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2597 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2600 if (recordsize != sizeof(*p))
2601 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2602 // byteswap in place and keep the pointer
2603 numrawweights = numrecords;
2604 rawweights = (pskrawweights_t *)buffer;
2605 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2607 p->weight = LittleFloat(p->weight);
2608 p->pntsindex = LittleLong(p->pntsindex);
2609 p->boneindex = LittleLong(p->boneindex);
2610 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2612 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2615 if (p->boneindex < 0 || p->boneindex >= numbones)
2617 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2625 while (animbuffer < animbufferend)
2627 pchunk = (pskchunk_t *)animbuffer;
2628 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2629 version = LittleLong(pchunk->version);
2630 recordsize = LittleLong(pchunk->recordsize);
2631 numrecords = LittleLong(pchunk->numrecords);
2632 if (developer_extra.integer)
2633 Con_DPrintf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2634 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2635 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);
2636 if (!strcmp(pchunk->id, "ANIMHEAD"))
2640 else if (!strcmp(pchunk->id, "BONENAMES"))
2643 if (recordsize != sizeof(*p))
2644 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2645 // byteswap in place and keep the pointer
2646 numanimbones = numrecords;
2647 //animbones = (pskboneinfo_t *)animbuffer;
2648 // NOTE: supposedly psa does not need to match the psk model, the
2649 // bones missing from the psa would simply use their base
2650 // positions from the psk, but this is hard for me to implement
2651 // and people can easily make animations that match.
2652 if (numanimbones != numbones)
2653 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2654 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2656 p->numchildren = LittleLong(p->numchildren);
2657 p->parent = LittleLong(p->parent);
2658 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2659 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2660 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2661 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2662 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2663 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2664 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2665 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2666 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2667 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2668 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2669 #ifdef PSKQUATNEGATIONS
2672 p->basepose.quat[0] *= -1;
2673 p->basepose.quat[1] *= -1;
2674 p->basepose.quat[2] *= -1;
2678 p->basepose.quat[0] *= 1;
2679 p->basepose.quat[1] *= -1;
2680 p->basepose.quat[2] *= 1;
2683 if (p->parent < 0 || p->parent >= numanimbones)
2685 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2688 // check that bones are the same as in the base
2689 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2690 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2694 else if (!strcmp(pchunk->id, "ANIMINFO"))
2697 if (recordsize != sizeof(*p))
2698 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2699 // byteswap in place and keep the pointer
2700 numanims = numrecords;
2701 anims = (pskaniminfo_t *)animbuffer;
2702 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2704 p->numbones = LittleLong(p->numbones);
2705 p->playtime = LittleFloat(p->playtime);
2706 p->fps = LittleFloat(p->fps);
2707 p->firstframe = LittleLong(p->firstframe);
2708 p->numframes = LittleLong(p->numframes);
2709 if (p->numbones != numbones)
2710 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2714 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2717 if (recordsize != sizeof(*p))
2718 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2719 numanimkeys = numrecords;
2720 animkeys = (pskanimkeys_t *)animbuffer;
2721 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2723 p->origin[0] = LittleFloat(p->origin[0]);
2724 p->origin[1] = LittleFloat(p->origin[1]);
2725 p->origin[2] = LittleFloat(p->origin[2]);
2726 p->quat[0] = LittleFloat(p->quat[0]);
2727 p->quat[1] = LittleFloat(p->quat[1]);
2728 p->quat[2] = LittleFloat(p->quat[2]);
2729 p->quat[3] = LittleFloat(p->quat[3]);
2730 p->frametime = LittleFloat(p->frametime);
2731 #ifdef PSKQUATNEGATIONS
2732 if (index % numbones)
2747 // TODO: allocate bonepose stuff
2750 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2753 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2754 Host_Error("%s: missing required chunks", loadmodel->name);
2756 loadmodel->numframes = 0;
2757 for (index = 0;index < numanims;index++)
2758 loadmodel->numframes += anims[index].numframes;
2760 if (numanimkeys != numbones * loadmodel->numframes)
2761 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2763 meshvertices = numvtxw;
2764 meshtriangles = numfaces;
2766 // load external .skin files if present
2767 skinfiles = Mod_LoadSkinFiles();
2768 if (loadmodel->numskins < 1)
2769 loadmodel->numskins = 1;
2770 loadmodel->num_bones = numbones;
2771 loadmodel->num_poses = loadmodel->numframes;
2772 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2773 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2774 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2775 loadmodel->surfmesh.num_vertices = meshvertices;
2776 loadmodel->surfmesh.num_triangles = meshtriangles;
2777 // do most allocations as one merged chunk
2778 size = loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + loadmodel->surfmesh.num_triangles * sizeof(int[3]) + (r_enableshadowvolumes.integer ? loadmodel->surfmesh.num_triangles * sizeof(int[3]) : 0) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[2]) + loadmodel->surfmesh.num_vertices * sizeof(unsigned short) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t) + ((loadmodel->surfmesh.num_vertices <= 65536) ? (loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3])) : 0);
2779 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2780 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2781 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2782 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2783 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2784 if (r_enableshadowvolumes.integer)
2786 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2788 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2789 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2790 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2791 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2792 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2793 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2794 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2795 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2796 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2797 loadmodel->surfmesh.num_blends = 0;
2798 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2799 if (loadmodel->surfmesh.num_vertices <= 65536)
2801 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2803 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2804 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(blendweights_t));
2806 for (i = 0;i < loadmodel->numskins;i++)
2808 loadmodel->skinscenes[i].firstframe = i;
2809 loadmodel->skinscenes[i].framecount = 1;
2810 loadmodel->skinscenes[i].loop = true;
2811 loadmodel->skinscenes[i].framerate = 10;
2815 for (index = 0, i = 0;index < nummatts;index++)
2817 // since psk models do not have named sections, reuse their shader name as the section name
2818 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2819 loadmodel->sortedmodelsurfaces[index] = index;
2820 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2821 loadmodel->data_surfaces[index].num_firstvertex = 0;
2822 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2825 // copy over the vertex locations and texcoords
2826 for (index = 0;index < numvtxw;index++)
2828 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2829 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2830 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2831 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2832 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2835 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2836 for (index = 0;index < numfaces;index++)
2837 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2838 for (index = 0, i = 0;index < nummatts;index++)
2840 loadmodel->data_surfaces[index].num_firsttriangle = i;
2841 i += loadmodel->data_surfaces[index].num_triangles;
2842 loadmodel->data_surfaces[index].num_triangles = 0;
2844 for (index = 0;index < numfaces;index++)
2846 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2847 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2848 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2849 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2852 // copy over the bones
2853 for (index = 0;index < numbones;index++)
2855 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2856 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2857 if (loadmodel->data_bones[index].parent >= index)
2858 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2861 // sort the psk point weights into the vertex weight tables
2862 // (which only accept up to 4 bones per vertex)
2863 for (index = 0;index < numvtxw;index++)
2865 int weightindex[4] = { 0, 0, 0, 0 };
2866 float weightinfluence[4] = { 0, 0, 0, 0 };
2868 for (j = 0;j < numrawweights;j++)
2870 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2872 int boneindex = rawweights[j].boneindex;
2873 float influence = rawweights[j].weight;
2874 for (l = 0;l < 4;l++)
2876 if (weightinfluence[l] < influence)
2878 // move lower influence weights out of the way first
2880 for (l2 = 3;l2 > l;l2--)
2882 weightinfluence[l2] = weightinfluence[l2-1];
2883 weightindex[l2] = weightindex[l2-1];
2885 // store the new weight
2886 weightinfluence[l] = influence;
2887 weightindex[l] = boneindex;
2893 loadmodel->surfmesh.blends[index] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
2895 if (loadmodel->surfmesh.num_blends < loadmodel->surfmesh.num_vertices)
2896 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2898 // set up the animscenes based on the anims
2899 for (index = 0, i = 0;index < numanims;index++)
2901 for (j = 0;j < anims[index].numframes;j++, i++)
2903 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2904 loadmodel->animscenes[i].firstframe = i;
2905 loadmodel->animscenes[i].framecount = 1;
2906 loadmodel->animscenes[i].loop = true;
2907 loadmodel->animscenes[i].framerate = anims[index].fps;
2911 // calculate the scaling value for bone origins so they can be compressed to short
2913 for (index = 0;index < numanimkeys;index++)
2915 pskanimkeys_t *k = animkeys + index;
2916 biggestorigin = max(biggestorigin, fabs(k->origin[0]));
2917 biggestorigin = max(biggestorigin, fabs(k->origin[1]));
2918 biggestorigin = max(biggestorigin, fabs(k->origin[2]));
2920 loadmodel->num_posescale = biggestorigin / 32767.0f;
2921 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2923 // load the poses from the animkeys
2924 for (index = 0;index < numanimkeys;index++)
2926 pskanimkeys_t *k = animkeys + index;
2928 Vector4Copy(k->quat, quat);
2930 Vector4Negate(quat, quat);
2931 Vector4Normalize2(quat, quat);
2932 // compress poses to the short[6] format for longterm storage
2933 loadmodel->data_poses6s[index*6+0] = k->origin[0] * loadmodel->num_poseinvscale;
2934 loadmodel->data_poses6s[index*6+1] = k->origin[1] * loadmodel->num_poseinvscale;
2935 loadmodel->data_poses6s[index*6+2] = k->origin[2] * loadmodel->num_poseinvscale;
2936 loadmodel->data_poses6s[index*6+3] = quat[0] * 32767.0f;
2937 loadmodel->data_poses6s[index*6+4] = quat[1] * 32767.0f;
2938 loadmodel->data_poses6s[index*6+5] = quat[2] * 32767.0f;
2940 Mod_FreeSkinFiles(skinfiles);
2941 Mem_Free(animfilebuffer);
2942 Mod_MakeSortedSurfaces(loadmodel);
2944 // compute all the mesh information that was not loaded from the file
2945 // TODO: honor smoothing groups somehow?
2946 if (loadmodel->surfmesh.data_element3s)
2947 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2948 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2949 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2950 Mod_BuildBaseBonePoses();
2951 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, r_smoothnormals_areaweighting.integer != 0);
2952 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);
2953 if (loadmodel->surfmesh.data_neighbor3i)
2954 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2955 Mod_Alias_CalculateBoundingBox();
2957 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2959 if (!loadmodel->surfmesh.isanimated)
2961 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2962 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2963 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2964 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2965 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2966 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2970 void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2972 unsigned char *data;
2974 const unsigned char *pbase, *pend;
2976 skinfile_t *skinfiles;
2977 int i, j, k, meshvertices, meshtriangles;
2978 float biggestorigin;
2979 const unsigned int *inelements;
2981 const int *inneighbors;
2983 float *outvertex, *outnormal, *outtexcoord, *outsvector, *outtvector;
2984 // this pointers into the file data are read only through Little* functions so they can be unaligned memory
2985 const float *vnormal = NULL;
2986 const float *vposition = NULL;
2987 const float *vtangent = NULL;
2988 const float *vtexcoord = NULL;
2989 const unsigned char *vblendindexes = NULL;
2990 const unsigned char *vblendweights = NULL;
2991 const unsigned short *framedata = NULL;
2992 // temporary memory allocations (because the data in the file may be misaligned)
2993 iqmanim_t *anims = NULL;
2994 iqmbounds_t *bounds = NULL;
2995 iqmjoint1_t *joint1 = NULL;
2996 iqmjoint_t *joint = NULL;
2997 iqmmesh_t *meshes = NULL;
2998 iqmpose1_t *pose1 = NULL;
2999 iqmpose_t *pose = NULL;
3000 iqmvertexarray_t *vas = NULL;
3002 pbase = (unsigned char *)buffer;
3003 pend = (unsigned char *)bufferend;
3005 if (pbase + sizeof(iqmheader_t) > pend)
3006 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model %d", loadmodel->name, (int)(pend - pbase));
3008 // copy struct (otherwise it may be misaligned)
3009 // LordHavoc: okay it's definitely not misaligned here, but for consistency...
3010 memcpy(&header, pbase, sizeof(iqmheader_t));
3012 if (memcmp(header.id, "INTERQUAKEMODEL", 16))
3013 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model", loadmodel->name);
3014 if (LittleLong(header.version) != 1 && LittleLong(header.version) != 2)
3015 Host_Error ("Mod_INTERQUAKEMODEL_Load: only version 1 and 2 models are currently supported (name = %s)", loadmodel->name);
3017 loadmodel->modeldatatypestring = "IQM";
3019 loadmodel->type = mod_alias;
3020 loadmodel->synctype = ST_RAND;
3023 header.version = LittleLong(header.version);
3024 header.filesize = LittleLong(header.filesize);
3025 header.flags = LittleLong(header.flags);
3026 header.num_text = LittleLong(header.num_text);
3027 header.ofs_text = LittleLong(header.ofs_text);
3028 header.num_meshes = LittleLong(header.num_meshes);
3029 header.ofs_meshes = LittleLong(header.ofs_meshes);
3030 header.num_vertexarrays = LittleLong(header.num_vertexarrays);
3031 header.num_vertexes = LittleLong(header.num_vertexes);
3032 header.ofs_vertexarrays = LittleLong(header.ofs_vertexarrays);
3033 header.num_triangles = LittleLong(header.num_triangles);
3034 header.ofs_triangles = LittleLong(header.ofs_triangles);
3035 header.ofs_neighbors = LittleLong(header.ofs_neighbors);
3036 header.num_joints = LittleLong(header.num_joints);
3037 header.ofs_joints = LittleLong(header.ofs_joints);
3038 header.num_poses = LittleLong(header.num_poses);
3039 header.ofs_poses = LittleLong(header.ofs_poses);
3040 header.num_anims = LittleLong(header.num_anims);
3041 header.ofs_anims = LittleLong(header.ofs_anims);
3042 header.num_frames = LittleLong(header.num_frames);
3043 header.num_framechannels = LittleLong(header.num_framechannels);
3044 header.ofs_frames = LittleLong(header.ofs_frames);
3045 header.ofs_bounds = LittleLong(header.ofs_bounds);
3046 header.num_comment = LittleLong(header.num_comment);
3047 header.ofs_comment = LittleLong(header.ofs_comment);
3048 header.num_extensions = LittleLong(header.num_extensions);
3049 header.ofs_extensions = LittleLong(header.ofs_extensions);
3051 if (header.num_triangles < 1 || header.num_vertexes < 3 || header.num_vertexarrays < 1 || header.num_meshes < 1)
3053 Con_Printf("%s has no geometry\n", loadmodel->name);
3057 if (header.version == 1)
3059 if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint1_t) > pend ||
3060 pbase + header.ofs_poses + header.num_poses*sizeof(iqmpose1_t) > pend)
3062 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3068 if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint_t) > pend ||
3069 pbase + header.ofs_poses + header.num_poses*sizeof(iqmpose_t) > pend)
3071 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3075 if (pbase + header.ofs_text + header.num_text > pend ||
3076 pbase + header.ofs_meshes + header.num_meshes*sizeof(iqmmesh_t) > pend ||
3077 pbase + header.ofs_vertexarrays + header.num_vertexarrays*sizeof(iqmvertexarray_t) > pend ||
3078 pbase + header.ofs_triangles + header.num_triangles*sizeof(int[3]) > pend ||
3079 (header.ofs_neighbors && pbase + header.ofs_neighbors + header.num_triangles*sizeof(int[3]) > pend) ||
3080 pbase + header.ofs_anims + header.num_anims*sizeof(iqmanim_t) > pend ||
3081 pbase + header.ofs_frames + header.num_frames*header.num_framechannels*sizeof(unsigned short) > pend ||
3082 (header.ofs_bounds && pbase + header.ofs_bounds + header.num_frames*sizeof(iqmbounds_t) > pend) ||
3083 pbase + header.ofs_comment + header.num_comment > pend)
3085 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3089 // copy structs to make them aligned in memory (otherwise we crash on Sparc and PowerPC and others)
3090 if (header.num_vertexarrays)
3091 vas = (iqmvertexarray_t *)(pbase + header.ofs_vertexarrays);
3092 if (header.num_anims)
3093 anims = (iqmanim_t *)(pbase + header.ofs_anims);
3094 if (header.ofs_bounds)
3095 bounds = (iqmbounds_t *)(pbase + header.ofs_bounds);
3096 if (header.num_meshes)
3097 meshes = (iqmmesh_t *)(pbase + header.ofs_meshes);
3099 for (i = 0;i < (int)header.num_vertexarrays;i++)
3101 iqmvertexarray_t va;
3103 va.type = LittleLong(vas[i].type);
3104 va.flags = LittleLong(vas[i].flags);
3105 va.format = LittleLong(vas[i].format);
3106 va.size = LittleLong(vas[i].size);
3107 va.offset = LittleLong(vas[i].offset);
3108 vsize = header.num_vertexes*va.size;
3111 case IQM_FLOAT: vsize *= sizeof(float); break;
3112 case IQM_UBYTE: vsize *= sizeof(unsigned char); break;
3115 if (pbase + va.offset + vsize > pend)
3117 // no need to copy the vertex data for alignment because LittleLong/LittleShort will be invoked on reading them, and the destination is aligned
3121 if (va.format == IQM_FLOAT && va.size == 3)
3122 vposition = (const float *)(pbase + va.offset);
3125 if (va.format == IQM_FLOAT && va.size == 2)
3126 vtexcoord = (const float *)(pbase + va.offset);
3129 if (va.format == IQM_FLOAT && va.size == 3)
3130 vnormal = (const float *)(pbase + va.offset);
3133 if (va.format == IQM_FLOAT && va.size == 4)
3134 vtangent = (const float *)(pbase + va.offset);
3136 case IQM_BLENDINDEXES:
3137 if (va.format == IQM_UBYTE && va.size == 4)
3138 vblendindexes = (const unsigned char *)(pbase + va.offset);
3140 case IQM_BLENDWEIGHTS:
3141 if (va.format == IQM_UBYTE && va.size == 4)
3142 vblendweights = (const unsigned char *)(pbase + va.offset);
3146 if (header.num_vertexes > 0 && (!vposition || !vtexcoord || ((header.num_frames > 0 || header.num_anims > 0) && (!vblendindexes || !vblendweights))))
3148 Con_Printf("%s is missing vertex array data\n", loadmodel->name);
3152 text = header.num_text && header.ofs_text ? (const char *)(pbase + header.ofs_text) : "";
3154 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
3155 loadmodel->DrawSky = NULL;
3156 loadmodel->DrawAddWaterPlanes = NULL;
3157 loadmodel->Draw = R_Q1BSP_Draw;
3158 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
3159 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
3160 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
3161 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
3162 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
3163 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
3164 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
3165 loadmodel->DrawLight = R_Q1BSP_DrawLight;
3166 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
3167 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
3168 loadmodel->PointSuperContents = NULL;
3170 // load external .skin files if present
3171 skinfiles = Mod_LoadSkinFiles();
3172 if (loadmodel->numskins < 1)
3173 loadmodel->numskins = 1;
3175 loadmodel->numframes = max(header.num_anims, 1);
3176 loadmodel->num_bones = header.num_joints;
3177 loadmodel->num_poses = max(header.num_frames, 1);
3178 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = header.num_meshes;
3179 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3180 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3182 meshvertices = header.num_vertexes;
3183 meshtriangles = header.num_triangles;
3185 // do most allocations as one merged chunk
3186 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + (r_enableshadowvolumes.integer ? meshtriangles * sizeof(int[3]) : 0) + meshvertices * sizeof(float[14]) + (vblendindexes && vblendweights ? meshvertices * sizeof(unsigned short) : 0) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
3187 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
3188 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
3189 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
3190 loadmodel->surfmesh.num_vertices = meshvertices;
3191 loadmodel->surfmesh.num_triangles = meshtriangles;
3192 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3193 if (r_enableshadowvolumes.integer)
3195 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3197 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
3198 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3199 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3200 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
3201 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
3202 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
3203 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
3204 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
3205 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
3206 if (vblendindexes && vblendweights)
3208 loadmodel->surfmesh.num_blends = 0;
3209 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
3211 if (meshvertices <= 65536)
3213 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
3215 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
3216 if (vblendindexes && vblendweights)
3217 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
3219 for (i = 0;i < loadmodel->numskins;i++)
3221 loadmodel->skinscenes[i].firstframe = i;
3222 loadmodel->skinscenes[i].framecount = 1;
3223 loadmodel->skinscenes[i].loop = true;
3224 loadmodel->skinscenes[i].framerate = 10;
3227 // load the bone info
3228 if (header.version == 1)
3230 iqmjoint1_t *injoint1 = (iqmjoint1_t *)(pbase + header.ofs_joints);
3231 if (loadmodel->num_bones)
3232 joint1 = (iqmjoint1_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(iqmjoint1_t));
3233 for (i = 0;i < loadmodel->num_bones;i++)
3235 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3236 joint1[i].name = LittleLong(injoint1[i].name);
3237 joint1[i].parent = LittleLong(injoint1[i].parent);
3238 for (j = 0;j < 3;j++)
3240 joint1[i].origin[j] = LittleFloat(injoint1[i].origin[j]);
3241 joint1[i].rotation[j] = LittleFloat(injoint1[i].rotation[j]);
3242 joint1[i].scale[j] = LittleFloat(injoint1[i].scale[j]);
3244 strlcpy(loadmodel->data_bones[i].name, &text[joint1[i].name], sizeof(loadmodel->data_bones[i].name));
3245 loadmodel->data_bones[i].parent = joint1[i].parent;
3246 if (loadmodel->data_bones[i].parent >= i)
3247 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3248 Matrix4x4_FromDoom3Joint(&relbase, joint1[i].origin[0], joint1[i].origin[1], joint1[i].origin[2], joint1[i].rotation[0], joint1[i].rotation[1], joint1[i].rotation[2]);
3249 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3250 if (loadmodel->data_bones[i].parent >= 0)
3252 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3253 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3254 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3256 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3261 iqmjoint_t *injoint = (iqmjoint_t *)(pbase + header.ofs_joints);
3262 if (header.num_joints)
3263 joint = (iqmjoint_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(iqmjoint_t));
3264 for (i = 0;i < loadmodel->num_bones;i++)
3266 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3267 joint[i].name = LittleLong(injoint[i].name);
3268 joint[i].parent = LittleLong(injoint[i].parent);
3269 for (j = 0;j < 3;j++)
3271 joint[i].origin[j] = LittleFloat(injoint[i].origin[j]);
3272 joint[i].rotation[j] = LittleFloat(injoint[i].rotation[j]);
3273 joint[i].scale[j] = LittleFloat(injoint[i].scale[j]);
3275 joint[i].rotation[3] = LittleFloat(injoint[i].rotation[3]);
3276 strlcpy(loadmodel->data_bones[i].name, &text[joint[i].name], sizeof(loadmodel->data_bones[i].name));
3277 loadmodel->data_bones[i].parent = joint[i].parent;
3278 if (loadmodel->data_bones[i].parent >= i)
3279 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3280 if (joint[i].rotation[3] > 0)
3281 Vector4Negate(joint[i].rotation, joint[i].rotation);
3282 Vector4Normalize2(joint[i].rotation, joint[i].rotation);
3283 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]);
3284 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3285 if (loadmodel->data_bones[i].parent >= 0)
3287 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3288 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3289 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3291 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3295 // set up the animscenes based on the anims
3296 for (i = 0;i < (int)header.num_anims;i++)
3299 anim.name = LittleLong(anims[i].name);
3300 anim.first_frame = LittleLong(anims[i].first_frame);
3301 anim.num_frames = LittleLong(anims[i].num_frames);
3302 anim.framerate = LittleFloat(anims[i].framerate);
3303 anim.flags = LittleLong(anims[i].flags);
3304 strlcpy(loadmodel->animscenes[i].name, &text[anim.name], sizeof(loadmodel->animscenes[i].name));
3305 loadmodel->animscenes[i].firstframe = anim.first_frame;
3306 loadmodel->animscenes[i].framecount = anim.num_frames;
3307 loadmodel->animscenes[i].loop = ((anim.flags & IQM_LOOP) != 0);
3308 loadmodel->animscenes[i].framerate = anim.framerate;
3310 if (header.num_anims <= 0)
3312 strlcpy(loadmodel->animscenes[0].name, "static", sizeof(loadmodel->animscenes[0].name));
3313 loadmodel->animscenes[0].firstframe = 0;
3314 loadmodel->animscenes[0].framecount = 1;
3315 loadmodel->animscenes[0].loop = true;
3316 loadmodel->animscenes[0].framerate = 10;
3320 if (header.version == 1)
3322 iqmpose1_t *inpose1 = (iqmpose1_t *)(pbase + header.ofs_poses);
3323 if (header.num_poses)
3324 pose1 = (iqmpose1_t *)Mem_Alloc(loadmodel->mempool, header.num_poses * sizeof(iqmpose1_t));
3325 for (i = 0;i < (int)header.num_poses;i++)
3328 pose1[i].parent = LittleLong(inpose1[i].parent);
3329 pose1[i].channelmask = LittleLong(inpose1[i].channelmask);
3330 for (j = 0;j < 9;j++)
3332 pose1[i].channeloffset[j] = LittleFloat(inpose1[i].channeloffset[j]);
3333 pose1[i].channelscale[j] = LittleFloat(inpose1[i].channelscale[j]);
3335 f = fabs(pose1[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3336 f = fabs(pose1[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3337 f = fabs(pose1[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3338 f = fabs(pose1[i].channeloffset[0] + 0xFFFF*pose1[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3339 f = fabs(pose1[i].channeloffset[1] + 0xFFFF*pose1[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3340 f = fabs(pose1[i].channeloffset[2] + 0xFFFF*pose1[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3342 if (header.num_frames <= 0)
3344 for (i = 0;i < loadmodel->num_bones;i++)
3347 f = fabs(joint1[i].origin[0]); biggestorigin = max(biggestorigin, f);
3348 f = fabs(joint1[i].origin[1]); biggestorigin = max(biggestorigin, f);
3349 f = fabs(joint1[i].origin[2]); biggestorigin = max(biggestorigin, f);
3355 iqmpose_t *inpose = (iqmpose_t *)(pbase + header.ofs_poses);
3356 if (header.num_poses)
3357 pose = (iqmpose_t *)Mem_Alloc(loadmodel->mempool, header.num_poses * sizeof(iqmpose_t));
3358 for (i = 0;i < (int)header.num_poses;i++)
3361 pose[i].parent = LittleLong(inpose[i].parent);
3362 pose[i].channelmask = LittleLong(inpose[i].channelmask);
3363 for (j = 0;j < 10;j++)
3365 pose[i].channeloffset[j] = LittleFloat(inpose[i].channeloffset[j]);
3366 pose[i].channelscale[j] = LittleFloat(inpose[i].channelscale[j]);
3368 f = fabs(pose[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3369 f = fabs(pose[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3370 f = fabs(pose[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3371 f = fabs(pose[i].channeloffset[0] + 0xFFFF*pose[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3372 f = fabs(pose[i].channeloffset[1] + 0xFFFF*pose[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3373 f = fabs(pose[i].channeloffset[2] + 0xFFFF*pose[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3375 if (header.num_frames <= 0)
3377 for (i = 0;i < loadmodel->num_bones;i++)
3380 f = fabs(joint[i].origin[0]); biggestorigin = max(biggestorigin, f);
3381 f = fabs(joint[i].origin[1]); biggestorigin = max(biggestorigin, f);
3382 f = fabs(joint[i].origin[2]); biggestorigin = max(biggestorigin, f);
3386 loadmodel->num_posescale = biggestorigin / 32767.0f;
3387 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3389 // load the pose data
3390 // this unaligned memory access is safe (LittleShort reads as bytes)
3391 framedata = (const unsigned short *)(pbase + header.ofs_frames);
3392 if (header.version == 1)
3394 for (i = 0, k = 0;i < (int)header.num_frames;i++)
3396 for (j = 0;j < (int)header.num_poses;j++, k++)
3398 loadmodel->data_poses6s[k*6 + 0] = loadmodel->num_poseinvscale * (pose1[j].channeloffset[0] + (pose1[j].channelmask&1 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[0] : 0));
3399 loadmodel->data_poses6s[k*6 + 1] = loadmodel->num_poseinvscale * (pose1[j].channeloffset[1] + (pose1[j].channelmask&2 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[1] : 0));
3400 loadmodel->data_poses6s[k*6 + 2] = loadmodel->num_poseinvscale * (pose1[j].channeloffset[2] + (pose1[j].channelmask&4 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[2] : 0));
3401 loadmodel->data_poses6s[k*6 + 3] = 32767.0f * (pose1[j].channeloffset[3] + (pose1[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[3] : 0));
3402 loadmodel->data_poses6s[k*6 + 4] = 32767.0f * (pose1[j].channeloffset[4] + (pose1[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[4] : 0));
3403 loadmodel->data_poses6s[k*6 + 5] = 32767.0f * (pose1[j].channeloffset[5] + (pose1[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[5] : 0));
3404 // skip scale data for now
3405 if(pose1[j].channelmask&64) framedata++;
3406 if(pose1[j].channelmask&128) framedata++;
3407 if(pose1[j].channelmask&256) framedata++;
3410 if (header.num_frames <= 0)
3412 for (i = 0;i < loadmodel->num_bones;i++)
3414 loadmodel->data_poses6s[i*6 + 0] = loadmodel->num_poseinvscale * joint1[i].origin[0];
3415 loadmodel->data_poses6s[i*6 + 1] = loadmodel->num_poseinvscale * joint1[i].origin[1];
3416 loadmodel->data_poses6s[i*6 + 2] = loadmodel->num_poseinvscale * joint1[i].origin[2];
3417 loadmodel->data_poses6s[i*6 + 3] = 32767.0f * joint1[i].rotation[0];
3418 loadmodel->data_poses6s[i*6 + 4] = 32767.0f * joint1[i].rotation[1];
3419 loadmodel->data_poses6s[i*6 + 5] = 32767.0f * joint1[i].rotation[2];
3425 for (i = 0, k = 0;i < (int)header.num_frames;i++)
3427 for (j = 0;j < (int)header.num_poses;j++, k++)
3430 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));
3431 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));
3432 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));
3433 rot[0] = pose[j].channeloffset[3] + (pose[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[3] : 0);
3434 rot[1] = pose[j].channeloffset[4] + (pose[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[4] : 0);
3435 rot[2] = pose[j].channeloffset[5] + (pose[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[5] : 0);
3436 rot[3] = pose[j].channeloffset[6] + (pose[j].channelmask&64 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[6] : 0);
3438 Vector4Negate(rot, rot);
3439 Vector4Normalize2(rot, rot);
3440 loadmodel->data_poses6s[k*6 + 3] = 32767.0f * rot[0];
3441 loadmodel->data_poses6s[k*6 + 4] = 32767.0f * rot[1];
3442 loadmodel->data_poses6s[k*6 + 5] = 32767.0f * rot[2];
3443 // skip scale data for now
3444 if(pose[j].channelmask&128) framedata++;
3445 if(pose[j].channelmask&256) framedata++;
3446 if(pose[j].channelmask&512) framedata++;
3449 if (header.num_frames <= 0)
3451 for (i = 0;i < loadmodel->num_bones;i++)
3453 loadmodel->data_poses6s[i*6 + 0] = loadmodel->num_poseinvscale * joint[i].origin[0];
3454 loadmodel->data_poses6s[i*6 + 1] = loadmodel->num_poseinvscale * joint[i].origin[1];
3455 loadmodel->data_poses6s[i*6 + 2] = loadmodel->num_poseinvscale * joint[i].origin[2];
3456 loadmodel->data_poses6s[i*6 + 3] = 32767.0f * joint[i].rotation[0];
3457 loadmodel->data_poses6s[i*6 + 4] = 32767.0f * joint[i].rotation[1];
3458 loadmodel->data_poses6s[i*6 + 5] = 32767.0f * joint[i].rotation[2];
3463 // load bounding box data
3464 if (header.ofs_bounds)
3466 float xyradius = 0, radius = 0;
3467 VectorClear(loadmodel->normalmins);
3468 VectorClear(loadmodel->normalmaxs);
3469 for (i = 0; i < (int)header.num_frames;i++)
3472 bound.mins[0] = LittleFloat(bounds[i].mins[0]);
3473 bound.mins[1] = LittleFloat(bounds[i].mins[1]);
3474 bound.mins[2] = LittleFloat(bounds[i].mins[2]);
3475 bound.maxs[0] = LittleFloat(bounds[i].maxs[0]);
3476 bound.maxs[1] = LittleFloat(bounds[i].maxs[1]);
3477 bound.maxs[2] = LittleFloat(bounds[i].maxs[2]);
3478 bound.xyradius = LittleFloat(bounds[i].xyradius);
3479 bound.radius = LittleFloat(bounds[i].radius);
3482 VectorCopy(bound.mins, loadmodel->normalmins);
3483 VectorCopy(bound.maxs, loadmodel->normalmaxs);
3487 if (loadmodel->normalmins[0] > bound.mins[0]) loadmodel->normalmins[0] = bound.mins[0];
3488 if (loadmodel->normalmins[1] > bound.mins[1]) loadmodel->normalmins[1] = bound.mins[1];
3489 if (loadmodel->normalmins[2] > bound.mins[2]) loadmodel->normalmins[2] = bound.mins[2];
3490 if (loadmodel->normalmaxs[0] < bound.maxs[0]) loadmodel->normalmaxs[0] = bound.maxs[0];
3491 if (loadmodel->normalmaxs[1] < bound.maxs[1]) loadmodel->normalmaxs[1] = bound.maxs[1];
3492 if (loadmodel->normalmaxs[2] < bound.maxs[2]) loadmodel->normalmaxs[2] = bound.maxs[2];
3494 if (bound.xyradius > xyradius)
3495 xyradius = bound.xyradius;
3496 if (bound.radius > radius)
3497 radius = bound.radius;
3499 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -xyradius;
3500 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = xyradius;
3501 loadmodel->yawmins[2] = loadmodel->normalmins[2];
3502 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
3503 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
3504 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
3505 loadmodel->radius = radius;
3506 loadmodel->radius2 = radius * radius;
3509 // load triangle data
3510 // this unaligned memory access is safe (LittleLong reads as bytes)
3511 inelements = (const unsigned int *)(pbase + header.ofs_triangles);
3512 outelements = loadmodel->surfmesh.data_element3i;
3513 for (i = 0;i < (int)header.num_triangles;i++)
3515 outelements[0] = LittleLong(inelements[0]);
3516 outelements[1] = LittleLong(inelements[1]);
3517 outelements[2] = LittleLong(inelements[2]);
3521 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, header.num_vertexes, __FILE__, __LINE__);
3523 if (header.ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
3525 // this unaligned memory access is safe (LittleLong reads as bytes)
3526 inneighbors = (const int *)(pbase + header.ofs_neighbors);
3527 outneighbors = loadmodel->surfmesh.data_neighbor3i;
3528 for (i = 0;i < (int)header.num_triangles;i++)
3530 outneighbors[0] = LittleLong(inneighbors[0]);
3531 outneighbors[1] = LittleLong(inneighbors[1]);
3532 outneighbors[2] = LittleLong(inneighbors[2]);
3539 // this unaligned memory access is safe (LittleFloat reads as bytes)
3540 outvertex = loadmodel->surfmesh.data_vertex3f;
3541 for (i = 0;i < (int)header.num_vertexes;i++)
3543 outvertex[0] = LittleFloat(vposition[0]);
3544 outvertex[1] = LittleFloat(vposition[1]);
3545 outvertex[2] = LittleFloat(vposition[2]);
3550 outtexcoord = loadmodel->surfmesh.data_texcoordtexture2f;
3551 // this unaligned memory access is safe (LittleFloat reads as bytes)
3552 for (i = 0;i < (int)header.num_vertexes;i++)
3554 outtexcoord[0] = LittleFloat(vtexcoord[0]);
3555 outtexcoord[1] = LittleFloat(vtexcoord[1]);
3560 // this unaligned memory access is safe (LittleFloat reads as bytes)
3563 outnormal = loadmodel->surfmesh.data_normal3f;
3564 for (i = 0;i < (int)header.num_vertexes;i++)
3566 outnormal[0] = LittleFloat(vnormal[0]);
3567 outnormal[1] = LittleFloat(vnormal[1]);
3568 outnormal[2] = LittleFloat(vnormal[2]);
3574 // this unaligned memory access is safe (LittleFloat reads as bytes)
3575 if(vnormal && vtangent)
3577 outnormal = loadmodel->surfmesh.data_normal3f;
3578 outsvector = loadmodel->surfmesh.data_svector3f;
3579 outtvector = loadmodel->surfmesh.data_tvector3f;
3580 for (i = 0;i < (int)header.num_vertexes;i++)
3582 outsvector[0] = LittleFloat(vtangent[0]);
3583 outsvector[1] = LittleFloat(vtangent[1]);
3584 outsvector[2] = LittleFloat(vtangent[2]);
3585 if(LittleFloat(vtangent[3]) < 0)
3586 CrossProduct(outsvector, outnormal, outtvector);
3588 CrossProduct(outnormal, outsvector, outtvector);
3596 // this unaligned memory access is safe (all bytes)
3597 if (vblendindexes && vblendweights)
3599 for (i = 0; i < (int)header.num_vertexes;i++)
3601 blendweights_t weights;
3602 memcpy(weights.index, vblendindexes + i*4, 4);
3603 memcpy(weights.influence, vblendweights + i*4, 4);
3604 loadmodel->surfmesh.blends[i] = Mod_Skeletal_AddBlend(loadmodel, &weights);
3609 for (i = 0;i < (int)header.num_meshes;i++)
3612 msurface_t *surface;
3614 mesh.name = LittleLong(meshes[i].name);
3615 mesh.material = LittleLong(meshes[i].material);
3616 mesh.first_vertex = LittleLong(meshes[i].first_vertex);
3617 mesh.num_vertexes = LittleLong(meshes[i].num_vertexes);
3618 mesh.first_triangle = LittleLong(meshes[i].first_triangle);
3619 mesh.num_triangles = LittleLong(meshes[i].num_triangles);
3621 loadmodel->sortedmodelsurfaces[i] = i;
3622 surface = loadmodel->data_surfaces + i;
3623 surface->texture = loadmodel->data_textures + i;
3624 surface->num_firsttriangle = mesh.first_triangle;
3625 surface->num_triangles = mesh.num_triangles;
3626 surface->num_firstvertex = mesh.first_vertex;
3627 surface->num_vertices = mesh.num_vertexes;
3629 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, &text[mesh.name], &text[mesh.material]);
3632 Mod_FreeSkinFiles(skinfiles);
3633 Mod_MakeSortedSurfaces(loadmodel);
3635 // compute all the mesh information that was not loaded from the file
3636 if (loadmodel->surfmesh.data_element3s)
3637 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3638 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3640 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, r_smoothnormals_areaweighting.integer != 0);
3641 if (!vnormal || !vtangent)
3642 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);
3643 if (!header.ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
3644 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3645 if (!header.ofs_bounds)
3646 Mod_Alias_CalculateBoundingBox();
3648 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
3650 if (!loadmodel->surfmesh.isanimated)
3652 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3653 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3654 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3655 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3656 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3657 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
3660 if (joint ) Mem_Free(joint );joint = NULL;
3661 if (joint1 ) Mem_Free(joint1 );joint1 = NULL;
3662 if (pose ) Mem_Free(pose );pose = NULL;
3663 if (pose1 ) Mem_Free(pose1 );pose1 = NULL;