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->specularscalemod = 1;
791 texture->specularpowermod = 1;
792 texture->surfaceflags = 0;
793 texture->supercontents = SUPERCONTENTS_SOLID;
794 if (!(texture->basematerialflags & MATERIALFLAG_BLENDED))
795 texture->supercontents |= SUPERCONTENTS_OPAQUE;
798 void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
801 static char stripbuf[MAX_QPATH];
802 skinfileitem_t *skinfileitem;
803 if(developer_extra.integer)
804 Con_DPrintf("Looking up texture for %s (default: %s)\n", meshname, shadername);
807 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
808 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
810 memset(skin, 0, sizeof(*skin));
812 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
814 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
815 if (!strcmp(skinfileitem->name, meshname))
817 Image_StripImageExtension(skinfileitem->replacement, stripbuf, sizeof(stripbuf));
818 if(developer_extra.integer)
819 Con_DPrintf("--> got %s from skin file\n", stripbuf);
820 Mod_LoadTextureFromQ3Shader(skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
826 // don't render unmentioned meshes
827 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
828 if(developer_extra.integer)
829 Con_DPrintf("--> skipping\n");
830 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
836 if(developer_extra.integer)
837 Con_DPrintf("--> using default\n");
838 Image_StripImageExtension(shadername, stripbuf, sizeof(stripbuf));
839 Mod_LoadTextureFromQ3Shader(skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
843 #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);
844 #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);
845 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
847 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
848 float scales, scalet, interval;
852 stvert_t *pinstverts;
853 dtriangle_t *pintriangles;
854 daliasskintype_t *pinskintype;
855 daliasskingroup_t *pinskingroup;
856 daliasskininterval_t *pinskinintervals;
857 daliasframetype_t *pinframetype;
858 daliasgroup_t *pinframegroup;
859 unsigned char *datapointer, *startframes, *startskins;
860 char name[MAX_QPATH];
861 skinframe_t *tempskinframe;
862 animscene_t *tempskinscenes;
863 texture_t *tempaliasskins;
865 int *vertonseam, *vertremap;
866 skinfile_t *skinfiles;
868 datapointer = (unsigned char *)buffer;
869 pinmodel = (mdl_t *)datapointer;
870 datapointer += sizeof(mdl_t);
872 version = LittleLong (pinmodel->version);
873 if (version != ALIAS_VERSION)
874 Host_Error ("%s has wrong version number (%i should be %i)",
875 loadmodel->name, version, ALIAS_VERSION);
877 loadmodel->modeldatatypestring = "MDL";
879 loadmodel->type = mod_alias;
880 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
881 loadmodel->DrawSky = NULL;
882 loadmodel->DrawAddWaterPlanes = NULL;
883 loadmodel->Draw = R_Q1BSP_Draw;
884 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
885 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
886 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
887 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
888 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
889 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
890 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
891 loadmodel->DrawLight = R_Q1BSP_DrawLight;
892 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
893 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
894 // FIXME add TraceBrush!
895 loadmodel->PointSuperContents = NULL;
897 loadmodel->num_surfaces = 1;
898 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
899 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
900 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
901 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
902 loadmodel->sortedmodelsurfaces[0] = 0;
904 loadmodel->numskins = LittleLong(pinmodel->numskins);
905 BOUNDI(loadmodel->numskins,0,65536);
906 skinwidth = LittleLong (pinmodel->skinwidth);
907 BOUNDI(skinwidth,0,65536);
908 skinheight = LittleLong (pinmodel->skinheight);
909 BOUNDI(skinheight,0,65536);
910 numverts = LittleLong(pinmodel->numverts);
911 BOUNDI(numverts,0,65536);
912 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
913 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
914 loadmodel->numframes = LittleLong(pinmodel->numframes);
915 BOUNDI(loadmodel->numframes,0,65536);
916 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
917 BOUNDI((int)loadmodel->synctype,0,2);
918 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
919 i = LittleLong (pinmodel->flags);
920 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
922 for (i = 0;i < 3;i++)
924 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
925 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
928 startskins = datapointer;
930 for (i = 0;i < loadmodel->numskins;i++)
932 pinskintype = (daliasskintype_t *)datapointer;
933 datapointer += sizeof(daliasskintype_t);
934 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
938 pinskingroup = (daliasskingroup_t *)datapointer;
939 datapointer += sizeof(daliasskingroup_t);
940 groupskins = LittleLong(pinskingroup->numskins);
941 datapointer += sizeof(daliasskininterval_t) * groupskins;
944 for (j = 0;j < groupskins;j++)
946 datapointer += skinwidth * skinheight;
951 pinstverts = (stvert_t *)datapointer;
952 datapointer += sizeof(stvert_t) * numverts;
954 pintriangles = (dtriangle_t *)datapointer;
955 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
957 startframes = datapointer;
958 loadmodel->surfmesh.num_morphframes = 0;
959 for (i = 0;i < loadmodel->numframes;i++)
961 pinframetype = (daliasframetype_t *)datapointer;
962 datapointer += sizeof(daliasframetype_t);
963 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
967 pinframegroup = (daliasgroup_t *)datapointer;
968 datapointer += sizeof(daliasgroup_t);
969 groupframes = LittleLong(pinframegroup->numframes);
970 datapointer += sizeof(daliasinterval_t) * groupframes;
973 for (j = 0;j < groupframes;j++)
975 datapointer += sizeof(daliasframe_t);
976 datapointer += sizeof(trivertx_t) * numverts;
977 loadmodel->surfmesh.num_morphframes++;
980 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
982 // store texture coordinates into temporary array, they will be stored
983 // after usage is determined (triangle data)
984 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
985 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
986 vertonseam = vertremap + numverts * 2;
988 scales = 1.0 / skinwidth;
989 scalet = 1.0 / skinheight;
990 for (i = 0;i < numverts;i++)
992 vertonseam[i] = LittleLong(pinstverts[i].onseam);
993 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
994 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
995 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
996 vertst[(i+numverts)*2+1] = vertst[i*2+1];
999 // load triangle data
1000 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1002 // read the triangle elements
1003 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1004 for (j = 0;j < 3;j++)
1005 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1006 // validate (note numverts is used because this is the original data)
1007 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1008 // now butcher the elements according to vertonseam and tri->facesfront
1009 // and then compact the vertex set to remove duplicates
1010 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1011 if (!LittleLong(pintriangles[i].facesfront)) // backface
1012 for (j = 0;j < 3;j++)
1013 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1014 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1016 // (this uses vertremap to count usage to save some memory)
1017 for (i = 0;i < numverts*2;i++)
1019 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1020 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1021 // build remapping table and compact array
1022 loadmodel->surfmesh.num_vertices = 0;
1023 for (i = 0;i < numverts*2;i++)
1027 vertremap[i] = loadmodel->surfmesh.num_vertices;
1028 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1029 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1030 loadmodel->surfmesh.num_vertices++;
1033 vertremap[i] = -1; // not used at all
1035 // remap the elements to the new vertex set
1036 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1037 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1038 // store the texture coordinates
1039 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1040 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1042 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1043 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1046 // generate ushort elements array if possible
1047 if (loadmodel->surfmesh.num_vertices <= 65536)
1048 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1049 if (loadmodel->surfmesh.data_element3s)
1050 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1051 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1054 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1055 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1056 if (r_enableshadowvolumes.integer)
1058 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1060 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1061 if (loadmodel->surfmesh.data_neighbor3i)
1062 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1063 Mod_Alias_CalculateBoundingBox();
1064 Mod_Alias_MorphMesh_CompileFrames();
1067 Mem_Free(vertremap);
1070 skinfiles = Mod_LoadSkinFiles();
1073 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1074 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1075 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1076 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1077 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1078 Mod_FreeSkinFiles(skinfiles);
1079 for (i = 0;i < loadmodel->numskins;i++)
1081 loadmodel->skinscenes[i].firstframe = i;
1082 loadmodel->skinscenes[i].framecount = 1;
1083 loadmodel->skinscenes[i].loop = true;
1084 loadmodel->skinscenes[i].framerate = 10;
1089 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1090 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1091 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1092 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1094 datapointer = startskins;
1095 for (i = 0;i < loadmodel->numskins;i++)
1097 pinskintype = (daliasskintype_t *)datapointer;
1098 datapointer += sizeof(daliasskintype_t);
1100 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1107 pinskingroup = (daliasskingroup_t *)datapointer;
1108 datapointer += sizeof(daliasskingroup_t);
1110 groupskins = LittleLong (pinskingroup->numskins);
1112 pinskinintervals = (daliasskininterval_t *)datapointer;
1113 datapointer += sizeof(daliasskininterval_t) * groupskins;
1115 interval = LittleFloat(pinskinintervals[0].interval);
1116 if (interval < 0.01f)
1118 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1123 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1124 loadmodel->skinscenes[i].firstframe = totalskins;
1125 loadmodel->skinscenes[i].framecount = groupskins;
1126 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1127 loadmodel->skinscenes[i].loop = true;
1129 for (j = 0;j < groupskins;j++)
1132 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1134 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1135 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))
1136 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));
1137 datapointer += skinwidth * skinheight;
1141 // check for skins that don't exist in the model, but do exist as external images
1142 // (this was added because yummyluv kept pestering me about support for it)
1143 // TODO: support shaders here?
1144 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)))
1146 // expand the arrays to make room
1147 tempskinscenes = loadmodel->skinscenes;
1148 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1149 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1150 Mem_Free(tempskinscenes);
1152 tempaliasskins = loadmodel->data_textures;
1153 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1154 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1155 Mem_Free(tempaliasskins);
1157 // store the info about the new skin
1158 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1159 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1160 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1161 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1162 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1163 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1165 //increase skin counts
1166 loadmodel->numskins++;
1169 // fix up the pointers since they are pointing at the old textures array
1170 // FIXME: this is a hack!
1171 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1172 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1176 surface = loadmodel->data_surfaces;
1177 surface->texture = loadmodel->data_textures;
1178 surface->num_firsttriangle = 0;
1179 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1180 surface->num_firstvertex = 0;
1181 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1183 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1185 if (!loadmodel->surfmesh.isanimated)
1187 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1188 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1189 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1190 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1191 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1192 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1196 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1198 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1199 float iskinwidth, iskinheight;
1200 unsigned char *data;
1201 msurface_t *surface;
1203 unsigned char *base, *datapointer;
1204 md2frame_t *pinframe;
1206 md2triangle_t *intri;
1207 unsigned short *inst;
1208 struct md2verthash_s
1210 struct md2verthash_s *next;
1214 *hash, **md2verthash, *md2verthashdata;
1215 skinfile_t *skinfiles;
1217 pinmodel = (md2_t *)buffer;
1218 base = (unsigned char *)buffer;
1220 version = LittleLong (pinmodel->version);
1221 if (version != MD2ALIAS_VERSION)
1222 Host_Error ("%s has wrong version number (%i should be %i)",
1223 loadmodel->name, version, MD2ALIAS_VERSION);
1225 loadmodel->modeldatatypestring = "MD2";
1227 loadmodel->type = mod_alias;
1228 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1229 loadmodel->DrawSky = NULL;
1230 loadmodel->DrawAddWaterPlanes = NULL;
1231 loadmodel->Draw = R_Q1BSP_Draw;
1232 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1233 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1234 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1235 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1236 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1237 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1238 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1239 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1240 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1241 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1242 loadmodel->PointSuperContents = NULL;
1244 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1245 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1246 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1247 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1248 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1249 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1250 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1251 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1253 end = LittleLong(pinmodel->ofs_end);
1254 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1255 Host_Error ("%s is not a valid model", loadmodel->name);
1256 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1257 Host_Error ("%s is not a valid model", loadmodel->name);
1258 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1259 Host_Error ("%s is not a valid model", loadmodel->name);
1260 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1261 Host_Error ("%s is not a valid model", loadmodel->name);
1262 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1263 Host_Error ("%s is not a valid model", loadmodel->name);
1265 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1266 numxyz = LittleLong(pinmodel->num_xyz);
1267 numst = LittleLong(pinmodel->num_st);
1268 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1269 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1270 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1271 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1272 skinwidth = LittleLong(pinmodel->skinwidth);
1273 skinheight = LittleLong(pinmodel->skinheight);
1274 iskinwidth = 1.0f / skinwidth;
1275 iskinheight = 1.0f / skinheight;
1277 loadmodel->num_surfaces = 1;
1278 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1279 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));
1280 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1281 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1282 loadmodel->sortedmodelsurfaces[0] = 0;
1283 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1284 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1285 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1286 if (r_enableshadowvolumes.integer)
1288 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1291 loadmodel->synctype = ST_RAND;
1294 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1295 skinfiles = Mod_LoadSkinFiles();
1298 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1299 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1300 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1301 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1302 Mod_FreeSkinFiles(skinfiles);
1304 else if (loadmodel->numskins)
1306 // skins found (most likely not a player model)
1307 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1308 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1309 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1310 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1311 Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
1315 // no skins (most likely a player model)
1316 loadmodel->numskins = 1;
1317 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1318 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1319 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1320 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1323 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1324 for (i = 0;i < loadmodel->numskins;i++)
1326 loadmodel->skinscenes[i].firstframe = i;
1327 loadmodel->skinscenes[i].framecount = 1;
1328 loadmodel->skinscenes[i].loop = true;
1329 loadmodel->skinscenes[i].framerate = 10;
1332 // load the triangles and stvert data
1333 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1334 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1335 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1336 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1337 // swap the triangle list
1338 loadmodel->surfmesh.num_vertices = 0;
1339 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1341 for (j = 0;j < 3;j++)
1343 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1344 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1347 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1352 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1355 hashindex = (xyz * 256 + st) & 65535;
1356 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1357 if (hash->xyz == xyz && hash->st == st)
1361 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1364 hash->next = md2verthash[hashindex];
1365 md2verthash[hashindex] = hash;
1367 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1371 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1372 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));
1373 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1374 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1375 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1378 hash = md2verthashdata + i;
1379 vertremap[i] = hash->xyz;
1380 sts = LittleShort(inst[hash->st*2+0]);
1381 stt = LittleShort(inst[hash->st*2+1]);
1382 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1384 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1388 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1389 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1392 Mem_Free(md2verthash);
1393 Mem_Free(md2verthashdata);
1395 // generate ushort elements array if possible
1396 if (loadmodel->surfmesh.num_vertices <= 65536)
1397 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1398 if (loadmodel->surfmesh.data_element3s)
1399 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1400 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1403 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1404 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1409 pinframe = (md2frame_t *)datapointer;
1410 datapointer += sizeof(md2frame_t);
1411 // store the frame scale/translate into the appropriate array
1412 for (j = 0;j < 3;j++)
1414 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1415 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1417 // convert the vertices
1418 v = (trivertx_t *)datapointer;
1419 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1420 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1421 out[k] = v[vertremap[k]];
1422 datapointer += numxyz * sizeof(trivertx_t);
1424 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1425 loadmodel->animscenes[i].firstframe = i;
1426 loadmodel->animscenes[i].framecount = 1;
1427 loadmodel->animscenes[i].framerate = 10;
1428 loadmodel->animscenes[i].loop = true;
1431 Mem_Free(vertremap);
1433 if (loadmodel->surfmesh.data_neighbor3i)
1434 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1435 Mod_Alias_CalculateBoundingBox();
1436 Mod_Alias_MorphMesh_CompileFrames();
1438 surface = loadmodel->data_surfaces;
1439 surface->texture = loadmodel->data_textures;
1440 surface->num_firsttriangle = 0;
1441 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1442 surface->num_firstvertex = 0;
1443 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1445 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1447 if (!loadmodel->surfmesh.isanimated)
1449 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1450 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1451 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1452 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1453 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1454 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1458 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1460 int i, j, k, version, meshvertices, meshtriangles;
1461 unsigned char *data;
1462 msurface_t *surface;
1463 md3modelheader_t *pinmodel;
1464 md3frameinfo_t *pinframe;
1467 skinfile_t *skinfiles;
1469 pinmodel = (md3modelheader_t *)buffer;
1471 if (memcmp(pinmodel->identifier, "IDP3", 4))
1472 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1473 version = LittleLong (pinmodel->version);
1474 if (version != MD3VERSION)
1475 Host_Error ("%s has wrong version number (%i should be %i)",
1476 loadmodel->name, version, MD3VERSION);
1478 skinfiles = Mod_LoadSkinFiles();
1479 if (loadmodel->numskins < 1)
1480 loadmodel->numskins = 1;
1482 loadmodel->modeldatatypestring = "MD3";
1484 loadmodel->type = mod_alias;
1485 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1486 loadmodel->DrawSky = NULL;
1487 loadmodel->DrawAddWaterPlanes = NULL;
1488 loadmodel->Draw = R_Q1BSP_Draw;
1489 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1490 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1491 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1492 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1493 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1494 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1495 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1496 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1497 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1498 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1499 loadmodel->PointSuperContents = NULL;
1500 loadmodel->synctype = ST_RAND;
1501 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1502 i = LittleLong (pinmodel->flags);
1503 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1505 // set up some global info about the model
1506 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1507 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1509 // make skinscenes for the skins (no groups)
1510 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1511 for (i = 0;i < loadmodel->numskins;i++)
1513 loadmodel->skinscenes[i].firstframe = i;
1514 loadmodel->skinscenes[i].framecount = 1;
1515 loadmodel->skinscenes[i].loop = true;
1516 loadmodel->skinscenes[i].framerate = 10;
1520 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1521 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1523 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1524 loadmodel->animscenes[i].firstframe = i;
1525 loadmodel->animscenes[i].framecount = 1;
1526 loadmodel->animscenes[i].framerate = 10;
1527 loadmodel->animscenes[i].loop = true;
1531 loadmodel->num_tagframes = loadmodel->numframes;
1532 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1533 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1534 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1536 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1537 for (j = 0;j < 9;j++)
1538 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1539 for (j = 0;j < 3;j++)
1540 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1541 //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);
1547 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)))
1549 if (memcmp(pinmesh->identifier, "IDP3", 4))
1550 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1551 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1552 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1553 meshvertices += LittleLong(pinmesh->num_vertices);
1554 meshtriangles += LittleLong(pinmesh->num_triangles);
1557 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1558 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1559 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1560 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));
1561 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1562 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1563 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1564 loadmodel->surfmesh.num_vertices = meshvertices;
1565 loadmodel->surfmesh.num_triangles = meshtriangles;
1566 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1567 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1568 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1569 if (r_enableshadowvolumes.integer)
1571 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1573 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1574 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1575 if (meshvertices <= 65536)
1577 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1582 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)))
1584 if (memcmp(pinmesh->identifier, "IDP3", 4))
1585 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1586 loadmodel->sortedmodelsurfaces[i] = i;
1587 surface = loadmodel->data_surfaces + i;
1588 surface->texture = loadmodel->data_textures + i;
1589 surface->num_firsttriangle = meshtriangles;
1590 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1591 surface->num_firstvertex = meshvertices;
1592 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1593 meshvertices += surface->num_vertices;
1594 meshtriangles += surface->num_triangles;
1596 for (j = 0;j < surface->num_triangles * 3;j++)
1597 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1598 for (j = 0;j < surface->num_vertices;j++)
1600 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1601 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1603 for (j = 0;j < loadmodel->numframes;j++)
1605 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1606 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1607 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1609 out->origin[0] = LittleShort(in->origin[0]);
1610 out->origin[1] = LittleShort(in->origin[1]);
1611 out->origin[2] = LittleShort(in->origin[2]);
1612 out->pitch = in->pitch;
1617 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1619 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1621 if (loadmodel->surfmesh.data_element3s)
1622 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1623 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1624 if (loadmodel->surfmesh.data_neighbor3i)
1625 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1626 Mod_Alias_MorphMesh_CompileFrames();
1627 Mod_Alias_CalculateBoundingBox();
1628 Mod_FreeSkinFiles(skinfiles);
1629 Mod_MakeSortedSurfaces(loadmodel);
1631 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1632 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1634 if (!loadmodel->surfmesh.isanimated)
1636 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1637 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1638 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1639 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1640 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1641 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1645 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1647 zymtype1header_t *pinmodel, *pheader;
1648 unsigned char *pbase;
1649 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1650 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose, f, biggestorigin, tempvec[3], modelscale;
1651 zymvertex_t *verts, *vertdata;
1655 skinfile_t *skinfiles;
1656 unsigned char *data;
1657 msurface_t *surface;
1659 pinmodel = (zymtype1header_t *)buffer;
1660 pbase = (unsigned char *)buffer;
1661 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1662 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1663 if (BigLong(pinmodel->type) != 1)
1664 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1666 loadmodel->modeldatatypestring = "ZYM";
1668 loadmodel->type = mod_alias;
1669 loadmodel->synctype = ST_RAND;
1673 pheader->type = BigLong(pinmodel->type);
1674 pheader->filesize = BigLong(pinmodel->filesize);
1675 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1676 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1677 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1678 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1679 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1680 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1681 pheader->radius = BigFloat(pinmodel->radius);
1682 pheader->numverts = BigLong(pinmodel->numverts);
1683 pheader->numtris = BigLong(pinmodel->numtris);
1684 pheader->numshaders = BigLong(pinmodel->numshaders);
1685 pheader->numbones = BigLong(pinmodel->numbones);
1686 pheader->numscenes = BigLong(pinmodel->numscenes);
1687 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1688 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1689 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1690 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1691 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1692 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1693 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1694 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1695 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1696 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1697 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1698 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1699 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1700 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1701 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1702 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1703 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1704 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1706 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1708 Con_Printf("%s has no geometry\n", loadmodel->name);
1711 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1713 Con_Printf("%s has no animations\n", loadmodel->name);
1717 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1718 loadmodel->DrawSky = NULL;
1719 loadmodel->DrawAddWaterPlanes = NULL;
1720 loadmodel->Draw = R_Q1BSP_Draw;
1721 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1722 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1723 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1724 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1725 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1726 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1727 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1728 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1729 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1730 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1731 loadmodel->PointSuperContents = NULL;
1733 loadmodel->numframes = pheader->numscenes;
1734 loadmodel->num_surfaces = pheader->numshaders;
1736 skinfiles = Mod_LoadSkinFiles();
1737 if (loadmodel->numskins < 1)
1738 loadmodel->numskins = 1;
1740 // make skinscenes for the skins (no groups)
1741 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1742 for (i = 0;i < loadmodel->numskins;i++)
1744 loadmodel->skinscenes[i].firstframe = i;
1745 loadmodel->skinscenes[i].framecount = 1;
1746 loadmodel->skinscenes[i].loop = true;
1747 loadmodel->skinscenes[i].framerate = 10;
1751 modelradius = pheader->radius;
1752 for (i = 0;i < 3;i++)
1754 loadmodel->normalmins[i] = pheader->mins[i];
1755 loadmodel->normalmaxs[i] = pheader->maxs[i];
1756 loadmodel->rotatedmins[i] = -modelradius;
1757 loadmodel->rotatedmaxs[i] = modelradius;
1759 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1760 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1761 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1762 if (loadmodel->yawmaxs[0] > modelradius)
1763 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1764 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1765 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1766 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1767 loadmodel->radius = modelradius;
1768 loadmodel->radius2 = modelradius * modelradius;
1770 // go through the lumps, swapping things
1772 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1773 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1774 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1775 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1776 for (i = 0;i < pheader->numscenes;i++)
1778 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1779 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1780 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1781 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1782 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1783 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1784 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1785 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1786 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1787 if (loadmodel->animscenes[i].framerate < 0)
1788 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1792 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1793 loadmodel->num_bones = pheader->numbones;
1794 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1795 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1796 for (i = 0;i < pheader->numbones;i++)
1798 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1799 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1800 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1801 if (loadmodel->data_bones[i].parent >= i)
1802 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1805 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1806 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1807 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1808 for (i = 0;i < pheader->numverts;i++)
1810 vertbonecounts[i] = BigLong(bonecount[i]);
1811 if (vertbonecounts[i] != 1)
1812 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1815 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1817 meshvertices = pheader->numverts;
1818 meshtriangles = pheader->numtris;
1820 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1821 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1822 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1823 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]));
1824 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1825 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1826 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1827 loadmodel->surfmesh.num_vertices = meshvertices;
1828 loadmodel->surfmesh.num_triangles = meshtriangles;
1829 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1830 if (r_enableshadowvolumes.integer)
1832 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1834 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1835 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1836 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1837 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1838 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1839 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1840 loadmodel->surfmesh.num_blends = 0;
1841 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
1842 if (loadmodel->surfmesh.num_vertices <= 65536)
1844 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1846 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
1847 loadmodel->surfmesh.data_blendweights = NULL;
1849 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1850 poses = (float *) (pheader->lump_poses.start + pbase);
1851 // figure out scale of model from root bone, for compatibility with old zmodel versions
1852 tempvec[0] = BigFloat(poses[0]);
1853 tempvec[1] = BigFloat(poses[1]);
1854 tempvec[2] = BigFloat(poses[2]);
1855 modelscale = VectorLength(tempvec);
1857 for (i = 0;i < loadmodel->num_bones * numposes * 12;i++)
1859 f = fabs(BigFloat(poses[i]));
1860 biggestorigin = max(biggestorigin, f);
1862 loadmodel->num_posescale = biggestorigin / 32767.0f;
1863 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
1864 for (i = 0;i < numposes;i++)
1866 const float *frameposes = (float *) (pheader->lump_poses.start + pbase) + 12*i*loadmodel->num_bones;
1867 for (j = 0;j < loadmodel->num_bones;j++)
1870 matrix4x4_t posematrix;
1871 for (k = 0;k < 12;k++)
1872 pose[k] = BigFloat(frameposes[j*12+k]);
1873 //if (j < loadmodel->num_bones)
1874 // 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));
1875 // scale child bones to match the root scale
1876 if (loadmodel->data_bones[j].parent >= 0)
1878 pose[3] *= modelscale;
1879 pose[7] *= modelscale;
1880 pose[11] *= modelscale;
1882 // normalize rotation matrix
1883 VectorNormalize(pose + 0);
1884 VectorNormalize(pose + 4);
1885 VectorNormalize(pose + 8);
1886 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
1887 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
1891 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1892 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1893 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1894 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1895 // (converting from weight-blending skeletal animation to
1896 // deformation-based skeletal animation)
1897 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1898 for (i = 0;i < loadmodel->num_bones;i++)
1901 for (k = 0;k < 12;k++)
1902 m[k] = BigFloat(poses[i*12+k]);
1903 if (loadmodel->data_bones[i].parent >= 0)
1904 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1906 for (k = 0;k < 12;k++)
1907 bonepose[12*i+k] = m[k];
1909 for (j = 0;j < pheader->numverts;j++)
1911 // this format really should have had a per vertexweight weight value...
1912 // but since it does not, the weighting is completely ignored and
1913 // only one weight is allowed per vertex
1914 int boneindex = BigLong(vertdata[j].bonenum);
1915 const float *m = bonepose + 12 * boneindex;
1916 float relativeorigin[3];
1917 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1918 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1919 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1920 // transform the vertex bone weight into the base mesh
1921 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1922 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1923 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1924 // store the weight as the primary weight on this vertex
1925 loadmodel->surfmesh.blends[j] = boneindex;
1928 // normals and tangents are calculated after elements are loaded
1930 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1931 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1932 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1933 for (i = 0;i < pheader->numverts;i++)
1935 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1936 // flip T coordinate for OpenGL
1937 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1940 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1941 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1942 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1944 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1945 //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)
1946 // byteswap, validate, and swap winding order of tris
1947 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1948 if (pheader->lump_render.length != count)
1949 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1950 renderlist = (int *) (pheader->lump_render.start + pbase);
1951 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1953 for (i = 0;i < loadmodel->num_surfaces;i++)
1955 int firstvertex, lastvertex;
1956 if (renderlist >= renderlistend)
1957 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1958 count = BigLong(*renderlist);renderlist++;
1959 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1960 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1962 loadmodel->sortedmodelsurfaces[i] = i;
1963 surface = loadmodel->data_surfaces + i;
1964 surface->texture = loadmodel->data_textures + i;
1965 surface->num_firsttriangle = meshtriangles;
1966 surface->num_triangles = count;
1967 meshtriangles += surface->num_triangles;
1969 // load the elements
1970 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
1971 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
1973 outelements[j*3+2] = BigLong(renderlist[0]);
1974 outelements[j*3+1] = BigLong(renderlist[1]);
1975 outelements[j*3+0] = BigLong(renderlist[2]);
1977 // validate the elements and find the used vertex range
1978 firstvertex = meshvertices;
1980 for (j = 0;j < surface->num_triangles * 3;j++)
1982 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
1983 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
1984 firstvertex = min(firstvertex, outelements[j]);
1985 lastvertex = max(lastvertex, outelements[j]);
1987 surface->num_firstvertex = firstvertex;
1988 surface->num_vertices = lastvertex + 1 - firstvertex;
1990 // since zym models do not have named sections, reuse their shader
1991 // name as the section name
1992 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
1993 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
1995 Mod_FreeSkinFiles(skinfiles);
1996 Mem_Free(vertbonecounts);
1998 Mod_MakeSortedSurfaces(loadmodel);
2000 // compute all the mesh information that was not loaded from the file
2001 if (loadmodel->surfmesh.data_element3s)
2002 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2003 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2004 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2005 Mod_BuildBaseBonePoses();
2006 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);
2007 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);
2008 if (loadmodel->surfmesh.data_neighbor3i)
2009 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2011 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2013 if (!loadmodel->surfmesh.isanimated)
2015 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2016 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2017 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2018 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2019 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2020 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2024 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2026 dpmheader_t *pheader;
2030 unsigned char *pbase;
2031 int i, j, k, meshvertices, meshtriangles;
2032 skinfile_t *skinfiles;
2033 unsigned char *data;
2035 float biggestorigin, tempvec[3], modelscale;
2039 pheader = (dpmheader_t *)buffer;
2040 pbase = (unsigned char *)buffer;
2041 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2042 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2043 if (BigLong(pheader->type) != 2)
2044 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2046 loadmodel->modeldatatypestring = "DPM";
2048 loadmodel->type = mod_alias;
2049 loadmodel->synctype = ST_RAND;
2052 pheader->type = BigLong(pheader->type);
2053 pheader->filesize = BigLong(pheader->filesize);
2054 pheader->mins[0] = BigFloat(pheader->mins[0]);
2055 pheader->mins[1] = BigFloat(pheader->mins[1]);
2056 pheader->mins[2] = BigFloat(pheader->mins[2]);
2057 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2058 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2059 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2060 pheader->yawradius = BigFloat(pheader->yawradius);
2061 pheader->allradius = BigFloat(pheader->allradius);
2062 pheader->num_bones = BigLong(pheader->num_bones);
2063 pheader->num_meshs = BigLong(pheader->num_meshs);
2064 pheader->num_frames = BigLong(pheader->num_frames);
2065 pheader->ofs_bones = BigLong(pheader->ofs_bones);
2066 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2067 pheader->ofs_frames = BigLong(pheader->ofs_frames);
2069 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2071 Con_Printf("%s has no geometry\n", loadmodel->name);
2074 if (pheader->num_frames < 1)
2076 Con_Printf("%s has no frames\n", loadmodel->name);
2080 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2081 loadmodel->DrawSky = NULL;
2082 loadmodel->DrawAddWaterPlanes = NULL;
2083 loadmodel->Draw = R_Q1BSP_Draw;
2084 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2085 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2086 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2087 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2088 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2089 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2090 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2091 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2092 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2093 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2094 loadmodel->PointSuperContents = NULL;
2097 for (i = 0;i < 3;i++)
2099 loadmodel->normalmins[i] = pheader->mins[i];
2100 loadmodel->normalmaxs[i] = pheader->maxs[i];
2101 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2102 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2103 loadmodel->rotatedmins[i] = -pheader->allradius;
2104 loadmodel->rotatedmaxs[i] = pheader->allradius;
2106 loadmodel->radius = pheader->allradius;
2107 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2109 // load external .skin files if present
2110 skinfiles = Mod_LoadSkinFiles();
2111 if (loadmodel->numskins < 1)
2112 loadmodel->numskins = 1;
2117 // gather combined statistics from the meshes
2118 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2119 for (i = 0;i < (int)pheader->num_meshs;i++)
2121 int numverts = BigLong(dpmmesh->num_verts);
2122 meshvertices += numverts;
2123 meshtriangles += BigLong(dpmmesh->num_tris);
2127 loadmodel->numframes = pheader->num_frames;
2128 loadmodel->num_bones = pheader->num_bones;
2129 loadmodel->num_poses = loadmodel->numframes;
2130 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2131 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2132 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2133 // do most allocations as one merged chunk
2134 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));
2135 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2136 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2137 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2138 loadmodel->surfmesh.num_vertices = meshvertices;
2139 loadmodel->surfmesh.num_triangles = meshtriangles;
2140 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2141 if (r_enableshadowvolumes.integer)
2143 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2145 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2146 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2147 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2148 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2149 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2150 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2151 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2152 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2153 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2154 loadmodel->surfmesh.num_blends = 0;
2155 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2156 if (meshvertices <= 65536)
2158 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2160 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2161 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
2163 for (i = 0;i < loadmodel->numskins;i++)
2165 loadmodel->skinscenes[i].firstframe = i;
2166 loadmodel->skinscenes[i].framecount = 1;
2167 loadmodel->skinscenes[i].loop = true;
2168 loadmodel->skinscenes[i].framerate = 10;
2171 // load the bone info
2172 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2173 for (i = 0;i < loadmodel->num_bones;i++)
2175 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2176 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2177 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2178 if (loadmodel->data_bones[i].parent >= i)
2179 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2183 frames = (dpmframe_t *) (pbase + pheader->ofs_frames);
2184 // figure out scale of model from root bone, for compatibility with old dpmodel versions
2185 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2186 tempvec[0] = BigFloat(poses[0]);
2187 tempvec[1] = BigFloat(poses[1]);
2188 tempvec[2] = BigFloat(poses[2]);
2189 modelscale = VectorLength(tempvec);
2191 for (i = 0;i < loadmodel->numframes;i++)
2193 memcpy(loadmodel->animscenes[i].name, frames[i].name, sizeof(frames[i].name));
2194 loadmodel->animscenes[i].firstframe = i;
2195 loadmodel->animscenes[i].framecount = 1;
2196 loadmodel->animscenes[i].loop = true;
2197 loadmodel->animscenes[i].framerate = 10;
2198 // load the bone poses for this frame
2199 poses = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2200 for (j = 0;j < loadmodel->num_bones*12;j++)
2202 f = fabs(BigFloat(poses[j]));
2203 biggestorigin = max(biggestorigin, f);
2205 // stuff not processed here: mins, maxs, yawradius, allradius
2207 loadmodel->num_posescale = biggestorigin / 32767.0f;
2208 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2209 for (i = 0;i < loadmodel->numframes;i++)
2211 const float *frameposes = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2212 for (j = 0;j < loadmodel->num_bones;j++)
2215 matrix4x4_t posematrix;
2216 for (k = 0;k < 12;k++)
2217 pose[k] = BigFloat(frameposes[j*12+k]);
2218 // scale child bones to match the root scale
2219 if (loadmodel->data_bones[j].parent >= 0)
2221 pose[3] *= modelscale;
2222 pose[7] *= modelscale;
2223 pose[11] *= modelscale;
2225 // normalize rotation matrix
2226 VectorNormalize(pose + 0);
2227 VectorNormalize(pose + 4);
2228 VectorNormalize(pose + 8);
2229 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2230 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
2234 // load the meshes now
2235 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2238 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2239 // (converting from weight-blending skeletal animation to
2240 // deformation-based skeletal animation)
2241 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2242 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2243 for (i = 0;i < loadmodel->num_bones;i++)
2246 for (k = 0;k < 12;k++)
2247 m[k] = BigFloat(poses[i*12+k]);
2248 if (loadmodel->data_bones[i].parent >= 0)
2249 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2251 for (k = 0;k < 12;k++)
2252 bonepose[12*i+k] = m[k];
2254 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2256 const int *inelements;
2258 const float *intexcoord;
2259 msurface_t *surface;
2261 loadmodel->sortedmodelsurfaces[i] = i;
2262 surface = loadmodel->data_surfaces + i;
2263 surface->texture = loadmodel->data_textures + i;
2264 surface->num_firsttriangle = meshtriangles;
2265 surface->num_triangles = BigLong(dpmmesh->num_tris);
2266 surface->num_firstvertex = meshvertices;
2267 surface->num_vertices = BigLong(dpmmesh->num_verts);
2268 meshvertices += surface->num_vertices;
2269 meshtriangles += surface->num_triangles;
2271 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2272 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2273 for (j = 0;j < surface->num_triangles;j++)
2275 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2276 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2277 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2278 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2283 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2284 for (j = 0;j < surface->num_vertices*2;j++)
2285 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2287 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2288 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2290 int weightindex[4] = { 0, 0, 0, 0 };
2291 float weightinfluence[4] = { 0, 0, 0, 0 };
2293 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2294 data += sizeof(dpmvertex_t);
2295 for (k = 0;k < numweights;k++)
2297 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2298 int boneindex = BigLong(vert->bonenum);
2299 const float *m = bonepose + 12 * boneindex;
2300 float influence = BigFloat(vert->influence);
2301 float relativeorigin[3], relativenormal[3];
2302 relativeorigin[0] = BigFloat(vert->origin[0]);
2303 relativeorigin[1] = BigFloat(vert->origin[1]);
2304 relativeorigin[2] = BigFloat(vert->origin[2]);
2305 relativenormal[0] = BigFloat(vert->normal[0]);
2306 relativenormal[1] = BigFloat(vert->normal[1]);
2307 relativenormal[2] = BigFloat(vert->normal[2]);
2308 // blend the vertex bone weights into the base mesh
2309 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2310 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2311 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2312 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2313 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2314 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2317 // store the first (and often only) weight
2318 weightinfluence[0] = influence;
2319 weightindex[0] = boneindex;
2323 // sort the new weight into this vertex's weight table
2324 // (which only accepts up to 4 bones per vertex)
2325 for (l = 0;l < 4;l++)
2327 if (weightinfluence[l] < influence)
2329 // move weaker influence weights out of the way first
2331 for (l2 = 3;l2 > l;l2--)
2333 weightinfluence[l2] = weightinfluence[l2-1];
2334 weightindex[l2] = weightindex[l2-1];
2336 // store the new weight
2337 weightinfluence[l] = influence;
2338 weightindex[l] = boneindex;
2343 data += sizeof(dpmbonevert_t);
2345 loadmodel->surfmesh.blends[j] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
2348 // since dpm models do not have named sections, reuse their shader name as the section name
2349 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2351 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2353 if (loadmodel->surfmesh.num_blends < meshvertices)
2354 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2356 Mod_FreeSkinFiles(skinfiles);
2357 Mod_MakeSortedSurfaces(loadmodel);
2359 // compute all the mesh information that was not loaded from the file
2360 if (loadmodel->surfmesh.data_element3s)
2361 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2362 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2363 Mod_BuildBaseBonePoses();
2364 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);
2365 if (loadmodel->surfmesh.data_neighbor3i)
2366 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2368 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2370 if (!loadmodel->surfmesh.isanimated)
2372 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2373 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2374 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2375 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2376 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2377 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2381 // no idea why PSK/PSA files contain weird quaternions but they do...
2382 #define PSKQUATNEGATIONS
2383 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2385 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2386 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2387 fs_offset_t filesize;
2392 pskboneinfo_t *bones;
2393 pskrawweights_t *rawweights;
2394 //pskboneinfo_t *animbones;
2395 pskaniminfo_t *anims;
2396 pskanimkeys_t *animkeys;
2397 void *animfilebuffer, *animbuffer, *animbufferend;
2398 unsigned char *data;
2400 skinfile_t *skinfiles;
2401 char animname[MAX_QPATH];
2403 float biggestorigin;
2405 pchunk = (pskchunk_t *)buffer;
2406 if (strcmp(pchunk->id, "ACTRHEAD"))
2407 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2409 loadmodel->modeldatatypestring = "PSK";
2411 loadmodel->type = mod_alias;
2412 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2413 loadmodel->DrawSky = NULL;
2414 loadmodel->DrawAddWaterPlanes = NULL;
2415 loadmodel->Draw = R_Q1BSP_Draw;
2416 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2417 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2418 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2419 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2420 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2421 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2422 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2423 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2424 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2425 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2426 loadmodel->PointSuperContents = NULL;
2427 loadmodel->synctype = ST_RAND;
2429 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2430 strlcat(animname, ".psa", sizeof(animname));
2431 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2432 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2433 if (animbuffer == NULL)
2434 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2453 while (buffer < bufferend)
2455 pchunk = (pskchunk_t *)buffer;
2456 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2457 version = LittleLong(pchunk->version);
2458 recordsize = LittleLong(pchunk->recordsize);
2459 numrecords = LittleLong(pchunk->numrecords);
2460 if (developer_extra.integer)
2461 Con_DPrintf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2462 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2463 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);
2464 if (!strcmp(pchunk->id, "ACTRHEAD"))
2468 else if (!strcmp(pchunk->id, "PNTS0000"))
2471 if (recordsize != sizeof(*p))
2472 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2473 // byteswap in place and keep the pointer
2474 numpnts = numrecords;
2475 pnts = (pskpnts_t *)buffer;
2476 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2478 p->origin[0] = LittleFloat(p->origin[0]);
2479 p->origin[1] = LittleFloat(p->origin[1]);
2480 p->origin[2] = LittleFloat(p->origin[2]);
2484 else if (!strcmp(pchunk->id, "VTXW0000"))
2487 if (recordsize != sizeof(*p))
2488 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2489 // byteswap in place and keep the pointer
2490 numvtxw = numrecords;
2491 vtxw = (pskvtxw_t *)buffer;
2492 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2494 p->pntsindex = LittleShort(p->pntsindex);
2495 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2496 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2497 if (p->pntsindex >= numpnts)
2499 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2505 else if (!strcmp(pchunk->id, "FACE0000"))
2508 if (recordsize != sizeof(*p))
2509 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2510 // byteswap in place and keep the pointer
2511 numfaces = numrecords;
2512 faces = (pskface_t *)buffer;
2513 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2515 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2516 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2517 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2518 p->group = LittleLong(p->group);
2519 if (p->vtxwindex[0] >= numvtxw)
2521 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2522 p->vtxwindex[0] = 0;
2524 if (p->vtxwindex[1] >= numvtxw)
2526 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2527 p->vtxwindex[1] = 0;
2529 if (p->vtxwindex[2] >= numvtxw)
2531 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2532 p->vtxwindex[2] = 0;
2537 else if (!strcmp(pchunk->id, "MATT0000"))
2540 if (recordsize != sizeof(*p))
2541 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2542 // byteswap in place and keep the pointer
2543 nummatts = numrecords;
2544 matts = (pskmatt_t *)buffer;
2545 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2551 else if (!strcmp(pchunk->id, "REFSKELT"))
2554 if (recordsize != sizeof(*p))
2555 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2556 // byteswap in place and keep the pointer
2557 numbones = numrecords;
2558 bones = (pskboneinfo_t *)buffer;
2559 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2561 p->numchildren = LittleLong(p->numchildren);
2562 p->parent = LittleLong(p->parent);
2563 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2564 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2565 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2566 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2567 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2568 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2569 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2570 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2571 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2572 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2573 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2574 #ifdef PSKQUATNEGATIONS
2577 p->basepose.quat[0] *= -1;
2578 p->basepose.quat[1] *= -1;
2579 p->basepose.quat[2] *= -1;
2583 p->basepose.quat[0] *= 1;
2584 p->basepose.quat[1] *= -1;
2585 p->basepose.quat[2] *= 1;
2588 if (p->parent < 0 || p->parent >= numbones)
2590 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2596 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2599 if (recordsize != sizeof(*p))
2600 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2601 // byteswap in place and keep the pointer
2602 numrawweights = numrecords;
2603 rawweights = (pskrawweights_t *)buffer;
2604 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2606 p->weight = LittleFloat(p->weight);
2607 p->pntsindex = LittleLong(p->pntsindex);
2608 p->boneindex = LittleLong(p->boneindex);
2609 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2611 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2614 if (p->boneindex < 0 || p->boneindex >= numbones)
2616 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2624 while (animbuffer < animbufferend)
2626 pchunk = (pskchunk_t *)animbuffer;
2627 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2628 version = LittleLong(pchunk->version);
2629 recordsize = LittleLong(pchunk->recordsize);
2630 numrecords = LittleLong(pchunk->numrecords);
2631 if (developer_extra.integer)
2632 Con_DPrintf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2633 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2634 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);
2635 if (!strcmp(pchunk->id, "ANIMHEAD"))
2639 else if (!strcmp(pchunk->id, "BONENAMES"))
2642 if (recordsize != sizeof(*p))
2643 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2644 // byteswap in place and keep the pointer
2645 numanimbones = numrecords;
2646 //animbones = (pskboneinfo_t *)animbuffer;
2647 // NOTE: supposedly psa does not need to match the psk model, the
2648 // bones missing from the psa would simply use their base
2649 // positions from the psk, but this is hard for me to implement
2650 // and people can easily make animations that match.
2651 if (numanimbones != numbones)
2652 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2653 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2655 p->numchildren = LittleLong(p->numchildren);
2656 p->parent = LittleLong(p->parent);
2657 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2658 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2659 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2660 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2661 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2662 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2663 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2664 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2665 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2666 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2667 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2668 #ifdef PSKQUATNEGATIONS
2671 p->basepose.quat[0] *= -1;
2672 p->basepose.quat[1] *= -1;
2673 p->basepose.quat[2] *= -1;
2677 p->basepose.quat[0] *= 1;
2678 p->basepose.quat[1] *= -1;
2679 p->basepose.quat[2] *= 1;
2682 if (p->parent < 0 || p->parent >= numanimbones)
2684 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2687 // check that bones are the same as in the base
2688 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2689 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2693 else if (!strcmp(pchunk->id, "ANIMINFO"))
2696 if (recordsize != sizeof(*p))
2697 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2698 // byteswap in place and keep the pointer
2699 numanims = numrecords;
2700 anims = (pskaniminfo_t *)animbuffer;
2701 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2703 p->numbones = LittleLong(p->numbones);
2704 p->playtime = LittleFloat(p->playtime);
2705 p->fps = LittleFloat(p->fps);
2706 p->firstframe = LittleLong(p->firstframe);
2707 p->numframes = LittleLong(p->numframes);
2708 if (p->numbones != numbones)
2709 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2713 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2716 if (recordsize != sizeof(*p))
2717 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2718 numanimkeys = numrecords;
2719 animkeys = (pskanimkeys_t *)animbuffer;
2720 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2722 p->origin[0] = LittleFloat(p->origin[0]);
2723 p->origin[1] = LittleFloat(p->origin[1]);
2724 p->origin[2] = LittleFloat(p->origin[2]);
2725 p->quat[0] = LittleFloat(p->quat[0]);
2726 p->quat[1] = LittleFloat(p->quat[1]);
2727 p->quat[2] = LittleFloat(p->quat[2]);
2728 p->quat[3] = LittleFloat(p->quat[3]);
2729 p->frametime = LittleFloat(p->frametime);
2730 #ifdef PSKQUATNEGATIONS
2731 if (index % numbones)
2746 // TODO: allocate bonepose stuff
2749 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2752 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2753 Host_Error("%s: missing required chunks", loadmodel->name);
2755 loadmodel->numframes = 0;
2756 for (index = 0;index < numanims;index++)
2757 loadmodel->numframes += anims[index].numframes;
2759 if (numanimkeys != numbones * loadmodel->numframes)
2760 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2762 meshvertices = numvtxw;
2763 meshtriangles = numfaces;
2765 // load external .skin files if present
2766 skinfiles = Mod_LoadSkinFiles();
2767 if (loadmodel->numskins < 1)
2768 loadmodel->numskins = 1;
2769 loadmodel->num_bones = numbones;
2770 loadmodel->num_poses = loadmodel->numframes;
2771 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2772 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2773 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2774 loadmodel->surfmesh.num_vertices = meshvertices;
2775 loadmodel->surfmesh.num_triangles = meshtriangles;
2776 // do most allocations as one merged chunk
2777 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);
2778 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2779 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2780 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2781 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2782 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2783 if (r_enableshadowvolumes.integer)
2785 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2787 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2788 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2789 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2790 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2791 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2792 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2793 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2794 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2795 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2796 loadmodel->surfmesh.num_blends = 0;
2797 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2798 if (loadmodel->surfmesh.num_vertices <= 65536)
2800 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2802 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2803 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(blendweights_t));
2805 for (i = 0;i < loadmodel->numskins;i++)
2807 loadmodel->skinscenes[i].firstframe = i;
2808 loadmodel->skinscenes[i].framecount = 1;
2809 loadmodel->skinscenes[i].loop = true;
2810 loadmodel->skinscenes[i].framerate = 10;
2814 for (index = 0, i = 0;index < nummatts;index++)
2816 // since psk models do not have named sections, reuse their shader name as the section name
2817 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2818 loadmodel->sortedmodelsurfaces[index] = index;
2819 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2820 loadmodel->data_surfaces[index].num_firstvertex = 0;
2821 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2824 // copy over the vertex locations and texcoords
2825 for (index = 0;index < numvtxw;index++)
2827 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2828 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2829 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2830 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2831 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2834 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2835 for (index = 0;index < numfaces;index++)
2836 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2837 for (index = 0, i = 0;index < nummatts;index++)
2839 loadmodel->data_surfaces[index].num_firsttriangle = i;
2840 i += loadmodel->data_surfaces[index].num_triangles;
2841 loadmodel->data_surfaces[index].num_triangles = 0;
2843 for (index = 0;index < numfaces;index++)
2845 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2846 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2847 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2848 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2851 // copy over the bones
2852 for (index = 0;index < numbones;index++)
2854 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2855 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2856 if (loadmodel->data_bones[index].parent >= index)
2857 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2860 // sort the psk point weights into the vertex weight tables
2861 // (which only accept up to 4 bones per vertex)
2862 for (index = 0;index < numvtxw;index++)
2864 int weightindex[4] = { 0, 0, 0, 0 };
2865 float weightinfluence[4] = { 0, 0, 0, 0 };
2867 for (j = 0;j < numrawweights;j++)
2869 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2871 int boneindex = rawweights[j].boneindex;
2872 float influence = rawweights[j].weight;
2873 for (l = 0;l < 4;l++)
2875 if (weightinfluence[l] < influence)
2877 // move lower influence weights out of the way first
2879 for (l2 = 3;l2 > l;l2--)
2881 weightinfluence[l2] = weightinfluence[l2-1];
2882 weightindex[l2] = weightindex[l2-1];
2884 // store the new weight
2885 weightinfluence[l] = influence;
2886 weightindex[l] = boneindex;
2892 loadmodel->surfmesh.blends[index] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
2894 if (loadmodel->surfmesh.num_blends < loadmodel->surfmesh.num_vertices)
2895 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2897 // set up the animscenes based on the anims
2898 for (index = 0, i = 0;index < numanims;index++)
2900 for (j = 0;j < anims[index].numframes;j++, i++)
2902 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2903 loadmodel->animscenes[i].firstframe = i;
2904 loadmodel->animscenes[i].framecount = 1;
2905 loadmodel->animscenes[i].loop = true;
2906 loadmodel->animscenes[i].framerate = anims[index].fps;
2910 // calculate the scaling value for bone origins so they can be compressed to short
2912 for (index = 0;index < numanimkeys;index++)
2914 pskanimkeys_t *k = animkeys + index;
2915 biggestorigin = max(biggestorigin, fabs(k->origin[0]));
2916 biggestorigin = max(biggestorigin, fabs(k->origin[1]));
2917 biggestorigin = max(biggestorigin, fabs(k->origin[2]));
2919 loadmodel->num_posescale = biggestorigin / 32767.0f;
2920 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2922 // load the poses from the animkeys
2923 for (index = 0;index < numanimkeys;index++)
2925 pskanimkeys_t *k = animkeys + index;
2927 Vector4Copy(k->quat, quat);
2929 Vector4Negate(quat, quat);
2930 Vector4Normalize2(quat, quat);
2931 // compress poses to the short[6] format for longterm storage
2932 loadmodel->data_poses6s[index*6+0] = k->origin[0] * loadmodel->num_poseinvscale;
2933 loadmodel->data_poses6s[index*6+1] = k->origin[1] * loadmodel->num_poseinvscale;
2934 loadmodel->data_poses6s[index*6+2] = k->origin[2] * loadmodel->num_poseinvscale;
2935 loadmodel->data_poses6s[index*6+3] = quat[0] * 32767.0f;
2936 loadmodel->data_poses6s[index*6+4] = quat[1] * 32767.0f;
2937 loadmodel->data_poses6s[index*6+5] = quat[2] * 32767.0f;
2939 Mod_FreeSkinFiles(skinfiles);
2940 Mem_Free(animfilebuffer);
2941 Mod_MakeSortedSurfaces(loadmodel);
2943 // compute all the mesh information that was not loaded from the file
2944 // TODO: honor smoothing groups somehow?
2945 if (loadmodel->surfmesh.data_element3s)
2946 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2947 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2948 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2949 Mod_BuildBaseBonePoses();
2950 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);
2951 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);
2952 if (loadmodel->surfmesh.data_neighbor3i)
2953 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2954 Mod_Alias_CalculateBoundingBox();
2956 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2958 if (!loadmodel->surfmesh.isanimated)
2960 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2961 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2962 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2963 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2964 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2965 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2969 void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2971 unsigned char *data;
2973 const unsigned char *pbase, *pend;
2974 iqmheader_t lheader, *header = &lheader;
2975 skinfile_t *skinfiles;
2976 int i, j, k, meshvertices, meshtriangles;
2977 float biggestorigin;
2978 const int *inelements;
2980 float *outvertex, *outnormal, *outtexcoord, *outsvector, *outtvector;
2981 // temporary memory allocations (because the data in the file may be misaligned)
2982 float *vnormal = NULL;
2983 float *vposition = NULL;
2984 float *vtangent = NULL;
2985 float *vtexcoord = NULL;
2986 iqmanim_t *anim = NULL;
2987 iqmbounds_t *bounds = NULL;
2988 iqmjoint1_t *joint1 = NULL;
2989 iqmjoint_t *joint = NULL;
2990 iqmmesh_t *mesh = NULL;
2991 iqmpose1_t *pose1 = NULL;
2992 iqmpose_t *pose = NULL;
2993 iqmvertexarray_t *va = NULL;
2994 unsigned char *vblendindexes = NULL;
2995 unsigned char *vblendweights = NULL;
2996 unsigned short *framedata = NULL;
2998 pbase = (unsigned char *)buffer;
2999 pend = (unsigned char *)bufferend;
3001 if (buffer + sizeof(iqmheader_t) > bufferend)
3002 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model", loadmodel->name);
3004 // copy struct (otherwise it may be misaligned)
3005 // LordHavoc: okay it's definitely not misaligned here, but for consistency...
3006 memcpy(header, pbase, sizeof(header));
3008 if (memcmp(header->id, "INTERQUAKEMODEL", 16))
3009 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model", loadmodel->name);
3010 if (LittleLong(header->version) != 1 && LittleLong(header->version) != 2)
3011 Host_Error ("Mod_INTERQUAKEMODEL_Load: only version 1 and 2 models are currently supported (name = %s)", loadmodel->name);
3013 loadmodel->modeldatatypestring = "IQM";
3015 loadmodel->type = mod_alias;
3016 loadmodel->synctype = ST_RAND;
3019 header->version = LittleLong(header->version);
3020 header->filesize = LittleLong(header->filesize);
3021 header->flags = LittleLong(header->flags);
3022 header->num_text = LittleLong(header->num_text);
3023 header->ofs_text = LittleLong(header->ofs_text);
3024 header->num_meshes = LittleLong(header->num_meshes);
3025 header->ofs_meshes = LittleLong(header->ofs_meshes);
3026 header->num_vertexarrays = LittleLong(header->num_vertexarrays);
3027 header->num_vertexes = LittleLong(header->num_vertexes);
3028 header->ofs_vertexarrays = LittleLong(header->ofs_vertexarrays);
3029 header->num_triangles = LittleLong(header->num_triangles);
3030 header->ofs_triangles = LittleLong(header->ofs_triangles);
3031 header->ofs_neighbors = LittleLong(header->ofs_neighbors);
3032 header->num_joints = LittleLong(header->num_joints);
3033 header->ofs_joints = LittleLong(header->ofs_joints);
3034 header->num_poses = LittleLong(header->num_poses);
3035 header->ofs_poses = LittleLong(header->ofs_poses);
3036 header->num_anims = LittleLong(header->num_anims);
3037 header->ofs_anims = LittleLong(header->ofs_anims);
3038 header->num_frames = LittleLong(header->num_frames);
3039 header->num_framechannels = LittleLong(header->num_framechannels);
3040 header->ofs_frames = LittleLong(header->ofs_frames);
3041 header->ofs_bounds = LittleLong(header->ofs_bounds);
3042 header->num_comment = LittleLong(header->num_comment);
3043 header->ofs_comment = LittleLong(header->ofs_comment);
3044 header->num_extensions = LittleLong(header->num_extensions);
3045 header->ofs_extensions = LittleLong(header->ofs_extensions);
3047 if (header->num_triangles < 1 || header->num_vertexes < 3 || header->num_vertexarrays < 1 || header->num_meshes < 1)
3049 Con_Printf("%s has no geometry\n", loadmodel->name);
3053 if (header->version == 1)
3055 if (pbase + header->ofs_joints + header->num_joints*sizeof(iqmjoint1_t) > pend ||
3056 pbase + header->ofs_poses + header->num_poses*sizeof(iqmpose1_t) > pend)
3058 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3064 if (pbase + header->ofs_joints + header->num_joints*sizeof(iqmjoint_t) > pend ||
3065 pbase + header->ofs_poses + header->num_poses*sizeof(iqmpose_t) > pend)
3067 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3071 if (pbase + header->ofs_text + header->num_text > pend ||
3072 pbase + header->ofs_meshes + header->num_meshes*sizeof(iqmmesh_t) > pend ||
3073 pbase + header->ofs_vertexarrays + header->num_vertexarrays*sizeof(iqmvertexarray_t) > pend ||
3074 pbase + header->ofs_triangles + header->num_triangles*sizeof(int[3]) > pend ||
3075 (header->ofs_neighbors && pbase + header->ofs_neighbors + header->num_triangles*sizeof(int[3]) > pend) ||
3076 pbase + header->ofs_anims + header->num_anims*sizeof(iqmanim_t) > pend ||
3077 pbase + header->ofs_frames + header->num_frames*header->num_framechannels*sizeof(unsigned short) > pend ||
3078 (header->ofs_bounds && pbase + header->ofs_bounds + header->num_frames*sizeof(iqmbounds_t) > pend) ||
3079 pbase + header->ofs_comment + header->num_comment > pend)
3081 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3085 // copy structs to make them aligned in memory (otherwise we crash on Sparc and PowerPC and others)
3086 if (header->num_vertexarrays)
3088 va = (iqmvertexarray_t *)Mem_Alloc(loadmodel->mempool, header->num_vertexarrays * sizeof(iqmvertexarray_t));
3089 memcpy(va, pbase + header->ofs_vertexarrays, header->num_vertexarrays * sizeof(iqmvertexarray_t));
3091 if (header->version == 1)
3093 if (loadmodel->num_bones)
3095 joint1 = (iqmjoint1_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(iqmjoint1_t));
3096 memcpy(joint1, pbase + header->ofs_joints, loadmodel->num_bones * sizeof(iqmjoint1_t));
3098 if (header->num_poses)
3100 pose1 = (iqmpose1_t *)Mem_Alloc(loadmodel->mempool, header->num_poses * sizeof(iqmpose1_t));
3101 memcpy(pose1, pbase + header->ofs_poses, header->num_poses * sizeof(iqmpose1_t));
3106 if (loadmodel->num_bones)
3108 joint = (iqmjoint_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(iqmjoint_t));
3109 memcpy(joint, pbase + header->ofs_joints, loadmodel->num_bones * sizeof(iqmjoint_t));
3111 if (header->num_poses)
3113 pose = (iqmpose_t *)Mem_Alloc(loadmodel->mempool, header->num_poses * sizeof(iqmpose_t));
3114 memcpy(pose, pbase + header->ofs_poses, header->num_poses * sizeof(iqmpose_t));
3117 if (header->num_anims)
3119 anim = (iqmanim_t *)Mem_Alloc(loadmodel->mempool, header->num_anims * sizeof(iqmanim_t));
3120 memcpy(anim, pbase + header->ofs_anims, header->num_anims * sizeof(iqmanim_t));
3122 if (header->num_framechannels)
3124 framedata = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short) * header->num_framechannels);
3125 memcpy(framedata, pbase + header->ofs_frames, sizeof(unsigned short) * header->num_framechannels);
3127 if (header->ofs_bounds)
3129 bounds = (iqmbounds_t *)Mem_Alloc(loadmodel->mempool, header->num_frames*sizeof(iqmbounds_t));
3130 memcpy(bounds, pbase + header->ofs_bounds, header->num_frames*sizeof(iqmbounds_t));
3132 if (header->num_triangles)
3133 memcpy(loadmodel->surfmesh.data_element3i, pbase + header->ofs_triangles, sizeof(unsigned int[3]) * header->num_triangles);
3134 if (header->ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
3135 memcpy(loadmodel->surfmesh.data_neighbor3i, pbase + header->ofs_neighbors, sizeof(int[3]) * header->num_triangles);
3136 if (header->num_meshes)
3138 mesh = Mem_Alloc(loadmodel->mempool, header->num_meshes * sizeof(iqmmesh_t));
3139 memcpy(mesh, pbase + header->ofs_meshes, header->num_meshes * sizeof(iqmmesh_t));
3142 for (i = 0;i < (int)header->num_vertexarrays;i++)
3145 va[i].type = LittleLong(va[i].type);
3146 va[i].flags = LittleLong(va[i].flags);
3147 va[i].format = LittleLong(va[i].format);
3148 va[i].size = LittleLong(va[i].size);
3149 va[i].offset = LittleLong(va[i].offset);
3150 vsize = header->num_vertexes*va[i].size;
3151 switch (va[i].format)
3153 case IQM_FLOAT: vsize *= sizeof(float); break;
3154 case IQM_UBYTE: vsize *= sizeof(unsigned char); break;
3157 if (pbase + va[i].offset + vsize > pend)
3162 if (va[i].format == IQM_FLOAT && va[i].size == 3)
3164 vposition = Mem_Alloc(loadmodel->mempool, sizeof(float[3]) * header->num_vertexes);
3165 memcpy(vposition, pbase + va[i].offset, sizeof(float[3]) * header->num_vertexes);
3169 if (va[i].format == IQM_FLOAT && va[i].size == 2)
3171 vtexcoord = Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * header->num_vertexes);
3172 memcpy(vtexcoord, pbase + va[i].offset, sizeof(float[2]) * header->num_vertexes);
3176 if (va[i].format == IQM_FLOAT && va[i].size == 3)
3178 vnormal = Mem_Alloc(loadmodel->mempool, sizeof(float[3]) * header->num_vertexes);
3179 memcpy(vnormal, pbase + va[i].offset, sizeof(float[3]) * header->num_vertexes);
3183 if (va[i].format == IQM_FLOAT && va[i].size == 4)
3185 vtangent = Mem_Alloc(loadmodel->mempool, sizeof(float[4]) * header->num_vertexes);
3186 memcpy(vtangent, pbase + va[i].offset, sizeof(float[4]) * header->num_vertexes);
3189 case IQM_BLENDINDEXES:
3190 if (va[i].format == IQM_UBYTE && va[i].size == 4)
3192 vblendindexes = Mem_Alloc(loadmodel->mempool, sizeof(unsigned char[4]) * header->num_vertexes);
3193 memcpy(vblendindexes, pbase + va[i].offset, sizeof(unsigned char[4]) * header->num_vertexes);
3196 case IQM_BLENDWEIGHTS:
3197 if (va[i].format == IQM_UBYTE && va[i].size == 4)
3199 vblendweights = Mem_Alloc(loadmodel->mempool, sizeof(unsigned char[4]) * header->num_vertexes);
3200 memcpy(vblendweights, pbase + va[i].offset, sizeof(unsigned char[4]) * header->num_vertexes);
3205 if (header->num_vertexes > 0 && (!vposition || !vtexcoord || ((header->num_frames > 0 || header->num_anims > 0) && (!vblendindexes || !vblendweights))))
3207 Con_Printf("%s is missing vertex array data\n", loadmodel->name);
3211 text = header->num_text && header->ofs_text ? (const char *)(pbase + header->ofs_text) : "";
3213 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
3214 loadmodel->DrawSky = NULL;
3215 loadmodel->DrawAddWaterPlanes = NULL;
3216 loadmodel->Draw = R_Q1BSP_Draw;
3217 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
3218 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
3219 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
3220 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
3221 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
3222 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
3223 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
3224 loadmodel->DrawLight = R_Q1BSP_DrawLight;
3225 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
3226 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
3227 loadmodel->PointSuperContents = NULL;
3229 // load external .skin files if present
3230 skinfiles = Mod_LoadSkinFiles();
3231 if (loadmodel->numskins < 1)
3232 loadmodel->numskins = 1;
3234 loadmodel->numframes = max(header->num_anims, 1);
3235 loadmodel->num_bones = header->num_joints;
3236 loadmodel->num_poses = max(header->num_frames, 1);
3237 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = header->num_meshes;
3238 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3239 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3241 meshvertices = header->num_vertexes;
3242 meshtriangles = header->num_triangles;
3244 // do most allocations as one merged chunk
3245 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));
3246 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
3247 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
3248 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
3249 loadmodel->surfmesh.num_vertices = meshvertices;
3250 loadmodel->surfmesh.num_triangles = meshtriangles;
3251 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3252 if (r_enableshadowvolumes.integer)
3254 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3256 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
3257 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3258 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3259 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
3260 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
3261 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
3262 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
3263 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
3264 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
3265 if (vblendindexes && vblendweights)
3267 loadmodel->surfmesh.num_blends = 0;
3268 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
3270 if (meshvertices <= 65536)
3272 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
3274 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
3275 if (vblendindexes && vblendweights)
3276 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
3278 for (i = 0;i < loadmodel->numskins;i++)
3280 loadmodel->skinscenes[i].firstframe = i;
3281 loadmodel->skinscenes[i].framecount = 1;
3282 loadmodel->skinscenes[i].loop = true;
3283 loadmodel->skinscenes[i].framerate = 10;
3286 // load the bone info
3287 if (header->version == 1)
3289 for (i = 0;i < loadmodel->num_bones;i++)
3291 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3292 joint1[i].name = LittleLong(joint1[i].name);
3293 joint1[i].parent = LittleLong(joint1[i].parent);
3294 for (j = 0;j < 3;j++)
3296 joint1[i].origin[j] = LittleFloat(joint1[i].origin[j]);
3297 joint1[i].rotation[j] = LittleFloat(joint1[i].rotation[j]);
3298 joint1[i].scale[j] = LittleFloat(joint1[i].scale[j]);
3300 strlcpy(loadmodel->data_bones[i].name, &text[joint1[i].name], sizeof(loadmodel->data_bones[i].name));
3301 loadmodel->data_bones[i].parent = joint1[i].parent;
3302 if (loadmodel->data_bones[i].parent >= i)
3303 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3304 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]);
3305 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3306 if (loadmodel->data_bones[i].parent >= 0)
3308 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3309 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3310 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3312 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3317 for (i = 0;i < loadmodel->num_bones;i++)
3319 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3320 joint[i].name = LittleLong(joint[i].name);
3321 joint[i].parent = LittleLong(joint[i].parent);
3322 for (j = 0;j < 3;j++)
3324 joint[i].origin[j] = LittleFloat(joint[i].origin[j]);
3325 joint[i].rotation[j] = LittleFloat(joint[i].rotation[j]);
3326 joint[i].scale[j] = LittleFloat(joint[i].scale[j]);
3328 joint[i].rotation[3] = LittleFloat(joint[i].rotation[3]);
3329 strlcpy(loadmodel->data_bones[i].name, &text[joint[i].name], sizeof(loadmodel->data_bones[i].name));
3330 loadmodel->data_bones[i].parent = joint[i].parent;
3331 if (loadmodel->data_bones[i].parent >= i)
3332 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3333 if (joint[i].rotation[3] > 0)
3334 Vector4Negate(joint[i].rotation, joint[i].rotation);
3335 Vector4Normalize2(joint[i].rotation, joint[i].rotation);
3336 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]);
3337 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3338 if (loadmodel->data_bones[i].parent >= 0)
3340 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3341 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3342 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3344 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3348 // set up the animscenes based on the anims
3349 for (i = 0;i < (int)header->num_anims;i++)
3351 anim[i].name = LittleLong(anim[i].name);
3352 anim[i].first_frame = LittleLong(anim[i].first_frame);
3353 anim[i].num_frames = LittleLong(anim[i].num_frames);
3354 anim[i].framerate = LittleFloat(anim[i].framerate);
3355 anim[i].flags = LittleLong(anim[i].flags);
3356 strlcpy(loadmodel->animscenes[i].name, &text[anim[i].name], sizeof(loadmodel->animscenes[i].name));
3357 loadmodel->animscenes[i].firstframe = anim[i].first_frame;
3358 loadmodel->animscenes[i].framecount = anim[i].num_frames;
3359 loadmodel->animscenes[i].loop = ((anim[i].flags & IQM_LOOP) != 0);
3360 loadmodel->animscenes[i].framerate = anim[i].framerate;
3362 if (header->num_anims <= 0)
3364 strlcpy(loadmodel->animscenes[0].name, "static", sizeof(loadmodel->animscenes[0].name));
3365 loadmodel->animscenes[0].firstframe = 0;
3366 loadmodel->animscenes[0].framecount = 1;
3367 loadmodel->animscenes[0].loop = true;
3368 loadmodel->animscenes[0].framerate = 10;
3372 if (header->version == 1)
3374 for (i = 0;i < (int)header->num_poses;i++)
3377 pose1[i].parent = LittleLong(pose1[i].parent);
3378 pose1[i].channelmask = LittleLong(pose1[i].channelmask);
3379 for (j = 0;j < 9;j++)
3381 pose1[i].channeloffset[j] = LittleFloat(pose1[i].channeloffset[j]);
3382 pose1[i].channelscale[j] = LittleFloat(pose1[i].channelscale[j]);
3384 f = fabs(pose1[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3385 f = fabs(pose1[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3386 f = fabs(pose1[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3387 f = fabs(pose1[i].channeloffset[0] + 0xFFFF*pose1[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3388 f = fabs(pose1[i].channeloffset[1] + 0xFFFF*pose1[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3389 f = fabs(pose1[i].channeloffset[2] + 0xFFFF*pose1[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3391 if (header->num_frames <= 0)
3393 for (i = 0;i < loadmodel->num_bones;i++)
3396 f = fabs(joint1[i].origin[0]); biggestorigin = max(biggestorigin, f);
3397 f = fabs(joint1[i].origin[1]); biggestorigin = max(biggestorigin, f);
3398 f = fabs(joint1[i].origin[2]); biggestorigin = max(biggestorigin, f);
3404 for (i = 0;i < (int)header->num_poses;i++)
3407 pose[i].parent = LittleLong(pose[i].parent);
3408 pose[i].channelmask = LittleLong(pose[i].channelmask);
3409 for (j = 0;j < 10;j++)
3411 pose[i].channeloffset[j] = LittleFloat(pose[i].channeloffset[j]);
3412 pose[i].channelscale[j] = LittleFloat(pose[i].channelscale[j]);
3414 f = fabs(pose[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3415 f = fabs(pose[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3416 f = fabs(pose[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3417 f = fabs(pose[i].channeloffset[0] + 0xFFFF*pose[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3418 f = fabs(pose[i].channeloffset[1] + 0xFFFF*pose[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3419 f = fabs(pose[i].channeloffset[2] + 0xFFFF*pose[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3421 if (header->num_frames <= 0)
3423 for (i = 0;i < loadmodel->num_bones;i++)
3426 f = fabs(joint[i].origin[0]); biggestorigin = max(biggestorigin, f);
3427 f = fabs(joint[i].origin[1]); biggestorigin = max(biggestorigin, f);
3428 f = fabs(joint[i].origin[2]); biggestorigin = max(biggestorigin, f);
3432 loadmodel->num_posescale = biggestorigin / 32767.0f;
3433 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3435 // load the pose data
3436 if (header->version == 1)
3438 for (i = 0, k = 0;i < (int)header->num_frames;i++)
3440 for (j = 0;j < (int)header->num_poses;j++, k++)
3442 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));
3443 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));
3444 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));
3445 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));
3446 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));
3447 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));
3448 // skip scale data for now
3449 if(pose1[j].channelmask&64) framedata++;
3450 if(pose1[j].channelmask&128) framedata++;
3451 if(pose1[j].channelmask&256) framedata++;
3454 if (header->num_frames <= 0)
3456 for (i = 0;i < loadmodel->num_bones;i++)
3458 loadmodel->data_poses6s[i*6 + 0] = loadmodel->num_poseinvscale * joint1[i].origin[0];
3459 loadmodel->data_poses6s[i*6 + 1] = loadmodel->num_poseinvscale * joint1[i].origin[1];
3460 loadmodel->data_poses6s[i*6 + 2] = loadmodel->num_poseinvscale * joint1[i].origin[2];
3461 loadmodel->data_poses6s[i*6 + 3] = 32767.0f * joint1[i].rotation[0];
3462 loadmodel->data_poses6s[i*6 + 4] = 32767.0f * joint1[i].rotation[1];
3463 loadmodel->data_poses6s[i*6 + 5] = 32767.0f * joint1[i].rotation[2];
3469 for (i = 0, k = 0;i < (int)header->num_frames;i++)
3471 for (j = 0;j < (int)header->num_poses;j++, k++)
3474 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));
3475 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));
3476 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));
3477 rot[0] = pose[j].channeloffset[3] + (pose[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[3] : 0);
3478 rot[1] = pose[j].channeloffset[4] + (pose[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[4] : 0);
3479 rot[2] = pose[j].channeloffset[5] + (pose[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[5] : 0);
3480 rot[3] = pose[j].channeloffset[6] + (pose[j].channelmask&64 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[6] : 0);
3482 Vector4Negate(rot, rot);
3483 Vector4Normalize2(rot, rot);
3484 loadmodel->data_poses6s[k*6 + 3] = 32767.0f * rot[0];
3485 loadmodel->data_poses6s[k*6 + 4] = 32767.0f * rot[1];
3486 loadmodel->data_poses6s[k*6 + 5] = 32767.0f * rot[2];
3487 // skip scale data for now
3488 if(pose[j].channelmask&128) framedata++;
3489 if(pose[j].channelmask&256) framedata++;
3490 if(pose[j].channelmask&512) framedata++;
3493 if (header->num_frames <= 0)
3495 for (i = 0;i < loadmodel->num_bones;i++)
3497 loadmodel->data_poses6s[i*6 + 0] = loadmodel->num_poseinvscale * joint[i].origin[0];
3498 loadmodel->data_poses6s[i*6 + 1] = loadmodel->num_poseinvscale * joint[i].origin[1];
3499 loadmodel->data_poses6s[i*6 + 2] = loadmodel->num_poseinvscale * joint[i].origin[2];
3500 loadmodel->data_poses6s[i*6 + 3] = 32767.0f * joint[i].rotation[0];
3501 loadmodel->data_poses6s[i*6 + 4] = 32767.0f * joint[i].rotation[1];
3502 loadmodel->data_poses6s[i*6 + 5] = 32767.0f * joint[i].rotation[2];
3507 // load bounding box data
3508 if (header->ofs_bounds)
3510 float xyradius = 0, radius = 0;
3511 VectorClear(loadmodel->normalmins);
3512 VectorClear(loadmodel->normalmaxs);
3513 for (i = 0; i < (int)header->num_frames;i++)
3515 bounds[i].mins[0] = LittleFloat(bounds[i].mins[0]);
3516 bounds[i].mins[1] = LittleFloat(bounds[i].mins[1]);
3517 bounds[i].mins[2] = LittleFloat(bounds[i].mins[2]);
3518 bounds[i].maxs[0] = LittleFloat(bounds[i].maxs[0]);
3519 bounds[i].maxs[1] = LittleFloat(bounds[i].maxs[1]);
3520 bounds[i].maxs[2] = LittleFloat(bounds[i].maxs[2]);
3521 bounds[i].xyradius = LittleFloat(bounds[i].xyradius);
3522 bounds[i].radius = LittleFloat(bounds[i].radius);
3525 VectorCopy(bounds[i].mins, loadmodel->normalmins);
3526 VectorCopy(bounds[i].maxs, loadmodel->normalmaxs);
3530 if (loadmodel->normalmins[0] > bounds[i].mins[0]) loadmodel->normalmins[0] = bounds[i].mins[0];
3531 if (loadmodel->normalmins[1] > bounds[i].mins[1]) loadmodel->normalmins[1] = bounds[i].mins[1];
3532 if (loadmodel->normalmins[2] > bounds[i].mins[2]) loadmodel->normalmins[2] = bounds[i].mins[2];
3533 if (loadmodel->normalmaxs[0] < bounds[i].maxs[0]) loadmodel->normalmaxs[0] = bounds[i].maxs[0];
3534 if (loadmodel->normalmaxs[1] < bounds[i].maxs[1]) loadmodel->normalmaxs[1] = bounds[i].maxs[1];
3535 if (loadmodel->normalmaxs[2] < bounds[i].maxs[2]) loadmodel->normalmaxs[2] = bounds[i].maxs[2];
3537 if (bounds[i].xyradius > xyradius)
3538 xyradius = bounds[i].xyradius;
3539 if (bounds[i].radius > radius)
3540 radius = bounds[i].radius;
3542 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -xyradius;
3543 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = xyradius;
3544 loadmodel->yawmins[2] = loadmodel->normalmins[2];
3545 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
3546 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
3547 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
3548 loadmodel->radius = radius;
3549 loadmodel->radius2 = radius * radius;
3552 // load triangle data
3553 inelements = loadmodel->surfmesh.data_element3i;
3554 outelements = loadmodel->surfmesh.data_element3i;
3555 for (i = 0;i < (int)header->num_triangles;i++)
3557 outelements[0] = LittleLong(inelements[0]);
3558 outelements[1] = LittleLong(inelements[1]);
3559 outelements[2] = LittleLong(inelements[2]);
3563 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, header->num_vertexes, __FILE__, __LINE__);
3565 if (header->ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
3567 inelements = loadmodel->surfmesh.data_neighbor3i;
3568 outelements = loadmodel->surfmesh.data_neighbor3i;
3569 for (i = 0;i < (int)header->num_triangles;i++)
3571 outelements[0] = LittleLong(inelements[0]);
3572 outelements[1] = LittleLong(inelements[1]);
3573 outelements[2] = LittleLong(inelements[2]);
3580 outvertex = loadmodel->surfmesh.data_vertex3f;
3581 for (i = 0;i < (int)header->num_vertexes;i++)
3583 outvertex[0] = LittleFloat(vposition[0]);
3584 outvertex[1] = LittleFloat(vposition[1]);
3585 outvertex[2] = LittleFloat(vposition[2]);
3590 outtexcoord = loadmodel->surfmesh.data_texcoordtexture2f;
3591 for (i = 0;i < (int)header->num_vertexes;i++)
3593 outtexcoord[0] = LittleFloat(vtexcoord[0]);
3594 outtexcoord[1] = LittleFloat(vtexcoord[1]);
3601 outnormal = loadmodel->surfmesh.data_normal3f;
3602 for (i = 0;i < (int)header->num_vertexes;i++)
3604 outnormal[0] = LittleFloat(vnormal[0]);
3605 outnormal[1] = LittleFloat(vnormal[1]);
3606 outnormal[2] = LittleFloat(vnormal[2]);
3612 if(vnormal && vtangent)
3614 outnormal = loadmodel->surfmesh.data_normal3f;
3615 outsvector = loadmodel->surfmesh.data_svector3f;
3616 outtvector = loadmodel->surfmesh.data_tvector3f;
3617 for (i = 0;i < (int)header->num_vertexes;i++)
3619 outsvector[0] = LittleFloat(vtangent[0]);
3620 outsvector[1] = LittleFloat(vtangent[1]);
3621 outsvector[2] = LittleFloat(vtangent[2]);
3622 if(LittleFloat(vtangent[3]) < 0)
3623 CrossProduct(outsvector, outnormal, outtvector);
3625 CrossProduct(outnormal, outsvector, outtvector);
3633 if (vblendindexes && vblendweights)
3635 for (i = 0; i < (int)header->num_vertexes;i++)
3637 blendweights_t weights;
3638 memcpy(weights.index, vblendindexes + i*4, 4);
3639 memcpy(weights.influence, vblendweights + i*4, 4);
3640 loadmodel->surfmesh.blends[i] = Mod_Skeletal_AddBlend(loadmodel, &weights);
3645 for (i = 0;i < (int)header->num_meshes;i++)
3647 msurface_t *surface;
3649 mesh[i].name = LittleLong(mesh[i].name);
3650 mesh[i].material = LittleLong(mesh[i].material);
3651 mesh[i].first_vertex = LittleLong(mesh[i].first_vertex);
3652 mesh[i].num_vertexes = LittleLong(mesh[i].num_vertexes);
3653 mesh[i].first_triangle = LittleLong(mesh[i].first_triangle);
3654 mesh[i].num_triangles = LittleLong(mesh[i].num_triangles);
3656 loadmodel->sortedmodelsurfaces[i] = i;
3657 surface = loadmodel->data_surfaces + i;
3658 surface->texture = loadmodel->data_textures + i;
3659 surface->num_firsttriangle = mesh[i].first_triangle;
3660 surface->num_triangles = mesh[i].num_triangles;
3661 surface->num_firstvertex = mesh[i].first_vertex;
3662 surface->num_vertices = mesh[i].num_vertexes;
3664 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, &text[mesh[i].name], &text[mesh[i].material]);
3667 Mod_FreeSkinFiles(skinfiles);
3668 Mod_MakeSortedSurfaces(loadmodel);
3670 // compute all the mesh information that was not loaded from the file
3671 if (loadmodel->surfmesh.data_element3s)
3672 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3673 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3675 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);
3676 if (!vnormal || !vtangent)
3677 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);
3678 if (!header->ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
3679 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3680 if (!header->ofs_bounds)
3681 Mod_Alias_CalculateBoundingBox();
3683 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
3685 if (!loadmodel->surfmesh.isanimated)
3687 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3688 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3689 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3690 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3691 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3692 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
3695 if (anim ) Mem_Free(anim );anim = NULL;
3696 if (bounds ) Mem_Free(bounds );bounds = NULL;
3697 if (framedata ) Mem_Free(framedata );framedata = NULL;
3698 if (joint ) Mem_Free(joint );joint = NULL;
3699 if (joint1 ) Mem_Free(joint1 );joint1 = NULL;
3700 if (mesh ) Mem_Free(mesh );mesh = NULL;
3701 if (pose ) Mem_Free(pose );pose = NULL;
3702 if (pose1 ) Mem_Free(pose1 );pose1 = NULL;
3703 if (va ) Mem_Free(va );va = NULL;
3704 if (vblendindexes) Mem_Free(vblendindexes);vblendindexes = NULL;
3705 if (vblendweights) Mem_Free(vblendweights);vblendweights = NULL;
3706 if (vnormal ) Mem_Free(vnormal );vnormal = NULL;
3707 if (vposition ) Mem_Free(vposition );vposition = NULL;
3708 if (vtangent ) Mem_Free(vtangent );vtangent = NULL;
3709 if (vtexcoord ) Mem_Free(vtexcoord );vtexcoord = NULL;