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_OFF;
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)
1057 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1058 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1059 if (loadmodel->surfmesh.data_neighbor3i)
1060 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1061 Mod_Alias_CalculateBoundingBox();
1062 Mod_Alias_MorphMesh_CompileFrames();
1065 Mem_Free(vertremap);
1068 skinfiles = Mod_LoadSkinFiles();
1071 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1072 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1073 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1074 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1075 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1076 Mod_FreeSkinFiles(skinfiles);
1077 for (i = 0;i < loadmodel->numskins;i++)
1079 loadmodel->skinscenes[i].firstframe = i;
1080 loadmodel->skinscenes[i].framecount = 1;
1081 loadmodel->skinscenes[i].loop = true;
1082 loadmodel->skinscenes[i].framerate = 10;
1087 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1088 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1089 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1090 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1092 datapointer = startskins;
1093 for (i = 0;i < loadmodel->numskins;i++)
1095 pinskintype = (daliasskintype_t *)datapointer;
1096 datapointer += sizeof(daliasskintype_t);
1098 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1105 pinskingroup = (daliasskingroup_t *)datapointer;
1106 datapointer += sizeof(daliasskingroup_t);
1108 groupskins = LittleLong (pinskingroup->numskins);
1110 pinskinintervals = (daliasskininterval_t *)datapointer;
1111 datapointer += sizeof(daliasskininterval_t) * groupskins;
1113 interval = LittleFloat(pinskinintervals[0].interval);
1114 if (interval < 0.01f)
1116 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1121 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1122 loadmodel->skinscenes[i].firstframe = totalskins;
1123 loadmodel->skinscenes[i].framecount = groupskins;
1124 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1125 loadmodel->skinscenes[i].loop = true;
1127 for (j = 0;j < groupskins;j++)
1130 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1132 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1133 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))
1134 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));
1135 datapointer += skinwidth * skinheight;
1139 // check for skins that don't exist in the model, but do exist as external images
1140 // (this was added because yummyluv kept pestering me about support for it)
1141 // TODO: support shaders here?
1142 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)))
1144 // expand the arrays to make room
1145 tempskinscenes = loadmodel->skinscenes;
1146 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1147 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1148 Mem_Free(tempskinscenes);
1150 tempaliasskins = loadmodel->data_textures;
1151 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1152 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1153 Mem_Free(tempaliasskins);
1155 // store the info about the new skin
1156 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1157 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1158 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1159 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1160 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1161 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1163 //increase skin counts
1164 loadmodel->numskins++;
1167 // fix up the pointers since they are pointing at the old textures array
1168 // FIXME: this is a hack!
1169 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1170 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1174 surface = loadmodel->data_surfaces;
1175 surface->texture = loadmodel->data_textures;
1176 surface->num_firsttriangle = 0;
1177 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1178 surface->num_firstvertex = 0;
1179 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1181 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1183 if (!loadmodel->surfmesh.isanimated)
1185 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1186 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1187 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1188 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1189 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1190 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1194 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1196 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1197 float iskinwidth, iskinheight;
1198 unsigned char *data;
1199 msurface_t *surface;
1201 unsigned char *base, *datapointer;
1202 md2frame_t *pinframe;
1204 md2triangle_t *intri;
1205 unsigned short *inst;
1206 struct md2verthash_s
1208 struct md2verthash_s *next;
1212 *hash, **md2verthash, *md2verthashdata;
1213 skinfile_t *skinfiles;
1215 pinmodel = (md2_t *)buffer;
1216 base = (unsigned char *)buffer;
1218 version = LittleLong (pinmodel->version);
1219 if (version != MD2ALIAS_VERSION)
1220 Host_Error ("%s has wrong version number (%i should be %i)",
1221 loadmodel->name, version, MD2ALIAS_VERSION);
1223 loadmodel->modeldatatypestring = "MD2";
1225 loadmodel->type = mod_alias;
1226 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1227 loadmodel->DrawSky = NULL;
1228 loadmodel->DrawAddWaterPlanes = NULL;
1229 loadmodel->Draw = R_Q1BSP_Draw;
1230 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1231 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1232 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1233 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1234 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1235 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1236 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1237 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1238 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1239 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1240 loadmodel->PointSuperContents = NULL;
1242 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1243 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1244 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1245 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1246 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1247 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1248 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1249 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1251 end = LittleLong(pinmodel->ofs_end);
1252 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1253 Host_Error ("%s is not a valid model", loadmodel->name);
1254 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1255 Host_Error ("%s is not a valid model", loadmodel->name);
1256 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1257 Host_Error ("%s is not a valid model", loadmodel->name);
1258 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1259 Host_Error ("%s is not a valid model", loadmodel->name);
1260 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1261 Host_Error ("%s is not a valid model", loadmodel->name);
1263 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1264 numxyz = LittleLong(pinmodel->num_xyz);
1265 numst = LittleLong(pinmodel->num_st);
1266 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1267 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1268 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1269 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1270 skinwidth = LittleLong(pinmodel->skinwidth);
1271 skinheight = LittleLong(pinmodel->skinheight);
1272 iskinwidth = 1.0f / skinwidth;
1273 iskinheight = 1.0f / skinheight;
1275 loadmodel->num_surfaces = 1;
1276 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1277 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));
1278 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1279 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1280 loadmodel->sortedmodelsurfaces[0] = 0;
1281 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1282 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1283 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1284 if (r_enableshadowvolumes.integer)
1285 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1287 loadmodel->synctype = ST_RAND;
1290 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1291 skinfiles = Mod_LoadSkinFiles();
1294 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1295 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1296 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1297 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1298 Mod_FreeSkinFiles(skinfiles);
1300 else if (loadmodel->numskins)
1302 // skins found (most likely not a player model)
1303 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1304 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1305 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1306 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1307 Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
1311 // no skins (most likely a player model)
1312 loadmodel->numskins = 1;
1313 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1314 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1315 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1316 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1319 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1320 for (i = 0;i < loadmodel->numskins;i++)
1322 loadmodel->skinscenes[i].firstframe = i;
1323 loadmodel->skinscenes[i].framecount = 1;
1324 loadmodel->skinscenes[i].loop = true;
1325 loadmodel->skinscenes[i].framerate = 10;
1328 // load the triangles and stvert data
1329 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1330 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1331 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1332 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1333 // swap the triangle list
1334 loadmodel->surfmesh.num_vertices = 0;
1335 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1337 for (j = 0;j < 3;j++)
1339 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1340 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1343 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1348 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1351 hashindex = (xyz * 256 + st) & 65535;
1352 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1353 if (hash->xyz == xyz && hash->st == st)
1357 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1360 hash->next = md2verthash[hashindex];
1361 md2verthash[hashindex] = hash;
1363 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1367 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1368 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));
1369 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1370 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1371 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1374 hash = md2verthashdata + i;
1375 vertremap[i] = hash->xyz;
1376 sts = LittleShort(inst[hash->st*2+0]);
1377 stt = LittleShort(inst[hash->st*2+1]);
1378 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1380 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1384 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1385 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1388 Mem_Free(md2verthash);
1389 Mem_Free(md2verthashdata);
1391 // generate ushort elements array if possible
1392 if (loadmodel->surfmesh.num_vertices <= 65536)
1393 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1394 if (loadmodel->surfmesh.data_element3s)
1395 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1396 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1399 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1400 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1405 pinframe = (md2frame_t *)datapointer;
1406 datapointer += sizeof(md2frame_t);
1407 // store the frame scale/translate into the appropriate array
1408 for (j = 0;j < 3;j++)
1410 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1411 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1413 // convert the vertices
1414 v = (trivertx_t *)datapointer;
1415 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1416 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1417 out[k] = v[vertremap[k]];
1418 datapointer += numxyz * sizeof(trivertx_t);
1420 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1421 loadmodel->animscenes[i].firstframe = i;
1422 loadmodel->animscenes[i].framecount = 1;
1423 loadmodel->animscenes[i].framerate = 10;
1424 loadmodel->animscenes[i].loop = true;
1427 Mem_Free(vertremap);
1429 if (loadmodel->surfmesh.data_neighbor3i)
1430 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1431 Mod_Alias_CalculateBoundingBox();
1432 Mod_Alias_MorphMesh_CompileFrames();
1434 surface = loadmodel->data_surfaces;
1435 surface->texture = loadmodel->data_textures;
1436 surface->num_firsttriangle = 0;
1437 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1438 surface->num_firstvertex = 0;
1439 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1441 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1443 if (!loadmodel->surfmesh.isanimated)
1445 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1446 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1447 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1448 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1449 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1450 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1454 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1456 int i, j, k, version, meshvertices, meshtriangles;
1457 unsigned char *data;
1458 msurface_t *surface;
1459 md3modelheader_t *pinmodel;
1460 md3frameinfo_t *pinframe;
1463 skinfile_t *skinfiles;
1465 pinmodel = (md3modelheader_t *)buffer;
1467 if (memcmp(pinmodel->identifier, "IDP3", 4))
1468 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1469 version = LittleLong (pinmodel->version);
1470 if (version != MD3VERSION)
1471 Host_Error ("%s has wrong version number (%i should be %i)",
1472 loadmodel->name, version, MD3VERSION);
1474 skinfiles = Mod_LoadSkinFiles();
1475 if (loadmodel->numskins < 1)
1476 loadmodel->numskins = 1;
1478 loadmodel->modeldatatypestring = "MD3";
1480 loadmodel->type = mod_alias;
1481 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1482 loadmodel->DrawSky = NULL;
1483 loadmodel->DrawAddWaterPlanes = NULL;
1484 loadmodel->Draw = R_Q1BSP_Draw;
1485 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1486 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1487 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1488 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1489 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1490 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1491 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1492 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1493 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1494 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1495 loadmodel->PointSuperContents = NULL;
1496 loadmodel->synctype = ST_RAND;
1497 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1498 i = LittleLong (pinmodel->flags);
1499 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1501 // set up some global info about the model
1502 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1503 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1505 // make skinscenes for the skins (no groups)
1506 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1507 for (i = 0;i < loadmodel->numskins;i++)
1509 loadmodel->skinscenes[i].firstframe = i;
1510 loadmodel->skinscenes[i].framecount = 1;
1511 loadmodel->skinscenes[i].loop = true;
1512 loadmodel->skinscenes[i].framerate = 10;
1516 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1517 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1519 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1520 loadmodel->animscenes[i].firstframe = i;
1521 loadmodel->animscenes[i].framecount = 1;
1522 loadmodel->animscenes[i].framerate = 10;
1523 loadmodel->animscenes[i].loop = true;
1527 loadmodel->num_tagframes = loadmodel->numframes;
1528 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1529 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1530 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1532 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1533 for (j = 0;j < 9;j++)
1534 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1535 for (j = 0;j < 3;j++)
1536 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1537 //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);
1543 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)))
1545 if (memcmp(pinmesh->identifier, "IDP3", 4))
1546 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1547 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1548 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1549 meshvertices += LittleLong(pinmesh->num_vertices);
1550 meshtriangles += LittleLong(pinmesh->num_triangles);
1553 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1554 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1555 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1556 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));
1557 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1558 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1559 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1560 loadmodel->surfmesh.num_vertices = meshvertices;
1561 loadmodel->surfmesh.num_triangles = meshtriangles;
1562 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1563 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1564 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1565 if (r_enableshadowvolumes.integer)
1566 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1567 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1568 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1569 if (meshvertices <= 65536)
1570 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1574 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)))
1576 if (memcmp(pinmesh->identifier, "IDP3", 4))
1577 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1578 loadmodel->sortedmodelsurfaces[i] = i;
1579 surface = loadmodel->data_surfaces + i;
1580 surface->texture = loadmodel->data_textures + i;
1581 surface->num_firsttriangle = meshtriangles;
1582 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1583 surface->num_firstvertex = meshvertices;
1584 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1585 meshvertices += surface->num_vertices;
1586 meshtriangles += surface->num_triangles;
1588 for (j = 0;j < surface->num_triangles * 3;j++)
1589 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1590 for (j = 0;j < surface->num_vertices;j++)
1592 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1593 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1595 for (j = 0;j < loadmodel->numframes;j++)
1597 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1598 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1599 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1601 out->origin[0] = LittleShort(in->origin[0]);
1602 out->origin[1] = LittleShort(in->origin[1]);
1603 out->origin[2] = LittleShort(in->origin[2]);
1604 out->pitch = in->pitch;
1609 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1611 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1613 if (loadmodel->surfmesh.data_element3s)
1614 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1615 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1616 if (loadmodel->surfmesh.data_neighbor3i)
1617 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1618 Mod_Alias_MorphMesh_CompileFrames();
1619 Mod_Alias_CalculateBoundingBox();
1620 Mod_FreeSkinFiles(skinfiles);
1621 Mod_MakeSortedSurfaces(loadmodel);
1623 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1624 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1626 if (!loadmodel->surfmesh.isanimated)
1628 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1629 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1630 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1631 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1632 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1633 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1637 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1639 zymtype1header_t *pinmodel, *pheader;
1640 unsigned char *pbase;
1641 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1642 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose, f, biggestorigin, tempvec[3], modelscale;
1643 zymvertex_t *verts, *vertdata;
1647 skinfile_t *skinfiles;
1648 unsigned char *data;
1649 msurface_t *surface;
1651 pinmodel = (zymtype1header_t *)buffer;
1652 pbase = (unsigned char *)buffer;
1653 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1654 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1655 if (BigLong(pinmodel->type) != 1)
1656 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1658 loadmodel->modeldatatypestring = "ZYM";
1660 loadmodel->type = mod_alias;
1661 loadmodel->synctype = ST_RAND;
1665 pheader->type = BigLong(pinmodel->type);
1666 pheader->filesize = BigLong(pinmodel->filesize);
1667 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1668 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1669 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1670 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1671 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1672 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1673 pheader->radius = BigFloat(pinmodel->radius);
1674 pheader->numverts = BigLong(pinmodel->numverts);
1675 pheader->numtris = BigLong(pinmodel->numtris);
1676 pheader->numshaders = BigLong(pinmodel->numshaders);
1677 pheader->numbones = BigLong(pinmodel->numbones);
1678 pheader->numscenes = BigLong(pinmodel->numscenes);
1679 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1680 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1681 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1682 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1683 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1684 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1685 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1686 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1687 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1688 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1689 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1690 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1691 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1692 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1693 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1694 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1695 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1696 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1698 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1700 Con_Printf("%s has no geometry\n", loadmodel->name);
1703 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1705 Con_Printf("%s has no animations\n", loadmodel->name);
1709 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1710 loadmodel->DrawSky = NULL;
1711 loadmodel->DrawAddWaterPlanes = NULL;
1712 loadmodel->Draw = R_Q1BSP_Draw;
1713 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1714 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1715 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1716 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1717 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1718 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1719 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1720 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1721 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1722 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1723 loadmodel->PointSuperContents = NULL;
1725 loadmodel->numframes = pheader->numscenes;
1726 loadmodel->num_surfaces = pheader->numshaders;
1728 skinfiles = Mod_LoadSkinFiles();
1729 if (loadmodel->numskins < 1)
1730 loadmodel->numskins = 1;
1732 // make skinscenes for the skins (no groups)
1733 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1734 for (i = 0;i < loadmodel->numskins;i++)
1736 loadmodel->skinscenes[i].firstframe = i;
1737 loadmodel->skinscenes[i].framecount = 1;
1738 loadmodel->skinscenes[i].loop = true;
1739 loadmodel->skinscenes[i].framerate = 10;
1743 modelradius = pheader->radius;
1744 for (i = 0;i < 3;i++)
1746 loadmodel->normalmins[i] = pheader->mins[i];
1747 loadmodel->normalmaxs[i] = pheader->maxs[i];
1748 loadmodel->rotatedmins[i] = -modelradius;
1749 loadmodel->rotatedmaxs[i] = modelradius;
1751 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1752 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1753 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1754 if (loadmodel->yawmaxs[0] > modelradius)
1755 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1756 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1757 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1758 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1759 loadmodel->radius = modelradius;
1760 loadmodel->radius2 = modelradius * modelradius;
1762 // go through the lumps, swapping things
1764 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1765 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1766 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1767 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1768 for (i = 0;i < pheader->numscenes;i++)
1770 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1771 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1772 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1773 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1774 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1775 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1776 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1777 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1778 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1779 if (loadmodel->animscenes[i].framerate < 0)
1780 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1784 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1785 loadmodel->num_bones = pheader->numbones;
1786 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1787 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1788 for (i = 0;i < pheader->numbones;i++)
1790 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1791 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1792 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1793 if (loadmodel->data_bones[i].parent >= i)
1794 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1797 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1798 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1799 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1800 for (i = 0;i < pheader->numverts;i++)
1802 vertbonecounts[i] = BigLong(bonecount[i]);
1803 if (vertbonecounts[i] != 1)
1804 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1807 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1809 meshvertices = pheader->numverts;
1810 meshtriangles = pheader->numtris;
1812 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1813 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1814 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1815 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]));
1816 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1817 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1818 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1819 loadmodel->surfmesh.num_vertices = meshvertices;
1820 loadmodel->surfmesh.num_triangles = meshtriangles;
1821 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1822 if (r_enableshadowvolumes.integer)
1823 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1824 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1825 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1826 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1827 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1828 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1829 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1830 loadmodel->surfmesh.num_blends = 0;
1831 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
1832 if (loadmodel->surfmesh.num_vertices <= 65536)
1833 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1834 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
1835 loadmodel->surfmesh.data_blendweights = NULL;
1837 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1838 poses = (float *) (pheader->lump_poses.start + pbase);
1839 // figure out scale of model from root bone, for compatibility with old zmodel versions
1840 tempvec[0] = BigFloat(poses[0]);
1841 tempvec[1] = BigFloat(poses[1]);
1842 tempvec[2] = BigFloat(poses[2]);
1843 modelscale = VectorLength(tempvec);
1845 for (i = 0;i < loadmodel->num_bones * numposes * 12;i++)
1847 f = fabs(BigFloat(poses[i]));
1848 biggestorigin = max(biggestorigin, f);
1850 loadmodel->num_posescale = biggestorigin / 32767.0f;
1851 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
1852 for (i = 0;i < numposes;i++)
1854 const float *frameposes = (float *) (pheader->lump_poses.start + pbase) + 12*i*loadmodel->num_bones;
1855 for (j = 0;j < loadmodel->num_bones;j++)
1858 matrix4x4_t posematrix;
1859 for (k = 0;k < 12;k++)
1860 pose[k] = BigFloat(frameposes[j*12+k]);
1861 //if (j < loadmodel->num_bones)
1862 // 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));
1863 // scale child bones to match the root scale
1864 if (loadmodel->data_bones[j].parent >= 0)
1866 pose[3] *= modelscale;
1867 pose[7] *= modelscale;
1868 pose[11] *= modelscale;
1870 // normalize rotation matrix
1871 VectorNormalize(pose + 0);
1872 VectorNormalize(pose + 4);
1873 VectorNormalize(pose + 8);
1874 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
1875 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
1879 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1880 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1881 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1882 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1883 // (converting from weight-blending skeletal animation to
1884 // deformation-based skeletal animation)
1885 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1886 for (i = 0;i < loadmodel->num_bones;i++)
1889 for (k = 0;k < 12;k++)
1890 m[k] = BigFloat(poses[i*12+k]);
1891 if (loadmodel->data_bones[i].parent >= 0)
1892 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1894 for (k = 0;k < 12;k++)
1895 bonepose[12*i+k] = m[k];
1897 for (j = 0;j < pheader->numverts;j++)
1899 // this format really should have had a per vertexweight weight value...
1900 // but since it does not, the weighting is completely ignored and
1901 // only one weight is allowed per vertex
1902 int boneindex = BigLong(vertdata[j].bonenum);
1903 const float *m = bonepose + 12 * boneindex;
1904 float relativeorigin[3];
1905 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1906 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1907 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1908 // transform the vertex bone weight into the base mesh
1909 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1910 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1911 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1912 // store the weight as the primary weight on this vertex
1913 loadmodel->surfmesh.blends[j] = boneindex;
1916 // normals and tangents are calculated after elements are loaded
1918 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1919 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1920 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1921 for (i = 0;i < pheader->numverts;i++)
1923 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1924 // flip T coordinate for OpenGL
1925 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1928 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1929 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1930 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1932 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1933 //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)
1934 // byteswap, validate, and swap winding order of tris
1935 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1936 if (pheader->lump_render.length != count)
1937 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1938 renderlist = (int *) (pheader->lump_render.start + pbase);
1939 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1941 for (i = 0;i < loadmodel->num_surfaces;i++)
1943 int firstvertex, lastvertex;
1944 if (renderlist >= renderlistend)
1945 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1946 count = BigLong(*renderlist);renderlist++;
1947 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1948 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1950 loadmodel->sortedmodelsurfaces[i] = i;
1951 surface = loadmodel->data_surfaces + i;
1952 surface->texture = loadmodel->data_textures + i;
1953 surface->num_firsttriangle = meshtriangles;
1954 surface->num_triangles = count;
1955 meshtriangles += surface->num_triangles;
1957 // load the elements
1958 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
1959 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
1961 outelements[j*3+2] = BigLong(renderlist[0]);
1962 outelements[j*3+1] = BigLong(renderlist[1]);
1963 outelements[j*3+0] = BigLong(renderlist[2]);
1965 // validate the elements and find the used vertex range
1966 firstvertex = meshvertices;
1968 for (j = 0;j < surface->num_triangles * 3;j++)
1970 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
1971 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
1972 firstvertex = min(firstvertex, outelements[j]);
1973 lastvertex = max(lastvertex, outelements[j]);
1975 surface->num_firstvertex = firstvertex;
1976 surface->num_vertices = lastvertex + 1 - firstvertex;
1978 // since zym models do not have named sections, reuse their shader
1979 // name as the section name
1980 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
1981 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
1983 Mod_FreeSkinFiles(skinfiles);
1984 Mem_Free(vertbonecounts);
1986 Mod_MakeSortedSurfaces(loadmodel);
1988 // compute all the mesh information that was not loaded from the file
1989 if (loadmodel->surfmesh.data_element3s)
1990 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1991 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1992 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
1993 Mod_BuildBaseBonePoses();
1994 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);
1995 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);
1996 if (loadmodel->surfmesh.data_neighbor3i)
1997 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1999 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2001 if (!loadmodel->surfmesh.isanimated)
2003 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2004 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2005 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2006 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2007 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2008 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2012 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2014 dpmheader_t *pheader;
2018 unsigned char *pbase;
2019 int i, j, k, meshvertices, meshtriangles;
2020 skinfile_t *skinfiles;
2021 unsigned char *data;
2023 float biggestorigin, tempvec[3], modelscale;
2027 pheader = (dpmheader_t *)buffer;
2028 pbase = (unsigned char *)buffer;
2029 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2030 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2031 if (BigLong(pheader->type) != 2)
2032 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2034 loadmodel->modeldatatypestring = "DPM";
2036 loadmodel->type = mod_alias;
2037 loadmodel->synctype = ST_RAND;
2040 pheader->type = BigLong(pheader->type);
2041 pheader->filesize = BigLong(pheader->filesize);
2042 pheader->mins[0] = BigFloat(pheader->mins[0]);
2043 pheader->mins[1] = BigFloat(pheader->mins[1]);
2044 pheader->mins[2] = BigFloat(pheader->mins[2]);
2045 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2046 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2047 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2048 pheader->yawradius = BigFloat(pheader->yawradius);
2049 pheader->allradius = BigFloat(pheader->allradius);
2050 pheader->num_bones = BigLong(pheader->num_bones);
2051 pheader->num_meshs = BigLong(pheader->num_meshs);
2052 pheader->num_frames = BigLong(pheader->num_frames);
2053 pheader->ofs_bones = BigLong(pheader->ofs_bones);
2054 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2055 pheader->ofs_frames = BigLong(pheader->ofs_frames);
2057 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2059 Con_Printf("%s has no geometry\n", loadmodel->name);
2062 if (pheader->num_frames < 1)
2064 Con_Printf("%s has no frames\n", loadmodel->name);
2068 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2069 loadmodel->DrawSky = NULL;
2070 loadmodel->DrawAddWaterPlanes = NULL;
2071 loadmodel->Draw = R_Q1BSP_Draw;
2072 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2073 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2074 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2075 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2076 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2077 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2078 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2079 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2080 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2081 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2082 loadmodel->PointSuperContents = NULL;
2085 for (i = 0;i < 3;i++)
2087 loadmodel->normalmins[i] = pheader->mins[i];
2088 loadmodel->normalmaxs[i] = pheader->maxs[i];
2089 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2090 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2091 loadmodel->rotatedmins[i] = -pheader->allradius;
2092 loadmodel->rotatedmaxs[i] = pheader->allradius;
2094 loadmodel->radius = pheader->allradius;
2095 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2097 // load external .skin files if present
2098 skinfiles = Mod_LoadSkinFiles();
2099 if (loadmodel->numskins < 1)
2100 loadmodel->numskins = 1;
2105 // gather combined statistics from the meshes
2106 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2107 for (i = 0;i < (int)pheader->num_meshs;i++)
2109 int numverts = BigLong(dpmmesh->num_verts);
2110 meshvertices += numverts;
2111 meshtriangles += BigLong(dpmmesh->num_tris);
2115 loadmodel->numframes = pheader->num_frames;
2116 loadmodel->num_bones = pheader->num_bones;
2117 loadmodel->num_poses = loadmodel->numframes;
2118 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2119 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2120 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2121 // do most allocations as one merged chunk
2122 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));
2123 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2124 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2125 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2126 loadmodel->surfmesh.num_vertices = meshvertices;
2127 loadmodel->surfmesh.num_triangles = meshtriangles;
2128 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2129 if (r_enableshadowvolumes.integer)
2130 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2131 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2132 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2133 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2134 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2135 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2136 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2137 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2138 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2139 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2140 loadmodel->surfmesh.num_blends = 0;
2141 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2142 if (meshvertices <= 65536)
2143 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2144 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2145 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
2147 for (i = 0;i < loadmodel->numskins;i++)
2149 loadmodel->skinscenes[i].firstframe = i;
2150 loadmodel->skinscenes[i].framecount = 1;
2151 loadmodel->skinscenes[i].loop = true;
2152 loadmodel->skinscenes[i].framerate = 10;
2155 // load the bone info
2156 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2157 for (i = 0;i < loadmodel->num_bones;i++)
2159 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2160 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2161 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2162 if (loadmodel->data_bones[i].parent >= i)
2163 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2167 frames = (dpmframe_t *) (pbase + pheader->ofs_frames);
2168 // figure out scale of model from root bone, for compatibility with old dpmodel versions
2169 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2170 tempvec[0] = BigFloat(poses[0]);
2171 tempvec[1] = BigFloat(poses[1]);
2172 tempvec[2] = BigFloat(poses[2]);
2173 modelscale = VectorLength(tempvec);
2175 for (i = 0;i < loadmodel->numframes;i++)
2177 memcpy(loadmodel->animscenes[i].name, frames[i].name, sizeof(frames[i].name));
2178 loadmodel->animscenes[i].firstframe = i;
2179 loadmodel->animscenes[i].framecount = 1;
2180 loadmodel->animscenes[i].loop = true;
2181 loadmodel->animscenes[i].framerate = 10;
2182 // load the bone poses for this frame
2183 poses = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2184 for (j = 0;j < loadmodel->num_bones*12;j++)
2186 f = fabs(BigFloat(poses[j]));
2187 biggestorigin = max(biggestorigin, f);
2189 // stuff not processed here: mins, maxs, yawradius, allradius
2191 loadmodel->num_posescale = biggestorigin / 32767.0f;
2192 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2193 for (i = 0;i < loadmodel->numframes;i++)
2195 const float *frameposes = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2196 for (j = 0;j < loadmodel->num_bones;j++)
2199 matrix4x4_t posematrix;
2200 for (k = 0;k < 12;k++)
2201 pose[k] = BigFloat(frameposes[j*12+k]);
2202 // scale child bones to match the root scale
2203 if (loadmodel->data_bones[j].parent >= 0)
2205 pose[3] *= modelscale;
2206 pose[7] *= modelscale;
2207 pose[11] *= modelscale;
2209 // normalize rotation matrix
2210 VectorNormalize(pose + 0);
2211 VectorNormalize(pose + 4);
2212 VectorNormalize(pose + 8);
2213 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2214 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
2218 // load the meshes now
2219 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2222 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2223 // (converting from weight-blending skeletal animation to
2224 // deformation-based skeletal animation)
2225 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2226 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2227 for (i = 0;i < loadmodel->num_bones;i++)
2230 for (k = 0;k < 12;k++)
2231 m[k] = BigFloat(poses[i*12+k]);
2232 if (loadmodel->data_bones[i].parent >= 0)
2233 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2235 for (k = 0;k < 12;k++)
2236 bonepose[12*i+k] = m[k];
2238 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2240 const int *inelements;
2242 const float *intexcoord;
2243 msurface_t *surface;
2245 loadmodel->sortedmodelsurfaces[i] = i;
2246 surface = loadmodel->data_surfaces + i;
2247 surface->texture = loadmodel->data_textures + i;
2248 surface->num_firsttriangle = meshtriangles;
2249 surface->num_triangles = BigLong(dpmmesh->num_tris);
2250 surface->num_firstvertex = meshvertices;
2251 surface->num_vertices = BigLong(dpmmesh->num_verts);
2252 meshvertices += surface->num_vertices;
2253 meshtriangles += surface->num_triangles;
2255 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2256 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2257 for (j = 0;j < surface->num_triangles;j++)
2259 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2260 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2261 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2262 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2267 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2268 for (j = 0;j < surface->num_vertices*2;j++)
2269 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2271 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2272 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2274 int weightindex[4] = { 0, 0, 0, 0 };
2275 float weightinfluence[4] = { 0, 0, 0, 0 };
2277 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2278 data += sizeof(dpmvertex_t);
2279 for (k = 0;k < numweights;k++)
2281 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2282 int boneindex = BigLong(vert->bonenum);
2283 const float *m = bonepose + 12 * boneindex;
2284 float influence = BigFloat(vert->influence);
2285 float relativeorigin[3], relativenormal[3];
2286 relativeorigin[0] = BigFloat(vert->origin[0]);
2287 relativeorigin[1] = BigFloat(vert->origin[1]);
2288 relativeorigin[2] = BigFloat(vert->origin[2]);
2289 relativenormal[0] = BigFloat(vert->normal[0]);
2290 relativenormal[1] = BigFloat(vert->normal[1]);
2291 relativenormal[2] = BigFloat(vert->normal[2]);
2292 // blend the vertex bone weights into the base mesh
2293 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2294 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2295 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2296 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2297 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2298 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2301 // store the first (and often only) weight
2302 weightinfluence[0] = influence;
2303 weightindex[0] = boneindex;
2307 // sort the new weight into this vertex's weight table
2308 // (which only accepts up to 4 bones per vertex)
2309 for (l = 0;l < 4;l++)
2311 if (weightinfluence[l] < influence)
2313 // move weaker influence weights out of the way first
2315 for (l2 = 3;l2 > l;l2--)
2317 weightinfluence[l2] = weightinfluence[l2-1];
2318 weightindex[l2] = weightindex[l2-1];
2320 // store the new weight
2321 weightinfluence[l] = influence;
2322 weightindex[l] = boneindex;
2327 data += sizeof(dpmbonevert_t);
2329 loadmodel->surfmesh.blends[j] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
2332 // since dpm models do not have named sections, reuse their shader name as the section name
2333 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2335 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2337 if (loadmodel->surfmesh.num_blends < meshvertices)
2338 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2340 Mod_FreeSkinFiles(skinfiles);
2341 Mod_MakeSortedSurfaces(loadmodel);
2343 // compute all the mesh information that was not loaded from the file
2344 if (loadmodel->surfmesh.data_element3s)
2345 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2346 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2347 Mod_BuildBaseBonePoses();
2348 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);
2349 if (loadmodel->surfmesh.data_neighbor3i)
2350 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2352 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2354 if (!loadmodel->surfmesh.isanimated)
2356 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2357 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2358 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2359 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2360 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2361 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2365 // no idea why PSK/PSA files contain weird quaternions but they do...
2366 #define PSKQUATNEGATIONS
2367 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2369 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2370 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2371 fs_offset_t filesize;
2376 pskboneinfo_t *bones;
2377 pskrawweights_t *rawweights;
2378 //pskboneinfo_t *animbones;
2379 pskaniminfo_t *anims;
2380 pskanimkeys_t *animkeys;
2381 void *animfilebuffer, *animbuffer, *animbufferend;
2382 unsigned char *data;
2384 skinfile_t *skinfiles;
2385 char animname[MAX_QPATH];
2387 float biggestorigin;
2389 pchunk = (pskchunk_t *)buffer;
2390 if (strcmp(pchunk->id, "ACTRHEAD"))
2391 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2393 loadmodel->modeldatatypestring = "PSK";
2395 loadmodel->type = mod_alias;
2396 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2397 loadmodel->DrawSky = NULL;
2398 loadmodel->DrawAddWaterPlanes = NULL;
2399 loadmodel->Draw = R_Q1BSP_Draw;
2400 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2401 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2402 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2403 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2404 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2405 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2406 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2407 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2408 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2409 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2410 loadmodel->PointSuperContents = NULL;
2411 loadmodel->synctype = ST_RAND;
2413 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2414 strlcat(animname, ".psa", sizeof(animname));
2415 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2416 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2417 if (animbuffer == NULL)
2418 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2437 while (buffer < bufferend)
2439 pchunk = (pskchunk_t *)buffer;
2440 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2441 version = LittleLong(pchunk->version);
2442 recordsize = LittleLong(pchunk->recordsize);
2443 numrecords = LittleLong(pchunk->numrecords);
2444 if (developer_extra.integer)
2445 Con_DPrintf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2446 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2447 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);
2448 if (!strcmp(pchunk->id, "ACTRHEAD"))
2452 else if (!strcmp(pchunk->id, "PNTS0000"))
2455 if (recordsize != sizeof(*p))
2456 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2457 // byteswap in place and keep the pointer
2458 numpnts = numrecords;
2459 pnts = (pskpnts_t *)buffer;
2460 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2462 p->origin[0] = LittleFloat(p->origin[0]);
2463 p->origin[1] = LittleFloat(p->origin[1]);
2464 p->origin[2] = LittleFloat(p->origin[2]);
2468 else if (!strcmp(pchunk->id, "VTXW0000"))
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 numvtxw = numrecords;
2475 vtxw = (pskvtxw_t *)buffer;
2476 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2478 p->pntsindex = LittleShort(p->pntsindex);
2479 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2480 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2481 if (p->pntsindex >= numpnts)
2483 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2489 else if (!strcmp(pchunk->id, "FACE0000"))
2492 if (recordsize != sizeof(*p))
2493 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2494 // byteswap in place and keep the pointer
2495 numfaces = numrecords;
2496 faces = (pskface_t *)buffer;
2497 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2499 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2500 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2501 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2502 p->group = LittleLong(p->group);
2503 if (p->vtxwindex[0] >= numvtxw)
2505 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2506 p->vtxwindex[0] = 0;
2508 if (p->vtxwindex[1] >= numvtxw)
2510 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2511 p->vtxwindex[1] = 0;
2513 if (p->vtxwindex[2] >= numvtxw)
2515 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2516 p->vtxwindex[2] = 0;
2521 else if (!strcmp(pchunk->id, "MATT0000"))
2524 if (recordsize != sizeof(*p))
2525 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2526 // byteswap in place and keep the pointer
2527 nummatts = numrecords;
2528 matts = (pskmatt_t *)buffer;
2529 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2535 else if (!strcmp(pchunk->id, "REFSKELT"))
2538 if (recordsize != sizeof(*p))
2539 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2540 // byteswap in place and keep the pointer
2541 numbones = numrecords;
2542 bones = (pskboneinfo_t *)buffer;
2543 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2545 p->numchildren = LittleLong(p->numchildren);
2546 p->parent = LittleLong(p->parent);
2547 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2548 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2549 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2550 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2551 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2552 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2553 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2554 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2555 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2556 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2557 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2558 #ifdef PSKQUATNEGATIONS
2561 p->basepose.quat[0] *= -1;
2562 p->basepose.quat[1] *= -1;
2563 p->basepose.quat[2] *= -1;
2567 p->basepose.quat[0] *= 1;
2568 p->basepose.quat[1] *= -1;
2569 p->basepose.quat[2] *= 1;
2572 if (p->parent < 0 || p->parent >= numbones)
2574 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2580 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2583 if (recordsize != sizeof(*p))
2584 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2585 // byteswap in place and keep the pointer
2586 numrawweights = numrecords;
2587 rawweights = (pskrawweights_t *)buffer;
2588 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2590 p->weight = LittleFloat(p->weight);
2591 p->pntsindex = LittleLong(p->pntsindex);
2592 p->boneindex = LittleLong(p->boneindex);
2593 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2595 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2598 if (p->boneindex < 0 || p->boneindex >= numbones)
2600 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2608 while (animbuffer < animbufferend)
2610 pchunk = (pskchunk_t *)animbuffer;
2611 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2612 version = LittleLong(pchunk->version);
2613 recordsize = LittleLong(pchunk->recordsize);
2614 numrecords = LittleLong(pchunk->numrecords);
2615 if (developer_extra.integer)
2616 Con_DPrintf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2617 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2618 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);
2619 if (!strcmp(pchunk->id, "ANIMHEAD"))
2623 else if (!strcmp(pchunk->id, "BONENAMES"))
2626 if (recordsize != sizeof(*p))
2627 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2628 // byteswap in place and keep the pointer
2629 numanimbones = numrecords;
2630 //animbones = (pskboneinfo_t *)animbuffer;
2631 // NOTE: supposedly psa does not need to match the psk model, the
2632 // bones missing from the psa would simply use their base
2633 // positions from the psk, but this is hard for me to implement
2634 // and people can easily make animations that match.
2635 if (numanimbones != numbones)
2636 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2637 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2639 p->numchildren = LittleLong(p->numchildren);
2640 p->parent = LittleLong(p->parent);
2641 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2642 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2643 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2644 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2645 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2646 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2647 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2648 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2649 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2650 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2651 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2652 #ifdef PSKQUATNEGATIONS
2655 p->basepose.quat[0] *= -1;
2656 p->basepose.quat[1] *= -1;
2657 p->basepose.quat[2] *= -1;
2661 p->basepose.quat[0] *= 1;
2662 p->basepose.quat[1] *= -1;
2663 p->basepose.quat[2] *= 1;
2666 if (p->parent < 0 || p->parent >= numanimbones)
2668 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2671 // check that bones are the same as in the base
2672 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2673 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2677 else if (!strcmp(pchunk->id, "ANIMINFO"))
2680 if (recordsize != sizeof(*p))
2681 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2682 // byteswap in place and keep the pointer
2683 numanims = numrecords;
2684 anims = (pskaniminfo_t *)animbuffer;
2685 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2687 p->numbones = LittleLong(p->numbones);
2688 p->playtime = LittleFloat(p->playtime);
2689 p->fps = LittleFloat(p->fps);
2690 p->firstframe = LittleLong(p->firstframe);
2691 p->numframes = LittleLong(p->numframes);
2692 if (p->numbones != numbones)
2693 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2697 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2700 if (recordsize != sizeof(*p))
2701 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2702 numanimkeys = numrecords;
2703 animkeys = (pskanimkeys_t *)animbuffer;
2704 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2706 p->origin[0] = LittleFloat(p->origin[0]);
2707 p->origin[1] = LittleFloat(p->origin[1]);
2708 p->origin[2] = LittleFloat(p->origin[2]);
2709 p->quat[0] = LittleFloat(p->quat[0]);
2710 p->quat[1] = LittleFloat(p->quat[1]);
2711 p->quat[2] = LittleFloat(p->quat[2]);
2712 p->quat[3] = LittleFloat(p->quat[3]);
2713 p->frametime = LittleFloat(p->frametime);
2714 #ifdef PSKQUATNEGATIONS
2715 if (index % numbones)
2730 // TODO: allocate bonepose stuff
2733 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2736 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2737 Host_Error("%s: missing required chunks", loadmodel->name);
2739 loadmodel->numframes = 0;
2740 for (index = 0;index < numanims;index++)
2741 loadmodel->numframes += anims[index].numframes;
2743 if (numanimkeys != numbones * loadmodel->numframes)
2744 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2746 meshvertices = numvtxw;
2747 meshtriangles = numfaces;
2749 // load external .skin files if present
2750 skinfiles = Mod_LoadSkinFiles();
2751 if (loadmodel->numskins < 1)
2752 loadmodel->numskins = 1;
2753 loadmodel->num_bones = numbones;
2754 loadmodel->num_poses = loadmodel->numframes;
2755 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2756 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2757 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2758 loadmodel->surfmesh.num_vertices = meshvertices;
2759 loadmodel->surfmesh.num_triangles = meshtriangles;
2760 // do most allocations as one merged chunk
2761 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);
2762 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2763 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2764 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2765 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2766 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2767 if (r_enableshadowvolumes.integer)
2768 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2769 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2770 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2771 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2772 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2773 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2774 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2775 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2776 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2777 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2778 loadmodel->surfmesh.num_blends = 0;
2779 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2780 if (loadmodel->surfmesh.num_vertices <= 65536)
2781 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2782 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2783 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(blendweights_t));
2785 for (i = 0;i < loadmodel->numskins;i++)
2787 loadmodel->skinscenes[i].firstframe = i;
2788 loadmodel->skinscenes[i].framecount = 1;
2789 loadmodel->skinscenes[i].loop = true;
2790 loadmodel->skinscenes[i].framerate = 10;
2794 for (index = 0, i = 0;index < nummatts;index++)
2796 // since psk models do not have named sections, reuse their shader name as the section name
2797 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2798 loadmodel->sortedmodelsurfaces[index] = index;
2799 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2800 loadmodel->data_surfaces[index].num_firstvertex = 0;
2801 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2804 // copy over the vertex locations and texcoords
2805 for (index = 0;index < numvtxw;index++)
2807 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2808 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2809 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2810 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2811 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2814 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2815 for (index = 0;index < numfaces;index++)
2816 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2817 for (index = 0, i = 0;index < nummatts;index++)
2819 loadmodel->data_surfaces[index].num_firsttriangle = i;
2820 i += loadmodel->data_surfaces[index].num_triangles;
2821 loadmodel->data_surfaces[index].num_triangles = 0;
2823 for (index = 0;index < numfaces;index++)
2825 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2826 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2827 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2828 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2831 // copy over the bones
2832 for (index = 0;index < numbones;index++)
2834 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2835 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2836 if (loadmodel->data_bones[index].parent >= index)
2837 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2840 // sort the psk point weights into the vertex weight tables
2841 // (which only accept up to 4 bones per vertex)
2842 for (index = 0;index < numvtxw;index++)
2844 int weightindex[4] = { 0, 0, 0, 0 };
2845 float weightinfluence[4] = { 0, 0, 0, 0 };
2847 for (j = 0;j < numrawweights;j++)
2849 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2851 int boneindex = rawweights[j].boneindex;
2852 float influence = rawweights[j].weight;
2853 for (l = 0;l < 4;l++)
2855 if (weightinfluence[l] < influence)
2857 // move lower influence weights out of the way first
2859 for (l2 = 3;l2 > l;l2--)
2861 weightinfluence[l2] = weightinfluence[l2-1];
2862 weightindex[l2] = weightindex[l2-1];
2864 // store the new weight
2865 weightinfluence[l] = influence;
2866 weightindex[l] = boneindex;
2872 loadmodel->surfmesh.blends[index] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
2874 if (loadmodel->surfmesh.num_blends < loadmodel->surfmesh.num_vertices)
2875 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2877 // set up the animscenes based on the anims
2878 for (index = 0, i = 0;index < numanims;index++)
2880 for (j = 0;j < anims[index].numframes;j++, i++)
2882 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2883 loadmodel->animscenes[i].firstframe = i;
2884 loadmodel->animscenes[i].framecount = 1;
2885 loadmodel->animscenes[i].loop = true;
2886 loadmodel->animscenes[i].framerate = anims[index].fps;
2890 // calculate the scaling value for bone origins so they can be compressed to short
2892 for (index = 0;index < numanimkeys;index++)
2894 pskanimkeys_t *k = animkeys + index;
2895 biggestorigin = max(biggestorigin, fabs(k->origin[0]));
2896 biggestorigin = max(biggestorigin, fabs(k->origin[1]));
2897 biggestorigin = max(biggestorigin, fabs(k->origin[2]));
2899 loadmodel->num_posescale = biggestorigin / 32767.0f;
2900 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2902 // load the poses from the animkeys
2903 for (index = 0;index < numanimkeys;index++)
2905 pskanimkeys_t *k = animkeys + index;
2907 Vector4Copy(k->quat, quat);
2909 Vector4Negate(quat, quat);
2910 Vector4Normalize2(quat, quat);
2911 // compress poses to the short[6] format for longterm storage
2912 loadmodel->data_poses6s[index*6+0] = k->origin[0] * loadmodel->num_poseinvscale;
2913 loadmodel->data_poses6s[index*6+1] = k->origin[1] * loadmodel->num_poseinvscale;
2914 loadmodel->data_poses6s[index*6+2] = k->origin[2] * loadmodel->num_poseinvscale;
2915 loadmodel->data_poses6s[index*6+3] = quat[0] * 32767.0f;
2916 loadmodel->data_poses6s[index*6+4] = quat[1] * 32767.0f;
2917 loadmodel->data_poses6s[index*6+5] = quat[2] * 32767.0f;
2919 Mod_FreeSkinFiles(skinfiles);
2920 Mem_Free(animfilebuffer);
2921 Mod_MakeSortedSurfaces(loadmodel);
2923 // compute all the mesh information that was not loaded from the file
2924 // TODO: honor smoothing groups somehow?
2925 if (loadmodel->surfmesh.data_element3s)
2926 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2927 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2928 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2929 Mod_BuildBaseBonePoses();
2930 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);
2931 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);
2932 if (loadmodel->surfmesh.data_neighbor3i)
2933 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2934 Mod_Alias_CalculateBoundingBox();
2936 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2938 if (!loadmodel->surfmesh.isanimated)
2940 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2941 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2942 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2943 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2944 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2945 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2949 void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2951 unsigned char *data;
2953 unsigned char *pbase, *pend;
2954 iqmheader_t *header;
2955 skinfile_t *skinfiles;
2956 int i, j, k, meshvertices, meshtriangles;
2957 float *vposition = NULL, *vtexcoord = NULL, *vnormal = NULL, *vtangent = NULL;
2958 unsigned char *vblendindexes = NULL, *vblendweights = NULL;
2963 iqmbounds_t *bounds;
2964 iqmvertexarray_t *va;
2965 unsigned short *framedata;
2966 float biggestorigin;
2967 const int *inelements;
2969 float *outvertex, *outnormal, *outtexcoord, *outsvector, *outtvector;
2971 pbase = (unsigned char *)buffer;
2972 pend = (unsigned char *)bufferend;
2973 header = (iqmheader_t *)buffer;
2974 if (memcmp(header->id, "INTERQUAKEMODEL", 16))
2975 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model", loadmodel->name);
2976 if (LittleLong(header->version) != 2)
2977 Host_Error ("Mod_INTERQUAKEMODEL_Load: only version 1 models are currently supported (name = %s)", loadmodel->name);
2979 loadmodel->modeldatatypestring = "IQM";
2981 loadmodel->type = mod_alias;
2982 loadmodel->synctype = ST_RAND;
2985 header->version = LittleLong(header->version);
2986 header->filesize = LittleLong(header->filesize);
2987 header->flags = LittleLong(header->flags);
2988 header->num_text = LittleLong(header->num_text);
2989 header->ofs_text = LittleLong(header->ofs_text);
2990 header->num_meshes = LittleLong(header->num_meshes);
2991 header->ofs_meshes = LittleLong(header->ofs_meshes);
2992 header->num_vertexarrays = LittleLong(header->num_vertexarrays);
2993 header->num_vertexes = LittleLong(header->num_vertexes);
2994 header->ofs_vertexarrays = LittleLong(header->ofs_vertexarrays);
2995 header->num_triangles = LittleLong(header->num_triangles);
2996 header->ofs_triangles = LittleLong(header->ofs_triangles);
2997 header->ofs_neighbors = LittleLong(header->ofs_neighbors);
2998 header->num_joints = LittleLong(header->num_joints);
2999 header->ofs_joints = LittleLong(header->ofs_joints);
3000 header->num_poses = LittleLong(header->num_poses);
3001 header->ofs_poses = LittleLong(header->ofs_poses);
3002 header->num_anims = LittleLong(header->num_anims);
3003 header->ofs_anims = LittleLong(header->ofs_anims);
3004 header->num_frames = LittleLong(header->num_frames);
3005 header->num_framechannels = LittleLong(header->num_framechannels);
3006 header->ofs_frames = LittleLong(header->ofs_frames);
3007 header->ofs_bounds = LittleLong(header->ofs_bounds);
3008 header->num_comment = LittleLong(header->num_comment);
3009 header->ofs_comment = LittleLong(header->ofs_comment);
3010 header->num_extensions = LittleLong(header->num_extensions);
3011 header->ofs_extensions = LittleLong(header->ofs_extensions);
3013 if (header->num_triangles < 1 || header->num_vertexes < 3 || header->num_vertexarrays < 1 || header->num_meshes < 1)
3015 Con_Printf("%s has no geometry\n", loadmodel->name);
3018 if (header->num_frames < 1 || header->num_anims < 1)
3020 Con_Printf("%s has no animations\n", loadmodel->name);
3024 if (pbase + header->ofs_text + header->num_text > pend ||
3025 pbase + header->ofs_meshes + header->num_meshes*sizeof(iqmmesh_t) > pend ||
3026 pbase + header->ofs_vertexarrays + header->num_vertexarrays*sizeof(iqmvertexarray_t) > pend ||
3027 pbase + header->ofs_triangles + header->num_triangles*sizeof(int[3]) > pend ||
3028 (header->ofs_neighbors && pbase + header->ofs_neighbors + header->num_triangles*sizeof(int[3]) > pend) ||
3029 pbase + header->ofs_joints + header->num_joints*sizeof(iqmjoint_t) > pend ||
3030 pbase + header->ofs_poses + header->num_poses*sizeof(iqmpose_t) > pend ||
3031 pbase + header->ofs_anims + header->num_anims*sizeof(iqmanim_t) > pend ||
3032 pbase + header->ofs_frames + header->num_frames*header->num_framechannels*sizeof(unsigned short) > pend ||
3033 (header->ofs_bounds && pbase + header->ofs_bounds + header->num_frames*sizeof(iqmbounds_t) > pend) ||
3034 pbase + header->ofs_comment + header->num_comment > pend)
3036 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3040 va = (iqmvertexarray_t *)(pbase + header->ofs_vertexarrays);
3041 for (i = 0;i < (int)header->num_vertexarrays;i++)
3044 va[i].type = LittleLong(va[i].type);
3045 va[i].flags = LittleLong(va[i].flags);
3046 va[i].format = LittleLong(va[i].format);
3047 va[i].size = LittleLong(va[i].size);
3048 va[i].offset = LittleLong(va[i].offset);
3049 vsize = header->num_vertexes*va[i].size;
3050 switch (va[i].format)
3052 case IQM_FLOAT: vsize *= sizeof(float); break;
3053 case IQM_UBYTE: vsize *= sizeof(unsigned char); break;
3056 if (pbase + va[i].offset + vsize > pend)
3061 if (va[i].format == IQM_FLOAT && va[i].size == 3)
3062 vposition = (float *)(pbase + va[i].offset);
3065 if (va[i].format == IQM_FLOAT && va[i].size == 2)
3066 vtexcoord = (float *)(pbase + va[i].offset);
3069 if (va[i].format == IQM_FLOAT && va[i].size == 3)
3070 vnormal = (float *)(pbase + va[i].offset);
3073 if (va[i].format == IQM_FLOAT && va[i].size == 4)
3074 vtangent = (float *)(pbase + va[i].offset);
3076 case IQM_BLENDINDEXES:
3077 if (va[i].format == IQM_UBYTE && va[i].size == 4)
3078 vblendindexes = (unsigned char *)(pbase + va[i].offset);
3080 case IQM_BLENDWEIGHTS:
3081 if (va[i].format == IQM_UBYTE && va[i].size == 4)
3082 vblendweights = (unsigned char *)(pbase + va[i].offset);
3086 if (!vposition || !vtexcoord || !vblendindexes || !vblendweights)
3088 Con_Printf("%s is missing vertex array data\n", loadmodel->name);
3092 text = header->num_text && header->ofs_text ? (const char *)(pbase + header->ofs_text) : "";
3094 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
3095 loadmodel->DrawSky = NULL;
3096 loadmodel->DrawAddWaterPlanes = NULL;
3097 loadmodel->Draw = R_Q1BSP_Draw;
3098 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
3099 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
3100 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
3101 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
3102 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
3103 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
3104 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
3105 loadmodel->DrawLight = R_Q1BSP_DrawLight;
3106 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
3107 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
3108 loadmodel->PointSuperContents = NULL;
3110 // load external .skin files if present
3111 skinfiles = Mod_LoadSkinFiles();
3112 if (loadmodel->numskins < 1)
3113 loadmodel->numskins = 1;
3115 loadmodel->numframes = header->num_anims;
3116 loadmodel->num_bones = header->num_joints;
3117 loadmodel->num_poses = header->num_frames;
3118 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = header->num_meshes;
3119 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3120 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3122 meshvertices = header->num_vertexes;
3123 meshtriangles = header->num_triangles;
3125 // do most allocations as one merged chunk
3126 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));
3127 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
3128 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
3129 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
3130 loadmodel->surfmesh.num_vertices = meshvertices;
3131 loadmodel->surfmesh.num_triangles = meshtriangles;
3132 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3133 if (r_enableshadowvolumes.integer)
3134 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3135 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
3136 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3137 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3138 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
3139 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
3140 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
3141 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
3142 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
3143 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
3144 loadmodel->surfmesh.num_blends = 0;
3145 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
3146 if (meshvertices <= 65536)
3147 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
3148 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
3149 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
3151 for (i = 0;i < loadmodel->numskins;i++)
3153 loadmodel->skinscenes[i].firstframe = i;
3154 loadmodel->skinscenes[i].framecount = 1;
3155 loadmodel->skinscenes[i].loop = true;
3156 loadmodel->skinscenes[i].framerate = 10;
3159 // load the bone info
3160 joint = (iqmjoint_t *) (pbase + header->ofs_joints);
3161 for (i = 0;i < loadmodel->num_bones;i++)
3163 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3164 joint[i].name = LittleLong(joint[i].name);
3165 joint[i].parent = LittleLong(joint[i].parent);
3166 for (j = 0;j < 3;j++)
3168 joint[i].origin[j] = LittleFloat(joint[i].origin[j]);
3169 joint[i].rotation[j] = LittleFloat(joint[i].rotation[j]);
3170 joint[i].scale[j] = LittleFloat(joint[i].scale[j]);
3172 strlcpy(loadmodel->data_bones[i].name, &text[joint[i].name], sizeof(loadmodel->data_bones[i].name));
3173 loadmodel->data_bones[i].parent = joint[i].parent;
3174 if (loadmodel->data_bones[i].parent >= i)
3175 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3176 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]);
3177 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3178 if (loadmodel->data_bones[i].parent >= 0)
3180 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3181 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3182 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3184 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3187 // set up the animscenes based on the anims
3188 anim = (iqmanim_t *) (pbase + header->ofs_anims);
3189 for (i = 0;i < (int)header->num_anims;i++)
3191 anim[i].name = LittleLong(anim[i].name);
3192 anim[i].first_frame = LittleLong(anim[i].first_frame);
3193 anim[i].num_frames = LittleLong(anim[i].num_frames);
3194 anim[i].framerate = LittleFloat(anim[i].framerate);
3195 anim[i].flags = LittleLong(anim[i].flags);
3196 strlcpy(loadmodel->animscenes[i].name, &text[anim[i].name], sizeof(loadmodel->animscenes[i].name));
3197 loadmodel->animscenes[i].firstframe = anim[i].first_frame;
3198 loadmodel->animscenes[i].framecount = anim[i].num_frames;
3199 loadmodel->animscenes[i].loop = ((anim[i].flags & IQM_LOOP) != 0);
3200 loadmodel->animscenes[i].framerate = anim[i].framerate;
3203 pose = (iqmpose_t *) (pbase + header->ofs_poses);
3205 for (i = 0;i < (int)header->num_poses;i++)
3208 pose[i].parent = LittleLong(pose[i].parent);
3209 pose[i].channelmask = LittleLong(pose[i].channelmask);
3210 pose[i].channeloffset[0] = LittleFloat(pose[i].channeloffset[0]);
3211 pose[i].channeloffset[1] = LittleFloat(pose[i].channeloffset[1]);
3212 pose[i].channeloffset[2] = LittleFloat(pose[i].channeloffset[2]);
3213 pose[i].channeloffset[3] = LittleFloat(pose[i].channeloffset[3]);
3214 pose[i].channeloffset[4] = LittleFloat(pose[i].channeloffset[4]);
3215 pose[i].channeloffset[5] = LittleFloat(pose[i].channeloffset[5]);
3216 pose[i].channeloffset[6] = LittleFloat(pose[i].channeloffset[6]);
3217 pose[i].channeloffset[7] = LittleFloat(pose[i].channeloffset[7]);
3218 pose[i].channeloffset[8] = LittleFloat(pose[i].channeloffset[8]);
3219 pose[i].channeloffset[9] = LittleFloat(pose[i].channeloffset[9]);
3220 pose[i].channelscale[0] = LittleFloat(pose[i].channelscale[0]);
3221 pose[i].channelscale[1] = LittleFloat(pose[i].channelscale[1]);
3222 pose[i].channelscale[2] = LittleFloat(pose[i].channelscale[2]);
3223 pose[i].channelscale[3] = LittleFloat(pose[i].channelscale[3]);
3224 pose[i].channelscale[4] = LittleFloat(pose[i].channelscale[4]);
3225 pose[i].channelscale[5] = LittleFloat(pose[i].channelscale[5]);
3226 pose[i].channelscale[6] = LittleFloat(pose[i].channelscale[6]);
3227 pose[i].channelscale[7] = LittleFloat(pose[i].channelscale[7]);
3228 pose[i].channelscale[8] = LittleFloat(pose[i].channelscale[8]);
3229 pose[i].channelscale[9] = LittleFloat(pose[i].channelscale[9]);
3230 f = fabs(pose[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3231 f = fabs(pose[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3232 f = fabs(pose[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3233 f = fabs(pose[i].channeloffset[0] + 0xFFFF*pose[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3234 f = fabs(pose[i].channeloffset[1] + 0xFFFF*pose[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3235 f = fabs(pose[i].channeloffset[2] + 0xFFFF*pose[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3237 loadmodel->num_posescale = biggestorigin / 32767.0f;
3238 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3240 // load the pose data
3241 framedata = (unsigned short *) (pbase + header->ofs_frames);
3242 for (i = 0, k = 0;i < (int)header->num_frames;i++)
3244 for (j = 0;j < (int)header->num_poses;j++, k++)
3247 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));
3248 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));
3249 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));
3250 rot[0] = pose[j].channeloffset[3] + (pose[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[3] : 0);
3251 rot[1] = pose[j].channeloffset[4] + (pose[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[4] : 0);
3252 rot[2] = pose[j].channeloffset[5] + (pose[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[5] : 0);
3253 rot[3] = pose[j].channeloffset[6] + (pose[j].channelmask&64 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[6] : 0);
3255 Vector4Negate(rot, rot);
3256 Vector4Normalize2(rot, rot);
3257 loadmodel->data_poses6s[k*6 + 3] = 32767.0f * rot[0];
3258 loadmodel->data_poses6s[k*6 + 4] = 32767.0f * rot[1];
3259 loadmodel->data_poses6s[k*6 + 5] = 32767.0f * rot[2];
3260 // skip scale data for now
3261 if(pose[j].channelmask&128) framedata++;
3262 if(pose[j].channelmask&256) framedata++;
3263 if(pose[j].channelmask&512) framedata++;
3267 // load bounding box data
3268 if (header->ofs_bounds)
3270 float xyradius = 0, radius = 0;
3271 bounds = (iqmbounds_t *) (pbase + header->ofs_bounds);
3272 VectorClear(loadmodel->normalmins);
3273 VectorClear(loadmodel->normalmaxs);
3274 for (i = 0; i < (int)header->num_frames;i++)
3276 bounds[i].mins[0] = LittleFloat(bounds[i].mins[0]);
3277 bounds[i].mins[1] = LittleFloat(bounds[i].mins[1]);
3278 bounds[i].mins[2] = LittleFloat(bounds[i].mins[2]);
3279 bounds[i].maxs[0] = LittleFloat(bounds[i].maxs[0]);
3280 bounds[i].maxs[1] = LittleFloat(bounds[i].maxs[1]);
3281 bounds[i].maxs[2] = LittleFloat(bounds[i].maxs[2]);
3282 bounds[i].xyradius = LittleFloat(bounds[i].xyradius);
3283 bounds[i].radius = LittleFloat(bounds[i].radius);
3286 VectorCopy(bounds[i].mins, loadmodel->normalmins);
3287 VectorCopy(bounds[i].maxs, loadmodel->normalmaxs);
3291 if (loadmodel->normalmins[0] > bounds[i].mins[0]) loadmodel->normalmins[0] = bounds[i].mins[0];
3292 if (loadmodel->normalmins[1] > bounds[i].mins[1]) loadmodel->normalmins[1] = bounds[i].mins[1];
3293 if (loadmodel->normalmins[2] > bounds[i].mins[2]) loadmodel->normalmins[2] = bounds[i].mins[2];
3294 if (loadmodel->normalmaxs[0] < bounds[i].maxs[0]) loadmodel->normalmaxs[0] = bounds[i].maxs[0];
3295 if (loadmodel->normalmaxs[1] < bounds[i].maxs[1]) loadmodel->normalmaxs[1] = bounds[i].maxs[1];
3296 if (loadmodel->normalmaxs[2] < bounds[i].maxs[2]) loadmodel->normalmaxs[2] = bounds[i].maxs[2];
3298 if (bounds[i].xyradius > xyradius)
3299 xyradius = bounds[i].xyradius;
3300 if (bounds[i].radius > radius)
3301 radius = bounds[i].radius;
3303 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -xyradius;
3304 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = xyradius;
3305 loadmodel->yawmins[2] = loadmodel->normalmins[2];
3306 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
3307 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
3308 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
3309 loadmodel->radius = radius;
3310 loadmodel->radius2 = radius * radius;
3313 // load triangle data
3314 inelements = (const int *) (pbase + header->ofs_triangles);
3315 outelements = loadmodel->surfmesh.data_element3i;
3316 for (i = 0;i < (int)header->num_triangles;i++)
3318 outelements[0] = LittleLong(inelements[0]);
3319 outelements[1] = LittleLong(inelements[1]);
3320 outelements[2] = LittleLong(inelements[2]);
3324 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, header->num_vertexes, __FILE__, __LINE__);
3326 if (header->ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
3328 inelements = (const int *) (pbase + header->ofs_neighbors);
3329 outelements = loadmodel->surfmesh.data_neighbor3i;
3330 for (i = 0;i < (int)header->num_triangles;i++)
3332 outelements[0] = LittleLong(inelements[0]);
3333 outelements[1] = LittleLong(inelements[1]);
3334 outelements[2] = LittleLong(inelements[2]);
3341 outvertex = loadmodel->surfmesh.data_vertex3f;
3342 for (i = 0;i < (int)header->num_vertexes;i++)
3344 outvertex[0] = LittleFloat(vposition[0]);
3345 outvertex[1] = LittleFloat(vposition[1]);
3346 outvertex[2] = LittleFloat(vposition[2]);
3351 outtexcoord = loadmodel->surfmesh.data_texcoordtexture2f;
3352 for (i = 0;i < (int)header->num_vertexes;i++)
3354 outtexcoord[0] = LittleFloat(vtexcoord[0]);
3355 outtexcoord[1] = LittleFloat(vtexcoord[1]);
3362 outnormal = loadmodel->surfmesh.data_normal3f;
3363 for (i = 0;i < (int)header->num_vertexes;i++)
3365 outnormal[0] = LittleFloat(vnormal[0]);
3366 outnormal[1] = LittleFloat(vnormal[1]);
3367 outnormal[2] = LittleFloat(vnormal[2]);
3373 if(vnormal && vtangent)
3375 outnormal = loadmodel->surfmesh.data_normal3f;
3376 outsvector = loadmodel->surfmesh.data_svector3f;
3377 outtvector = loadmodel->surfmesh.data_tvector3f;
3378 for (i = 0;i < (int)header->num_vertexes;i++)
3380 outsvector[0] = LittleFloat(vtangent[0]);
3381 outsvector[1] = LittleFloat(vtangent[1]);
3382 outsvector[2] = LittleFloat(vtangent[2]);
3383 if(LittleFloat(vtangent[3]) < 0)
3384 CrossProduct(outsvector, outnormal, outtvector);
3386 CrossProduct(outnormal, outsvector, outtvector);
3394 for (i = 0; i < (int)header->num_vertexes;i++)
3396 blendweights_t weights;
3397 memcpy(weights.index, vblendindexes + i*4, 4);
3398 memcpy(weights.influence, vblendweights + i*4, 4);
3399 loadmodel->surfmesh.blends[i] = Mod_Skeletal_AddBlend(loadmodel, &weights);
3403 mesh = (iqmmesh_t *) (pbase + header->ofs_meshes);
3404 for (i = 0;i < (int)header->num_meshes;i++)
3406 msurface_t *surface;
3408 mesh[i].name = LittleLong(mesh[i].name);
3409 mesh[i].material = LittleLong(mesh[i].material);
3410 mesh[i].first_vertex = LittleLong(mesh[i].first_vertex);
3411 mesh[i].num_vertexes = LittleLong(mesh[i].num_vertexes);
3412 mesh[i].first_triangle = LittleLong(mesh[i].first_triangle);
3413 mesh[i].num_triangles = LittleLong(mesh[i].num_triangles);
3415 loadmodel->sortedmodelsurfaces[i] = i;
3416 surface = loadmodel->data_surfaces + i;
3417 surface->texture = loadmodel->data_textures + i;
3418 surface->num_firsttriangle = mesh[i].first_triangle;
3419 surface->num_triangles = mesh[i].num_triangles;
3420 surface->num_firstvertex = mesh[i].first_vertex;
3421 surface->num_vertices = mesh[i].num_vertexes;
3423 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, &text[mesh[i].name], &text[mesh[i].material]);
3426 Mod_FreeSkinFiles(skinfiles);
3427 Mod_MakeSortedSurfaces(loadmodel);
3429 // compute all the mesh information that was not loaded from the file
3430 if (loadmodel->surfmesh.data_element3s)
3431 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3432 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3434 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);
3435 if (!vnormal || !vtangent)
3436 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);
3437 if (!header->ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
3438 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3439 if (!header->ofs_bounds)
3440 Mod_Alias_CalculateBoundingBox();
3442 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
3444 if (!loadmodel->surfmesh.isanimated)
3446 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3447 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3448 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3449 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3450 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3451 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;