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 equivilant 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;
856 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
857 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
859 memset(skin, 0, sizeof(*skin));
861 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
863 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
864 if (!strcmp(skinfileitem->name, meshname))
866 Image_StripImageExtension(skinfileitem->replacement, stripbuf, sizeof(stripbuf));
867 Mod_LoadTextureFromQ3Shader(skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
873 // don't render unmentioned meshes
874 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
875 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
881 Image_StripImageExtension(shadername, stripbuf, sizeof(stripbuf));
882 Mod_LoadTextureFromQ3Shader(skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
886 #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);
887 #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);
888 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
890 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
891 float scales, scalet, interval;
895 stvert_t *pinstverts;
896 dtriangle_t *pintriangles;
897 daliasskintype_t *pinskintype;
898 daliasskingroup_t *pinskingroup;
899 daliasskininterval_t *pinskinintervals;
900 daliasframetype_t *pinframetype;
901 daliasgroup_t *pinframegroup;
902 unsigned char *datapointer, *startframes, *startskins;
903 char name[MAX_QPATH];
904 skinframe_t *tempskinframe;
905 animscene_t *tempskinscenes;
906 texture_t *tempaliasskins;
908 int *vertonseam, *vertremap;
909 skinfile_t *skinfiles;
911 datapointer = (unsigned char *)buffer;
912 pinmodel = (mdl_t *)datapointer;
913 datapointer += sizeof(mdl_t);
915 version = LittleLong (pinmodel->version);
916 if (version != ALIAS_VERSION)
917 Host_Error ("%s has wrong version number (%i should be %i)",
918 loadmodel->name, version, ALIAS_VERSION);
920 loadmodel->modeldatatypestring = "MDL";
922 loadmodel->type = mod_alias;
923 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
924 loadmodel->DrawSky = NULL;
925 loadmodel->DrawAddWaterPlanes = NULL;
926 loadmodel->Draw = R_Q1BSP_Draw;
927 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
928 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
929 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
930 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
931 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
932 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
933 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
934 loadmodel->DrawLight = R_Q1BSP_DrawLight;
935 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
936 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
937 // FIXME add TraceBrush!
938 loadmodel->PointSuperContents = NULL;
940 loadmodel->num_surfaces = 1;
941 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
942 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
943 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
944 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
945 loadmodel->sortedmodelsurfaces[0] = 0;
947 loadmodel->numskins = LittleLong(pinmodel->numskins);
948 BOUNDI(loadmodel->numskins,0,65536);
949 skinwidth = LittleLong (pinmodel->skinwidth);
950 BOUNDI(skinwidth,0,65536);
951 skinheight = LittleLong (pinmodel->skinheight);
952 BOUNDI(skinheight,0,65536);
953 numverts = LittleLong(pinmodel->numverts);
954 BOUNDI(numverts,0,65536);
955 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
956 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
957 loadmodel->numframes = LittleLong(pinmodel->numframes);
958 BOUNDI(loadmodel->numframes,0,65536);
959 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
960 BOUNDI((int)loadmodel->synctype,0,2);
961 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
962 i = LittleLong (pinmodel->flags);
963 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
965 for (i = 0;i < 3;i++)
967 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
968 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
971 startskins = datapointer;
973 for (i = 0;i < loadmodel->numskins;i++)
975 pinskintype = (daliasskintype_t *)datapointer;
976 datapointer += sizeof(daliasskintype_t);
977 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
981 pinskingroup = (daliasskingroup_t *)datapointer;
982 datapointer += sizeof(daliasskingroup_t);
983 groupskins = LittleLong(pinskingroup->numskins);
984 datapointer += sizeof(daliasskininterval_t) * groupskins;
987 for (j = 0;j < groupskins;j++)
989 datapointer += skinwidth * skinheight;
994 pinstverts = (stvert_t *)datapointer;
995 datapointer += sizeof(stvert_t) * numverts;
997 pintriangles = (dtriangle_t *)datapointer;
998 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
1000 startframes = datapointer;
1001 loadmodel->surfmesh.num_morphframes = 0;
1002 for (i = 0;i < loadmodel->numframes;i++)
1004 pinframetype = (daliasframetype_t *)datapointer;
1005 datapointer += sizeof(daliasframetype_t);
1006 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
1010 pinframegroup = (daliasgroup_t *)datapointer;
1011 datapointer += sizeof(daliasgroup_t);
1012 groupframes = LittleLong(pinframegroup->numframes);
1013 datapointer += sizeof(daliasinterval_t) * groupframes;
1016 for (j = 0;j < groupframes;j++)
1018 datapointer += sizeof(daliasframe_t);
1019 datapointer += sizeof(trivertx_t) * numverts;
1020 loadmodel->surfmesh.num_morphframes++;
1023 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1025 // store texture coordinates into temporary array, they will be stored
1026 // after usage is determined (triangle data)
1027 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
1028 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
1029 vertonseam = vertremap + numverts * 2;
1031 scales = 1.0 / skinwidth;
1032 scalet = 1.0 / skinheight;
1033 for (i = 0;i < numverts;i++)
1035 vertonseam[i] = LittleLong(pinstverts[i].onseam);
1036 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
1037 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
1038 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
1039 vertst[(i+numverts)*2+1] = vertst[i*2+1];
1042 // load triangle data
1043 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1045 // read the triangle elements
1046 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1047 for (j = 0;j < 3;j++)
1048 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1049 // validate (note numverts is used because this is the original data)
1050 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1051 // now butcher the elements according to vertonseam and tri->facesfront
1052 // and then compact the vertex set to remove duplicates
1053 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1054 if (!LittleLong(pintriangles[i].facesfront)) // backface
1055 for (j = 0;j < 3;j++)
1056 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1057 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1059 // (this uses vertremap to count usage to save some memory)
1060 for (i = 0;i < numverts*2;i++)
1062 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1063 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1064 // build remapping table and compact array
1065 loadmodel->surfmesh.num_vertices = 0;
1066 for (i = 0;i < numverts*2;i++)
1070 vertremap[i] = loadmodel->surfmesh.num_vertices;
1071 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1072 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1073 loadmodel->surfmesh.num_vertices++;
1076 vertremap[i] = -1; // not used at all
1078 // remap the elements to the new vertex set
1079 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1080 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1081 // store the texture coordinates
1082 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1083 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1085 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1086 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1089 // generate ushort elements array if possible
1090 if (loadmodel->surfmesh.num_vertices <= 65536)
1091 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1092 if (loadmodel->surfmesh.data_element3s)
1093 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1094 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1097 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1098 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1099 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1100 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1101 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1102 Mod_Alias_CalculateBoundingBox();
1103 Mod_Alias_MorphMesh_CompileFrames();
1106 Mem_Free(vertremap);
1109 skinfiles = Mod_LoadSkinFiles();
1112 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1113 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1114 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1115 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1116 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1117 Mod_FreeSkinFiles(skinfiles);
1118 for (i = 0;i < loadmodel->numskins;i++)
1120 loadmodel->skinscenes[i].firstframe = i;
1121 loadmodel->skinscenes[i].framecount = 1;
1122 loadmodel->skinscenes[i].loop = true;
1123 loadmodel->skinscenes[i].framerate = 10;
1128 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1129 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1130 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1131 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1133 datapointer = startskins;
1134 for (i = 0;i < loadmodel->numskins;i++)
1136 pinskintype = (daliasskintype_t *)datapointer;
1137 datapointer += sizeof(daliasskintype_t);
1139 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1146 pinskingroup = (daliasskingroup_t *)datapointer;
1147 datapointer += sizeof(daliasskingroup_t);
1149 groupskins = LittleLong (pinskingroup->numskins);
1151 pinskinintervals = (daliasskininterval_t *)datapointer;
1152 datapointer += sizeof(daliasskininterval_t) * groupskins;
1154 interval = LittleFloat(pinskinintervals[0].interval);
1155 if (interval < 0.01f)
1157 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1162 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1163 loadmodel->skinscenes[i].firstframe = totalskins;
1164 loadmodel->skinscenes[i].framecount = groupskins;
1165 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1166 loadmodel->skinscenes[i].loop = true;
1168 for (j = 0;j < groupskins;j++)
1171 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1173 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1174 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))
1175 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));
1176 datapointer += skinwidth * skinheight;
1180 // check for skins that don't exist in the model, but do exist as external images
1181 // (this was added because yummyluv kept pestering me about support for it)
1182 // TODO: support shaders here?
1183 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)))
1185 // expand the arrays to make room
1186 tempskinscenes = loadmodel->skinscenes;
1187 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1188 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1189 Mem_Free(tempskinscenes);
1191 tempaliasskins = loadmodel->data_textures;
1192 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1193 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1194 Mem_Free(tempaliasskins);
1196 // store the info about the new skin
1197 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1198 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1199 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1200 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1201 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1202 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1204 //increase skin counts
1205 loadmodel->numskins++;
1208 // fix up the pointers since they are pointing at the old textures array
1209 // FIXME: this is a hack!
1210 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1211 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1215 surface = loadmodel->data_surfaces;
1216 surface->texture = loadmodel->data_textures;
1217 surface->num_firsttriangle = 0;
1218 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1219 surface->num_firstvertex = 0;
1220 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1222 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1224 if (!loadmodel->surfmesh.isanimated)
1226 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1227 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1228 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1229 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1230 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1231 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1235 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1237 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1238 float iskinwidth, iskinheight;
1239 unsigned char *data;
1240 msurface_t *surface;
1242 unsigned char *base, *datapointer;
1243 md2frame_t *pinframe;
1245 md2triangle_t *intri;
1246 unsigned short *inst;
1247 struct md2verthash_s
1249 struct md2verthash_s *next;
1253 *hash, **md2verthash, *md2verthashdata;
1254 skinfile_t *skinfiles;
1256 pinmodel = (md2_t *)buffer;
1257 base = (unsigned char *)buffer;
1259 version = LittleLong (pinmodel->version);
1260 if (version != MD2ALIAS_VERSION)
1261 Host_Error ("%s has wrong version number (%i should be %i)",
1262 loadmodel->name, version, MD2ALIAS_VERSION);
1264 loadmodel->modeldatatypestring = "MD2";
1266 loadmodel->type = mod_alias;
1267 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1268 loadmodel->DrawSky = NULL;
1269 loadmodel->DrawAddWaterPlanes = NULL;
1270 loadmodel->Draw = R_Q1BSP_Draw;
1271 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1272 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1273 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1274 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1275 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1276 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1277 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1278 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1279 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1280 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1281 loadmodel->PointSuperContents = NULL;
1283 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1284 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1285 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1286 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1287 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1288 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1289 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1290 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1292 end = LittleLong(pinmodel->ofs_end);
1293 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1294 Host_Error ("%s is not a valid model", loadmodel->name);
1295 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1296 Host_Error ("%s is not a valid model", loadmodel->name);
1297 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1298 Host_Error ("%s is not a valid model", loadmodel->name);
1299 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1300 Host_Error ("%s is not a valid model", loadmodel->name);
1301 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1302 Host_Error ("%s is not a valid model", loadmodel->name);
1304 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1305 numxyz = LittleLong(pinmodel->num_xyz);
1306 numst = LittleLong(pinmodel->num_st);
1307 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1308 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1309 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1310 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1311 skinwidth = LittleLong(pinmodel->skinwidth);
1312 skinheight = LittleLong(pinmodel->skinheight);
1313 iskinwidth = 1.0f / skinwidth;
1314 iskinheight = 1.0f / skinheight;
1316 loadmodel->num_surfaces = 1;
1317 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1318 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->numframes * sizeof(animscene_t) + loadmodel->numframes * sizeof(float[6]) + loadmodel->surfmesh.num_triangles * sizeof(int[3]) + loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1319 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1320 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1321 loadmodel->sortedmodelsurfaces[0] = 0;
1322 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1323 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1324 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1325 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1327 loadmodel->synctype = ST_RAND;
1330 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1331 skinfiles = Mod_LoadSkinFiles();
1334 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1335 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1336 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1337 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1338 Mod_FreeSkinFiles(skinfiles);
1340 else if (loadmodel->numskins)
1342 // skins found (most likely not a player model)
1343 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1344 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1345 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1346 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1347 Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
1351 // no skins (most likely a player model)
1352 loadmodel->numskins = 1;
1353 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1354 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1355 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1356 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1359 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1360 for (i = 0;i < loadmodel->numskins;i++)
1362 loadmodel->skinscenes[i].firstframe = i;
1363 loadmodel->skinscenes[i].framecount = 1;
1364 loadmodel->skinscenes[i].loop = true;
1365 loadmodel->skinscenes[i].framerate = 10;
1368 // load the triangles and stvert data
1369 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1370 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1371 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1372 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1373 // swap the triangle list
1374 loadmodel->surfmesh.num_vertices = 0;
1375 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1377 for (j = 0;j < 3;j++)
1379 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1380 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1383 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1388 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1391 hashindex = (xyz * 256 + st) & 65535;
1392 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1393 if (hash->xyz == xyz && hash->st == st)
1397 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1400 hash->next = md2verthash[hashindex];
1401 md2verthash[hashindex] = hash;
1403 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1407 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1408 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));
1409 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1410 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1411 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1414 hash = md2verthashdata + i;
1415 vertremap[i] = hash->xyz;
1416 sts = LittleShort(inst[hash->st*2+0]);
1417 stt = LittleShort(inst[hash->st*2+1]);
1418 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1420 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1424 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1425 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1428 Mem_Free(md2verthash);
1429 Mem_Free(md2verthashdata);
1431 // generate ushort elements array if possible
1432 if (loadmodel->surfmesh.num_vertices <= 65536)
1433 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1434 if (loadmodel->surfmesh.data_element3s)
1435 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1436 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1439 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1440 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1445 pinframe = (md2frame_t *)datapointer;
1446 datapointer += sizeof(md2frame_t);
1447 // store the frame scale/translate into the appropriate array
1448 for (j = 0;j < 3;j++)
1450 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1451 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1453 // convert the vertices
1454 v = (trivertx_t *)datapointer;
1455 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1456 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1457 out[k] = v[vertremap[k]];
1458 datapointer += numxyz * sizeof(trivertx_t);
1460 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1461 loadmodel->animscenes[i].firstframe = i;
1462 loadmodel->animscenes[i].framecount = 1;
1463 loadmodel->animscenes[i].framerate = 10;
1464 loadmodel->animscenes[i].loop = true;
1467 Mem_Free(vertremap);
1469 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1470 Mod_Alias_CalculateBoundingBox();
1471 Mod_Alias_MorphMesh_CompileFrames();
1473 surface = loadmodel->data_surfaces;
1474 surface->texture = loadmodel->data_textures;
1475 surface->num_firsttriangle = 0;
1476 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1477 surface->num_firstvertex = 0;
1478 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1480 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1482 if (!loadmodel->surfmesh.isanimated)
1484 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1485 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1486 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1487 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1488 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1489 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1493 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1495 int i, j, k, version, meshvertices, meshtriangles;
1496 unsigned char *data;
1497 msurface_t *surface;
1498 md3modelheader_t *pinmodel;
1499 md3frameinfo_t *pinframe;
1502 skinfile_t *skinfiles;
1504 pinmodel = (md3modelheader_t *)buffer;
1506 if (memcmp(pinmodel->identifier, "IDP3", 4))
1507 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1508 version = LittleLong (pinmodel->version);
1509 if (version != MD3VERSION)
1510 Host_Error ("%s has wrong version number (%i should be %i)",
1511 loadmodel->name, version, MD3VERSION);
1513 skinfiles = Mod_LoadSkinFiles();
1514 if (loadmodel->numskins < 1)
1515 loadmodel->numskins = 1;
1517 loadmodel->modeldatatypestring = "MD3";
1519 loadmodel->type = mod_alias;
1520 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1521 loadmodel->DrawSky = NULL;
1522 loadmodel->DrawAddWaterPlanes = NULL;
1523 loadmodel->Draw = R_Q1BSP_Draw;
1524 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1525 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1526 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1527 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1528 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1529 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1530 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1531 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1532 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1533 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1534 loadmodel->PointSuperContents = NULL;
1535 loadmodel->synctype = ST_RAND;
1536 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1537 i = LittleLong (pinmodel->flags);
1538 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1540 // set up some global info about the model
1541 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1542 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1544 // make skinscenes for the skins (no groups)
1545 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1546 for (i = 0;i < loadmodel->numskins;i++)
1548 loadmodel->skinscenes[i].firstframe = i;
1549 loadmodel->skinscenes[i].framecount = 1;
1550 loadmodel->skinscenes[i].loop = true;
1551 loadmodel->skinscenes[i].framerate = 10;
1555 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1556 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1558 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1559 loadmodel->animscenes[i].firstframe = i;
1560 loadmodel->animscenes[i].framecount = 1;
1561 loadmodel->animscenes[i].framerate = 10;
1562 loadmodel->animscenes[i].loop = true;
1566 loadmodel->num_tagframes = loadmodel->numframes;
1567 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1568 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1569 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1571 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1572 for (j = 0;j < 9;j++)
1573 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1574 for (j = 0;j < 3;j++)
1575 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1576 //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);
1582 for (i = 0, pinmesh = (md3mesh_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_meshes));i < loadmodel->num_surfaces;i++, pinmesh = (md3mesh_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_end)))
1584 if (memcmp(pinmesh->identifier, "IDP3", 4))
1585 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1586 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1587 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1588 meshvertices += LittleLong(pinmesh->num_vertices);
1589 meshtriangles += LittleLong(pinmesh->num_triangles);
1592 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1593 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1594 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1595 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshvertices * sizeof(float[2]) + meshvertices * loadmodel->numframes * sizeof(md3vertex_t));
1596 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1597 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1598 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1599 loadmodel->surfmesh.num_vertices = meshvertices;
1600 loadmodel->surfmesh.num_triangles = meshtriangles;
1601 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1602 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1603 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1604 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1605 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1606 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1607 if (meshvertices <= 65536)
1608 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1612 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)))
1614 if (memcmp(pinmesh->identifier, "IDP3", 4))
1615 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1616 loadmodel->sortedmodelsurfaces[i] = i;
1617 surface = loadmodel->data_surfaces + i;
1618 surface->texture = loadmodel->data_textures + i;
1619 surface->num_firsttriangle = meshtriangles;
1620 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1621 surface->num_firstvertex = meshvertices;
1622 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1623 meshvertices += surface->num_vertices;
1624 meshtriangles += surface->num_triangles;
1626 for (j = 0;j < surface->num_triangles * 3;j++)
1627 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1628 for (j = 0;j < surface->num_vertices;j++)
1630 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1631 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1633 for (j = 0;j < loadmodel->numframes;j++)
1635 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1636 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1637 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1639 out->origin[0] = LittleShort(in->origin[0]);
1640 out->origin[1] = LittleShort(in->origin[1]);
1641 out->origin[2] = LittleShort(in->origin[2]);
1642 out->pitch = in->pitch;
1647 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1649 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1651 if (loadmodel->surfmesh.data_element3s)
1652 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1653 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1654 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1655 Mod_Alias_MorphMesh_CompileFrames();
1656 Mod_Alias_CalculateBoundingBox();
1657 Mod_FreeSkinFiles(skinfiles);
1658 Mod_MakeSortedSurfaces(loadmodel);
1660 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1661 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1663 if (!loadmodel->surfmesh.isanimated)
1665 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1666 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1667 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1668 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1669 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1670 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1674 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1676 zymtype1header_t *pinmodel, *pheader;
1677 unsigned char *pbase;
1678 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1679 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose, f, biggestorigin, tempvec[3], modelscale;
1680 zymvertex_t *verts, *vertdata;
1684 skinfile_t *skinfiles;
1685 unsigned char *data;
1686 msurface_t *surface;
1688 pinmodel = (zymtype1header_t *)buffer;
1689 pbase = (unsigned char *)buffer;
1690 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1691 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1692 if (BigLong(pinmodel->type) != 1)
1693 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1695 loadmodel->modeldatatypestring = "ZYM";
1697 loadmodel->type = mod_alias;
1698 loadmodel->synctype = ST_RAND;
1702 pheader->type = BigLong(pinmodel->type);
1703 pheader->filesize = BigLong(pinmodel->filesize);
1704 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1705 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1706 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1707 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1708 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1709 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1710 pheader->radius = BigFloat(pinmodel->radius);
1711 pheader->numverts = BigLong(pinmodel->numverts);
1712 pheader->numtris = BigLong(pinmodel->numtris);
1713 pheader->numshaders = BigLong(pinmodel->numshaders);
1714 pheader->numbones = BigLong(pinmodel->numbones);
1715 pheader->numscenes = BigLong(pinmodel->numscenes);
1716 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1717 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1718 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1719 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1720 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1721 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1722 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1723 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1724 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1725 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1726 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1727 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1728 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1729 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1730 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1731 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1732 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1733 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1735 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1737 Con_Printf("%s has no geometry\n", loadmodel->name);
1740 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1742 Con_Printf("%s has no animations\n", loadmodel->name);
1746 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1747 loadmodel->DrawSky = NULL;
1748 loadmodel->DrawAddWaterPlanes = NULL;
1749 loadmodel->Draw = R_Q1BSP_Draw;
1750 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1751 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1752 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1753 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1754 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1755 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1756 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1757 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1758 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1759 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1760 loadmodel->PointSuperContents = NULL;
1762 loadmodel->numframes = pheader->numscenes;
1763 loadmodel->num_surfaces = pheader->numshaders;
1765 skinfiles = Mod_LoadSkinFiles();
1766 if (loadmodel->numskins < 1)
1767 loadmodel->numskins = 1;
1769 // make skinscenes for the skins (no groups)
1770 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1771 for (i = 0;i < loadmodel->numskins;i++)
1773 loadmodel->skinscenes[i].firstframe = i;
1774 loadmodel->skinscenes[i].framecount = 1;
1775 loadmodel->skinscenes[i].loop = true;
1776 loadmodel->skinscenes[i].framerate = 10;
1780 modelradius = pheader->radius;
1781 for (i = 0;i < 3;i++)
1783 loadmodel->normalmins[i] = pheader->mins[i];
1784 loadmodel->normalmaxs[i] = pheader->maxs[i];
1785 loadmodel->rotatedmins[i] = -modelradius;
1786 loadmodel->rotatedmaxs[i] = modelradius;
1788 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1789 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1790 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1791 if (loadmodel->yawmaxs[0] > modelradius)
1792 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1793 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1794 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1795 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1796 loadmodel->radius = modelradius;
1797 loadmodel->radius2 = modelradius * modelradius;
1799 // go through the lumps, swapping things
1801 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1802 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1803 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1804 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1805 for (i = 0;i < pheader->numscenes;i++)
1807 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1808 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1809 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1810 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1811 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1812 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1813 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1814 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1815 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1816 if (loadmodel->animscenes[i].framerate < 0)
1817 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1821 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1822 loadmodel->num_bones = pheader->numbones;
1823 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1824 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1825 for (i = 0;i < pheader->numbones;i++)
1827 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1828 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1829 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1830 if (loadmodel->data_bones[i].parent >= i)
1831 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1834 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1835 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1836 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1837 for (i = 0;i < pheader->numverts;i++)
1839 vertbonecounts[i] = BigLong(bonecount[i]);
1840 if (vertbonecounts[i] != 1)
1841 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1844 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1846 meshvertices = pheader->numverts;
1847 meshtriangles = pheader->numtris;
1849 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1850 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1851 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1852 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshvertices * sizeof(float[14]) + meshvertices * sizeof(unsigned short) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]) + loadmodel->num_bones * sizeof(float[12]));
1853 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1854 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1855 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1856 loadmodel->surfmesh.num_vertices = meshvertices;
1857 loadmodel->surfmesh.num_triangles = meshtriangles;
1858 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1859 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1860 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1861 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1862 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1863 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1864 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1865 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1866 loadmodel->surfmesh.num_blends = 0;
1867 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
1868 if (loadmodel->surfmesh.num_vertices <= 65536)
1869 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1870 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
1871 loadmodel->surfmesh.data_blendweights = NULL;
1873 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1874 poses = (float *) (pheader->lump_poses.start + pbase);
1875 // figure out scale of model from root bone, for compatibility with old zmodel versions
1876 tempvec[0] = BigFloat(poses[0]);
1877 tempvec[1] = BigFloat(poses[1]);
1878 tempvec[2] = BigFloat(poses[2]);
1879 modelscale = VectorLength(tempvec);
1881 for (i = 0;i < loadmodel->num_bones * numposes * 12;i++)
1883 f = fabs(BigFloat(poses[i]));
1884 biggestorigin = max(biggestorigin, f);
1886 loadmodel->num_posescale = biggestorigin / 32767.0f;
1887 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
1888 for (i = 0;i < numposes;i++)
1890 const float *frameposes = (float *) (pheader->lump_poses.start + pbase) + 12*i*loadmodel->num_bones;
1891 for (j = 0;j < loadmodel->num_bones;j++)
1894 matrix4x4_t posematrix;
1895 for (k = 0;k < 12;k++)
1896 pose[k] = BigFloat(frameposes[j*12+k]);
1897 //if (j < loadmodel->num_bones)
1898 // 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));
1899 // scale child bones to match the root scale
1900 if (loadmodel->data_bones[j].parent >= 0)
1902 pose[3] *= modelscale;
1903 pose[7] *= modelscale;
1904 pose[11] *= modelscale;
1906 // normalize rotation matrix
1907 VectorNormalize(pose + 0);
1908 VectorNormalize(pose + 4);
1909 VectorNormalize(pose + 8);
1910 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
1911 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
1915 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1916 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1917 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1918 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1919 // (converting from weight-blending skeletal animation to
1920 // deformation-based skeletal animation)
1921 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1922 for (i = 0;i < loadmodel->num_bones;i++)
1925 for (k = 0;k < 12;k++)
1926 m[k] = BigFloat(poses[i*12+k]);
1927 if (loadmodel->data_bones[i].parent >= 0)
1928 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1930 for (k = 0;k < 12;k++)
1931 bonepose[12*i+k] = m[k];
1933 for (j = 0;j < pheader->numverts;j++)
1935 // this format really should have had a per vertexweight weight value...
1936 // but since it does not, the weighting is completely ignored and
1937 // only one weight is allowed per vertex
1938 int boneindex = BigLong(vertdata[j].bonenum);
1939 const float *m = bonepose + 12 * boneindex;
1940 float relativeorigin[3];
1941 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1942 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1943 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1944 // transform the vertex bone weight into the base mesh
1945 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1946 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1947 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1948 // store the weight as the primary weight on this vertex
1949 loadmodel->surfmesh.blends[j] = boneindex;
1952 // normals and tangents are calculated after elements are loaded
1954 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1955 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1956 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1957 for (i = 0;i < pheader->numverts;i++)
1959 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1960 // flip T coordinate for OpenGL
1961 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1964 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1965 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1966 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1968 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1969 //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)
1970 // byteswap, validate, and swap winding order of tris
1971 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1972 if (pheader->lump_render.length != count)
1973 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1974 renderlist = (int *) (pheader->lump_render.start + pbase);
1975 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1977 for (i = 0;i < loadmodel->num_surfaces;i++)
1979 int firstvertex, lastvertex;
1980 if (renderlist >= renderlistend)
1981 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1982 count = BigLong(*renderlist);renderlist++;
1983 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1984 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1986 loadmodel->sortedmodelsurfaces[i] = i;
1987 surface = loadmodel->data_surfaces + i;
1988 surface->texture = loadmodel->data_textures + i;
1989 surface->num_firsttriangle = meshtriangles;
1990 surface->num_triangles = count;
1991 meshtriangles += surface->num_triangles;
1993 // load the elements
1994 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
1995 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
1997 outelements[j*3+2] = BigLong(renderlist[0]);
1998 outelements[j*3+1] = BigLong(renderlist[1]);
1999 outelements[j*3+0] = BigLong(renderlist[2]);
2001 // validate the elements and find the used vertex range
2002 firstvertex = meshvertices;
2004 for (j = 0;j < surface->num_triangles * 3;j++)
2006 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
2007 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
2008 firstvertex = min(firstvertex, outelements[j]);
2009 lastvertex = max(lastvertex, outelements[j]);
2011 surface->num_firstvertex = firstvertex;
2012 surface->num_vertices = lastvertex + 1 - firstvertex;
2014 // since zym models do not have named sections, reuse their shader
2015 // name as the section name
2016 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
2017 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
2019 Mod_FreeSkinFiles(skinfiles);
2020 Mem_Free(vertbonecounts);
2022 Mod_MakeSortedSurfaces(loadmodel);
2024 // compute all the mesh information that was not loaded from the file
2025 if (loadmodel->surfmesh.data_element3s)
2026 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2027 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2028 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2029 Mod_BuildBaseBonePoses();
2030 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2031 Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, true);
2032 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2034 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2036 if (!loadmodel->surfmesh.isanimated)
2038 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2039 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2040 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2041 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2042 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2043 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2047 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2049 dpmheader_t *pheader;
2053 unsigned char *pbase;
2054 int i, j, k, meshvertices, meshtriangles;
2055 skinfile_t *skinfiles;
2056 unsigned char *data;
2058 float biggestorigin, tempvec[3], modelscale;
2062 pheader = (dpmheader_t *)buffer;
2063 pbase = (unsigned char *)buffer;
2064 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2065 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2066 if (BigLong(pheader->type) != 2)
2067 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2069 loadmodel->modeldatatypestring = "DPM";
2071 loadmodel->type = mod_alias;
2072 loadmodel->synctype = ST_RAND;
2075 pheader->type = BigLong(pheader->type);
2076 pheader->filesize = BigLong(pheader->filesize);
2077 pheader->mins[0] = BigFloat(pheader->mins[0]);
2078 pheader->mins[1] = BigFloat(pheader->mins[1]);
2079 pheader->mins[2] = BigFloat(pheader->mins[2]);
2080 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2081 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2082 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2083 pheader->yawradius = BigFloat(pheader->yawradius);
2084 pheader->allradius = BigFloat(pheader->allradius);
2085 pheader->num_bones = BigLong(pheader->num_bones);
2086 pheader->num_meshs = BigLong(pheader->num_meshs);
2087 pheader->num_frames = BigLong(pheader->num_frames);
2088 pheader->ofs_bones = BigLong(pheader->ofs_bones);
2089 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2090 pheader->ofs_frames = BigLong(pheader->ofs_frames);
2092 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2094 Con_Printf("%s has no geometry\n", loadmodel->name);
2097 if (pheader->num_frames < 1)
2099 Con_Printf("%s has no frames\n", loadmodel->name);
2103 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2104 loadmodel->DrawSky = NULL;
2105 loadmodel->DrawAddWaterPlanes = NULL;
2106 loadmodel->Draw = R_Q1BSP_Draw;
2107 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2108 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2109 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2110 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2111 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2112 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2113 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2114 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2115 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2116 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2117 loadmodel->PointSuperContents = NULL;
2120 for (i = 0;i < 3;i++)
2122 loadmodel->normalmins[i] = pheader->mins[i];
2123 loadmodel->normalmaxs[i] = pheader->maxs[i];
2124 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2125 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2126 loadmodel->rotatedmins[i] = -pheader->allradius;
2127 loadmodel->rotatedmaxs[i] = pheader->allradius;
2129 loadmodel->radius = pheader->allradius;
2130 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2132 // load external .skin files if present
2133 skinfiles = Mod_LoadSkinFiles();
2134 if (loadmodel->numskins < 1)
2135 loadmodel->numskins = 1;
2140 // gather combined statistics from the meshes
2141 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2142 for (i = 0;i < (int)pheader->num_meshs;i++)
2144 int numverts = BigLong(dpmmesh->num_verts);
2145 meshvertices += numverts;
2146 meshtriangles += BigLong(dpmmesh->num_tris);
2150 loadmodel->numframes = pheader->num_frames;
2151 loadmodel->num_bones = pheader->num_bones;
2152 loadmodel->num_poses = loadmodel->numframes;
2153 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2154 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2155 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2156 // do most allocations as one merged chunk
2157 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshtriangles * sizeof(int[3]) + meshvertices * (sizeof(float[14]) + sizeof(unsigned short)) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
2158 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2159 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2160 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2161 loadmodel->surfmesh.num_vertices = meshvertices;
2162 loadmodel->surfmesh.num_triangles = meshtriangles;
2163 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2164 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2165 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2166 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2167 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2168 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2169 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2170 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2171 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2172 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2173 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2174 loadmodel->surfmesh.num_blends = 0;
2175 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2176 if (meshvertices <= 65536)
2177 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2178 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2179 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
2181 for (i = 0;i < loadmodel->numskins;i++)
2183 loadmodel->skinscenes[i].firstframe = i;
2184 loadmodel->skinscenes[i].framecount = 1;
2185 loadmodel->skinscenes[i].loop = true;
2186 loadmodel->skinscenes[i].framerate = 10;
2189 // load the bone info
2190 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2191 for (i = 0;i < loadmodel->num_bones;i++)
2193 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2194 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2195 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2196 if (loadmodel->data_bones[i].parent >= i)
2197 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2201 frames = (dpmframe_t *) (pbase + pheader->ofs_frames);
2202 // figure out scale of model from root bone, for compatibility with old dpmodel versions
2203 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2204 tempvec[0] = BigFloat(poses[0]);
2205 tempvec[1] = BigFloat(poses[1]);
2206 tempvec[2] = BigFloat(poses[2]);
2207 modelscale = VectorLength(tempvec);
2209 for (i = 0;i < loadmodel->numframes;i++)
2211 memcpy(loadmodel->animscenes[i].name, frames[i].name, sizeof(frames[i].name));
2212 loadmodel->animscenes[i].firstframe = i;
2213 loadmodel->animscenes[i].framecount = 1;
2214 loadmodel->animscenes[i].loop = true;
2215 loadmodel->animscenes[i].framerate = 10;
2216 // load the bone poses for this frame
2217 poses = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2218 for (j = 0;j < loadmodel->num_bones*12;j++)
2220 f = fabs(BigFloat(poses[j]));
2221 biggestorigin = max(biggestorigin, f);
2223 // stuff not processed here: mins, maxs, yawradius, allradius
2225 loadmodel->num_posescale = biggestorigin / 32767.0f;
2226 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2227 for (i = 0;i < loadmodel->numframes;i++)
2229 const float *frameposes = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2230 for (j = 0;j < loadmodel->num_bones;j++)
2233 matrix4x4_t posematrix;
2234 for (k = 0;k < 12;k++)
2235 pose[k] = BigFloat(frameposes[j*12+k]);
2236 // scale child bones to match the root scale
2237 if (loadmodel->data_bones[j].parent >= 0)
2239 pose[3] *= modelscale;
2240 pose[7] *= modelscale;
2241 pose[11] *= modelscale;
2243 // normalize rotation matrix
2244 VectorNormalize(pose + 0);
2245 VectorNormalize(pose + 4);
2246 VectorNormalize(pose + 8);
2247 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2248 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
2252 // load the meshes now
2253 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2256 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2257 // (converting from weight-blending skeletal animation to
2258 // deformation-based skeletal animation)
2259 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2260 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2261 for (i = 0;i < loadmodel->num_bones;i++)
2264 for (k = 0;k < 12;k++)
2265 m[k] = BigFloat(poses[i*12+k]);
2266 if (loadmodel->data_bones[i].parent >= 0)
2267 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2269 for (k = 0;k < 12;k++)
2270 bonepose[12*i+k] = m[k];
2272 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2274 const int *inelements;
2276 const float *intexcoord;
2277 msurface_t *surface;
2279 loadmodel->sortedmodelsurfaces[i] = i;
2280 surface = loadmodel->data_surfaces + i;
2281 surface->texture = loadmodel->data_textures + i;
2282 surface->num_firsttriangle = meshtriangles;
2283 surface->num_triangles = BigLong(dpmmesh->num_tris);
2284 surface->num_firstvertex = meshvertices;
2285 surface->num_vertices = BigLong(dpmmesh->num_verts);
2286 meshvertices += surface->num_vertices;
2287 meshtriangles += surface->num_triangles;
2289 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2290 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2291 for (j = 0;j < surface->num_triangles;j++)
2293 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2294 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2295 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2296 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2301 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2302 for (j = 0;j < surface->num_vertices*2;j++)
2303 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2305 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2306 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2308 int weightindex[4] = { 0, 0, 0, 0 };
2309 float weightinfluence[4] = { 0, 0, 0, 0 };
2311 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2312 data += sizeof(dpmvertex_t);
2313 for (k = 0;k < numweights;k++)
2315 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2316 int boneindex = BigLong(vert->bonenum);
2317 const float *m = bonepose + 12 * boneindex;
2318 float influence = BigFloat(vert->influence);
2319 float relativeorigin[3], relativenormal[3];
2320 relativeorigin[0] = BigFloat(vert->origin[0]);
2321 relativeorigin[1] = BigFloat(vert->origin[1]);
2322 relativeorigin[2] = BigFloat(vert->origin[2]);
2323 relativenormal[0] = BigFloat(vert->normal[0]);
2324 relativenormal[1] = BigFloat(vert->normal[1]);
2325 relativenormal[2] = BigFloat(vert->normal[2]);
2326 // blend the vertex bone weights into the base mesh
2327 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2328 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2329 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2330 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2331 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2332 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2335 // store the first (and often only) weight
2336 weightinfluence[0] = influence;
2337 weightindex[0] = boneindex;
2341 // sort the new weight into this vertex's weight table
2342 // (which only accepts up to 4 bones per vertex)
2343 for (l = 0;l < 4;l++)
2345 if (weightinfluence[l] < influence)
2347 // move weaker influence weights out of the way first
2349 for (l2 = 3;l2 > l;l2--)
2351 weightinfluence[l2] = weightinfluence[l2-1];
2352 weightindex[l2] = weightindex[l2-1];
2354 // store the new weight
2355 weightinfluence[l] = influence;
2356 weightindex[l] = boneindex;
2361 data += sizeof(dpmbonevert_t);
2363 loadmodel->surfmesh.blends[j] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
2366 // since dpm models do not have named sections, reuse their shader name as the section name
2367 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2369 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2371 if (loadmodel->surfmesh.num_blends < meshvertices)
2372 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2374 Mod_FreeSkinFiles(skinfiles);
2375 Mod_MakeSortedSurfaces(loadmodel);
2377 // compute all the mesh information that was not loaded from the file
2378 if (loadmodel->surfmesh.data_element3s)
2379 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2380 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2381 Mod_BuildBaseBonePoses();
2382 Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, true);
2383 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2385 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2387 if (!loadmodel->surfmesh.isanimated)
2389 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2390 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2391 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2392 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2393 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2394 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2398 // no idea why PSK/PSA files contain weird quaternions but they do...
2399 #define PSKQUATNEGATIONS
2400 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2402 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2403 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2404 fs_offset_t filesize;
2409 pskboneinfo_t *bones;
2410 pskrawweights_t *rawweights;
2411 //pskboneinfo_t *animbones;
2412 pskaniminfo_t *anims;
2413 pskanimkeys_t *animkeys;
2414 void *animfilebuffer, *animbuffer, *animbufferend;
2415 unsigned char *data;
2417 skinfile_t *skinfiles;
2418 char animname[MAX_QPATH];
2420 float biggestorigin;
2422 pchunk = (pskchunk_t *)buffer;
2423 if (strcmp(pchunk->id, "ACTRHEAD"))
2424 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2426 loadmodel->modeldatatypestring = "PSK";
2428 loadmodel->type = mod_alias;
2429 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2430 loadmodel->DrawSky = NULL;
2431 loadmodel->DrawAddWaterPlanes = NULL;
2432 loadmodel->Draw = R_Q1BSP_Draw;
2433 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2434 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2435 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2436 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2437 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2438 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2439 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2440 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2441 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2442 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2443 loadmodel->PointSuperContents = NULL;
2444 loadmodel->synctype = ST_RAND;
2446 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2447 strlcat(animname, ".psa", sizeof(animname));
2448 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2449 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2450 if (animbuffer == NULL)
2451 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2470 while (buffer < bufferend)
2472 pchunk = (pskchunk_t *)buffer;
2473 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2474 version = LittleLong(pchunk->version);
2475 recordsize = LittleLong(pchunk->recordsize);
2476 numrecords = LittleLong(pchunk->numrecords);
2477 if (developer_extra.integer)
2478 Con_DPrintf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2479 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2480 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);
2481 if (!strcmp(pchunk->id, "ACTRHEAD"))
2485 else if (!strcmp(pchunk->id, "PNTS0000"))
2488 if (recordsize != sizeof(*p))
2489 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2490 // byteswap in place and keep the pointer
2491 numpnts = numrecords;
2492 pnts = (pskpnts_t *)buffer;
2493 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2495 p->origin[0] = LittleFloat(p->origin[0]);
2496 p->origin[1] = LittleFloat(p->origin[1]);
2497 p->origin[2] = LittleFloat(p->origin[2]);
2501 else if (!strcmp(pchunk->id, "VTXW0000"))
2504 if (recordsize != sizeof(*p))
2505 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2506 // byteswap in place and keep the pointer
2507 numvtxw = numrecords;
2508 vtxw = (pskvtxw_t *)buffer;
2509 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2511 p->pntsindex = LittleShort(p->pntsindex);
2512 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2513 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2514 if (p->pntsindex >= numpnts)
2516 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2522 else if (!strcmp(pchunk->id, "FACE0000"))
2525 if (recordsize != sizeof(*p))
2526 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2527 // byteswap in place and keep the pointer
2528 numfaces = numrecords;
2529 faces = (pskface_t *)buffer;
2530 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2532 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2533 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2534 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2535 p->group = LittleLong(p->group);
2536 if (p->vtxwindex[0] >= numvtxw)
2538 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2539 p->vtxwindex[0] = 0;
2541 if (p->vtxwindex[1] >= numvtxw)
2543 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2544 p->vtxwindex[1] = 0;
2546 if (p->vtxwindex[2] >= numvtxw)
2548 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2549 p->vtxwindex[2] = 0;
2554 else if (!strcmp(pchunk->id, "MATT0000"))
2557 if (recordsize != sizeof(*p))
2558 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2559 // byteswap in place and keep the pointer
2560 nummatts = numrecords;
2561 matts = (pskmatt_t *)buffer;
2562 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2568 else if (!strcmp(pchunk->id, "REFSKELT"))
2571 if (recordsize != sizeof(*p))
2572 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2573 // byteswap in place and keep the pointer
2574 numbones = numrecords;
2575 bones = (pskboneinfo_t *)buffer;
2576 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2578 p->numchildren = LittleLong(p->numchildren);
2579 p->parent = LittleLong(p->parent);
2580 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2581 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2582 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2583 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2584 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2585 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2586 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2587 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2588 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2589 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2590 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2591 #ifdef PSKQUATNEGATIONS
2594 p->basepose.quat[0] *= -1;
2595 p->basepose.quat[1] *= -1;
2596 p->basepose.quat[2] *= -1;
2600 p->basepose.quat[0] *= 1;
2601 p->basepose.quat[1] *= -1;
2602 p->basepose.quat[2] *= 1;
2605 if (p->parent < 0 || p->parent >= numbones)
2607 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2613 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2616 if (recordsize != sizeof(*p))
2617 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2618 // byteswap in place and keep the pointer
2619 numrawweights = numrecords;
2620 rawweights = (pskrawweights_t *)buffer;
2621 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2623 p->weight = LittleFloat(p->weight);
2624 p->pntsindex = LittleLong(p->pntsindex);
2625 p->boneindex = LittleLong(p->boneindex);
2626 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2628 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2631 if (p->boneindex < 0 || p->boneindex >= numbones)
2633 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2641 while (animbuffer < animbufferend)
2643 pchunk = (pskchunk_t *)animbuffer;
2644 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2645 version = LittleLong(pchunk->version);
2646 recordsize = LittleLong(pchunk->recordsize);
2647 numrecords = LittleLong(pchunk->numrecords);
2648 if (developer_extra.integer)
2649 Con_DPrintf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2650 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2651 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);
2652 if (!strcmp(pchunk->id, "ANIMHEAD"))
2656 else if (!strcmp(pchunk->id, "BONENAMES"))
2659 if (recordsize != sizeof(*p))
2660 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2661 // byteswap in place and keep the pointer
2662 numanimbones = numrecords;
2663 //animbones = (pskboneinfo_t *)animbuffer;
2664 // NOTE: supposedly psa does not need to match the psk model, the
2665 // bones missing from the psa would simply use their base
2666 // positions from the psk, but this is hard for me to implement
2667 // and people can easily make animations that match.
2668 if (numanimbones != numbones)
2669 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2670 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2672 p->numchildren = LittleLong(p->numchildren);
2673 p->parent = LittleLong(p->parent);
2674 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2675 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2676 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2677 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2678 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2679 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2680 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2681 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2682 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2683 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2684 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2685 #ifdef PSKQUATNEGATIONS
2688 p->basepose.quat[0] *= -1;
2689 p->basepose.quat[1] *= -1;
2690 p->basepose.quat[2] *= -1;
2694 p->basepose.quat[0] *= 1;
2695 p->basepose.quat[1] *= -1;
2696 p->basepose.quat[2] *= 1;
2699 if (p->parent < 0 || p->parent >= numanimbones)
2701 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2704 // check that bones are the same as in the base
2705 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2706 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2710 else if (!strcmp(pchunk->id, "ANIMINFO"))
2713 if (recordsize != sizeof(*p))
2714 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2715 // byteswap in place and keep the pointer
2716 numanims = numrecords;
2717 anims = (pskaniminfo_t *)animbuffer;
2718 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2720 p->numbones = LittleLong(p->numbones);
2721 p->playtime = LittleFloat(p->playtime);
2722 p->fps = LittleFloat(p->fps);
2723 p->firstframe = LittleLong(p->firstframe);
2724 p->numframes = LittleLong(p->numframes);
2725 if (p->numbones != numbones)
2726 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2730 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2733 if (recordsize != sizeof(*p))
2734 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2735 numanimkeys = numrecords;
2736 animkeys = (pskanimkeys_t *)animbuffer;
2737 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2739 p->origin[0] = LittleFloat(p->origin[0]);
2740 p->origin[1] = LittleFloat(p->origin[1]);
2741 p->origin[2] = LittleFloat(p->origin[2]);
2742 p->quat[0] = LittleFloat(p->quat[0]);
2743 p->quat[1] = LittleFloat(p->quat[1]);
2744 p->quat[2] = LittleFloat(p->quat[2]);
2745 p->quat[3] = LittleFloat(p->quat[3]);
2746 p->frametime = LittleFloat(p->frametime);
2747 #ifdef PSKQUATNEGATIONS
2748 if (index % numbones)
2763 // TODO: allocate bonepose stuff
2766 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2769 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2770 Host_Error("%s: missing required chunks", loadmodel->name);
2772 loadmodel->numframes = 0;
2773 for (index = 0;index < numanims;index++)
2774 loadmodel->numframes += anims[index].numframes;
2776 if (numanimkeys != numbones * loadmodel->numframes)
2777 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2779 meshvertices = numvtxw;
2780 meshtriangles = numfaces;
2782 // load external .skin files if present
2783 skinfiles = Mod_LoadSkinFiles();
2784 if (loadmodel->numskins < 1)
2785 loadmodel->numskins = 1;
2786 loadmodel->num_bones = numbones;
2787 loadmodel->num_poses = loadmodel->numframes;
2788 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2789 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2790 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2791 loadmodel->surfmesh.num_vertices = meshvertices;
2792 loadmodel->surfmesh.num_triangles = meshtriangles;
2793 // do most allocations as one merged chunk
2794 size = loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + loadmodel->surfmesh.num_triangles * sizeof(int[3]) + loadmodel->surfmesh.num_triangles * sizeof(int[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[2]) + loadmodel->surfmesh.num_vertices * sizeof(unsigned short) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t) + ((loadmodel->surfmesh.num_vertices <= 65536) ? (loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3])) : 0);
2795 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2796 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2797 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2798 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2799 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2800 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2801 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2802 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2803 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2804 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2805 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2806 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2807 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2808 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2809 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2810 loadmodel->surfmesh.num_blends = 0;
2811 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2812 if (loadmodel->surfmesh.num_vertices <= 65536)
2813 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2814 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2815 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(blendweights_t));
2817 for (i = 0;i < loadmodel->numskins;i++)
2819 loadmodel->skinscenes[i].firstframe = i;
2820 loadmodel->skinscenes[i].framecount = 1;
2821 loadmodel->skinscenes[i].loop = true;
2822 loadmodel->skinscenes[i].framerate = 10;
2826 for (index = 0, i = 0;index < nummatts;index++)
2828 // since psk models do not have named sections, reuse their shader name as the section name
2829 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2830 loadmodel->sortedmodelsurfaces[index] = index;
2831 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2832 loadmodel->data_surfaces[index].num_firstvertex = 0;
2833 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2836 // copy over the vertex locations and texcoords
2837 for (index = 0;index < numvtxw;index++)
2839 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2840 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2841 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2842 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2843 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2846 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2847 for (index = 0;index < numfaces;index++)
2848 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2849 for (index = 0, i = 0;index < nummatts;index++)
2851 loadmodel->data_surfaces[index].num_firsttriangle = i;
2852 i += loadmodel->data_surfaces[index].num_triangles;
2853 loadmodel->data_surfaces[index].num_triangles = 0;
2855 for (index = 0;index < numfaces;index++)
2857 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2858 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2859 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2860 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2863 // copy over the bones
2864 for (index = 0;index < numbones;index++)
2866 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2867 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2868 if (loadmodel->data_bones[index].parent >= index)
2869 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2872 // sort the psk point weights into the vertex weight tables
2873 // (which only accept up to 4 bones per vertex)
2874 for (index = 0;index < numvtxw;index++)
2876 int weightindex[4] = { 0, 0, 0, 0 };
2877 float weightinfluence[4] = { 0, 0, 0, 0 };
2879 for (j = 0;j < numrawweights;j++)
2881 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2883 int boneindex = rawweights[j].boneindex;
2884 float influence = rawweights[j].weight;
2885 for (l = 0;l < 4;l++)
2887 if (weightinfluence[l] < influence)
2889 // move lower influence weights out of the way first
2891 for (l2 = 3;l2 > l;l2--)
2893 weightinfluence[l2] = weightinfluence[l2-1];
2894 weightindex[l2] = weightindex[l2-1];
2896 // store the new weight
2897 weightinfluence[l] = influence;
2898 weightindex[l] = boneindex;
2904 loadmodel->surfmesh.blends[index] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
2906 if (loadmodel->surfmesh.num_blends < loadmodel->surfmesh.num_vertices)
2907 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2909 // set up the animscenes based on the anims
2910 for (index = 0, i = 0;index < numanims;index++)
2912 for (j = 0;j < anims[index].numframes;j++, i++)
2914 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2915 loadmodel->animscenes[i].firstframe = i;
2916 loadmodel->animscenes[i].framecount = 1;
2917 loadmodel->animscenes[i].loop = true;
2918 loadmodel->animscenes[i].framerate = anims[index].fps;
2922 // calculate the scaling value for bone origins so they can be compressed to short
2924 for (index = 0;index < numanimkeys;index++)
2926 pskanimkeys_t *k = animkeys + index;
2927 biggestorigin = max(biggestorigin, fabs(k->origin[0]));
2928 biggestorigin = max(biggestorigin, fabs(k->origin[1]));
2929 biggestorigin = max(biggestorigin, fabs(k->origin[2]));
2931 loadmodel->num_posescale = biggestorigin / 32767.0f;
2932 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2934 // load the poses from the animkeys
2935 for (index = 0;index < numanimkeys;index++)
2937 pskanimkeys_t *k = animkeys + index;
2939 Vector4Copy(k->quat, quat);
2941 Vector4Negate(quat, quat);
2942 Vector4Normalize2(quat, quat);
2943 // compress poses to the short[6] format for longterm storage
2944 loadmodel->data_poses6s[index*6+0] = k->origin[0] * loadmodel->num_poseinvscale;
2945 loadmodel->data_poses6s[index*6+1] = k->origin[1] * loadmodel->num_poseinvscale;
2946 loadmodel->data_poses6s[index*6+2] = k->origin[2] * loadmodel->num_poseinvscale;
2947 loadmodel->data_poses6s[index*6+3] = quat[0] * 32767.0f;
2948 loadmodel->data_poses6s[index*6+4] = quat[1] * 32767.0f;
2949 loadmodel->data_poses6s[index*6+5] = quat[2] * 32767.0f;
2951 Mod_FreeSkinFiles(skinfiles);
2952 Mem_Free(animfilebuffer);
2953 Mod_MakeSortedSurfaces(loadmodel);
2955 // compute all the mesh information that was not loaded from the file
2956 // TODO: honor smoothing groups somehow?
2957 if (loadmodel->surfmesh.data_element3s)
2958 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2959 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2960 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2961 Mod_BuildBaseBonePoses();
2962 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2963 Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, true);
2964 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2965 Mod_Alias_CalculateBoundingBox();
2967 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2969 if (!loadmodel->surfmesh.isanimated)
2971 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2972 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2973 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2974 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2975 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2976 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2980 void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2982 unsigned char *data;
2984 unsigned char *pbase, *pend;
2985 iqmheader_t *header;
2986 skinfile_t *skinfiles;
2987 int i, j, k, meshvertices, meshtriangles;
2988 float *vposition = NULL, *vtexcoord = NULL, *vnormal = NULL, *vtangent = NULL;
2989 unsigned char *vblendindexes = NULL, *vblendweights = NULL;
2994 iqmbounds_t *bounds;
2995 iqmvertexarray_t *va;
2996 unsigned short *framedata;
2997 float biggestorigin;
2998 const int *inelements;
3000 float *outvertex, *outnormal, *outtexcoord, *outsvector, *outtvector;
3002 pbase = (unsigned char *)buffer;
3003 pend = (unsigned char *)bufferend;
3004 header = (iqmheader_t *)buffer;
3005 if (memcmp(header->id, "INTERQUAKEMODEL", 16))
3006 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model", loadmodel->name);
3007 if (LittleLong(header->version) != 1)
3008 Host_Error ("Mod_INTERQUAKEMODEL_Load: only version 1 models are currently supported (name = %s)", loadmodel->name);
3010 loadmodel->modeldatatypestring = "IQM";
3012 loadmodel->type = mod_alias;
3013 loadmodel->synctype = ST_RAND;
3016 header->version = LittleLong(header->version);
3017 header->filesize = LittleLong(header->filesize);
3018 header->flags = LittleLong(header->flags);
3019 header->num_text = LittleLong(header->num_text);
3020 header->ofs_text = LittleLong(header->ofs_text);
3021 header->num_meshes = LittleLong(header->num_meshes);
3022 header->ofs_meshes = LittleLong(header->ofs_meshes);
3023 header->num_vertexarrays = LittleLong(header->num_vertexarrays);
3024 header->num_vertexes = LittleLong(header->num_vertexes);
3025 header->ofs_vertexarrays = LittleLong(header->ofs_vertexarrays);
3026 header->num_triangles = LittleLong(header->num_triangles);
3027 header->ofs_triangles = LittleLong(header->ofs_triangles);
3028 header->ofs_neighbors = LittleLong(header->ofs_neighbors);
3029 header->num_joints = LittleLong(header->num_joints);
3030 header->ofs_joints = LittleLong(header->ofs_joints);
3031 header->num_poses = LittleLong(header->num_poses);
3032 header->ofs_poses = LittleLong(header->ofs_poses);
3033 header->num_anims = LittleLong(header->num_anims);
3034 header->ofs_anims = LittleLong(header->ofs_anims);
3035 header->num_frames = LittleLong(header->num_frames);
3036 header->num_framechannels = LittleLong(header->num_framechannels);
3037 header->ofs_frames = LittleLong(header->ofs_frames);
3038 header->ofs_bounds = LittleLong(header->ofs_bounds);
3039 header->num_comment = LittleLong(header->num_comment);
3040 header->ofs_comment = LittleLong(header->ofs_comment);
3041 header->num_extensions = LittleLong(header->num_extensions);
3042 header->ofs_extensions = LittleLong(header->ofs_extensions);
3044 if (header->num_triangles < 1 || header->num_vertexes < 3 || header->num_vertexarrays < 1 || header->num_meshes < 1)
3046 Con_Printf("%s has no geometry\n", loadmodel->name);
3049 if (header->num_frames < 1 || header->num_anims < 1)
3051 Con_Printf("%s has no animations\n", loadmodel->name);
3055 if (pbase + header->ofs_text + header->num_text > pend ||
3056 pbase + header->ofs_meshes + header->num_meshes*sizeof(iqmmesh_t) > pend ||
3057 pbase + header->ofs_vertexarrays + header->num_vertexarrays*sizeof(iqmvertexarray_t) > pend ||
3058 pbase + header->ofs_triangles + header->num_triangles*sizeof(int[3]) > pend ||
3059 (header->ofs_neighbors && pbase + header->ofs_neighbors + header->num_triangles*sizeof(int[3]) > pend) ||
3060 pbase + header->ofs_joints + header->num_joints*sizeof(iqmjoint_t) > pend ||
3061 pbase + header->ofs_poses + header->num_poses*sizeof(iqmpose_t) > pend ||
3062 pbase + header->ofs_anims + header->num_anims*sizeof(iqmanim_t) > pend ||
3063 pbase + header->ofs_frames + header->num_frames*header->num_framechannels*sizeof(unsigned short) > pend ||
3064 (header->ofs_bounds && pbase + header->ofs_bounds + header->num_frames*sizeof(iqmbounds_t) > pend) ||
3065 pbase + header->ofs_comment + header->num_comment > pend)
3067 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3071 va = (iqmvertexarray_t *)(pbase + header->ofs_vertexarrays);
3072 for (i = 0;i < (int)header->num_vertexarrays;i++)
3075 va[i].type = LittleLong(va[i].type);
3076 va[i].flags = LittleLong(va[i].flags);
3077 va[i].format = LittleLong(va[i].format);
3078 va[i].size = LittleLong(va[i].size);
3079 va[i].offset = LittleLong(va[i].offset);
3080 vsize = header->num_vertexes*va[i].size;
3081 switch (va[i].format)
3083 case IQM_FLOAT: vsize *= sizeof(float); break;
3084 case IQM_UBYTE: vsize *= sizeof(unsigned char); break;
3087 if (pbase + va[i].offset + vsize > pend)
3092 if (va[i].format == IQM_FLOAT && va[i].size == 3)
3093 vposition = (float *)(pbase + va[i].offset);
3096 if (va[i].format == IQM_FLOAT && va[i].size == 2)
3097 vtexcoord = (float *)(pbase + va[i].offset);
3100 if (va[i].format == IQM_FLOAT && va[i].size == 3)
3101 vnormal = (float *)(pbase + va[i].offset);
3104 if (va[i].format == IQM_FLOAT && va[i].size == 4)
3105 vtangent = (float *)(pbase + va[i].offset);
3107 case IQM_BLENDINDEXES:
3108 if (va[i].format == IQM_UBYTE && va[i].size == 4)
3109 vblendindexes = (unsigned char *)(pbase + va[i].offset);
3111 case IQM_BLENDWEIGHTS:
3112 if (va[i].format == IQM_UBYTE && va[i].size == 4)
3113 vblendweights = (unsigned char *)(pbase + va[i].offset);
3117 if (!vposition || !vtexcoord || !vblendindexes || !vblendweights)
3119 Con_Printf("%s is missing vertex array data\n", loadmodel->name);
3123 text = header->num_text && header->ofs_text ? (const char *)(pbase + header->ofs_text) : "";
3125 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
3126 loadmodel->DrawSky = NULL;
3127 loadmodel->DrawAddWaterPlanes = NULL;
3128 loadmodel->Draw = R_Q1BSP_Draw;
3129 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
3130 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
3131 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
3132 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
3133 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
3134 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
3135 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
3136 loadmodel->DrawLight = R_Q1BSP_DrawLight;
3137 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
3138 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
3139 loadmodel->PointSuperContents = NULL;
3141 // load external .skin files if present
3142 skinfiles = Mod_LoadSkinFiles();
3143 if (loadmodel->numskins < 1)
3144 loadmodel->numskins = 1;
3146 loadmodel->numframes = header->num_anims;
3147 loadmodel->num_bones = header->num_joints;
3148 loadmodel->num_poses = header->num_frames;
3149 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = header->num_meshes;
3150 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3151 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3153 meshvertices = header->num_vertexes;
3154 meshtriangles = header->num_triangles;
3156 // do most allocations as one merged chunk
3157 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshtriangles * sizeof(int[3]) + meshvertices * (sizeof(float[14]) + sizeof(unsigned short)) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
3158 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
3159 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
3160 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
3161 loadmodel->surfmesh.num_vertices = meshvertices;
3162 loadmodel->surfmesh.num_triangles = meshtriangles;
3163 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3164 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3165 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
3166 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3167 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3168 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
3169 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
3170 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
3171 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
3172 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
3173 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
3174 loadmodel->surfmesh.num_blends = 0;
3175 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
3176 if (meshvertices <= 65536)
3177 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
3178 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
3179 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
3181 for (i = 0;i < loadmodel->numskins;i++)
3183 loadmodel->skinscenes[i].firstframe = i;
3184 loadmodel->skinscenes[i].framecount = 1;
3185 loadmodel->skinscenes[i].loop = true;
3186 loadmodel->skinscenes[i].framerate = 10;
3189 // load the bone info
3190 joint = (iqmjoint_t *) (pbase + header->ofs_joints);
3191 for (i = 0;i < loadmodel->num_bones;i++)
3193 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3194 joint[i].name = LittleLong(joint[i].name);
3195 joint[i].parent = LittleLong(joint[i].parent);
3196 for (j = 0;j < 3;j++)
3198 joint[i].origin[j] = LittleFloat(joint[i].origin[j]);
3199 joint[i].rotation[j] = LittleFloat(joint[i].rotation[j]);
3200 joint[i].scale[j] = LittleFloat(joint[i].scale[j]);
3202 strlcpy(loadmodel->data_bones[i].name, &text[joint[i].name], sizeof(loadmodel->data_bones[i].name));
3203 loadmodel->data_bones[i].parent = joint[i].parent;
3204 if (loadmodel->data_bones[i].parent >= i)
3205 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3206 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]);
3207 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3208 if (loadmodel->data_bones[i].parent >= 0)
3210 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3211 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3212 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3214 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3217 // set up the animscenes based on the anims
3218 anim = (iqmanim_t *) (pbase + header->ofs_anims);
3219 for (i = 0;i < (int)header->num_anims;i++)
3221 anim[i].name = LittleLong(anim[i].name);
3222 anim[i].first_frame = LittleLong(anim[i].first_frame);
3223 anim[i].num_frames = LittleLong(anim[i].num_frames);
3224 anim[i].framerate = LittleFloat(anim[i].framerate);
3225 anim[i].flags = LittleLong(anim[i].flags);
3226 strlcpy(loadmodel->animscenes[i].name, &text[anim[i].name], sizeof(loadmodel->animscenes[i].name));
3227 loadmodel->animscenes[i].firstframe = anim[i].first_frame;
3228 loadmodel->animscenes[i].framecount = anim[i].num_frames;
3229 loadmodel->animscenes[i].loop = ((anim[i].flags & IQM_LOOP) != 0);
3230 loadmodel->animscenes[i].framerate = anim[i].framerate;
3233 pose = (iqmpose_t *) (pbase + header->ofs_poses);
3235 for (i = 0;i < (int)header->num_poses;i++)
3238 pose[i].parent = LittleLong(pose[i].parent);
3239 pose[i].channelmask = LittleLong(pose[i].channelmask);
3240 pose[i].channeloffset[0] = LittleFloat(pose[i].channeloffset[0]);
3241 pose[i].channeloffset[1] = LittleFloat(pose[i].channeloffset[1]);
3242 pose[i].channeloffset[2] = LittleFloat(pose[i].channeloffset[2]);
3243 pose[i].channeloffset[3] = LittleFloat(pose[i].channeloffset[3]);
3244 pose[i].channeloffset[4] = LittleFloat(pose[i].channeloffset[4]);
3245 pose[i].channeloffset[5] = LittleFloat(pose[i].channeloffset[5]);
3246 pose[i].channeloffset[6] = LittleFloat(pose[i].channeloffset[6]);
3247 pose[i].channeloffset[7] = LittleFloat(pose[i].channeloffset[7]);
3248 pose[i].channeloffset[8] = LittleFloat(pose[i].channeloffset[8]);
3249 pose[i].channelscale[0] = LittleFloat(pose[i].channelscale[0]);
3250 pose[i].channelscale[1] = LittleFloat(pose[i].channelscale[1]);
3251 pose[i].channelscale[2] = LittleFloat(pose[i].channelscale[2]);
3252 pose[i].channelscale[3] = LittleFloat(pose[i].channelscale[3]);
3253 pose[i].channelscale[4] = LittleFloat(pose[i].channelscale[4]);
3254 pose[i].channelscale[5] = LittleFloat(pose[i].channelscale[5]);
3255 pose[i].channelscale[6] = LittleFloat(pose[i].channelscale[6]);
3256 pose[i].channelscale[7] = LittleFloat(pose[i].channelscale[7]);
3257 pose[i].channelscale[8] = LittleFloat(pose[i].channelscale[8]);
3258 f = fabs(pose[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3259 f = fabs(pose[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3260 f = fabs(pose[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3261 f = fabs(pose[i].channeloffset[0] + 0xFFFF*pose[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3262 f = fabs(pose[i].channeloffset[1] + 0xFFFF*pose[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3263 f = fabs(pose[i].channeloffset[2] + 0xFFFF*pose[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3265 loadmodel->num_posescale = biggestorigin / 32767.0f;
3266 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3268 // load the pose data
3269 framedata = (unsigned short *) (pbase + header->ofs_frames);
3270 for (i = 0, k = 0;i < (int)header->num_frames;i++)
3272 for (j = 0;j < (int)header->num_poses;j++, k++)
3274 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));
3275 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));
3276 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));
3277 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));
3278 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));
3279 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));
3280 // skip scale data for now
3281 if(pose[j].channelmask&64) framedata++;
3282 if(pose[j].channelmask&128) framedata++;
3283 if(pose[j].channelmask&256) framedata++;
3287 // load bounding box data
3288 if (header->ofs_bounds)
3290 float xyradius = 0, radius = 0;
3291 bounds = (iqmbounds_t *) (pbase + header->ofs_bounds);
3292 VectorClear(loadmodel->normalmins);
3293 VectorClear(loadmodel->normalmaxs);
3294 for (i = 0; i < (int)header->num_frames;i++)
3296 bounds[i].mins[0] = LittleFloat(bounds[i].mins[0]);
3297 bounds[i].mins[1] = LittleFloat(bounds[i].mins[1]);
3298 bounds[i].mins[2] = LittleFloat(bounds[i].mins[2]);
3299 bounds[i].maxs[0] = LittleFloat(bounds[i].maxs[0]);
3300 bounds[i].maxs[1] = LittleFloat(bounds[i].maxs[1]);
3301 bounds[i].maxs[2] = LittleFloat(bounds[i].maxs[2]);
3302 bounds[i].xyradius = LittleFloat(bounds[i].xyradius);
3303 bounds[i].radius = LittleFloat(bounds[i].radius);
3306 VectorCopy(bounds[i].mins, loadmodel->normalmins);
3307 VectorCopy(bounds[i].maxs, loadmodel->normalmaxs);
3311 if (loadmodel->normalmins[0] > bounds[i].mins[0]) loadmodel->normalmins[0] = bounds[i].mins[0];
3312 if (loadmodel->normalmins[1] > bounds[i].mins[1]) loadmodel->normalmins[1] = bounds[i].mins[1];
3313 if (loadmodel->normalmins[2] > bounds[i].mins[2]) loadmodel->normalmins[2] = bounds[i].mins[2];
3314 if (loadmodel->normalmaxs[0] < bounds[i].maxs[0]) loadmodel->normalmaxs[0] = bounds[i].maxs[0];
3315 if (loadmodel->normalmaxs[1] < bounds[i].maxs[1]) loadmodel->normalmaxs[1] = bounds[i].maxs[1];
3316 if (loadmodel->normalmaxs[2] < bounds[i].maxs[2]) loadmodel->normalmaxs[2] = bounds[i].maxs[2];
3318 if (bounds[i].xyradius > xyradius)
3319 xyradius = bounds[i].xyradius;
3320 if (bounds[i].radius > radius)
3321 radius = bounds[i].radius;
3323 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -xyradius;
3324 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = xyradius;
3325 loadmodel->yawmins[2] = loadmodel->normalmins[2];
3326 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
3327 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
3328 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
3329 loadmodel->radius = radius;
3330 loadmodel->radius2 = radius * radius;
3333 // load triangle data
3334 inelements = (const int *) (pbase + header->ofs_triangles);
3335 outelements = loadmodel->surfmesh.data_element3i;
3336 for (i = 0;i < (int)header->num_triangles;i++)
3338 outelements[0] = LittleLong(inelements[0]);
3339 outelements[1] = LittleLong(inelements[1]);
3340 outelements[2] = LittleLong(inelements[2]);
3344 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, header->num_vertexes, __FILE__, __LINE__);
3346 if (header->ofs_neighbors)
3348 inelements = (const int *) (pbase + header->ofs_neighbors);
3349 outelements = loadmodel->surfmesh.data_neighbor3i;
3350 for (i = 0;i < (int)header->num_triangles;i++)
3352 outelements[0] = LittleLong(inelements[0]);
3353 outelements[1] = LittleLong(inelements[1]);
3354 outelements[2] = LittleLong(inelements[2]);
3361 outvertex = loadmodel->surfmesh.data_vertex3f;
3362 for (i = 0;i < (int)header->num_vertexes;i++)
3364 outvertex[0] = LittleFloat(vposition[0]);
3365 outvertex[1] = LittleFloat(vposition[1]);
3366 outvertex[2] = LittleFloat(vposition[2]);
3371 outtexcoord = loadmodel->surfmesh.data_texcoordtexture2f;
3372 for (i = 0;i < (int)header->num_vertexes;i++)
3374 outtexcoord[0] = LittleFloat(vtexcoord[0]);
3375 outtexcoord[1] = LittleFloat(vtexcoord[1]);
3382 outnormal = loadmodel->surfmesh.data_normal3f;
3383 for (i = 0;i < (int)header->num_vertexes;i++)
3385 outnormal[0] = LittleFloat(vnormal[0]);
3386 outnormal[1] = LittleFloat(vnormal[1]);
3387 outnormal[2] = LittleFloat(vnormal[2]);
3393 if(vnormal && vtangent)
3395 outnormal = loadmodel->surfmesh.data_normal3f;
3396 outsvector = loadmodel->surfmesh.data_svector3f;
3397 outtvector = loadmodel->surfmesh.data_tvector3f;
3398 for (i = 0;i < (int)header->num_vertexes;i++)
3400 outsvector[0] = LittleFloat(vtangent[0]);
3401 outsvector[1] = LittleFloat(vtangent[1]);
3402 outsvector[2] = LittleFloat(vtangent[2]);
3403 if(LittleFloat(vtangent[3]) < 0)
3404 CrossProduct(outsvector, outnormal, outtvector);
3406 CrossProduct(outnormal, outsvector, outtvector);
3414 for (i = 0; i < (int)header->num_vertexes;i++)
3416 blendweights_t weights;
3417 memcpy(weights.index, vblendindexes + i*4, 4);
3418 memcpy(weights.influence, vblendweights + i*4, 4);
3419 loadmodel->surfmesh.blends[i] = Mod_Skeletal_AddBlend(loadmodel, &weights);
3423 mesh = (iqmmesh_t *) (pbase + header->ofs_meshes);
3424 for (i = 0;i < (int)header->num_meshes;i++)
3426 msurface_t *surface;
3428 mesh[i].name = LittleLong(mesh[i].name);
3429 mesh[i].material = LittleLong(mesh[i].material);
3430 mesh[i].first_vertex = LittleLong(mesh[i].first_vertex);
3431 mesh[i].num_vertexes = LittleLong(mesh[i].num_vertexes);
3432 mesh[i].first_triangle = LittleLong(mesh[i].first_triangle);
3433 mesh[i].num_triangles = LittleLong(mesh[i].num_triangles);
3435 loadmodel->sortedmodelsurfaces[i] = i;
3436 surface = loadmodel->data_surfaces + i;
3437 surface->texture = loadmodel->data_textures + i;
3438 surface->num_firsttriangle = mesh[i].first_triangle;
3439 surface->num_triangles = mesh[i].num_triangles;
3440 surface->num_firstvertex = mesh[i].first_vertex;
3441 surface->num_vertices = mesh[i].num_vertexes;
3443 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, &text[mesh[i].name], &text[mesh[i].material]);
3446 Mod_FreeSkinFiles(skinfiles);
3447 Mod_MakeSortedSurfaces(loadmodel);
3449 // compute all the mesh information that was not loaded from the file
3450 if (loadmodel->surfmesh.data_element3s)
3451 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3452 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3454 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
3455 if (!vnormal || !vtangent)
3456 Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, true);
3457 if (!header->ofs_neighbors)
3458 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3459 if (!header->ofs_bounds)
3460 Mod_Alias_CalculateBoundingBox();
3462 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
3464 if (!loadmodel->surfmesh.isanimated)
3466 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3467 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3468 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3469 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3470 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3471 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;