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);
79 // code from SDL, shortened as we can expect CPUID to work
80 static int CPUID_Features(void)
83 # if defined(__GNUC__) && defined(__i386__)
86 " xorl %%eax,%%eax \n"
88 " cpuid # Get family/model/stepping/features\n"
93 : "%eax", "%ecx", "%edx", "%edi"
95 # elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
99 cpuid ; Get family/model/stepping/features
103 # error SSE_POSSIBLE set but no CPUID implementation
108 static qboolean Have_SSE(void)
110 // COMMANDLINEOPTION: SSE: -nosse disables SSE support and detection
111 if(COM_CheckParm("-nosse"))
113 // COMMANDLINEOPTION: SSE: -forcesse enables SSE support and disables detection
117 if(COM_CheckParm("-forcesse"))
119 if(CPUID_Features() & (1 << 25))
126 void Mod_AliasInit (void)
129 Cvar_RegisterVariable(&r_skeletal_debugbone);
130 Cvar_RegisterVariable(&r_skeletal_debugbonecomponent);
131 Cvar_RegisterVariable(&r_skeletal_debugbonevalue);
132 Cvar_RegisterVariable(&r_skeletal_debugtranslatex);
133 Cvar_RegisterVariable(&r_skeletal_debugtranslatey);
134 Cvar_RegisterVariable(&r_skeletal_debugtranslatez);
135 Cvar_RegisterVariable(&mod_alias_supporttagscale);
136 for (i = 0;i < 320;i++)
137 mod_md3_sin[i] = sin(i * M_PI * 2.0f / 256.0);
142 Con_Printf("Skeletal animation uses SSE code path\n");
143 r_skeletal_use_sse_defined = true;
144 Cvar_RegisterVariable(&r_skeletal_use_sse);
147 Con_Printf("Skeletal animation uses generic code path (SSE disabled or not detected)\n");
150 Con_Printf("Skeletal animation uses generic code path (SSE not compiled in)\n");
154 int Mod_Skeletal_AddBlend(dp_model_t *model, const blendweights_t *newweights)
157 blendweights_t *weights;
158 if(!newweights->influence[1])
159 return newweights->index[0];
160 weights = model->surfmesh.data_blendweights;
161 for (i = 0;i < model->surfmesh.num_blends;i++, weights++)
163 if (!memcmp(weights, newweights, sizeof(blendweights_t)))
164 return model->num_bones + i;
166 model->surfmesh.num_blends++;
167 memcpy(weights, newweights, sizeof(blendweights_t));
168 return model->num_bones + i;
171 int Mod_Skeletal_CompressBlend(dp_model_t *model, const int *newindex, const float *newinfluence)
175 blendweights_t newweights;
179 for (i = 0;i < 4;i++)
180 scale += newinfluence[i];
181 scale = 255.0f / scale;
183 for (i = 0;i < 4;i++)
185 newweights.index[i] = newindex[i];
186 newweights.influence[i] = (unsigned char)(newinfluence[i] * scale);
187 total += newweights.influence[i];
191 for (i = 0;i < 4;i++)
193 if(newweights.influence[i] > 0 && total > 255)
195 newweights.influence[i]--;
202 for (i = 0; i < 4;i++)
204 if(newweights.influence[i] < 255 && total < 255)
206 newweights.influence[i]++;
211 return Mod_Skeletal_AddBlend(model, &newweights);
214 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)
217 int i, numblends, blendnum;
218 int numverts = model->surfmesh.num_vertices;
220 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
222 //VectorMA(translate, model->surfmesh.num_morphmdlframetranslate, frameblend[blendnum].lerp, translate);
223 if (frameblend[blendnum].lerp > 0)
224 numblends = blendnum + 1;
226 // special case for the first blend because it avoids some adds and the need to memset the arrays first
227 for (blendnum = 0;blendnum < numblends;blendnum++)
229 const md3vertex_t *verts = model->surfmesh.data_morphmd3vertex + numverts * frameblend[blendnum].subframe;
232 float scale = frameblend[blendnum].lerp * (1.0f / 64.0f);
235 for (i = 0;i < numverts;i++)
237 vertex3f[i * 3 + 0] = verts[i].origin[0] * scale;
238 vertex3f[i * 3 + 1] = verts[i].origin[1] * scale;
239 vertex3f[i * 3 + 2] = verts[i].origin[2] * scale;
244 for (i = 0;i < numverts;i++)
246 vertex3f[i * 3 + 0] += verts[i].origin[0] * scale;
247 vertex3f[i * 3 + 1] += verts[i].origin[1] * scale;
248 vertex3f[i * 3 + 2] += verts[i].origin[2] * scale;
252 // the yaw and pitch stored in md3 models are 8bit quantized angles
253 // (0-255), and as such a lookup table is very well suited to
254 // decoding them, and since cosine is equivalent to sine with an
255 // extra 45 degree rotation, this uses one lookup table for both
256 // sine and cosine with a +64 bias to get cosine.
259 float lerp = frameblend[blendnum].lerp;
262 for (i = 0;i < numverts;i++)
264 normal3f[i * 3 + 0] = mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
265 normal3f[i * 3 + 1] = mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
266 normal3f[i * 3 + 2] = mod_md3_sin[verts[i].pitch + 64] * lerp;
271 for (i = 0;i < numverts;i++)
273 normal3f[i * 3 + 0] += mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
274 normal3f[i * 3 + 1] += mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
275 normal3f[i * 3 + 2] += mod_md3_sin[verts[i].pitch + 64] * lerp;
281 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
282 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
285 for (i = 0;i < numverts;i++, texvecvert++)
287 VectorScale(texvecvert->svec, f, svector3f + i*3);
288 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
293 for (i = 0;i < numverts;i++, texvecvert++)
295 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
296 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
302 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)
305 int i, numblends, blendnum;
306 int numverts = model->surfmesh.num_vertices;
308 VectorClear(translate);
310 // blend the frame translates to avoid redundantly doing so on each vertex
311 // (a bit of a brain twister but it works)
312 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
314 if (model->surfmesh.data_morphmd2framesize6f)
315 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6 + 3, translate);
317 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.num_morphmdlframetranslate, translate);
318 if (frameblend[blendnum].lerp > 0)
319 numblends = blendnum + 1;
321 // special case for the first blend because it avoids some adds and the need to memset the arrays first
322 for (blendnum = 0;blendnum < numblends;blendnum++)
324 const trivertx_t *verts = model->surfmesh.data_morphmdlvertex + numverts * frameblend[blendnum].subframe;
328 if (model->surfmesh.data_morphmd2framesize6f)
329 VectorScale(model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6, frameblend[blendnum].lerp, scale);
331 VectorScale(model->surfmesh.num_morphmdlframescale, frameblend[blendnum].lerp, scale);
334 for (i = 0;i < numverts;i++)
336 vertex3f[i * 3 + 0] = translate[0] + verts[i].v[0] * scale[0];
337 vertex3f[i * 3 + 1] = translate[1] + verts[i].v[1] * scale[1];
338 vertex3f[i * 3 + 2] = translate[2] + verts[i].v[2] * scale[2];
343 for (i = 0;i < numverts;i++)
345 vertex3f[i * 3 + 0] += verts[i].v[0] * scale[0];
346 vertex3f[i * 3 + 1] += verts[i].v[1] * scale[1];
347 vertex3f[i * 3 + 2] += verts[i].v[2] * scale[2];
351 // the vertex normals in mdl models are an index into a table of
352 // 162 unique values, this very crude quantization reduces the
353 // vertex normal to only one byte, which saves a lot of space but
354 // also makes lighting pretty coarse
357 float lerp = frameblend[blendnum].lerp;
360 for (i = 0;i < numverts;i++)
362 const float *vn = m_bytenormals[verts[i].lightnormalindex];
363 VectorScale(vn, lerp, normal3f + i*3);
368 for (i = 0;i < numverts;i++)
370 const float *vn = m_bytenormals[verts[i].lightnormalindex];
371 VectorMA(normal3f + i*3, lerp, vn, normal3f + i*3);
377 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
378 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
381 for (i = 0;i < numverts;i++, texvecvert++)
383 VectorScale(texvecvert->svec, f, svector3f + i*3);
384 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
389 for (i = 0;i < numverts;i++, texvecvert++)
391 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
392 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
399 int Mod_Alias_GetTagMatrix(const dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, int tagindex, matrix4x4_t *outmatrix)
402 matrix4x4_t parentbonematrix;
403 matrix4x4_t tempbonematrix;
404 matrix4x4_t bonematrix;
405 matrix4x4_t blendmatrix;
412 *outmatrix = identitymatrix;
413 if (skeleton && skeleton->relativetransforms)
415 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
417 *outmatrix = skeleton->relativetransforms[tagindex];
418 while ((tagindex = model->data_bones[tagindex].parent) >= 0)
421 Matrix4x4_Concat(outmatrix, &skeleton->relativetransforms[tagindex], &temp);
424 else if (model->num_bones)
426 if (tagindex < 0 || tagindex >= model->num_bones)
428 Matrix4x4_Clear(&blendmatrix);
429 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
431 lerp = frameblend[blendindex].lerp;
432 Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
433 parenttagindex = tagindex;
434 while ((parenttagindex = model->data_bones[parenttagindex].parent) >= 0)
436 Matrix4x4_FromBonePose6s(&parentbonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + parenttagindex));
437 tempbonematrix = bonematrix;
438 Matrix4x4_Concat(&bonematrix, &parentbonematrix, &tempbonematrix);
440 Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
442 *outmatrix = blendmatrix;
444 else if (model->num_tags)
446 if (tagindex < 0 || tagindex >= model->num_tags)
448 for (k = 0;k < 12;k++)
450 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
452 lerp = frameblend[blendindex].lerp;
453 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
454 for (k = 0;k < 12;k++)
455 blendtag[k] += input[k] * lerp;
457 Matrix4x4_FromArray12FloatGL(outmatrix, blendtag);
460 if(!mod_alias_supporttagscale.integer)
461 Matrix4x4_Normalize3(outmatrix, outmatrix);
466 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)
471 matrix4x4_t bonematrix;
472 matrix4x4_t blendmatrix;
476 if (skeleton && skeleton->relativetransforms)
478 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
480 *parentindex = skeleton->model->data_bones[tagindex].parent;
481 *tagname = skeleton->model->data_bones[tagindex].name;
482 *tag_localmatrix = skeleton->relativetransforms[tagindex];
485 else if (model->num_bones)
487 if (tagindex < 0 || tagindex >= model->num_bones)
489 *parentindex = model->data_bones[tagindex].parent;
490 *tagname = model->data_bones[tagindex].name;
491 Matrix4x4_Clear(&blendmatrix);
492 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
494 lerp = frameblend[blendindex].lerp;
495 Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
496 Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
498 *tag_localmatrix = blendmatrix;
501 else if (model->num_tags)
503 if (tagindex < 0 || tagindex >= model->num_tags)
506 *tagname = model->data_tags[tagindex].name;
507 for (k = 0;k < 12;k++)
509 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
511 lerp = frameblend[blendindex].lerp;
512 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
513 for (k = 0;k < 12;k++)
514 blendtag[k] += input[k] * lerp;
516 Matrix4x4_FromArray12FloatGL(tag_localmatrix, blendtag);
523 int Mod_Alias_GetTagIndexForName(const dp_model_t *model, unsigned int skin, const char *tagname)
526 if(skin >= (unsigned int)model->numskins)
528 if (model->num_bones)
529 for (i = 0;i < model->num_bones;i++)
530 if (!strcasecmp(tagname, model->data_bones[i].name))
533 for (i = 0;i < model->num_tags;i++)
534 if (!strcasecmp(tagname, model->data_tags[i].name))
539 static void Mod_BuildBaseBonePoses(void)
542 matrix4x4_t *basebonepose;
543 float *outinvmatrix = loadmodel->data_baseboneposeinverse;
544 matrix4x4_t bonematrix;
545 matrix4x4_t tempbonematrix;
546 if (!loadmodel->num_bones)
548 basebonepose = (matrix4x4_t *)Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(matrix4x4_t));
549 for (boneindex = 0;boneindex < loadmodel->num_bones;boneindex++)
551 Matrix4x4_FromBonePose6s(&bonematrix, loadmodel->num_posescale, loadmodel->data_poses6s + 6 * boneindex);
552 if (loadmodel->data_bones[boneindex].parent >= 0)
554 tempbonematrix = bonematrix;
555 Matrix4x4_Concat(&bonematrix, basebonepose + loadmodel->data_bones[boneindex].parent, &tempbonematrix);
557 basebonepose[boneindex] = bonematrix;
558 Matrix4x4_Invert_Simple(&tempbonematrix, basebonepose + boneindex);
559 Matrix4x4_ToArray12FloatD3D(&tempbonematrix, outinvmatrix + 12*boneindex);
561 Mem_Free(basebonepose);
564 static void Mod_Alias_CalculateBoundingBox(void)
567 qboolean firstvertex = true;
568 float dist, yawradius, radius;
571 frameblend_t frameblend[MAX_FRAMEBLENDS];
572 memset(frameblend, 0, sizeof(frameblend));
573 frameblend[0].lerp = 1;
574 vertex3f = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
575 VectorClear(loadmodel->normalmins);
576 VectorClear(loadmodel->normalmaxs);
579 for (frameblend[0].subframe = 0;frameblend[0].subframe < loadmodel->num_poses;frameblend[0].subframe++)
581 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, vertex3f, NULL, NULL, NULL);
582 for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
587 VectorCopy(v, loadmodel->normalmins);
588 VectorCopy(v, loadmodel->normalmaxs);
592 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
593 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
594 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
595 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
596 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
597 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
599 dist = v[0] * v[0] + v[1] * v[1];
600 if (yawradius < dist)
609 radius = sqrt(radius);
610 yawradius = sqrt(yawradius);
611 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
612 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
613 loadmodel->yawmins[2] = loadmodel->normalmins[2];
614 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
615 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
616 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
617 loadmodel->radius = radius;
618 loadmodel->radius2 = radius * radius;
621 static void Mod_Alias_MorphMesh_CompileFrames(void)
624 frameblend_t frameblend[MAX_FRAMEBLENDS];
625 unsigned char *datapointer;
626 memset(frameblend, 0, sizeof(frameblend));
627 frameblend[0].lerp = 1;
628 datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
629 loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
630 loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
631 loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
632 loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
633 loadmodel->surfmesh.data_morphtexvecvertex = (texvecvertex_t *)datapointer;datapointer += loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices * sizeof(texvecvertex_t);
634 // 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)
635 for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
637 frameblend[0].subframe = i;
638 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
639 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);
640 // encode the svector and tvector in 3 byte format for permanent storage
641 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
643 VectorScaleCast(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
644 VectorScaleCast(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
649 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)
652 float segmentmins[3], segmentmaxs[3];
654 static int maxvertices = 0;
655 static float *vertex3f = NULL;
656 memset(trace, 0, sizeof(*trace));
658 trace->realfraction = 1;
659 trace->hitsupercontentsmask = hitsupercontentsmask;
660 if (maxvertices < model->surfmesh.num_vertices)
664 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
665 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
667 segmentmins[0] = min(start[0], end[0]) - 1;
668 segmentmins[1] = min(start[1], end[1]) - 1;
669 segmentmins[2] = min(start[2], end[2]) - 1;
670 segmentmaxs[0] = max(start[0], end[0]) + 1;
671 segmentmaxs[1] = max(start[1], end[1]) + 1;
672 segmentmaxs[2] = max(start[2], end[2]) + 1;
673 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
674 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
675 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);
678 static int maxvertices = 0;
679 static float *vertex3f = NULL;
681 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)
684 vec3_t shiftstart, shiftend;
685 float segmentmins[3], segmentmaxs[3];
687 colboxbrushf_t thisbrush_start, thisbrush_end;
688 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
690 if (VectorCompare(boxmins, boxmaxs))
692 VectorAdd(start, boxmins, shiftstart);
693 VectorAdd(end, boxmins, shiftend);
694 Mod_MDLMD2MD3_TraceLine(model, frameblend, skeleton, trace, shiftstart, shiftend, hitsupercontentsmask);
695 VectorSubtract(trace->endpos, boxmins, trace->endpos);
699 // box trace, performed as brush trace
700 memset(trace, 0, sizeof(*trace));
702 trace->realfraction = 1;
703 trace->hitsupercontentsmask = hitsupercontentsmask;
704 if (maxvertices < model->surfmesh.num_vertices)
708 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
709 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
711 segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
712 segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
713 segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
714 segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
715 segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
716 segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
717 VectorAdd(start, boxmins, boxstartmins);
718 VectorAdd(start, boxmaxs, boxstartmaxs);
719 VectorAdd(end, boxmins, boxendmins);
720 VectorAdd(end, boxmaxs, boxendmaxs);
721 Collision_BrushForBox(&thisbrush_start, boxstartmins, boxstartmaxs, 0, 0, NULL);
722 Collision_BrushForBox(&thisbrush_end, boxendmins, boxendmaxs, 0, 0, NULL);
723 if (maxvertices < model->surfmesh.num_vertices)
727 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
728 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
730 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
731 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
732 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);
735 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
738 for (i = 0;i < inverts;i++)
740 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
742 j = vertremap[i]; // not onseam
745 j = vertremap[i+inverts]; // onseam
751 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
753 int i, f, pose, groupframes;
755 daliasframetype_t *pframetype;
756 daliasframe_t *pinframe;
757 daliasgroup_t *group;
758 daliasinterval_t *intervals;
761 scene = loadmodel->animscenes;
762 for (f = 0;f < loadmodel->numframes;f++)
764 pframetype = (daliasframetype_t *)datapointer;
765 datapointer += sizeof(daliasframetype_t);
766 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
768 // a single frame is still treated as a group
775 group = (daliasgroup_t *)datapointer;
776 datapointer += sizeof(daliasgroup_t);
777 groupframes = LittleLong (group->numframes);
779 // intervals (time per frame)
780 intervals = (daliasinterval_t *)datapointer;
781 datapointer += sizeof(daliasinterval_t) * groupframes;
783 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
784 if (interval < 0.01f)
786 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
791 // get scene name from first frame
792 pinframe = (daliasframe_t *)datapointer;
794 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
795 scene->firstframe = pose;
796 scene->framecount = groupframes;
797 scene->framerate = 1.0f / interval;
802 for (i = 0;i < groupframes;i++)
804 pinframe = (daliasframe_t *)datapointer;
805 datapointer += sizeof(daliasframe_t);
806 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
807 datapointer += sizeof(trivertx_t) * inverts;
813 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
815 if (cls.state == ca_dedicated)
819 skinframe = R_SkinFrame_LoadMissing();
820 memset(texture, 0, sizeof(*texture));
821 texture->currentframe = texture;
822 //texture->animated = false;
823 texture->numskinframes = 1;
824 texture->skinframerate = 1;
825 texture->skinframes[0] = skinframe;
826 texture->currentskinframe = skinframe;
827 //texture->backgroundnumskinframes = 0;
828 //texture->customblendfunc[0] = 0;
829 //texture->customblendfunc[1] = 0;
830 //texture->surfaceflags = 0;
831 //texture->supercontents = 0;
832 //texture->surfaceparms = 0;
833 //texture->textureflags = 0;
835 texture->basematerialflags = MATERIALFLAG_WALL;
836 if (texture->currentskinframe->hasalpha)
837 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
838 texture->currentmaterialflags = texture->basematerialflags;
839 texture->offsetmapping = OFFSETMAPPING_OFF;
840 texture->offsetscale = 1;
841 texture->specularscalemod = 1;
842 texture->specularpowermod = 1;
843 texture->surfaceflags = 0;
844 texture->supercontents = SUPERCONTENTS_SOLID;
845 if (!(texture->basematerialflags & MATERIALFLAG_BLENDED))
846 texture->supercontents |= SUPERCONTENTS_OPAQUE;
849 void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
852 static char stripbuf[MAX_QPATH];
853 skinfileitem_t *skinfileitem;
854 if(developer_extra.integer)
855 Con_DPrintf("Looking up texture for %s (default: %s)\n", meshname, shadername);
858 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
859 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
861 memset(skin, 0, sizeof(*skin));
863 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
865 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
866 if (!strcmp(skinfileitem->name, meshname))
868 Image_StripImageExtension(skinfileitem->replacement, stripbuf, sizeof(stripbuf));
869 if(developer_extra.integer)
870 Con_DPrintf("--> got %s from skin file\n", stripbuf);
871 Mod_LoadTextureFromQ3Shader(skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
877 // don't render unmentioned meshes
878 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
879 if(developer_extra.integer)
880 Con_DPrintf("--> skipping\n");
881 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
887 if(developer_extra.integer)
888 Con_DPrintf("--> using default\n");
889 Image_StripImageExtension(shadername, stripbuf, sizeof(stripbuf));
890 Mod_LoadTextureFromQ3Shader(skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
894 #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);
895 #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);
896 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
898 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
899 float scales, scalet, interval;
903 stvert_t *pinstverts;
904 dtriangle_t *pintriangles;
905 daliasskintype_t *pinskintype;
906 daliasskingroup_t *pinskingroup;
907 daliasskininterval_t *pinskinintervals;
908 daliasframetype_t *pinframetype;
909 daliasgroup_t *pinframegroup;
910 unsigned char *datapointer, *startframes, *startskins;
911 char name[MAX_QPATH];
912 skinframe_t *tempskinframe;
913 animscene_t *tempskinscenes;
914 texture_t *tempaliasskins;
916 int *vertonseam, *vertremap;
917 skinfile_t *skinfiles;
919 datapointer = (unsigned char *)buffer;
920 pinmodel = (mdl_t *)datapointer;
921 datapointer += sizeof(mdl_t);
923 version = LittleLong (pinmodel->version);
924 if (version != ALIAS_VERSION)
925 Host_Error ("%s has wrong version number (%i should be %i)",
926 loadmodel->name, version, ALIAS_VERSION);
928 loadmodel->modeldatatypestring = "MDL";
930 loadmodel->type = mod_alias;
931 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
932 loadmodel->DrawSky = NULL;
933 loadmodel->DrawAddWaterPlanes = NULL;
934 loadmodel->Draw = R_Q1BSP_Draw;
935 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
936 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
937 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
938 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
939 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
940 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
941 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
942 loadmodel->DrawLight = R_Q1BSP_DrawLight;
943 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
944 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
945 // FIXME add TraceBrush!
946 loadmodel->PointSuperContents = NULL;
948 loadmodel->num_surfaces = 1;
949 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
950 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
951 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
952 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
953 loadmodel->sortedmodelsurfaces[0] = 0;
955 loadmodel->numskins = LittleLong(pinmodel->numskins);
956 BOUNDI(loadmodel->numskins,0,65536);
957 skinwidth = LittleLong (pinmodel->skinwidth);
958 BOUNDI(skinwidth,0,65536);
959 skinheight = LittleLong (pinmodel->skinheight);
960 BOUNDI(skinheight,0,65536);
961 numverts = LittleLong(pinmodel->numverts);
962 BOUNDI(numverts,0,65536);
963 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
964 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
965 loadmodel->numframes = LittleLong(pinmodel->numframes);
966 BOUNDI(loadmodel->numframes,0,65536);
967 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
968 BOUNDI((int)loadmodel->synctype,0,2);
969 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
970 i = LittleLong (pinmodel->flags);
971 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
973 for (i = 0;i < 3;i++)
975 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
976 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
979 startskins = datapointer;
981 for (i = 0;i < loadmodel->numskins;i++)
983 pinskintype = (daliasskintype_t *)datapointer;
984 datapointer += sizeof(daliasskintype_t);
985 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
989 pinskingroup = (daliasskingroup_t *)datapointer;
990 datapointer += sizeof(daliasskingroup_t);
991 groupskins = LittleLong(pinskingroup->numskins);
992 datapointer += sizeof(daliasskininterval_t) * groupskins;
995 for (j = 0;j < groupskins;j++)
997 datapointer += skinwidth * skinheight;
1002 pinstverts = (stvert_t *)datapointer;
1003 datapointer += sizeof(stvert_t) * numverts;
1005 pintriangles = (dtriangle_t *)datapointer;
1006 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
1008 startframes = datapointer;
1009 loadmodel->surfmesh.num_morphframes = 0;
1010 for (i = 0;i < loadmodel->numframes;i++)
1012 pinframetype = (daliasframetype_t *)datapointer;
1013 datapointer += sizeof(daliasframetype_t);
1014 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
1018 pinframegroup = (daliasgroup_t *)datapointer;
1019 datapointer += sizeof(daliasgroup_t);
1020 groupframes = LittleLong(pinframegroup->numframes);
1021 datapointer += sizeof(daliasinterval_t) * groupframes;
1024 for (j = 0;j < groupframes;j++)
1026 datapointer += sizeof(daliasframe_t);
1027 datapointer += sizeof(trivertx_t) * numverts;
1028 loadmodel->surfmesh.num_morphframes++;
1031 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1033 // store texture coordinates into temporary array, they will be stored
1034 // after usage is determined (triangle data)
1035 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
1036 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
1037 vertonseam = vertremap + numverts * 2;
1039 scales = 1.0 / skinwidth;
1040 scalet = 1.0 / skinheight;
1041 for (i = 0;i < numverts;i++)
1043 vertonseam[i] = LittleLong(pinstverts[i].onseam);
1044 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
1045 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
1046 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
1047 vertst[(i+numverts)*2+1] = vertst[i*2+1];
1050 // load triangle data
1051 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1053 // read the triangle elements
1054 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1055 for (j = 0;j < 3;j++)
1056 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1057 // validate (note numverts is used because this is the original data)
1058 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1059 // now butcher the elements according to vertonseam and tri->facesfront
1060 // and then compact the vertex set to remove duplicates
1061 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1062 if (!LittleLong(pintriangles[i].facesfront)) // backface
1063 for (j = 0;j < 3;j++)
1064 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1065 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1067 // (this uses vertremap to count usage to save some memory)
1068 for (i = 0;i < numverts*2;i++)
1070 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1071 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1072 // build remapping table and compact array
1073 loadmodel->surfmesh.num_vertices = 0;
1074 for (i = 0;i < numverts*2;i++)
1078 vertremap[i] = loadmodel->surfmesh.num_vertices;
1079 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1080 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1081 loadmodel->surfmesh.num_vertices++;
1084 vertremap[i] = -1; // not used at all
1086 // remap the elements to the new vertex set
1087 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1088 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1089 // store the texture coordinates
1090 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1091 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1093 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1094 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1097 // generate ushort elements array if possible
1098 if (loadmodel->surfmesh.num_vertices <= 65536)
1099 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1100 if (loadmodel->surfmesh.data_element3s)
1101 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1102 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1105 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1106 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1107 if (r_enableshadowvolumes.integer)
1108 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1109 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1110 if (loadmodel->surfmesh.data_neighbor3i)
1111 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1112 Mod_Alias_CalculateBoundingBox();
1113 Mod_Alias_MorphMesh_CompileFrames();
1116 Mem_Free(vertremap);
1119 skinfiles = Mod_LoadSkinFiles();
1122 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1123 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1124 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1125 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1126 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1127 Mod_FreeSkinFiles(skinfiles);
1128 for (i = 0;i < loadmodel->numskins;i++)
1130 loadmodel->skinscenes[i].firstframe = i;
1131 loadmodel->skinscenes[i].framecount = 1;
1132 loadmodel->skinscenes[i].loop = true;
1133 loadmodel->skinscenes[i].framerate = 10;
1138 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1139 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1140 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1141 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1143 datapointer = startskins;
1144 for (i = 0;i < loadmodel->numskins;i++)
1146 pinskintype = (daliasskintype_t *)datapointer;
1147 datapointer += sizeof(daliasskintype_t);
1149 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1156 pinskingroup = (daliasskingroup_t *)datapointer;
1157 datapointer += sizeof(daliasskingroup_t);
1159 groupskins = LittleLong (pinskingroup->numskins);
1161 pinskinintervals = (daliasskininterval_t *)datapointer;
1162 datapointer += sizeof(daliasskininterval_t) * groupskins;
1164 interval = LittleFloat(pinskinintervals[0].interval);
1165 if (interval < 0.01f)
1167 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1172 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1173 loadmodel->skinscenes[i].firstframe = totalskins;
1174 loadmodel->skinscenes[i].framecount = groupskins;
1175 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1176 loadmodel->skinscenes[i].loop = true;
1178 for (j = 0;j < groupskins;j++)
1181 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1183 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1184 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))
1185 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));
1186 datapointer += skinwidth * skinheight;
1190 // check for skins that don't exist in the model, but do exist as external images
1191 // (this was added because yummyluv kept pestering me about support for it)
1192 // TODO: support shaders here?
1193 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)))
1195 // expand the arrays to make room
1196 tempskinscenes = loadmodel->skinscenes;
1197 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1198 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1199 Mem_Free(tempskinscenes);
1201 tempaliasskins = loadmodel->data_textures;
1202 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1203 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1204 Mem_Free(tempaliasskins);
1206 // store the info about the new skin
1207 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1208 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1209 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1210 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1211 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1212 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1214 //increase skin counts
1215 loadmodel->numskins++;
1218 // fix up the pointers since they are pointing at the old textures array
1219 // FIXME: this is a hack!
1220 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1221 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1225 surface = loadmodel->data_surfaces;
1226 surface->texture = loadmodel->data_textures;
1227 surface->num_firsttriangle = 0;
1228 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1229 surface->num_firstvertex = 0;
1230 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1232 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1234 if (!loadmodel->surfmesh.isanimated)
1236 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1237 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1238 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1239 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1240 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1241 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1245 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1247 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1248 float iskinwidth, iskinheight;
1249 unsigned char *data;
1250 msurface_t *surface;
1252 unsigned char *base, *datapointer;
1253 md2frame_t *pinframe;
1255 md2triangle_t *intri;
1256 unsigned short *inst;
1257 struct md2verthash_s
1259 struct md2verthash_s *next;
1263 *hash, **md2verthash, *md2verthashdata;
1264 skinfile_t *skinfiles;
1266 pinmodel = (md2_t *)buffer;
1267 base = (unsigned char *)buffer;
1269 version = LittleLong (pinmodel->version);
1270 if (version != MD2ALIAS_VERSION)
1271 Host_Error ("%s has wrong version number (%i should be %i)",
1272 loadmodel->name, version, MD2ALIAS_VERSION);
1274 loadmodel->modeldatatypestring = "MD2";
1276 loadmodel->type = mod_alias;
1277 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1278 loadmodel->DrawSky = NULL;
1279 loadmodel->DrawAddWaterPlanes = NULL;
1280 loadmodel->Draw = R_Q1BSP_Draw;
1281 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1282 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1283 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1284 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1285 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1286 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1287 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1288 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1289 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1290 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1291 loadmodel->PointSuperContents = NULL;
1293 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1294 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1295 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1296 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1297 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1298 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1299 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1300 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1302 end = LittleLong(pinmodel->ofs_end);
1303 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1304 Host_Error ("%s is not a valid model", loadmodel->name);
1305 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1306 Host_Error ("%s is not a valid model", loadmodel->name);
1307 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1308 Host_Error ("%s is not a valid model", loadmodel->name);
1309 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1310 Host_Error ("%s is not a valid model", loadmodel->name);
1311 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1312 Host_Error ("%s is not a valid model", loadmodel->name);
1314 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1315 numxyz = LittleLong(pinmodel->num_xyz);
1316 numst = LittleLong(pinmodel->num_st);
1317 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1318 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1319 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1320 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1321 skinwidth = LittleLong(pinmodel->skinwidth);
1322 skinheight = LittleLong(pinmodel->skinheight);
1323 iskinwidth = 1.0f / skinwidth;
1324 iskinheight = 1.0f / skinheight;
1326 loadmodel->num_surfaces = 1;
1327 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1328 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));
1329 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1330 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1331 loadmodel->sortedmodelsurfaces[0] = 0;
1332 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1333 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1334 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1335 if (r_enableshadowvolumes.integer)
1336 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1338 loadmodel->synctype = ST_RAND;
1341 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1342 skinfiles = Mod_LoadSkinFiles();
1345 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1346 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1347 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1348 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1349 Mod_FreeSkinFiles(skinfiles);
1351 else if (loadmodel->numskins)
1353 // skins found (most likely not a player model)
1354 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1355 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1356 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1357 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1358 Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
1362 // no skins (most likely a player model)
1363 loadmodel->numskins = 1;
1364 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1365 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1366 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1367 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1370 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1371 for (i = 0;i < loadmodel->numskins;i++)
1373 loadmodel->skinscenes[i].firstframe = i;
1374 loadmodel->skinscenes[i].framecount = 1;
1375 loadmodel->skinscenes[i].loop = true;
1376 loadmodel->skinscenes[i].framerate = 10;
1379 // load the triangles and stvert data
1380 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1381 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1382 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1383 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1384 // swap the triangle list
1385 loadmodel->surfmesh.num_vertices = 0;
1386 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1388 for (j = 0;j < 3;j++)
1390 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1391 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1394 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1399 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1402 hashindex = (xyz * 256 + st) & 65535;
1403 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1404 if (hash->xyz == xyz && hash->st == st)
1408 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1411 hash->next = md2verthash[hashindex];
1412 md2verthash[hashindex] = hash;
1414 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1418 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1419 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));
1420 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1421 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1422 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1425 hash = md2verthashdata + i;
1426 vertremap[i] = hash->xyz;
1427 sts = LittleShort(inst[hash->st*2+0]);
1428 stt = LittleShort(inst[hash->st*2+1]);
1429 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1431 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1435 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1436 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1439 Mem_Free(md2verthash);
1440 Mem_Free(md2verthashdata);
1442 // generate ushort elements array if possible
1443 if (loadmodel->surfmesh.num_vertices <= 65536)
1444 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1445 if (loadmodel->surfmesh.data_element3s)
1446 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1447 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1450 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1451 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1456 pinframe = (md2frame_t *)datapointer;
1457 datapointer += sizeof(md2frame_t);
1458 // store the frame scale/translate into the appropriate array
1459 for (j = 0;j < 3;j++)
1461 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1462 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1464 // convert the vertices
1465 v = (trivertx_t *)datapointer;
1466 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1467 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1468 out[k] = v[vertremap[k]];
1469 datapointer += numxyz * sizeof(trivertx_t);
1471 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1472 loadmodel->animscenes[i].firstframe = i;
1473 loadmodel->animscenes[i].framecount = 1;
1474 loadmodel->animscenes[i].framerate = 10;
1475 loadmodel->animscenes[i].loop = true;
1478 Mem_Free(vertremap);
1480 if (loadmodel->surfmesh.data_neighbor3i)
1481 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1482 Mod_Alias_CalculateBoundingBox();
1483 Mod_Alias_MorphMesh_CompileFrames();
1485 surface = loadmodel->data_surfaces;
1486 surface->texture = loadmodel->data_textures;
1487 surface->num_firsttriangle = 0;
1488 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1489 surface->num_firstvertex = 0;
1490 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1492 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1494 if (!loadmodel->surfmesh.isanimated)
1496 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1497 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1498 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1499 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1500 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1501 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1505 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1507 int i, j, k, version, meshvertices, meshtriangles;
1508 unsigned char *data;
1509 msurface_t *surface;
1510 md3modelheader_t *pinmodel;
1511 md3frameinfo_t *pinframe;
1514 skinfile_t *skinfiles;
1516 pinmodel = (md3modelheader_t *)buffer;
1518 if (memcmp(pinmodel->identifier, "IDP3", 4))
1519 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1520 version = LittleLong (pinmodel->version);
1521 if (version != MD3VERSION)
1522 Host_Error ("%s has wrong version number (%i should be %i)",
1523 loadmodel->name, version, MD3VERSION);
1525 skinfiles = Mod_LoadSkinFiles();
1526 if (loadmodel->numskins < 1)
1527 loadmodel->numskins = 1;
1529 loadmodel->modeldatatypestring = "MD3";
1531 loadmodel->type = mod_alias;
1532 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1533 loadmodel->DrawSky = NULL;
1534 loadmodel->DrawAddWaterPlanes = NULL;
1535 loadmodel->Draw = R_Q1BSP_Draw;
1536 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1537 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1538 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1539 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1540 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1541 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1542 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1543 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1544 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1545 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1546 loadmodel->PointSuperContents = NULL;
1547 loadmodel->synctype = ST_RAND;
1548 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1549 i = LittleLong (pinmodel->flags);
1550 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1552 // set up some global info about the model
1553 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1554 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1556 // make skinscenes for the skins (no groups)
1557 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1558 for (i = 0;i < loadmodel->numskins;i++)
1560 loadmodel->skinscenes[i].firstframe = i;
1561 loadmodel->skinscenes[i].framecount = 1;
1562 loadmodel->skinscenes[i].loop = true;
1563 loadmodel->skinscenes[i].framerate = 10;
1567 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1568 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1570 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1571 loadmodel->animscenes[i].firstframe = i;
1572 loadmodel->animscenes[i].framecount = 1;
1573 loadmodel->animscenes[i].framerate = 10;
1574 loadmodel->animscenes[i].loop = true;
1578 loadmodel->num_tagframes = loadmodel->numframes;
1579 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1580 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1581 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1583 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1584 for (j = 0;j < 9;j++)
1585 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1586 for (j = 0;j < 3;j++)
1587 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1588 //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);
1594 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)))
1596 if (memcmp(pinmesh->identifier, "IDP3", 4))
1597 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1598 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1599 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1600 meshvertices += LittleLong(pinmesh->num_vertices);
1601 meshtriangles += LittleLong(pinmesh->num_triangles);
1604 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1605 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1606 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1607 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));
1608 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1609 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1610 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1611 loadmodel->surfmesh.num_vertices = meshvertices;
1612 loadmodel->surfmesh.num_triangles = meshtriangles;
1613 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1614 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1615 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1616 if (r_enableshadowvolumes.integer)
1617 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1618 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1619 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1620 if (meshvertices <= 65536)
1621 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1625 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)))
1627 if (memcmp(pinmesh->identifier, "IDP3", 4))
1628 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1629 loadmodel->sortedmodelsurfaces[i] = i;
1630 surface = loadmodel->data_surfaces + i;
1631 surface->texture = loadmodel->data_textures + i;
1632 surface->num_firsttriangle = meshtriangles;
1633 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1634 surface->num_firstvertex = meshvertices;
1635 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1636 meshvertices += surface->num_vertices;
1637 meshtriangles += surface->num_triangles;
1639 for (j = 0;j < surface->num_triangles * 3;j++)
1640 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1641 for (j = 0;j < surface->num_vertices;j++)
1643 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1644 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1646 for (j = 0;j < loadmodel->numframes;j++)
1648 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1649 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1650 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1652 out->origin[0] = LittleShort(in->origin[0]);
1653 out->origin[1] = LittleShort(in->origin[1]);
1654 out->origin[2] = LittleShort(in->origin[2]);
1655 out->pitch = in->pitch;
1660 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1662 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1664 if (loadmodel->surfmesh.data_element3s)
1665 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1666 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1667 if (loadmodel->surfmesh.data_neighbor3i)
1668 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1669 Mod_Alias_MorphMesh_CompileFrames();
1670 Mod_Alias_CalculateBoundingBox();
1671 Mod_FreeSkinFiles(skinfiles);
1672 Mod_MakeSortedSurfaces(loadmodel);
1674 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1675 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1677 if (!loadmodel->surfmesh.isanimated)
1679 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1680 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1681 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1682 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1683 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1684 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1688 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1690 zymtype1header_t *pinmodel, *pheader;
1691 unsigned char *pbase;
1692 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1693 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose, f, biggestorigin, tempvec[3], modelscale;
1694 zymvertex_t *verts, *vertdata;
1698 skinfile_t *skinfiles;
1699 unsigned char *data;
1700 msurface_t *surface;
1702 pinmodel = (zymtype1header_t *)buffer;
1703 pbase = (unsigned char *)buffer;
1704 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1705 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1706 if (BigLong(pinmodel->type) != 1)
1707 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1709 loadmodel->modeldatatypestring = "ZYM";
1711 loadmodel->type = mod_alias;
1712 loadmodel->synctype = ST_RAND;
1716 pheader->type = BigLong(pinmodel->type);
1717 pheader->filesize = BigLong(pinmodel->filesize);
1718 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1719 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1720 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1721 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1722 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1723 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1724 pheader->radius = BigFloat(pinmodel->radius);
1725 pheader->numverts = BigLong(pinmodel->numverts);
1726 pheader->numtris = BigLong(pinmodel->numtris);
1727 pheader->numshaders = BigLong(pinmodel->numshaders);
1728 pheader->numbones = BigLong(pinmodel->numbones);
1729 pheader->numscenes = BigLong(pinmodel->numscenes);
1730 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1731 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1732 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1733 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1734 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1735 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1736 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1737 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1738 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1739 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1740 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1741 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1742 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1743 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1744 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1745 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1746 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1747 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1749 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1751 Con_Printf("%s has no geometry\n", loadmodel->name);
1754 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1756 Con_Printf("%s has no animations\n", loadmodel->name);
1760 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1761 loadmodel->DrawSky = NULL;
1762 loadmodel->DrawAddWaterPlanes = NULL;
1763 loadmodel->Draw = R_Q1BSP_Draw;
1764 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1765 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1766 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1767 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1768 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1769 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1770 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1771 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1772 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1773 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1774 loadmodel->PointSuperContents = NULL;
1776 loadmodel->numframes = pheader->numscenes;
1777 loadmodel->num_surfaces = pheader->numshaders;
1779 skinfiles = Mod_LoadSkinFiles();
1780 if (loadmodel->numskins < 1)
1781 loadmodel->numskins = 1;
1783 // make skinscenes for the skins (no groups)
1784 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1785 for (i = 0;i < loadmodel->numskins;i++)
1787 loadmodel->skinscenes[i].firstframe = i;
1788 loadmodel->skinscenes[i].framecount = 1;
1789 loadmodel->skinscenes[i].loop = true;
1790 loadmodel->skinscenes[i].framerate = 10;
1794 modelradius = pheader->radius;
1795 for (i = 0;i < 3;i++)
1797 loadmodel->normalmins[i] = pheader->mins[i];
1798 loadmodel->normalmaxs[i] = pheader->maxs[i];
1799 loadmodel->rotatedmins[i] = -modelradius;
1800 loadmodel->rotatedmaxs[i] = modelradius;
1802 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1803 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1804 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1805 if (loadmodel->yawmaxs[0] > modelradius)
1806 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1807 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1808 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1809 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1810 loadmodel->radius = modelradius;
1811 loadmodel->radius2 = modelradius * modelradius;
1813 // go through the lumps, swapping things
1815 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1816 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1817 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1818 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1819 for (i = 0;i < pheader->numscenes;i++)
1821 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1822 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1823 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1824 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1825 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1826 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1827 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1828 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1829 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1830 if (loadmodel->animscenes[i].framerate < 0)
1831 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1835 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1836 loadmodel->num_bones = pheader->numbones;
1837 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1838 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1839 for (i = 0;i < pheader->numbones;i++)
1841 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1842 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1843 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1844 if (loadmodel->data_bones[i].parent >= i)
1845 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1848 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1849 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1850 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1851 for (i = 0;i < pheader->numverts;i++)
1853 vertbonecounts[i] = BigLong(bonecount[i]);
1854 if (vertbonecounts[i] != 1)
1855 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1858 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1860 meshvertices = pheader->numverts;
1861 meshtriangles = pheader->numtris;
1863 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1864 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1865 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1866 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]));
1867 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1868 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1869 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1870 loadmodel->surfmesh.num_vertices = meshvertices;
1871 loadmodel->surfmesh.num_triangles = meshtriangles;
1872 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1873 if (r_enableshadowvolumes.integer)
1874 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1875 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1876 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1877 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1878 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1879 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1880 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1881 loadmodel->surfmesh.num_blends = 0;
1882 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
1883 if (loadmodel->surfmesh.num_vertices <= 65536)
1884 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1885 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
1886 loadmodel->surfmesh.data_blendweights = NULL;
1888 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1889 poses = (float *) (pheader->lump_poses.start + pbase);
1890 // figure out scale of model from root bone, for compatibility with old zmodel versions
1891 tempvec[0] = BigFloat(poses[0]);
1892 tempvec[1] = BigFloat(poses[1]);
1893 tempvec[2] = BigFloat(poses[2]);
1894 modelscale = VectorLength(tempvec);
1896 for (i = 0;i < loadmodel->num_bones * numposes * 12;i++)
1898 f = fabs(BigFloat(poses[i]));
1899 biggestorigin = max(biggestorigin, f);
1901 loadmodel->num_posescale = biggestorigin / 32767.0f;
1902 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
1903 for (i = 0;i < numposes;i++)
1905 const float *frameposes = (float *) (pheader->lump_poses.start + pbase) + 12*i*loadmodel->num_bones;
1906 for (j = 0;j < loadmodel->num_bones;j++)
1909 matrix4x4_t posematrix;
1910 for (k = 0;k < 12;k++)
1911 pose[k] = BigFloat(frameposes[j*12+k]);
1912 //if (j < loadmodel->num_bones)
1913 // 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));
1914 // scale child bones to match the root scale
1915 if (loadmodel->data_bones[j].parent >= 0)
1917 pose[3] *= modelscale;
1918 pose[7] *= modelscale;
1919 pose[11] *= modelscale;
1921 // normalize rotation matrix
1922 VectorNormalize(pose + 0);
1923 VectorNormalize(pose + 4);
1924 VectorNormalize(pose + 8);
1925 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
1926 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
1930 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1931 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1932 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1933 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1934 // (converting from weight-blending skeletal animation to
1935 // deformation-based skeletal animation)
1936 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1937 for (i = 0;i < loadmodel->num_bones;i++)
1940 for (k = 0;k < 12;k++)
1941 m[k] = BigFloat(poses[i*12+k]);
1942 if (loadmodel->data_bones[i].parent >= 0)
1943 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1945 for (k = 0;k < 12;k++)
1946 bonepose[12*i+k] = m[k];
1948 for (j = 0;j < pheader->numverts;j++)
1950 // this format really should have had a per vertexweight weight value...
1951 // but since it does not, the weighting is completely ignored and
1952 // only one weight is allowed per vertex
1953 int boneindex = BigLong(vertdata[j].bonenum);
1954 const float *m = bonepose + 12 * boneindex;
1955 float relativeorigin[3];
1956 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1957 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1958 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1959 // transform the vertex bone weight into the base mesh
1960 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1961 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1962 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1963 // store the weight as the primary weight on this vertex
1964 loadmodel->surfmesh.blends[j] = boneindex;
1967 // normals and tangents are calculated after elements are loaded
1969 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1970 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1971 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1972 for (i = 0;i < pheader->numverts;i++)
1974 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1975 // flip T coordinate for OpenGL
1976 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1979 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1980 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1981 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1983 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1984 //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)
1985 // byteswap, validate, and swap winding order of tris
1986 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1987 if (pheader->lump_render.length != count)
1988 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1989 renderlist = (int *) (pheader->lump_render.start + pbase);
1990 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1992 for (i = 0;i < loadmodel->num_surfaces;i++)
1994 int firstvertex, lastvertex;
1995 if (renderlist >= renderlistend)
1996 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1997 count = BigLong(*renderlist);renderlist++;
1998 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1999 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2001 loadmodel->sortedmodelsurfaces[i] = i;
2002 surface = loadmodel->data_surfaces + i;
2003 surface->texture = loadmodel->data_textures + i;
2004 surface->num_firsttriangle = meshtriangles;
2005 surface->num_triangles = count;
2006 meshtriangles += surface->num_triangles;
2008 // load the elements
2009 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2010 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
2012 outelements[j*3+2] = BigLong(renderlist[0]);
2013 outelements[j*3+1] = BigLong(renderlist[1]);
2014 outelements[j*3+0] = BigLong(renderlist[2]);
2016 // validate the elements and find the used vertex range
2017 firstvertex = meshvertices;
2019 for (j = 0;j < surface->num_triangles * 3;j++)
2021 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
2022 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
2023 firstvertex = min(firstvertex, outelements[j]);
2024 lastvertex = max(lastvertex, outelements[j]);
2026 surface->num_firstvertex = firstvertex;
2027 surface->num_vertices = lastvertex + 1 - firstvertex;
2029 // since zym models do not have named sections, reuse their shader
2030 // name as the section name
2031 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
2032 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
2034 Mod_FreeSkinFiles(skinfiles);
2035 Mem_Free(vertbonecounts);
2037 Mod_MakeSortedSurfaces(loadmodel);
2039 // compute all the mesh information that was not loaded from the file
2040 if (loadmodel->surfmesh.data_element3s)
2041 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2042 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2043 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2044 Mod_BuildBaseBonePoses();
2045 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);
2046 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);
2047 if (loadmodel->surfmesh.data_neighbor3i)
2048 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2050 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2052 if (!loadmodel->surfmesh.isanimated)
2054 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2055 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2056 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2057 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2058 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2059 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2063 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2065 dpmheader_t *pheader;
2069 unsigned char *pbase;
2070 int i, j, k, meshvertices, meshtriangles;
2071 skinfile_t *skinfiles;
2072 unsigned char *data;
2074 float biggestorigin, tempvec[3], modelscale;
2078 pheader = (dpmheader_t *)buffer;
2079 pbase = (unsigned char *)buffer;
2080 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2081 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2082 if (BigLong(pheader->type) != 2)
2083 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2085 loadmodel->modeldatatypestring = "DPM";
2087 loadmodel->type = mod_alias;
2088 loadmodel->synctype = ST_RAND;
2091 pheader->type = BigLong(pheader->type);
2092 pheader->filesize = BigLong(pheader->filesize);
2093 pheader->mins[0] = BigFloat(pheader->mins[0]);
2094 pheader->mins[1] = BigFloat(pheader->mins[1]);
2095 pheader->mins[2] = BigFloat(pheader->mins[2]);
2096 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2097 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2098 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2099 pheader->yawradius = BigFloat(pheader->yawradius);
2100 pheader->allradius = BigFloat(pheader->allradius);
2101 pheader->num_bones = BigLong(pheader->num_bones);
2102 pheader->num_meshs = BigLong(pheader->num_meshs);
2103 pheader->num_frames = BigLong(pheader->num_frames);
2104 pheader->ofs_bones = BigLong(pheader->ofs_bones);
2105 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2106 pheader->ofs_frames = BigLong(pheader->ofs_frames);
2108 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2110 Con_Printf("%s has no geometry\n", loadmodel->name);
2113 if (pheader->num_frames < 1)
2115 Con_Printf("%s has no frames\n", loadmodel->name);
2119 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2120 loadmodel->DrawSky = NULL;
2121 loadmodel->DrawAddWaterPlanes = NULL;
2122 loadmodel->Draw = R_Q1BSP_Draw;
2123 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2124 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2125 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2126 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2127 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2128 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2129 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2130 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2131 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2132 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2133 loadmodel->PointSuperContents = NULL;
2136 for (i = 0;i < 3;i++)
2138 loadmodel->normalmins[i] = pheader->mins[i];
2139 loadmodel->normalmaxs[i] = pheader->maxs[i];
2140 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2141 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2142 loadmodel->rotatedmins[i] = -pheader->allradius;
2143 loadmodel->rotatedmaxs[i] = pheader->allradius;
2145 loadmodel->radius = pheader->allradius;
2146 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2148 // load external .skin files if present
2149 skinfiles = Mod_LoadSkinFiles();
2150 if (loadmodel->numskins < 1)
2151 loadmodel->numskins = 1;
2156 // gather combined statistics from the meshes
2157 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2158 for (i = 0;i < (int)pheader->num_meshs;i++)
2160 int numverts = BigLong(dpmmesh->num_verts);
2161 meshvertices += numverts;
2162 meshtriangles += BigLong(dpmmesh->num_tris);
2166 loadmodel->numframes = pheader->num_frames;
2167 loadmodel->num_bones = pheader->num_bones;
2168 loadmodel->num_poses = loadmodel->numframes;
2169 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2170 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2171 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2172 // do most allocations as one merged chunk
2173 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));
2174 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2175 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2176 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2177 loadmodel->surfmesh.num_vertices = meshvertices;
2178 loadmodel->surfmesh.num_triangles = meshtriangles;
2179 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2180 if (r_enableshadowvolumes.integer)
2181 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2182 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2183 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2184 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2185 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2186 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2187 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2188 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2189 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2190 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2191 loadmodel->surfmesh.num_blends = 0;
2192 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2193 if (meshvertices <= 65536)
2194 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2195 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2196 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
2198 for (i = 0;i < loadmodel->numskins;i++)
2200 loadmodel->skinscenes[i].firstframe = i;
2201 loadmodel->skinscenes[i].framecount = 1;
2202 loadmodel->skinscenes[i].loop = true;
2203 loadmodel->skinscenes[i].framerate = 10;
2206 // load the bone info
2207 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2208 for (i = 0;i < loadmodel->num_bones;i++)
2210 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2211 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2212 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2213 if (loadmodel->data_bones[i].parent >= i)
2214 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2218 frames = (dpmframe_t *) (pbase + pheader->ofs_frames);
2219 // figure out scale of model from root bone, for compatibility with old dpmodel versions
2220 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2221 tempvec[0] = BigFloat(poses[0]);
2222 tempvec[1] = BigFloat(poses[1]);
2223 tempvec[2] = BigFloat(poses[2]);
2224 modelscale = VectorLength(tempvec);
2226 for (i = 0;i < loadmodel->numframes;i++)
2228 memcpy(loadmodel->animscenes[i].name, frames[i].name, sizeof(frames[i].name));
2229 loadmodel->animscenes[i].firstframe = i;
2230 loadmodel->animscenes[i].framecount = 1;
2231 loadmodel->animscenes[i].loop = true;
2232 loadmodel->animscenes[i].framerate = 10;
2233 // load the bone poses for this frame
2234 poses = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2235 for (j = 0;j < loadmodel->num_bones*12;j++)
2237 f = fabs(BigFloat(poses[j]));
2238 biggestorigin = max(biggestorigin, f);
2240 // stuff not processed here: mins, maxs, yawradius, allradius
2242 loadmodel->num_posescale = biggestorigin / 32767.0f;
2243 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2244 for (i = 0;i < loadmodel->numframes;i++)
2246 const float *frameposes = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2247 for (j = 0;j < loadmodel->num_bones;j++)
2250 matrix4x4_t posematrix;
2251 for (k = 0;k < 12;k++)
2252 pose[k] = BigFloat(frameposes[j*12+k]);
2253 // scale child bones to match the root scale
2254 if (loadmodel->data_bones[j].parent >= 0)
2256 pose[3] *= modelscale;
2257 pose[7] *= modelscale;
2258 pose[11] *= modelscale;
2260 // normalize rotation matrix
2261 VectorNormalize(pose + 0);
2262 VectorNormalize(pose + 4);
2263 VectorNormalize(pose + 8);
2264 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2265 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
2269 // load the meshes now
2270 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2273 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2274 // (converting from weight-blending skeletal animation to
2275 // deformation-based skeletal animation)
2276 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2277 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2278 for (i = 0;i < loadmodel->num_bones;i++)
2281 for (k = 0;k < 12;k++)
2282 m[k] = BigFloat(poses[i*12+k]);
2283 if (loadmodel->data_bones[i].parent >= 0)
2284 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2286 for (k = 0;k < 12;k++)
2287 bonepose[12*i+k] = m[k];
2289 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2291 const int *inelements;
2293 const float *intexcoord;
2294 msurface_t *surface;
2296 loadmodel->sortedmodelsurfaces[i] = i;
2297 surface = loadmodel->data_surfaces + i;
2298 surface->texture = loadmodel->data_textures + i;
2299 surface->num_firsttriangle = meshtriangles;
2300 surface->num_triangles = BigLong(dpmmesh->num_tris);
2301 surface->num_firstvertex = meshvertices;
2302 surface->num_vertices = BigLong(dpmmesh->num_verts);
2303 meshvertices += surface->num_vertices;
2304 meshtriangles += surface->num_triangles;
2306 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2307 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2308 for (j = 0;j < surface->num_triangles;j++)
2310 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2311 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2312 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2313 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2318 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2319 for (j = 0;j < surface->num_vertices*2;j++)
2320 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2322 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2323 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2325 int weightindex[4] = { 0, 0, 0, 0 };
2326 float weightinfluence[4] = { 0, 0, 0, 0 };
2328 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2329 data += sizeof(dpmvertex_t);
2330 for (k = 0;k < numweights;k++)
2332 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2333 int boneindex = BigLong(vert->bonenum);
2334 const float *m = bonepose + 12 * boneindex;
2335 float influence = BigFloat(vert->influence);
2336 float relativeorigin[3], relativenormal[3];
2337 relativeorigin[0] = BigFloat(vert->origin[0]);
2338 relativeorigin[1] = BigFloat(vert->origin[1]);
2339 relativeorigin[2] = BigFloat(vert->origin[2]);
2340 relativenormal[0] = BigFloat(vert->normal[0]);
2341 relativenormal[1] = BigFloat(vert->normal[1]);
2342 relativenormal[2] = BigFloat(vert->normal[2]);
2343 // blend the vertex bone weights into the base mesh
2344 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2345 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2346 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2347 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2348 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2349 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2352 // store the first (and often only) weight
2353 weightinfluence[0] = influence;
2354 weightindex[0] = boneindex;
2358 // sort the new weight into this vertex's weight table
2359 // (which only accepts up to 4 bones per vertex)
2360 for (l = 0;l < 4;l++)
2362 if (weightinfluence[l] < influence)
2364 // move weaker influence weights out of the way first
2366 for (l2 = 3;l2 > l;l2--)
2368 weightinfluence[l2] = weightinfluence[l2-1];
2369 weightindex[l2] = weightindex[l2-1];
2371 // store the new weight
2372 weightinfluence[l] = influence;
2373 weightindex[l] = boneindex;
2378 data += sizeof(dpmbonevert_t);
2380 loadmodel->surfmesh.blends[j] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
2383 // since dpm models do not have named sections, reuse their shader name as the section name
2384 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2386 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2388 if (loadmodel->surfmesh.num_blends < meshvertices)
2389 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2391 Mod_FreeSkinFiles(skinfiles);
2392 Mod_MakeSortedSurfaces(loadmodel);
2394 // compute all the mesh information that was not loaded from the file
2395 if (loadmodel->surfmesh.data_element3s)
2396 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2397 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2398 Mod_BuildBaseBonePoses();
2399 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);
2400 if (loadmodel->surfmesh.data_neighbor3i)
2401 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2403 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2405 if (!loadmodel->surfmesh.isanimated)
2407 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2408 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2409 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2410 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2411 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2412 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2416 // no idea why PSK/PSA files contain weird quaternions but they do...
2417 #define PSKQUATNEGATIONS
2418 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2420 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2421 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2422 fs_offset_t filesize;
2427 pskboneinfo_t *bones;
2428 pskrawweights_t *rawweights;
2429 //pskboneinfo_t *animbones;
2430 pskaniminfo_t *anims;
2431 pskanimkeys_t *animkeys;
2432 void *animfilebuffer, *animbuffer, *animbufferend;
2433 unsigned char *data;
2435 skinfile_t *skinfiles;
2436 char animname[MAX_QPATH];
2438 float biggestorigin;
2440 pchunk = (pskchunk_t *)buffer;
2441 if (strcmp(pchunk->id, "ACTRHEAD"))
2442 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2444 loadmodel->modeldatatypestring = "PSK";
2446 loadmodel->type = mod_alias;
2447 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2448 loadmodel->DrawSky = NULL;
2449 loadmodel->DrawAddWaterPlanes = NULL;
2450 loadmodel->Draw = R_Q1BSP_Draw;
2451 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2452 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2453 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2454 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2455 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2456 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2457 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2458 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2459 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2460 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2461 loadmodel->PointSuperContents = NULL;
2462 loadmodel->synctype = ST_RAND;
2464 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2465 strlcat(animname, ".psa", sizeof(animname));
2466 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2467 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2468 if (animbuffer == NULL)
2469 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2488 while (buffer < bufferend)
2490 pchunk = (pskchunk_t *)buffer;
2491 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2492 version = LittleLong(pchunk->version);
2493 recordsize = LittleLong(pchunk->recordsize);
2494 numrecords = LittleLong(pchunk->numrecords);
2495 if (developer_extra.integer)
2496 Con_DPrintf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2497 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2498 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);
2499 if (!strcmp(pchunk->id, "ACTRHEAD"))
2503 else if (!strcmp(pchunk->id, "PNTS0000"))
2506 if (recordsize != sizeof(*p))
2507 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2508 // byteswap in place and keep the pointer
2509 numpnts = numrecords;
2510 pnts = (pskpnts_t *)buffer;
2511 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2513 p->origin[0] = LittleFloat(p->origin[0]);
2514 p->origin[1] = LittleFloat(p->origin[1]);
2515 p->origin[2] = LittleFloat(p->origin[2]);
2519 else if (!strcmp(pchunk->id, "VTXW0000"))
2522 if (recordsize != sizeof(*p))
2523 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2524 // byteswap in place and keep the pointer
2525 numvtxw = numrecords;
2526 vtxw = (pskvtxw_t *)buffer;
2527 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2529 p->pntsindex = LittleShort(p->pntsindex);
2530 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2531 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2532 if (p->pntsindex >= numpnts)
2534 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2540 else if (!strcmp(pchunk->id, "FACE0000"))
2543 if (recordsize != sizeof(*p))
2544 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2545 // byteswap in place and keep the pointer
2546 numfaces = numrecords;
2547 faces = (pskface_t *)buffer;
2548 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2550 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2551 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2552 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2553 p->group = LittleLong(p->group);
2554 if (p->vtxwindex[0] >= numvtxw)
2556 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2557 p->vtxwindex[0] = 0;
2559 if (p->vtxwindex[1] >= numvtxw)
2561 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2562 p->vtxwindex[1] = 0;
2564 if (p->vtxwindex[2] >= numvtxw)
2566 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2567 p->vtxwindex[2] = 0;
2572 else if (!strcmp(pchunk->id, "MATT0000"))
2575 if (recordsize != sizeof(*p))
2576 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2577 // byteswap in place and keep the pointer
2578 nummatts = numrecords;
2579 matts = (pskmatt_t *)buffer;
2580 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2586 else if (!strcmp(pchunk->id, "REFSKELT"))
2589 if (recordsize != sizeof(*p))
2590 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2591 // byteswap in place and keep the pointer
2592 numbones = numrecords;
2593 bones = (pskboneinfo_t *)buffer;
2594 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2596 p->numchildren = LittleLong(p->numchildren);
2597 p->parent = LittleLong(p->parent);
2598 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2599 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2600 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2601 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2602 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2603 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2604 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2605 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2606 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2607 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2608 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2609 #ifdef PSKQUATNEGATIONS
2612 p->basepose.quat[0] *= -1;
2613 p->basepose.quat[1] *= -1;
2614 p->basepose.quat[2] *= -1;
2618 p->basepose.quat[0] *= 1;
2619 p->basepose.quat[1] *= -1;
2620 p->basepose.quat[2] *= 1;
2623 if (p->parent < 0 || p->parent >= numbones)
2625 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2631 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2634 if (recordsize != sizeof(*p))
2635 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2636 // byteswap in place and keep the pointer
2637 numrawweights = numrecords;
2638 rawweights = (pskrawweights_t *)buffer;
2639 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2641 p->weight = LittleFloat(p->weight);
2642 p->pntsindex = LittleLong(p->pntsindex);
2643 p->boneindex = LittleLong(p->boneindex);
2644 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2646 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2649 if (p->boneindex < 0 || p->boneindex >= numbones)
2651 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2659 while (animbuffer < animbufferend)
2661 pchunk = (pskchunk_t *)animbuffer;
2662 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2663 version = LittleLong(pchunk->version);
2664 recordsize = LittleLong(pchunk->recordsize);
2665 numrecords = LittleLong(pchunk->numrecords);
2666 if (developer_extra.integer)
2667 Con_DPrintf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2668 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2669 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);
2670 if (!strcmp(pchunk->id, "ANIMHEAD"))
2674 else if (!strcmp(pchunk->id, "BONENAMES"))
2677 if (recordsize != sizeof(*p))
2678 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2679 // byteswap in place and keep the pointer
2680 numanimbones = numrecords;
2681 //animbones = (pskboneinfo_t *)animbuffer;
2682 // NOTE: supposedly psa does not need to match the psk model, the
2683 // bones missing from the psa would simply use their base
2684 // positions from the psk, but this is hard for me to implement
2685 // and people can easily make animations that match.
2686 if (numanimbones != numbones)
2687 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2688 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2690 p->numchildren = LittleLong(p->numchildren);
2691 p->parent = LittleLong(p->parent);
2692 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2693 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2694 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2695 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2696 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2697 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2698 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2699 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2700 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2701 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2702 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2703 #ifdef PSKQUATNEGATIONS
2706 p->basepose.quat[0] *= -1;
2707 p->basepose.quat[1] *= -1;
2708 p->basepose.quat[2] *= -1;
2712 p->basepose.quat[0] *= 1;
2713 p->basepose.quat[1] *= -1;
2714 p->basepose.quat[2] *= 1;
2717 if (p->parent < 0 || p->parent >= numanimbones)
2719 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2722 // check that bones are the same as in the base
2723 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2724 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2728 else if (!strcmp(pchunk->id, "ANIMINFO"))
2731 if (recordsize != sizeof(*p))
2732 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2733 // byteswap in place and keep the pointer
2734 numanims = numrecords;
2735 anims = (pskaniminfo_t *)animbuffer;
2736 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2738 p->numbones = LittleLong(p->numbones);
2739 p->playtime = LittleFloat(p->playtime);
2740 p->fps = LittleFloat(p->fps);
2741 p->firstframe = LittleLong(p->firstframe);
2742 p->numframes = LittleLong(p->numframes);
2743 if (p->numbones != numbones)
2744 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2748 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2751 if (recordsize != sizeof(*p))
2752 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2753 numanimkeys = numrecords;
2754 animkeys = (pskanimkeys_t *)animbuffer;
2755 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2757 p->origin[0] = LittleFloat(p->origin[0]);
2758 p->origin[1] = LittleFloat(p->origin[1]);
2759 p->origin[2] = LittleFloat(p->origin[2]);
2760 p->quat[0] = LittleFloat(p->quat[0]);
2761 p->quat[1] = LittleFloat(p->quat[1]);
2762 p->quat[2] = LittleFloat(p->quat[2]);
2763 p->quat[3] = LittleFloat(p->quat[3]);
2764 p->frametime = LittleFloat(p->frametime);
2765 #ifdef PSKQUATNEGATIONS
2766 if (index % numbones)
2781 // TODO: allocate bonepose stuff
2784 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2787 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2788 Host_Error("%s: missing required chunks", loadmodel->name);
2790 loadmodel->numframes = 0;
2791 for (index = 0;index < numanims;index++)
2792 loadmodel->numframes += anims[index].numframes;
2794 if (numanimkeys != numbones * loadmodel->numframes)
2795 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2797 meshvertices = numvtxw;
2798 meshtriangles = numfaces;
2800 // load external .skin files if present
2801 skinfiles = Mod_LoadSkinFiles();
2802 if (loadmodel->numskins < 1)
2803 loadmodel->numskins = 1;
2804 loadmodel->num_bones = numbones;
2805 loadmodel->num_poses = loadmodel->numframes;
2806 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2807 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2808 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2809 loadmodel->surfmesh.num_vertices = meshvertices;
2810 loadmodel->surfmesh.num_triangles = meshtriangles;
2811 // do most allocations as one merged chunk
2812 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);
2813 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2814 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2815 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2816 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2817 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2818 if (r_enableshadowvolumes.integer)
2819 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2820 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2821 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2822 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2823 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2824 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2825 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2826 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2827 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2828 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2829 loadmodel->surfmesh.num_blends = 0;
2830 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2831 if (loadmodel->surfmesh.num_vertices <= 65536)
2832 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2833 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2834 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(blendweights_t));
2836 for (i = 0;i < loadmodel->numskins;i++)
2838 loadmodel->skinscenes[i].firstframe = i;
2839 loadmodel->skinscenes[i].framecount = 1;
2840 loadmodel->skinscenes[i].loop = true;
2841 loadmodel->skinscenes[i].framerate = 10;
2845 for (index = 0, i = 0;index < nummatts;index++)
2847 // since psk models do not have named sections, reuse their shader name as the section name
2848 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2849 loadmodel->sortedmodelsurfaces[index] = index;
2850 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2851 loadmodel->data_surfaces[index].num_firstvertex = 0;
2852 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2855 // copy over the vertex locations and texcoords
2856 for (index = 0;index < numvtxw;index++)
2858 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2859 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2860 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2861 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2862 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2865 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2866 for (index = 0;index < numfaces;index++)
2867 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2868 for (index = 0, i = 0;index < nummatts;index++)
2870 loadmodel->data_surfaces[index].num_firsttriangle = i;
2871 i += loadmodel->data_surfaces[index].num_triangles;
2872 loadmodel->data_surfaces[index].num_triangles = 0;
2874 for (index = 0;index < numfaces;index++)
2876 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2877 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2878 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2879 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2882 // copy over the bones
2883 for (index = 0;index < numbones;index++)
2885 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2886 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2887 if (loadmodel->data_bones[index].parent >= index)
2888 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2891 // sort the psk point weights into the vertex weight tables
2892 // (which only accept up to 4 bones per vertex)
2893 for (index = 0;index < numvtxw;index++)
2895 int weightindex[4] = { 0, 0, 0, 0 };
2896 float weightinfluence[4] = { 0, 0, 0, 0 };
2898 for (j = 0;j < numrawweights;j++)
2900 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2902 int boneindex = rawweights[j].boneindex;
2903 float influence = rawweights[j].weight;
2904 for (l = 0;l < 4;l++)
2906 if (weightinfluence[l] < influence)
2908 // move lower influence weights out of the way first
2910 for (l2 = 3;l2 > l;l2--)
2912 weightinfluence[l2] = weightinfluence[l2-1];
2913 weightindex[l2] = weightindex[l2-1];
2915 // store the new weight
2916 weightinfluence[l] = influence;
2917 weightindex[l] = boneindex;
2923 loadmodel->surfmesh.blends[index] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
2925 if (loadmodel->surfmesh.num_blends < loadmodel->surfmesh.num_vertices)
2926 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2928 // set up the animscenes based on the anims
2929 for (index = 0, i = 0;index < numanims;index++)
2931 for (j = 0;j < anims[index].numframes;j++, i++)
2933 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2934 loadmodel->animscenes[i].firstframe = i;
2935 loadmodel->animscenes[i].framecount = 1;
2936 loadmodel->animscenes[i].loop = true;
2937 loadmodel->animscenes[i].framerate = anims[index].fps;
2941 // calculate the scaling value for bone origins so they can be compressed to short
2943 for (index = 0;index < numanimkeys;index++)
2945 pskanimkeys_t *k = animkeys + index;
2946 biggestorigin = max(biggestorigin, fabs(k->origin[0]));
2947 biggestorigin = max(biggestorigin, fabs(k->origin[1]));
2948 biggestorigin = max(biggestorigin, fabs(k->origin[2]));
2950 loadmodel->num_posescale = biggestorigin / 32767.0f;
2951 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2953 // load the poses from the animkeys
2954 for (index = 0;index < numanimkeys;index++)
2956 pskanimkeys_t *k = animkeys + index;
2958 Vector4Copy(k->quat, quat);
2960 Vector4Negate(quat, quat);
2961 Vector4Normalize2(quat, quat);
2962 // compress poses to the short[6] format for longterm storage
2963 loadmodel->data_poses6s[index*6+0] = k->origin[0] * loadmodel->num_poseinvscale;
2964 loadmodel->data_poses6s[index*6+1] = k->origin[1] * loadmodel->num_poseinvscale;
2965 loadmodel->data_poses6s[index*6+2] = k->origin[2] * loadmodel->num_poseinvscale;
2966 loadmodel->data_poses6s[index*6+3] = quat[0] * 32767.0f;
2967 loadmodel->data_poses6s[index*6+4] = quat[1] * 32767.0f;
2968 loadmodel->data_poses6s[index*6+5] = quat[2] * 32767.0f;
2970 Mod_FreeSkinFiles(skinfiles);
2971 Mem_Free(animfilebuffer);
2972 Mod_MakeSortedSurfaces(loadmodel);
2974 // compute all the mesh information that was not loaded from the file
2975 // TODO: honor smoothing groups somehow?
2976 if (loadmodel->surfmesh.data_element3s)
2977 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2978 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2979 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2980 Mod_BuildBaseBonePoses();
2981 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);
2982 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);
2983 if (loadmodel->surfmesh.data_neighbor3i)
2984 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2985 Mod_Alias_CalculateBoundingBox();
2987 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2989 if (!loadmodel->surfmesh.isanimated)
2991 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2992 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2993 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2994 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2995 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2996 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
3000 void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
3002 unsigned char *data;
3004 unsigned char *pbase, *pend;
3005 iqmheader_t *header;
3006 skinfile_t *skinfiles;
3007 int i, j, k, meshvertices, meshtriangles;
3008 float *vposition = NULL, *vtexcoord = NULL, *vnormal = NULL, *vtangent = NULL;
3009 unsigned char *vblendindexes = NULL, *vblendweights = NULL;
3014 iqmbounds_t *bounds;
3015 iqmvertexarray_t *va;
3016 unsigned short *framedata;
3017 float biggestorigin;
3018 const int *inelements;
3020 float *outvertex, *outnormal, *outtexcoord, *outsvector, *outtvector;
3022 pbase = (unsigned char *)buffer;
3023 pend = (unsigned char *)bufferend;
3024 header = (iqmheader_t *)buffer;
3025 if (memcmp(header->id, "INTERQUAKEMODEL", 16))
3026 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model", loadmodel->name);
3027 if (LittleLong(header->version) != 1)
3028 Host_Error ("Mod_INTERQUAKEMODEL_Load: only version 1 models are currently supported (name = %s)", loadmodel->name);
3030 loadmodel->modeldatatypestring = "IQM";
3032 loadmodel->type = mod_alias;
3033 loadmodel->synctype = ST_RAND;
3036 header->version = LittleLong(header->version);
3037 header->filesize = LittleLong(header->filesize);
3038 header->flags = LittleLong(header->flags);
3039 header->num_text = LittleLong(header->num_text);
3040 header->ofs_text = LittleLong(header->ofs_text);
3041 header->num_meshes = LittleLong(header->num_meshes);
3042 header->ofs_meshes = LittleLong(header->ofs_meshes);
3043 header->num_vertexarrays = LittleLong(header->num_vertexarrays);
3044 header->num_vertexes = LittleLong(header->num_vertexes);
3045 header->ofs_vertexarrays = LittleLong(header->ofs_vertexarrays);
3046 header->num_triangles = LittleLong(header->num_triangles);
3047 header->ofs_triangles = LittleLong(header->ofs_triangles);
3048 header->ofs_neighbors = LittleLong(header->ofs_neighbors);
3049 header->num_joints = LittleLong(header->num_joints);
3050 header->ofs_joints = LittleLong(header->ofs_joints);
3051 header->num_poses = LittleLong(header->num_poses);
3052 header->ofs_poses = LittleLong(header->ofs_poses);
3053 header->num_anims = LittleLong(header->num_anims);
3054 header->ofs_anims = LittleLong(header->ofs_anims);
3055 header->num_frames = LittleLong(header->num_frames);
3056 header->num_framechannels = LittleLong(header->num_framechannels);
3057 header->ofs_frames = LittleLong(header->ofs_frames);
3058 header->ofs_bounds = LittleLong(header->ofs_bounds);
3059 header->num_comment = LittleLong(header->num_comment);
3060 header->ofs_comment = LittleLong(header->ofs_comment);
3061 header->num_extensions = LittleLong(header->num_extensions);
3062 header->ofs_extensions = LittleLong(header->ofs_extensions);
3064 if (header->num_triangles < 1 || header->num_vertexes < 3 || header->num_vertexarrays < 1 || header->num_meshes < 1)
3066 Con_Printf("%s has no geometry\n", loadmodel->name);
3069 if (header->num_frames < 1 || header->num_anims < 1)
3071 Con_Printf("%s has no animations\n", loadmodel->name);
3075 if (pbase + header->ofs_text + header->num_text > pend ||
3076 pbase + header->ofs_meshes + header->num_meshes*sizeof(iqmmesh_t) > pend ||
3077 pbase + header->ofs_vertexarrays + header->num_vertexarrays*sizeof(iqmvertexarray_t) > pend ||
3078 pbase + header->ofs_triangles + header->num_triangles*sizeof(int[3]) > pend ||
3079 (header->ofs_neighbors && pbase + header->ofs_neighbors + header->num_triangles*sizeof(int[3]) > pend) ||
3080 pbase + header->ofs_joints + header->num_joints*sizeof(iqmjoint_t) > pend ||
3081 pbase + header->ofs_poses + header->num_poses*sizeof(iqmpose_t) > pend ||
3082 pbase + header->ofs_anims + header->num_anims*sizeof(iqmanim_t) > pend ||
3083 pbase + header->ofs_frames + header->num_frames*header->num_framechannels*sizeof(unsigned short) > pend ||
3084 (header->ofs_bounds && pbase + header->ofs_bounds + header->num_frames*sizeof(iqmbounds_t) > pend) ||
3085 pbase + header->ofs_comment + header->num_comment > pend)
3087 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3091 va = (iqmvertexarray_t *)(pbase + header->ofs_vertexarrays);
3092 for (i = 0;i < (int)header->num_vertexarrays;i++)
3095 va[i].type = LittleLong(va[i].type);
3096 va[i].flags = LittleLong(va[i].flags);
3097 va[i].format = LittleLong(va[i].format);
3098 va[i].size = LittleLong(va[i].size);
3099 va[i].offset = LittleLong(va[i].offset);
3100 vsize = header->num_vertexes*va[i].size;
3101 switch (va[i].format)
3103 case IQM_FLOAT: vsize *= sizeof(float); break;
3104 case IQM_UBYTE: vsize *= sizeof(unsigned char); break;
3107 if (pbase + va[i].offset + vsize > pend)
3112 if (va[i].format == IQM_FLOAT && va[i].size == 3)
3113 vposition = (float *)(pbase + va[i].offset);
3116 if (va[i].format == IQM_FLOAT && va[i].size == 2)
3117 vtexcoord = (float *)(pbase + va[i].offset);
3120 if (va[i].format == IQM_FLOAT && va[i].size == 3)
3121 vnormal = (float *)(pbase + va[i].offset);
3124 if (va[i].format == IQM_FLOAT && va[i].size == 4)
3125 vtangent = (float *)(pbase + va[i].offset);
3127 case IQM_BLENDINDEXES:
3128 if (va[i].format == IQM_UBYTE && va[i].size == 4)
3129 vblendindexes = (unsigned char *)(pbase + va[i].offset);
3131 case IQM_BLENDWEIGHTS:
3132 if (va[i].format == IQM_UBYTE && va[i].size == 4)
3133 vblendweights = (unsigned char *)(pbase + va[i].offset);
3137 if (!vposition || !vtexcoord || !vblendindexes || !vblendweights)
3139 Con_Printf("%s is missing vertex array data\n", loadmodel->name);
3143 text = header->num_text && header->ofs_text ? (const char *)(pbase + header->ofs_text) : "";
3145 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
3146 loadmodel->DrawSky = NULL;
3147 loadmodel->DrawAddWaterPlanes = NULL;
3148 loadmodel->Draw = R_Q1BSP_Draw;
3149 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
3150 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
3151 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
3152 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
3153 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
3154 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
3155 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
3156 loadmodel->DrawLight = R_Q1BSP_DrawLight;
3157 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
3158 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
3159 loadmodel->PointSuperContents = NULL;
3161 // load external .skin files if present
3162 skinfiles = Mod_LoadSkinFiles();
3163 if (loadmodel->numskins < 1)
3164 loadmodel->numskins = 1;
3166 loadmodel->numframes = header->num_anims;
3167 loadmodel->num_bones = header->num_joints;
3168 loadmodel->num_poses = header->num_frames;
3169 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = header->num_meshes;
3170 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3171 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3173 meshvertices = header->num_vertexes;
3174 meshtriangles = header->num_triangles;
3176 // do most allocations as one merged chunk
3177 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));
3178 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
3179 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
3180 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
3181 loadmodel->surfmesh.num_vertices = meshvertices;
3182 loadmodel->surfmesh.num_triangles = meshtriangles;
3183 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3184 if (r_enableshadowvolumes.integer)
3185 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3186 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
3187 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3188 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3189 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
3190 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
3191 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
3192 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
3193 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
3194 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
3195 loadmodel->surfmesh.num_blends = 0;
3196 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
3197 if (meshvertices <= 65536)
3198 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
3199 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
3200 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
3202 for (i = 0;i < loadmodel->numskins;i++)
3204 loadmodel->skinscenes[i].firstframe = i;
3205 loadmodel->skinscenes[i].framecount = 1;
3206 loadmodel->skinscenes[i].loop = true;
3207 loadmodel->skinscenes[i].framerate = 10;
3210 // load the bone info
3211 joint = (iqmjoint_t *) (pbase + header->ofs_joints);
3212 for (i = 0;i < loadmodel->num_bones;i++)
3214 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3215 joint[i].name = LittleLong(joint[i].name);
3216 joint[i].parent = LittleLong(joint[i].parent);
3217 for (j = 0;j < 3;j++)
3219 joint[i].origin[j] = LittleFloat(joint[i].origin[j]);
3220 joint[i].rotation[j] = LittleFloat(joint[i].rotation[j]);
3221 joint[i].scale[j] = LittleFloat(joint[i].scale[j]);
3223 strlcpy(loadmodel->data_bones[i].name, &text[joint[i].name], sizeof(loadmodel->data_bones[i].name));
3224 loadmodel->data_bones[i].parent = joint[i].parent;
3225 if (loadmodel->data_bones[i].parent >= i)
3226 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3227 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]);
3228 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3229 if (loadmodel->data_bones[i].parent >= 0)
3231 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3232 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3233 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3235 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3238 // set up the animscenes based on the anims
3239 anim = (iqmanim_t *) (pbase + header->ofs_anims);
3240 for (i = 0;i < (int)header->num_anims;i++)
3242 anim[i].name = LittleLong(anim[i].name);
3243 anim[i].first_frame = LittleLong(anim[i].first_frame);
3244 anim[i].num_frames = LittleLong(anim[i].num_frames);
3245 anim[i].framerate = LittleFloat(anim[i].framerate);
3246 anim[i].flags = LittleLong(anim[i].flags);
3247 strlcpy(loadmodel->animscenes[i].name, &text[anim[i].name], sizeof(loadmodel->animscenes[i].name));
3248 loadmodel->animscenes[i].firstframe = anim[i].first_frame;
3249 loadmodel->animscenes[i].framecount = anim[i].num_frames;
3250 loadmodel->animscenes[i].loop = ((anim[i].flags & IQM_LOOP) != 0);
3251 loadmodel->animscenes[i].framerate = anim[i].framerate;
3254 pose = (iqmpose_t *) (pbase + header->ofs_poses);
3256 for (i = 0;i < (int)header->num_poses;i++)
3259 pose[i].parent = LittleLong(pose[i].parent);
3260 pose[i].channelmask = LittleLong(pose[i].channelmask);
3261 pose[i].channeloffset[0] = LittleFloat(pose[i].channeloffset[0]);
3262 pose[i].channeloffset[1] = LittleFloat(pose[i].channeloffset[1]);
3263 pose[i].channeloffset[2] = LittleFloat(pose[i].channeloffset[2]);
3264 pose[i].channeloffset[3] = LittleFloat(pose[i].channeloffset[3]);
3265 pose[i].channeloffset[4] = LittleFloat(pose[i].channeloffset[4]);
3266 pose[i].channeloffset[5] = LittleFloat(pose[i].channeloffset[5]);
3267 pose[i].channeloffset[6] = LittleFloat(pose[i].channeloffset[6]);
3268 pose[i].channeloffset[7] = LittleFloat(pose[i].channeloffset[7]);
3269 pose[i].channeloffset[8] = LittleFloat(pose[i].channeloffset[8]);
3270 pose[i].channelscale[0] = LittleFloat(pose[i].channelscale[0]);
3271 pose[i].channelscale[1] = LittleFloat(pose[i].channelscale[1]);
3272 pose[i].channelscale[2] = LittleFloat(pose[i].channelscale[2]);
3273 pose[i].channelscale[3] = LittleFloat(pose[i].channelscale[3]);
3274 pose[i].channelscale[4] = LittleFloat(pose[i].channelscale[4]);
3275 pose[i].channelscale[5] = LittleFloat(pose[i].channelscale[5]);
3276 pose[i].channelscale[6] = LittleFloat(pose[i].channelscale[6]);
3277 pose[i].channelscale[7] = LittleFloat(pose[i].channelscale[7]);
3278 pose[i].channelscale[8] = LittleFloat(pose[i].channelscale[8]);
3279 f = fabs(pose[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3280 f = fabs(pose[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3281 f = fabs(pose[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3282 f = fabs(pose[i].channeloffset[0] + 0xFFFF*pose[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3283 f = fabs(pose[i].channeloffset[1] + 0xFFFF*pose[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3284 f = fabs(pose[i].channeloffset[2] + 0xFFFF*pose[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3286 loadmodel->num_posescale = biggestorigin / 32767.0f;
3287 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3289 // load the pose data
3290 framedata = (unsigned short *) (pbase + header->ofs_frames);
3291 for (i = 0, k = 0;i < (int)header->num_frames;i++)
3293 for (j = 0;j < (int)header->num_poses;j++, k++)
3295 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));
3296 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));
3297 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));
3298 loadmodel->data_poses6s[k*6 + 3] = 32767.0f * (pose[j].channeloffset[3] + (pose[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[3] : 0));
3299 loadmodel->data_poses6s[k*6 + 4] = 32767.0f * (pose[j].channeloffset[4] + (pose[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[4] : 0));
3300 loadmodel->data_poses6s[k*6 + 5] = 32767.0f * (pose[j].channeloffset[5] + (pose[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[5] : 0));
3301 // skip scale data for now
3302 if(pose[j].channelmask&64) framedata++;
3303 if(pose[j].channelmask&128) framedata++;
3304 if(pose[j].channelmask&256) framedata++;
3308 // load bounding box data
3309 if (header->ofs_bounds)
3311 float xyradius = 0, radius = 0;
3312 bounds = (iqmbounds_t *) (pbase + header->ofs_bounds);
3313 VectorClear(loadmodel->normalmins);
3314 VectorClear(loadmodel->normalmaxs);
3315 for (i = 0; i < (int)header->num_frames;i++)
3317 bounds[i].mins[0] = LittleFloat(bounds[i].mins[0]);
3318 bounds[i].mins[1] = LittleFloat(bounds[i].mins[1]);
3319 bounds[i].mins[2] = LittleFloat(bounds[i].mins[2]);
3320 bounds[i].maxs[0] = LittleFloat(bounds[i].maxs[0]);
3321 bounds[i].maxs[1] = LittleFloat(bounds[i].maxs[1]);
3322 bounds[i].maxs[2] = LittleFloat(bounds[i].maxs[2]);
3323 bounds[i].xyradius = LittleFloat(bounds[i].xyradius);
3324 bounds[i].radius = LittleFloat(bounds[i].radius);
3327 VectorCopy(bounds[i].mins, loadmodel->normalmins);
3328 VectorCopy(bounds[i].maxs, loadmodel->normalmaxs);
3332 if (loadmodel->normalmins[0] > bounds[i].mins[0]) loadmodel->normalmins[0] = bounds[i].mins[0];
3333 if (loadmodel->normalmins[1] > bounds[i].mins[1]) loadmodel->normalmins[1] = bounds[i].mins[1];
3334 if (loadmodel->normalmins[2] > bounds[i].mins[2]) loadmodel->normalmins[2] = bounds[i].mins[2];
3335 if (loadmodel->normalmaxs[0] < bounds[i].maxs[0]) loadmodel->normalmaxs[0] = bounds[i].maxs[0];
3336 if (loadmodel->normalmaxs[1] < bounds[i].maxs[1]) loadmodel->normalmaxs[1] = bounds[i].maxs[1];
3337 if (loadmodel->normalmaxs[2] < bounds[i].maxs[2]) loadmodel->normalmaxs[2] = bounds[i].maxs[2];
3339 if (bounds[i].xyradius > xyradius)
3340 xyradius = bounds[i].xyradius;
3341 if (bounds[i].radius > radius)
3342 radius = bounds[i].radius;
3344 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -xyradius;
3345 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = xyradius;
3346 loadmodel->yawmins[2] = loadmodel->normalmins[2];
3347 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
3348 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
3349 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
3350 loadmodel->radius = radius;
3351 loadmodel->radius2 = radius * radius;
3354 // load triangle data
3355 inelements = (const int *) (pbase + header->ofs_triangles);
3356 outelements = loadmodel->surfmesh.data_element3i;
3357 for (i = 0;i < (int)header->num_triangles;i++)
3359 outelements[0] = LittleLong(inelements[0]);
3360 outelements[1] = LittleLong(inelements[1]);
3361 outelements[2] = LittleLong(inelements[2]);
3365 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, header->num_vertexes, __FILE__, __LINE__);
3367 if (header->ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
3369 inelements = (const int *) (pbase + header->ofs_neighbors);
3370 outelements = loadmodel->surfmesh.data_neighbor3i;
3371 for (i = 0;i < (int)header->num_triangles;i++)
3373 outelements[0] = LittleLong(inelements[0]);
3374 outelements[1] = LittleLong(inelements[1]);
3375 outelements[2] = LittleLong(inelements[2]);
3382 outvertex = loadmodel->surfmesh.data_vertex3f;
3383 for (i = 0;i < (int)header->num_vertexes;i++)
3385 outvertex[0] = LittleFloat(vposition[0]);
3386 outvertex[1] = LittleFloat(vposition[1]);
3387 outvertex[2] = LittleFloat(vposition[2]);
3392 outtexcoord = loadmodel->surfmesh.data_texcoordtexture2f;
3393 for (i = 0;i < (int)header->num_vertexes;i++)
3395 outtexcoord[0] = LittleFloat(vtexcoord[0]);
3396 outtexcoord[1] = LittleFloat(vtexcoord[1]);
3403 outnormal = loadmodel->surfmesh.data_normal3f;
3404 for (i = 0;i < (int)header->num_vertexes;i++)
3406 outnormal[0] = LittleFloat(vnormal[0]);
3407 outnormal[1] = LittleFloat(vnormal[1]);
3408 outnormal[2] = LittleFloat(vnormal[2]);
3414 if(vnormal && vtangent)
3416 outnormal = loadmodel->surfmesh.data_normal3f;
3417 outsvector = loadmodel->surfmesh.data_svector3f;
3418 outtvector = loadmodel->surfmesh.data_tvector3f;
3419 for (i = 0;i < (int)header->num_vertexes;i++)
3421 outsvector[0] = LittleFloat(vtangent[0]);
3422 outsvector[1] = LittleFloat(vtangent[1]);
3423 outsvector[2] = LittleFloat(vtangent[2]);
3424 if(LittleFloat(vtangent[3]) < 0)
3425 CrossProduct(outsvector, outnormal, outtvector);
3427 CrossProduct(outnormal, outsvector, outtvector);
3435 for (i = 0; i < (int)header->num_vertexes;i++)
3437 blendweights_t weights;
3438 memcpy(weights.index, vblendindexes + i*4, 4);
3439 memcpy(weights.influence, vblendweights + i*4, 4);
3440 loadmodel->surfmesh.blends[i] = Mod_Skeletal_AddBlend(loadmodel, &weights);
3444 mesh = (iqmmesh_t *) (pbase + header->ofs_meshes);
3445 for (i = 0;i < (int)header->num_meshes;i++)
3447 msurface_t *surface;
3449 mesh[i].name = LittleLong(mesh[i].name);
3450 mesh[i].material = LittleLong(mesh[i].material);
3451 mesh[i].first_vertex = LittleLong(mesh[i].first_vertex);
3452 mesh[i].num_vertexes = LittleLong(mesh[i].num_vertexes);
3453 mesh[i].first_triangle = LittleLong(mesh[i].first_triangle);
3454 mesh[i].num_triangles = LittleLong(mesh[i].num_triangles);
3456 loadmodel->sortedmodelsurfaces[i] = i;
3457 surface = loadmodel->data_surfaces + i;
3458 surface->texture = loadmodel->data_textures + i;
3459 surface->num_firsttriangle = mesh[i].first_triangle;
3460 surface->num_triangles = mesh[i].num_triangles;
3461 surface->num_firstvertex = mesh[i].first_vertex;
3462 surface->num_vertices = mesh[i].num_vertexes;
3464 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, &text[mesh[i].name], &text[mesh[i].material]);
3467 Mod_FreeSkinFiles(skinfiles);
3468 Mod_MakeSortedSurfaces(loadmodel);
3470 // compute all the mesh information that was not loaded from the file
3471 if (loadmodel->surfmesh.data_element3s)
3472 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3473 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3475 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);
3476 if (!vnormal || !vtangent)
3477 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);
3478 if (!header->ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
3479 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3480 if (!header->ofs_bounds)
3481 Mod_Alias_CalculateBoundingBox();
3483 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
3485 if (!loadmodel->surfmesh.isanimated)
3487 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3488 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3489 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3490 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3491 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3492 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;