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;
854 if(developer_extra.integer)
855 Con_DPrintf("Looking up texture for %s (default: %s)\n", meshname, shadername);
858 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
859 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
861 memset(skin, 0, sizeof(*skin));
863 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
865 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
866 if (!strcmp(skinfileitem->name, meshname))
868 Image_StripImageExtension(skinfileitem->replacement, stripbuf, sizeof(stripbuf));
869 if(developer_extra.integer)
870 Con_DPrintf("--> got %s from skin file\n", stripbuf);
871 Mod_LoadTextureFromQ3Shader(skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
877 // don't render unmentioned meshes
878 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
879 if(developer_extra.integer)
880 Con_DPrintf("--> skipping\n");
881 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
887 if(developer_extra.integer)
888 Con_DPrintf("--> using default\n");
889 Image_StripImageExtension(shadername, stripbuf, sizeof(stripbuf));
890 Mod_LoadTextureFromQ3Shader(skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
894 #define BOUNDI(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid ##VALUE (%d exceeds %d - %d)", loadmodel->name, VALUE, MIN, MAX);
895 #define BOUNDF(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid ##VALUE (%f exceeds %f - %f)", loadmodel->name, VALUE, MIN, MAX);
896 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
898 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
899 float scales, scalet, interval;
903 stvert_t *pinstverts;
904 dtriangle_t *pintriangles;
905 daliasskintype_t *pinskintype;
906 daliasskingroup_t *pinskingroup;
907 daliasskininterval_t *pinskinintervals;
908 daliasframetype_t *pinframetype;
909 daliasgroup_t *pinframegroup;
910 unsigned char *datapointer, *startframes, *startskins;
911 char name[MAX_QPATH];
912 skinframe_t *tempskinframe;
913 animscene_t *tempskinscenes;
914 texture_t *tempaliasskins;
916 int *vertonseam, *vertremap;
917 skinfile_t *skinfiles;
919 datapointer = (unsigned char *)buffer;
920 pinmodel = (mdl_t *)datapointer;
921 datapointer += sizeof(mdl_t);
923 version = LittleLong (pinmodel->version);
924 if (version != ALIAS_VERSION)
925 Host_Error ("%s has wrong version number (%i should be %i)",
926 loadmodel->name, version, ALIAS_VERSION);
928 loadmodel->modeldatatypestring = "MDL";
930 loadmodel->type = mod_alias;
931 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
932 loadmodel->DrawSky = NULL;
933 loadmodel->DrawAddWaterPlanes = NULL;
934 loadmodel->Draw = R_Q1BSP_Draw;
935 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
936 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
937 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
938 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
939 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
940 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
941 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
942 loadmodel->DrawLight = R_Q1BSP_DrawLight;
943 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
944 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
945 // FIXME add TraceBrush!
946 loadmodel->PointSuperContents = NULL;
948 loadmodel->num_surfaces = 1;
949 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
950 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
951 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
952 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
953 loadmodel->sortedmodelsurfaces[0] = 0;
955 loadmodel->numskins = LittleLong(pinmodel->numskins);
956 BOUNDI(loadmodel->numskins,0,65536);
957 skinwidth = LittleLong (pinmodel->skinwidth);
958 BOUNDI(skinwidth,0,65536);
959 skinheight = LittleLong (pinmodel->skinheight);
960 BOUNDI(skinheight,0,65536);
961 numverts = LittleLong(pinmodel->numverts);
962 BOUNDI(numverts,0,65536);
963 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
964 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
965 loadmodel->numframes = LittleLong(pinmodel->numframes);
966 BOUNDI(loadmodel->numframes,0,65536);
967 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
968 BOUNDI((int)loadmodel->synctype,0,2);
969 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
970 i = LittleLong (pinmodel->flags);
971 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
973 for (i = 0;i < 3;i++)
975 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
976 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
979 startskins = datapointer;
981 for (i = 0;i < loadmodel->numskins;i++)
983 pinskintype = (daliasskintype_t *)datapointer;
984 datapointer += sizeof(daliasskintype_t);
985 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
989 pinskingroup = (daliasskingroup_t *)datapointer;
990 datapointer += sizeof(daliasskingroup_t);
991 groupskins = LittleLong(pinskingroup->numskins);
992 datapointer += sizeof(daliasskininterval_t) * groupskins;
995 for (j = 0;j < groupskins;j++)
997 datapointer += skinwidth * skinheight;
1002 pinstverts = (stvert_t *)datapointer;
1003 datapointer += sizeof(stvert_t) * numverts;
1005 pintriangles = (dtriangle_t *)datapointer;
1006 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
1008 startframes = datapointer;
1009 loadmodel->surfmesh.num_morphframes = 0;
1010 for (i = 0;i < loadmodel->numframes;i++)
1012 pinframetype = (daliasframetype_t *)datapointer;
1013 datapointer += sizeof(daliasframetype_t);
1014 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
1018 pinframegroup = (daliasgroup_t *)datapointer;
1019 datapointer += sizeof(daliasgroup_t);
1020 groupframes = LittleLong(pinframegroup->numframes);
1021 datapointer += sizeof(daliasinterval_t) * groupframes;
1024 for (j = 0;j < groupframes;j++)
1026 datapointer += sizeof(daliasframe_t);
1027 datapointer += sizeof(trivertx_t) * numverts;
1028 loadmodel->surfmesh.num_morphframes++;
1031 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1033 // store texture coordinates into temporary array, they will be stored
1034 // after usage is determined (triangle data)
1035 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
1036 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
1037 vertonseam = vertremap + numverts * 2;
1039 scales = 1.0 / skinwidth;
1040 scalet = 1.0 / skinheight;
1041 for (i = 0;i < numverts;i++)
1043 vertonseam[i] = LittleLong(pinstverts[i].onseam);
1044 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
1045 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
1046 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
1047 vertst[(i+numverts)*2+1] = vertst[i*2+1];
1050 // load triangle data
1051 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1053 // read the triangle elements
1054 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1055 for (j = 0;j < 3;j++)
1056 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1057 // validate (note numverts is used because this is the original data)
1058 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1059 // now butcher the elements according to vertonseam and tri->facesfront
1060 // and then compact the vertex set to remove duplicates
1061 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1062 if (!LittleLong(pintriangles[i].facesfront)) // backface
1063 for (j = 0;j < 3;j++)
1064 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1065 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1067 // (this uses vertremap to count usage to save some memory)
1068 for (i = 0;i < numverts*2;i++)
1070 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1071 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1072 // build remapping table and compact array
1073 loadmodel->surfmesh.num_vertices = 0;
1074 for (i = 0;i < numverts*2;i++)
1078 vertremap[i] = loadmodel->surfmesh.num_vertices;
1079 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1080 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1081 loadmodel->surfmesh.num_vertices++;
1084 vertremap[i] = -1; // not used at all
1086 // remap the elements to the new vertex set
1087 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1088 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1089 // store the texture coordinates
1090 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1091 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1093 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1094 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1097 // generate ushort elements array if possible
1098 if (loadmodel->surfmesh.num_vertices <= 65536)
1099 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1100 if (loadmodel->surfmesh.data_element3s)
1101 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1102 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1105 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1106 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1107 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1108 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1109 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1110 Mod_Alias_CalculateBoundingBox();
1111 Mod_Alias_MorphMesh_CompileFrames();
1114 Mem_Free(vertremap);
1117 skinfiles = Mod_LoadSkinFiles();
1120 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1121 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1122 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1123 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1124 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1125 Mod_FreeSkinFiles(skinfiles);
1126 for (i = 0;i < loadmodel->numskins;i++)
1128 loadmodel->skinscenes[i].firstframe = i;
1129 loadmodel->skinscenes[i].framecount = 1;
1130 loadmodel->skinscenes[i].loop = true;
1131 loadmodel->skinscenes[i].framerate = 10;
1136 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1137 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1138 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1139 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1141 datapointer = startskins;
1142 for (i = 0;i < loadmodel->numskins;i++)
1144 pinskintype = (daliasskintype_t *)datapointer;
1145 datapointer += sizeof(daliasskintype_t);
1147 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1154 pinskingroup = (daliasskingroup_t *)datapointer;
1155 datapointer += sizeof(daliasskingroup_t);
1157 groupskins = LittleLong (pinskingroup->numskins);
1159 pinskinintervals = (daliasskininterval_t *)datapointer;
1160 datapointer += sizeof(daliasskininterval_t) * groupskins;
1162 interval = LittleFloat(pinskinintervals[0].interval);
1163 if (interval < 0.01f)
1165 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1170 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1171 loadmodel->skinscenes[i].firstframe = totalskins;
1172 loadmodel->skinscenes[i].framecount = groupskins;
1173 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1174 loadmodel->skinscenes[i].loop = true;
1176 for (j = 0;j < groupskins;j++)
1179 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1181 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1182 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))
1183 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));
1184 datapointer += skinwidth * skinheight;
1188 // check for skins that don't exist in the model, but do exist as external images
1189 // (this was added because yummyluv kept pestering me about support for it)
1190 // TODO: support shaders here?
1191 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)))
1193 // expand the arrays to make room
1194 tempskinscenes = loadmodel->skinscenes;
1195 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1196 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1197 Mem_Free(tempskinscenes);
1199 tempaliasskins = loadmodel->data_textures;
1200 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1201 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1202 Mem_Free(tempaliasskins);
1204 // store the info about the new skin
1205 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1206 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1207 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1208 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1209 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1210 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1212 //increase skin counts
1213 loadmodel->numskins++;
1216 // fix up the pointers since they are pointing at the old textures array
1217 // FIXME: this is a hack!
1218 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1219 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1223 surface = loadmodel->data_surfaces;
1224 surface->texture = loadmodel->data_textures;
1225 surface->num_firsttriangle = 0;
1226 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1227 surface->num_firstvertex = 0;
1228 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1230 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1232 if (!loadmodel->surfmesh.isanimated)
1234 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1235 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1236 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1237 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1238 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1239 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1243 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1245 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1246 float iskinwidth, iskinheight;
1247 unsigned char *data;
1248 msurface_t *surface;
1250 unsigned char *base, *datapointer;
1251 md2frame_t *pinframe;
1253 md2triangle_t *intri;
1254 unsigned short *inst;
1255 struct md2verthash_s
1257 struct md2verthash_s *next;
1261 *hash, **md2verthash, *md2verthashdata;
1262 skinfile_t *skinfiles;
1264 pinmodel = (md2_t *)buffer;
1265 base = (unsigned char *)buffer;
1267 version = LittleLong (pinmodel->version);
1268 if (version != MD2ALIAS_VERSION)
1269 Host_Error ("%s has wrong version number (%i should be %i)",
1270 loadmodel->name, version, MD2ALIAS_VERSION);
1272 loadmodel->modeldatatypestring = "MD2";
1274 loadmodel->type = mod_alias;
1275 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1276 loadmodel->DrawSky = NULL;
1277 loadmodel->DrawAddWaterPlanes = NULL;
1278 loadmodel->Draw = R_Q1BSP_Draw;
1279 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1280 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1281 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1282 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1283 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1284 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1285 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1286 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1287 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1288 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1289 loadmodel->PointSuperContents = NULL;
1291 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1292 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1293 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1294 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1295 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1296 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1297 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1298 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1300 end = LittleLong(pinmodel->ofs_end);
1301 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1302 Host_Error ("%s is not a valid model", loadmodel->name);
1303 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1304 Host_Error ("%s is not a valid model", loadmodel->name);
1305 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1306 Host_Error ("%s is not a valid model", loadmodel->name);
1307 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1308 Host_Error ("%s is not a valid model", loadmodel->name);
1309 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1310 Host_Error ("%s is not a valid model", loadmodel->name);
1312 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1313 numxyz = LittleLong(pinmodel->num_xyz);
1314 numst = LittleLong(pinmodel->num_st);
1315 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1316 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1317 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1318 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1319 skinwidth = LittleLong(pinmodel->skinwidth);
1320 skinheight = LittleLong(pinmodel->skinheight);
1321 iskinwidth = 1.0f / skinwidth;
1322 iskinheight = 1.0f / skinheight;
1324 loadmodel->num_surfaces = 1;
1325 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1326 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]));
1327 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1328 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1329 loadmodel->sortedmodelsurfaces[0] = 0;
1330 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1331 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1332 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1333 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1335 loadmodel->synctype = ST_RAND;
1338 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1339 skinfiles = Mod_LoadSkinFiles();
1342 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1343 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1344 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1345 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1346 Mod_FreeSkinFiles(skinfiles);
1348 else if (loadmodel->numskins)
1350 // skins found (most likely not a player model)
1351 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1352 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1353 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1354 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1355 Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
1359 // no skins (most likely a player model)
1360 loadmodel->numskins = 1;
1361 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1362 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1363 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1364 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1367 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1368 for (i = 0;i < loadmodel->numskins;i++)
1370 loadmodel->skinscenes[i].firstframe = i;
1371 loadmodel->skinscenes[i].framecount = 1;
1372 loadmodel->skinscenes[i].loop = true;
1373 loadmodel->skinscenes[i].framerate = 10;
1376 // load the triangles and stvert data
1377 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1378 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1379 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1380 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1381 // swap the triangle list
1382 loadmodel->surfmesh.num_vertices = 0;
1383 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1385 for (j = 0;j < 3;j++)
1387 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1388 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1391 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1396 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1399 hashindex = (xyz * 256 + st) & 65535;
1400 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1401 if (hash->xyz == xyz && hash->st == st)
1405 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1408 hash->next = md2verthash[hashindex];
1409 md2verthash[hashindex] = hash;
1411 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1415 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1416 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));
1417 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1418 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1419 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1422 hash = md2verthashdata + i;
1423 vertremap[i] = hash->xyz;
1424 sts = LittleShort(inst[hash->st*2+0]);
1425 stt = LittleShort(inst[hash->st*2+1]);
1426 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1428 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1432 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1433 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1436 Mem_Free(md2verthash);
1437 Mem_Free(md2verthashdata);
1439 // generate ushort elements array if possible
1440 if (loadmodel->surfmesh.num_vertices <= 65536)
1441 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1442 if (loadmodel->surfmesh.data_element3s)
1443 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1444 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1447 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1448 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1453 pinframe = (md2frame_t *)datapointer;
1454 datapointer += sizeof(md2frame_t);
1455 // store the frame scale/translate into the appropriate array
1456 for (j = 0;j < 3;j++)
1458 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1459 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1461 // convert the vertices
1462 v = (trivertx_t *)datapointer;
1463 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1464 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1465 out[k] = v[vertremap[k]];
1466 datapointer += numxyz * sizeof(trivertx_t);
1468 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1469 loadmodel->animscenes[i].firstframe = i;
1470 loadmodel->animscenes[i].framecount = 1;
1471 loadmodel->animscenes[i].framerate = 10;
1472 loadmodel->animscenes[i].loop = true;
1475 Mem_Free(vertremap);
1477 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1478 Mod_Alias_CalculateBoundingBox();
1479 Mod_Alias_MorphMesh_CompileFrames();
1481 surface = loadmodel->data_surfaces;
1482 surface->texture = loadmodel->data_textures;
1483 surface->num_firsttriangle = 0;
1484 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1485 surface->num_firstvertex = 0;
1486 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1488 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1490 if (!loadmodel->surfmesh.isanimated)
1492 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1493 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1494 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1495 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1496 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1497 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1501 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1503 int i, j, k, version, meshvertices, meshtriangles;
1504 unsigned char *data;
1505 msurface_t *surface;
1506 md3modelheader_t *pinmodel;
1507 md3frameinfo_t *pinframe;
1510 skinfile_t *skinfiles;
1512 pinmodel = (md3modelheader_t *)buffer;
1514 if (memcmp(pinmodel->identifier, "IDP3", 4))
1515 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1516 version = LittleLong (pinmodel->version);
1517 if (version != MD3VERSION)
1518 Host_Error ("%s has wrong version number (%i should be %i)",
1519 loadmodel->name, version, MD3VERSION);
1521 skinfiles = Mod_LoadSkinFiles();
1522 if (loadmodel->numskins < 1)
1523 loadmodel->numskins = 1;
1525 loadmodel->modeldatatypestring = "MD3";
1527 loadmodel->type = mod_alias;
1528 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1529 loadmodel->DrawSky = NULL;
1530 loadmodel->DrawAddWaterPlanes = NULL;
1531 loadmodel->Draw = R_Q1BSP_Draw;
1532 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1533 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1534 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1535 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1536 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1537 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1538 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1539 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1540 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1541 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1542 loadmodel->PointSuperContents = NULL;
1543 loadmodel->synctype = ST_RAND;
1544 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1545 i = LittleLong (pinmodel->flags);
1546 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1548 // set up some global info about the model
1549 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1550 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1552 // make skinscenes for the skins (no groups)
1553 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1554 for (i = 0;i < loadmodel->numskins;i++)
1556 loadmodel->skinscenes[i].firstframe = i;
1557 loadmodel->skinscenes[i].framecount = 1;
1558 loadmodel->skinscenes[i].loop = true;
1559 loadmodel->skinscenes[i].framerate = 10;
1563 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1564 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1566 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1567 loadmodel->animscenes[i].firstframe = i;
1568 loadmodel->animscenes[i].framecount = 1;
1569 loadmodel->animscenes[i].framerate = 10;
1570 loadmodel->animscenes[i].loop = true;
1574 loadmodel->num_tagframes = loadmodel->numframes;
1575 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1576 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1577 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1579 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1580 for (j = 0;j < 9;j++)
1581 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1582 for (j = 0;j < 3;j++)
1583 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1584 //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);
1590 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)))
1592 if (memcmp(pinmesh->identifier, "IDP3", 4))
1593 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1594 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1595 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1596 meshvertices += LittleLong(pinmesh->num_vertices);
1597 meshtriangles += LittleLong(pinmesh->num_triangles);
1600 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1601 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1602 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1603 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));
1604 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1605 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1606 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1607 loadmodel->surfmesh.num_vertices = meshvertices;
1608 loadmodel->surfmesh.num_triangles = meshtriangles;
1609 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1610 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1611 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1612 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1613 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1614 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1615 if (meshvertices <= 65536)
1616 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1620 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)))
1622 if (memcmp(pinmesh->identifier, "IDP3", 4))
1623 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1624 loadmodel->sortedmodelsurfaces[i] = i;
1625 surface = loadmodel->data_surfaces + i;
1626 surface->texture = loadmodel->data_textures + i;
1627 surface->num_firsttriangle = meshtriangles;
1628 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1629 surface->num_firstvertex = meshvertices;
1630 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1631 meshvertices += surface->num_vertices;
1632 meshtriangles += surface->num_triangles;
1634 for (j = 0;j < surface->num_triangles * 3;j++)
1635 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1636 for (j = 0;j < surface->num_vertices;j++)
1638 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1639 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1641 for (j = 0;j < loadmodel->numframes;j++)
1643 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1644 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1645 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1647 out->origin[0] = LittleShort(in->origin[0]);
1648 out->origin[1] = LittleShort(in->origin[1]);
1649 out->origin[2] = LittleShort(in->origin[2]);
1650 out->pitch = in->pitch;
1655 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1657 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1659 if (loadmodel->surfmesh.data_element3s)
1660 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1661 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1662 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1663 Mod_Alias_MorphMesh_CompileFrames();
1664 Mod_Alias_CalculateBoundingBox();
1665 Mod_FreeSkinFiles(skinfiles);
1666 Mod_MakeSortedSurfaces(loadmodel);
1668 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1669 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1671 if (!loadmodel->surfmesh.isanimated)
1673 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1674 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1675 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1676 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1677 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1678 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1682 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1684 zymtype1header_t *pinmodel, *pheader;
1685 unsigned char *pbase;
1686 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1687 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose, f, biggestorigin, tempvec[3], modelscale;
1688 zymvertex_t *verts, *vertdata;
1692 skinfile_t *skinfiles;
1693 unsigned char *data;
1694 msurface_t *surface;
1696 pinmodel = (zymtype1header_t *)buffer;
1697 pbase = (unsigned char *)buffer;
1698 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1699 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1700 if (BigLong(pinmodel->type) != 1)
1701 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1703 loadmodel->modeldatatypestring = "ZYM";
1705 loadmodel->type = mod_alias;
1706 loadmodel->synctype = ST_RAND;
1710 pheader->type = BigLong(pinmodel->type);
1711 pheader->filesize = BigLong(pinmodel->filesize);
1712 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1713 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1714 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1715 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1716 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1717 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1718 pheader->radius = BigFloat(pinmodel->radius);
1719 pheader->numverts = BigLong(pinmodel->numverts);
1720 pheader->numtris = BigLong(pinmodel->numtris);
1721 pheader->numshaders = BigLong(pinmodel->numshaders);
1722 pheader->numbones = BigLong(pinmodel->numbones);
1723 pheader->numscenes = BigLong(pinmodel->numscenes);
1724 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1725 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1726 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1727 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1728 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1729 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1730 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1731 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1732 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1733 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1734 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1735 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1736 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1737 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1738 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1739 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1740 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1741 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1743 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1745 Con_Printf("%s has no geometry\n", loadmodel->name);
1748 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1750 Con_Printf("%s has no animations\n", loadmodel->name);
1754 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1755 loadmodel->DrawSky = NULL;
1756 loadmodel->DrawAddWaterPlanes = NULL;
1757 loadmodel->Draw = R_Q1BSP_Draw;
1758 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1759 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1760 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1761 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1762 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1763 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1764 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1765 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1766 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1767 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1768 loadmodel->PointSuperContents = NULL;
1770 loadmodel->numframes = pheader->numscenes;
1771 loadmodel->num_surfaces = pheader->numshaders;
1773 skinfiles = Mod_LoadSkinFiles();
1774 if (loadmodel->numskins < 1)
1775 loadmodel->numskins = 1;
1777 // make skinscenes for the skins (no groups)
1778 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1779 for (i = 0;i < loadmodel->numskins;i++)
1781 loadmodel->skinscenes[i].firstframe = i;
1782 loadmodel->skinscenes[i].framecount = 1;
1783 loadmodel->skinscenes[i].loop = true;
1784 loadmodel->skinscenes[i].framerate = 10;
1788 modelradius = pheader->radius;
1789 for (i = 0;i < 3;i++)
1791 loadmodel->normalmins[i] = pheader->mins[i];
1792 loadmodel->normalmaxs[i] = pheader->maxs[i];
1793 loadmodel->rotatedmins[i] = -modelradius;
1794 loadmodel->rotatedmaxs[i] = modelradius;
1796 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1797 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1798 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1799 if (loadmodel->yawmaxs[0] > modelradius)
1800 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1801 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1802 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1803 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1804 loadmodel->radius = modelradius;
1805 loadmodel->radius2 = modelradius * modelradius;
1807 // go through the lumps, swapping things
1809 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1810 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1811 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1812 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1813 for (i = 0;i < pheader->numscenes;i++)
1815 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1816 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1817 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1818 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1819 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1820 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1821 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1822 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1823 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1824 if (loadmodel->animscenes[i].framerate < 0)
1825 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1829 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1830 loadmodel->num_bones = pheader->numbones;
1831 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1832 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1833 for (i = 0;i < pheader->numbones;i++)
1835 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1836 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1837 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1838 if (loadmodel->data_bones[i].parent >= i)
1839 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1842 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1843 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1844 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1845 for (i = 0;i < pheader->numverts;i++)
1847 vertbonecounts[i] = BigLong(bonecount[i]);
1848 if (vertbonecounts[i] != 1)
1849 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1852 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1854 meshvertices = pheader->numverts;
1855 meshtriangles = pheader->numtris;
1857 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1858 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1859 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1860 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]));
1861 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1862 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1863 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1864 loadmodel->surfmesh.num_vertices = meshvertices;
1865 loadmodel->surfmesh.num_triangles = meshtriangles;
1866 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1867 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1868 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1869 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1870 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1871 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1872 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1873 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1874 loadmodel->surfmesh.num_blends = 0;
1875 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
1876 if (loadmodel->surfmesh.num_vertices <= 65536)
1877 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1878 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
1879 loadmodel->surfmesh.data_blendweights = NULL;
1881 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1882 poses = (float *) (pheader->lump_poses.start + pbase);
1883 // figure out scale of model from root bone, for compatibility with old zmodel versions
1884 tempvec[0] = BigFloat(poses[0]);
1885 tempvec[1] = BigFloat(poses[1]);
1886 tempvec[2] = BigFloat(poses[2]);
1887 modelscale = VectorLength(tempvec);
1889 for (i = 0;i < loadmodel->num_bones * numposes * 12;i++)
1891 f = fabs(BigFloat(poses[i]));
1892 biggestorigin = max(biggestorigin, f);
1894 loadmodel->num_posescale = biggestorigin / 32767.0f;
1895 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
1896 for (i = 0;i < numposes;i++)
1898 const float *frameposes = (float *) (pheader->lump_poses.start + pbase) + 12*i*loadmodel->num_bones;
1899 for (j = 0;j < loadmodel->num_bones;j++)
1902 matrix4x4_t posematrix;
1903 for (k = 0;k < 12;k++)
1904 pose[k] = BigFloat(frameposes[j*12+k]);
1905 //if (j < loadmodel->num_bones)
1906 // 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));
1907 // scale child bones to match the root scale
1908 if (loadmodel->data_bones[j].parent >= 0)
1910 pose[3] *= modelscale;
1911 pose[7] *= modelscale;
1912 pose[11] *= modelscale;
1914 // normalize rotation matrix
1915 VectorNormalize(pose + 0);
1916 VectorNormalize(pose + 4);
1917 VectorNormalize(pose + 8);
1918 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
1919 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
1923 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1924 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1925 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1926 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1927 // (converting from weight-blending skeletal animation to
1928 // deformation-based skeletal animation)
1929 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1930 for (i = 0;i < loadmodel->num_bones;i++)
1933 for (k = 0;k < 12;k++)
1934 m[k] = BigFloat(poses[i*12+k]);
1935 if (loadmodel->data_bones[i].parent >= 0)
1936 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1938 for (k = 0;k < 12;k++)
1939 bonepose[12*i+k] = m[k];
1941 for (j = 0;j < pheader->numverts;j++)
1943 // this format really should have had a per vertexweight weight value...
1944 // but since it does not, the weighting is completely ignored and
1945 // only one weight is allowed per vertex
1946 int boneindex = BigLong(vertdata[j].bonenum);
1947 const float *m = bonepose + 12 * boneindex;
1948 float relativeorigin[3];
1949 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1950 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1951 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1952 // transform the vertex bone weight into the base mesh
1953 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1954 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1955 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1956 // store the weight as the primary weight on this vertex
1957 loadmodel->surfmesh.blends[j] = boneindex;
1960 // normals and tangents are calculated after elements are loaded
1962 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1963 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1964 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1965 for (i = 0;i < pheader->numverts;i++)
1967 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1968 // flip T coordinate for OpenGL
1969 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1972 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1973 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1974 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1976 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1977 //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)
1978 // byteswap, validate, and swap winding order of tris
1979 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1980 if (pheader->lump_render.length != count)
1981 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1982 renderlist = (int *) (pheader->lump_render.start + pbase);
1983 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1985 for (i = 0;i < loadmodel->num_surfaces;i++)
1987 int firstvertex, lastvertex;
1988 if (renderlist >= renderlistend)
1989 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1990 count = BigLong(*renderlist);renderlist++;
1991 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1992 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1994 loadmodel->sortedmodelsurfaces[i] = i;
1995 surface = loadmodel->data_surfaces + i;
1996 surface->texture = loadmodel->data_textures + i;
1997 surface->num_firsttriangle = meshtriangles;
1998 surface->num_triangles = count;
1999 meshtriangles += surface->num_triangles;
2001 // load the elements
2002 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2003 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
2005 outelements[j*3+2] = BigLong(renderlist[0]);
2006 outelements[j*3+1] = BigLong(renderlist[1]);
2007 outelements[j*3+0] = BigLong(renderlist[2]);
2009 // validate the elements and find the used vertex range
2010 firstvertex = meshvertices;
2012 for (j = 0;j < surface->num_triangles * 3;j++)
2014 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
2015 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
2016 firstvertex = min(firstvertex, outelements[j]);
2017 lastvertex = max(lastvertex, outelements[j]);
2019 surface->num_firstvertex = firstvertex;
2020 surface->num_vertices = lastvertex + 1 - firstvertex;
2022 // since zym models do not have named sections, reuse their shader
2023 // name as the section name
2024 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
2025 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
2027 Mod_FreeSkinFiles(skinfiles);
2028 Mem_Free(vertbonecounts);
2030 Mod_MakeSortedSurfaces(loadmodel);
2032 // compute all the mesh information that was not loaded from the file
2033 if (loadmodel->surfmesh.data_element3s)
2034 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2035 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2036 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2037 Mod_BuildBaseBonePoses();
2038 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2039 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);
2040 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2042 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2044 if (!loadmodel->surfmesh.isanimated)
2046 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2047 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2048 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2049 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2050 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2051 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2055 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2057 dpmheader_t *pheader;
2061 unsigned char *pbase;
2062 int i, j, k, meshvertices, meshtriangles;
2063 skinfile_t *skinfiles;
2064 unsigned char *data;
2066 float biggestorigin, tempvec[3], modelscale;
2070 pheader = (dpmheader_t *)buffer;
2071 pbase = (unsigned char *)buffer;
2072 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2073 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2074 if (BigLong(pheader->type) != 2)
2075 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2077 loadmodel->modeldatatypestring = "DPM";
2079 loadmodel->type = mod_alias;
2080 loadmodel->synctype = ST_RAND;
2083 pheader->type = BigLong(pheader->type);
2084 pheader->filesize = BigLong(pheader->filesize);
2085 pheader->mins[0] = BigFloat(pheader->mins[0]);
2086 pheader->mins[1] = BigFloat(pheader->mins[1]);
2087 pheader->mins[2] = BigFloat(pheader->mins[2]);
2088 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2089 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2090 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2091 pheader->yawradius = BigFloat(pheader->yawradius);
2092 pheader->allradius = BigFloat(pheader->allradius);
2093 pheader->num_bones = BigLong(pheader->num_bones);
2094 pheader->num_meshs = BigLong(pheader->num_meshs);
2095 pheader->num_frames = BigLong(pheader->num_frames);
2096 pheader->ofs_bones = BigLong(pheader->ofs_bones);
2097 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2098 pheader->ofs_frames = BigLong(pheader->ofs_frames);
2100 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2102 Con_Printf("%s has no geometry\n", loadmodel->name);
2105 if (pheader->num_frames < 1)
2107 Con_Printf("%s has no frames\n", loadmodel->name);
2111 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2112 loadmodel->DrawSky = NULL;
2113 loadmodel->DrawAddWaterPlanes = NULL;
2114 loadmodel->Draw = R_Q1BSP_Draw;
2115 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2116 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2117 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2118 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2119 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2120 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2121 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2122 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2123 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2124 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2125 loadmodel->PointSuperContents = NULL;
2128 for (i = 0;i < 3;i++)
2130 loadmodel->normalmins[i] = pheader->mins[i];
2131 loadmodel->normalmaxs[i] = pheader->maxs[i];
2132 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2133 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2134 loadmodel->rotatedmins[i] = -pheader->allradius;
2135 loadmodel->rotatedmaxs[i] = pheader->allradius;
2137 loadmodel->radius = pheader->allradius;
2138 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2140 // load external .skin files if present
2141 skinfiles = Mod_LoadSkinFiles();
2142 if (loadmodel->numskins < 1)
2143 loadmodel->numskins = 1;
2148 // gather combined statistics from the meshes
2149 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2150 for (i = 0;i < (int)pheader->num_meshs;i++)
2152 int numverts = BigLong(dpmmesh->num_verts);
2153 meshvertices += numverts;
2154 meshtriangles += BigLong(dpmmesh->num_tris);
2158 loadmodel->numframes = pheader->num_frames;
2159 loadmodel->num_bones = pheader->num_bones;
2160 loadmodel->num_poses = loadmodel->numframes;
2161 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2162 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2163 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2164 // do most allocations as one merged chunk
2165 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));
2166 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2167 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2168 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2169 loadmodel->surfmesh.num_vertices = meshvertices;
2170 loadmodel->surfmesh.num_triangles = meshtriangles;
2171 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2172 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2173 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2174 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2175 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2176 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2177 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2178 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2179 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2180 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2181 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2182 loadmodel->surfmesh.num_blends = 0;
2183 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2184 if (meshvertices <= 65536)
2185 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2186 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2187 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
2189 for (i = 0;i < loadmodel->numskins;i++)
2191 loadmodel->skinscenes[i].firstframe = i;
2192 loadmodel->skinscenes[i].framecount = 1;
2193 loadmodel->skinscenes[i].loop = true;
2194 loadmodel->skinscenes[i].framerate = 10;
2197 // load the bone info
2198 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2199 for (i = 0;i < loadmodel->num_bones;i++)
2201 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2202 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2203 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2204 if (loadmodel->data_bones[i].parent >= i)
2205 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2209 frames = (dpmframe_t *) (pbase + pheader->ofs_frames);
2210 // figure out scale of model from root bone, for compatibility with old dpmodel versions
2211 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2212 tempvec[0] = BigFloat(poses[0]);
2213 tempvec[1] = BigFloat(poses[1]);
2214 tempvec[2] = BigFloat(poses[2]);
2215 modelscale = VectorLength(tempvec);
2217 for (i = 0;i < loadmodel->numframes;i++)
2219 memcpy(loadmodel->animscenes[i].name, frames[i].name, sizeof(frames[i].name));
2220 loadmodel->animscenes[i].firstframe = i;
2221 loadmodel->animscenes[i].framecount = 1;
2222 loadmodel->animscenes[i].loop = true;
2223 loadmodel->animscenes[i].framerate = 10;
2224 // load the bone poses for this frame
2225 poses = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2226 for (j = 0;j < loadmodel->num_bones*12;j++)
2228 f = fabs(BigFloat(poses[j]));
2229 biggestorigin = max(biggestorigin, f);
2231 // stuff not processed here: mins, maxs, yawradius, allradius
2233 loadmodel->num_posescale = biggestorigin / 32767.0f;
2234 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2235 for (i = 0;i < loadmodel->numframes;i++)
2237 const float *frameposes = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2238 for (j = 0;j < loadmodel->num_bones;j++)
2241 matrix4x4_t posematrix;
2242 for (k = 0;k < 12;k++)
2243 pose[k] = BigFloat(frameposes[j*12+k]);
2244 // scale child bones to match the root scale
2245 if (loadmodel->data_bones[j].parent >= 0)
2247 pose[3] *= modelscale;
2248 pose[7] *= modelscale;
2249 pose[11] *= modelscale;
2251 // normalize rotation matrix
2252 VectorNormalize(pose + 0);
2253 VectorNormalize(pose + 4);
2254 VectorNormalize(pose + 8);
2255 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2256 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
2260 // load the meshes now
2261 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2264 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2265 // (converting from weight-blending skeletal animation to
2266 // deformation-based skeletal animation)
2267 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2268 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2269 for (i = 0;i < loadmodel->num_bones;i++)
2272 for (k = 0;k < 12;k++)
2273 m[k] = BigFloat(poses[i*12+k]);
2274 if (loadmodel->data_bones[i].parent >= 0)
2275 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2277 for (k = 0;k < 12;k++)
2278 bonepose[12*i+k] = m[k];
2280 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2282 const int *inelements;
2284 const float *intexcoord;
2285 msurface_t *surface;
2287 loadmodel->sortedmodelsurfaces[i] = i;
2288 surface = loadmodel->data_surfaces + i;
2289 surface->texture = loadmodel->data_textures + i;
2290 surface->num_firsttriangle = meshtriangles;
2291 surface->num_triangles = BigLong(dpmmesh->num_tris);
2292 surface->num_firstvertex = meshvertices;
2293 surface->num_vertices = BigLong(dpmmesh->num_verts);
2294 meshvertices += surface->num_vertices;
2295 meshtriangles += surface->num_triangles;
2297 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2298 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2299 for (j = 0;j < surface->num_triangles;j++)
2301 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2302 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2303 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2304 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2309 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2310 for (j = 0;j < surface->num_vertices*2;j++)
2311 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2313 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2314 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2316 int weightindex[4] = { 0, 0, 0, 0 };
2317 float weightinfluence[4] = { 0, 0, 0, 0 };
2319 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2320 data += sizeof(dpmvertex_t);
2321 for (k = 0;k < numweights;k++)
2323 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2324 int boneindex = BigLong(vert->bonenum);
2325 const float *m = bonepose + 12 * boneindex;
2326 float influence = BigFloat(vert->influence);
2327 float relativeorigin[3], relativenormal[3];
2328 relativeorigin[0] = BigFloat(vert->origin[0]);
2329 relativeorigin[1] = BigFloat(vert->origin[1]);
2330 relativeorigin[2] = BigFloat(vert->origin[2]);
2331 relativenormal[0] = BigFloat(vert->normal[0]);
2332 relativenormal[1] = BigFloat(vert->normal[1]);
2333 relativenormal[2] = BigFloat(vert->normal[2]);
2334 // blend the vertex bone weights into the base mesh
2335 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2336 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2337 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2338 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2339 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2340 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2343 // store the first (and often only) weight
2344 weightinfluence[0] = influence;
2345 weightindex[0] = boneindex;
2349 // sort the new weight into this vertex's weight table
2350 // (which only accepts up to 4 bones per vertex)
2351 for (l = 0;l < 4;l++)
2353 if (weightinfluence[l] < influence)
2355 // move weaker influence weights out of the way first
2357 for (l2 = 3;l2 > l;l2--)
2359 weightinfluence[l2] = weightinfluence[l2-1];
2360 weightindex[l2] = weightindex[l2-1];
2362 // store the new weight
2363 weightinfluence[l] = influence;
2364 weightindex[l] = boneindex;
2369 data += sizeof(dpmbonevert_t);
2371 loadmodel->surfmesh.blends[j] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
2374 // since dpm models do not have named sections, reuse their shader name as the section name
2375 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2377 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2379 if (loadmodel->surfmesh.num_blends < meshvertices)
2380 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2382 Mod_FreeSkinFiles(skinfiles);
2383 Mod_MakeSortedSurfaces(loadmodel);
2385 // compute all the mesh information that was not loaded from the file
2386 if (loadmodel->surfmesh.data_element3s)
2387 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2388 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2389 Mod_BuildBaseBonePoses();
2390 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);
2391 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2393 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2395 if (!loadmodel->surfmesh.isanimated)
2397 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2398 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2399 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2400 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2401 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2402 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2406 // no idea why PSK/PSA files contain weird quaternions but they do...
2407 #define PSKQUATNEGATIONS
2408 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2410 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2411 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2412 fs_offset_t filesize;
2417 pskboneinfo_t *bones;
2418 pskrawweights_t *rawweights;
2419 //pskboneinfo_t *animbones;
2420 pskaniminfo_t *anims;
2421 pskanimkeys_t *animkeys;
2422 void *animfilebuffer, *animbuffer, *animbufferend;
2423 unsigned char *data;
2425 skinfile_t *skinfiles;
2426 char animname[MAX_QPATH];
2428 float biggestorigin;
2430 pchunk = (pskchunk_t *)buffer;
2431 if (strcmp(pchunk->id, "ACTRHEAD"))
2432 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2434 loadmodel->modeldatatypestring = "PSK";
2436 loadmodel->type = mod_alias;
2437 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2438 loadmodel->DrawSky = NULL;
2439 loadmodel->DrawAddWaterPlanes = NULL;
2440 loadmodel->Draw = R_Q1BSP_Draw;
2441 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2442 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2443 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2444 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2445 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2446 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2447 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2448 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2449 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2450 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2451 loadmodel->PointSuperContents = NULL;
2452 loadmodel->synctype = ST_RAND;
2454 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2455 strlcat(animname, ".psa", sizeof(animname));
2456 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2457 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2458 if (animbuffer == NULL)
2459 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2478 while (buffer < bufferend)
2480 pchunk = (pskchunk_t *)buffer;
2481 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2482 version = LittleLong(pchunk->version);
2483 recordsize = LittleLong(pchunk->recordsize);
2484 numrecords = LittleLong(pchunk->numrecords);
2485 if (developer_extra.integer)
2486 Con_DPrintf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2487 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2488 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);
2489 if (!strcmp(pchunk->id, "ACTRHEAD"))
2493 else if (!strcmp(pchunk->id, "PNTS0000"))
2496 if (recordsize != sizeof(*p))
2497 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2498 // byteswap in place and keep the pointer
2499 numpnts = numrecords;
2500 pnts = (pskpnts_t *)buffer;
2501 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2503 p->origin[0] = LittleFloat(p->origin[0]);
2504 p->origin[1] = LittleFloat(p->origin[1]);
2505 p->origin[2] = LittleFloat(p->origin[2]);
2509 else if (!strcmp(pchunk->id, "VTXW0000"))
2512 if (recordsize != sizeof(*p))
2513 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2514 // byteswap in place and keep the pointer
2515 numvtxw = numrecords;
2516 vtxw = (pskvtxw_t *)buffer;
2517 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2519 p->pntsindex = LittleShort(p->pntsindex);
2520 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2521 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2522 if (p->pntsindex >= numpnts)
2524 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2530 else if (!strcmp(pchunk->id, "FACE0000"))
2533 if (recordsize != sizeof(*p))
2534 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2535 // byteswap in place and keep the pointer
2536 numfaces = numrecords;
2537 faces = (pskface_t *)buffer;
2538 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2540 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2541 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2542 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2543 p->group = LittleLong(p->group);
2544 if (p->vtxwindex[0] >= numvtxw)
2546 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2547 p->vtxwindex[0] = 0;
2549 if (p->vtxwindex[1] >= numvtxw)
2551 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2552 p->vtxwindex[1] = 0;
2554 if (p->vtxwindex[2] >= numvtxw)
2556 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2557 p->vtxwindex[2] = 0;
2562 else if (!strcmp(pchunk->id, "MATT0000"))
2565 if (recordsize != sizeof(*p))
2566 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2567 // byteswap in place and keep the pointer
2568 nummatts = numrecords;
2569 matts = (pskmatt_t *)buffer;
2570 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2576 else if (!strcmp(pchunk->id, "REFSKELT"))
2579 if (recordsize != sizeof(*p))
2580 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2581 // byteswap in place and keep the pointer
2582 numbones = numrecords;
2583 bones = (pskboneinfo_t *)buffer;
2584 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2586 p->numchildren = LittleLong(p->numchildren);
2587 p->parent = LittleLong(p->parent);
2588 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2589 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2590 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2591 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2592 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2593 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2594 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2595 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2596 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2597 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2598 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2599 #ifdef PSKQUATNEGATIONS
2602 p->basepose.quat[0] *= -1;
2603 p->basepose.quat[1] *= -1;
2604 p->basepose.quat[2] *= -1;
2608 p->basepose.quat[0] *= 1;
2609 p->basepose.quat[1] *= -1;
2610 p->basepose.quat[2] *= 1;
2613 if (p->parent < 0 || p->parent >= numbones)
2615 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2621 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2624 if (recordsize != sizeof(*p))
2625 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2626 // byteswap in place and keep the pointer
2627 numrawweights = numrecords;
2628 rawweights = (pskrawweights_t *)buffer;
2629 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2631 p->weight = LittleFloat(p->weight);
2632 p->pntsindex = LittleLong(p->pntsindex);
2633 p->boneindex = LittleLong(p->boneindex);
2634 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2636 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2639 if (p->boneindex < 0 || p->boneindex >= numbones)
2641 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2649 while (animbuffer < animbufferend)
2651 pchunk = (pskchunk_t *)animbuffer;
2652 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2653 version = LittleLong(pchunk->version);
2654 recordsize = LittleLong(pchunk->recordsize);
2655 numrecords = LittleLong(pchunk->numrecords);
2656 if (developer_extra.integer)
2657 Con_DPrintf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2658 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2659 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);
2660 if (!strcmp(pchunk->id, "ANIMHEAD"))
2664 else if (!strcmp(pchunk->id, "BONENAMES"))
2667 if (recordsize != sizeof(*p))
2668 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2669 // byteswap in place and keep the pointer
2670 numanimbones = numrecords;
2671 //animbones = (pskboneinfo_t *)animbuffer;
2672 // NOTE: supposedly psa does not need to match the psk model, the
2673 // bones missing from the psa would simply use their base
2674 // positions from the psk, but this is hard for me to implement
2675 // and people can easily make animations that match.
2676 if (numanimbones != numbones)
2677 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2678 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2680 p->numchildren = LittleLong(p->numchildren);
2681 p->parent = LittleLong(p->parent);
2682 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2683 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2684 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2685 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2686 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2687 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2688 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2689 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2690 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2691 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2692 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2693 #ifdef PSKQUATNEGATIONS
2696 p->basepose.quat[0] *= -1;
2697 p->basepose.quat[1] *= -1;
2698 p->basepose.quat[2] *= -1;
2702 p->basepose.quat[0] *= 1;
2703 p->basepose.quat[1] *= -1;
2704 p->basepose.quat[2] *= 1;
2707 if (p->parent < 0 || p->parent >= numanimbones)
2709 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2712 // check that bones are the same as in the base
2713 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2714 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2718 else if (!strcmp(pchunk->id, "ANIMINFO"))
2721 if (recordsize != sizeof(*p))
2722 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2723 // byteswap in place and keep the pointer
2724 numanims = numrecords;
2725 anims = (pskaniminfo_t *)animbuffer;
2726 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2728 p->numbones = LittleLong(p->numbones);
2729 p->playtime = LittleFloat(p->playtime);
2730 p->fps = LittleFloat(p->fps);
2731 p->firstframe = LittleLong(p->firstframe);
2732 p->numframes = LittleLong(p->numframes);
2733 if (p->numbones != numbones)
2734 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2738 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2741 if (recordsize != sizeof(*p))
2742 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2743 numanimkeys = numrecords;
2744 animkeys = (pskanimkeys_t *)animbuffer;
2745 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2747 p->origin[0] = LittleFloat(p->origin[0]);
2748 p->origin[1] = LittleFloat(p->origin[1]);
2749 p->origin[2] = LittleFloat(p->origin[2]);
2750 p->quat[0] = LittleFloat(p->quat[0]);
2751 p->quat[1] = LittleFloat(p->quat[1]);
2752 p->quat[2] = LittleFloat(p->quat[2]);
2753 p->quat[3] = LittleFloat(p->quat[3]);
2754 p->frametime = LittleFloat(p->frametime);
2755 #ifdef PSKQUATNEGATIONS
2756 if (index % numbones)
2771 // TODO: allocate bonepose stuff
2774 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2777 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2778 Host_Error("%s: missing required chunks", loadmodel->name);
2780 loadmodel->numframes = 0;
2781 for (index = 0;index < numanims;index++)
2782 loadmodel->numframes += anims[index].numframes;
2784 if (numanimkeys != numbones * loadmodel->numframes)
2785 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2787 meshvertices = numvtxw;
2788 meshtriangles = numfaces;
2790 // load external .skin files if present
2791 skinfiles = Mod_LoadSkinFiles();
2792 if (loadmodel->numskins < 1)
2793 loadmodel->numskins = 1;
2794 loadmodel->num_bones = numbones;
2795 loadmodel->num_poses = loadmodel->numframes;
2796 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2797 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2798 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2799 loadmodel->surfmesh.num_vertices = meshvertices;
2800 loadmodel->surfmesh.num_triangles = meshtriangles;
2801 // do most allocations as one merged chunk
2802 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);
2803 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2804 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2805 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2806 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2807 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2808 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2809 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2810 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2811 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2812 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2813 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2814 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2815 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2816 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2817 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2818 loadmodel->surfmesh.num_blends = 0;
2819 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2820 if (loadmodel->surfmesh.num_vertices <= 65536)
2821 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2822 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2823 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(blendweights_t));
2825 for (i = 0;i < loadmodel->numskins;i++)
2827 loadmodel->skinscenes[i].firstframe = i;
2828 loadmodel->skinscenes[i].framecount = 1;
2829 loadmodel->skinscenes[i].loop = true;
2830 loadmodel->skinscenes[i].framerate = 10;
2834 for (index = 0, i = 0;index < nummatts;index++)
2836 // since psk models do not have named sections, reuse their shader name as the section name
2837 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2838 loadmodel->sortedmodelsurfaces[index] = index;
2839 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2840 loadmodel->data_surfaces[index].num_firstvertex = 0;
2841 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2844 // copy over the vertex locations and texcoords
2845 for (index = 0;index < numvtxw;index++)
2847 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2848 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2849 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2850 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2851 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2854 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2855 for (index = 0;index < numfaces;index++)
2856 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2857 for (index = 0, i = 0;index < nummatts;index++)
2859 loadmodel->data_surfaces[index].num_firsttriangle = i;
2860 i += loadmodel->data_surfaces[index].num_triangles;
2861 loadmodel->data_surfaces[index].num_triangles = 0;
2863 for (index = 0;index < numfaces;index++)
2865 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2866 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2867 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2868 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2871 // copy over the bones
2872 for (index = 0;index < numbones;index++)
2874 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2875 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2876 if (loadmodel->data_bones[index].parent >= index)
2877 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2880 // sort the psk point weights into the vertex weight tables
2881 // (which only accept up to 4 bones per vertex)
2882 for (index = 0;index < numvtxw;index++)
2884 int weightindex[4] = { 0, 0, 0, 0 };
2885 float weightinfluence[4] = { 0, 0, 0, 0 };
2887 for (j = 0;j < numrawweights;j++)
2889 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2891 int boneindex = rawweights[j].boneindex;
2892 float influence = rawweights[j].weight;
2893 for (l = 0;l < 4;l++)
2895 if (weightinfluence[l] < influence)
2897 // move lower influence weights out of the way first
2899 for (l2 = 3;l2 > l;l2--)
2901 weightinfluence[l2] = weightinfluence[l2-1];
2902 weightindex[l2] = weightindex[l2-1];
2904 // store the new weight
2905 weightinfluence[l] = influence;
2906 weightindex[l] = boneindex;
2912 loadmodel->surfmesh.blends[index] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
2914 if (loadmodel->surfmesh.num_blends < loadmodel->surfmesh.num_vertices)
2915 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2917 // set up the animscenes based on the anims
2918 for (index = 0, i = 0;index < numanims;index++)
2920 for (j = 0;j < anims[index].numframes;j++, i++)
2922 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2923 loadmodel->animscenes[i].firstframe = i;
2924 loadmodel->animscenes[i].framecount = 1;
2925 loadmodel->animscenes[i].loop = true;
2926 loadmodel->animscenes[i].framerate = anims[index].fps;
2930 // calculate the scaling value for bone origins so they can be compressed to short
2932 for (index = 0;index < numanimkeys;index++)
2934 pskanimkeys_t *k = animkeys + index;
2935 biggestorigin = max(biggestorigin, fabs(k->origin[0]));
2936 biggestorigin = max(biggestorigin, fabs(k->origin[1]));
2937 biggestorigin = max(biggestorigin, fabs(k->origin[2]));
2939 loadmodel->num_posescale = biggestorigin / 32767.0f;
2940 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2942 // load the poses from the animkeys
2943 for (index = 0;index < numanimkeys;index++)
2945 pskanimkeys_t *k = animkeys + index;
2947 Vector4Copy(k->quat, quat);
2949 Vector4Negate(quat, quat);
2950 Vector4Normalize2(quat, quat);
2951 // compress poses to the short[6] format for longterm storage
2952 loadmodel->data_poses6s[index*6+0] = k->origin[0] * loadmodel->num_poseinvscale;
2953 loadmodel->data_poses6s[index*6+1] = k->origin[1] * loadmodel->num_poseinvscale;
2954 loadmodel->data_poses6s[index*6+2] = k->origin[2] * loadmodel->num_poseinvscale;
2955 loadmodel->data_poses6s[index*6+3] = quat[0] * 32767.0f;
2956 loadmodel->data_poses6s[index*6+4] = quat[1] * 32767.0f;
2957 loadmodel->data_poses6s[index*6+5] = quat[2] * 32767.0f;
2959 Mod_FreeSkinFiles(skinfiles);
2960 Mem_Free(animfilebuffer);
2961 Mod_MakeSortedSurfaces(loadmodel);
2963 // compute all the mesh information that was not loaded from the file
2964 // TODO: honor smoothing groups somehow?
2965 if (loadmodel->surfmesh.data_element3s)
2966 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2967 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2968 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2969 Mod_BuildBaseBonePoses();
2970 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2971 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);
2972 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2973 Mod_Alias_CalculateBoundingBox();
2975 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2977 if (!loadmodel->surfmesh.isanimated)
2979 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2980 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2981 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2982 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2983 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2984 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2988 void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2990 unsigned char *data;
2992 unsigned char *pbase, *pend;
2993 iqmheader_t *header;
2994 skinfile_t *skinfiles;
2995 int i, j, k, meshvertices, meshtriangles;
2996 float *vposition = NULL, *vtexcoord = NULL, *vnormal = NULL, *vtangent = NULL;
2997 unsigned char *vblendindexes = NULL, *vblendweights = NULL;
3002 iqmbounds_t *bounds;
3003 iqmvertexarray_t *va;
3004 unsigned short *framedata;
3005 float biggestorigin;
3006 const int *inelements;
3008 float *outvertex, *outnormal, *outtexcoord, *outsvector, *outtvector;
3010 pbase = (unsigned char *)buffer;
3011 pend = (unsigned char *)bufferend;
3012 header = (iqmheader_t *)buffer;
3013 if (memcmp(header->id, "INTERQUAKEMODEL", 16))
3014 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model", loadmodel->name);
3015 if (LittleLong(header->version) != 1)
3016 Host_Error ("Mod_INTERQUAKEMODEL_Load: only version 1 models are currently supported (name = %s)", loadmodel->name);
3018 loadmodel->modeldatatypestring = "IQM";
3020 loadmodel->type = mod_alias;
3021 loadmodel->synctype = ST_RAND;
3024 header->version = LittleLong(header->version);
3025 header->filesize = LittleLong(header->filesize);
3026 header->flags = LittleLong(header->flags);
3027 header->num_text = LittleLong(header->num_text);
3028 header->ofs_text = LittleLong(header->ofs_text);
3029 header->num_meshes = LittleLong(header->num_meshes);
3030 header->ofs_meshes = LittleLong(header->ofs_meshes);
3031 header->num_vertexarrays = LittleLong(header->num_vertexarrays);
3032 header->num_vertexes = LittleLong(header->num_vertexes);
3033 header->ofs_vertexarrays = LittleLong(header->ofs_vertexarrays);
3034 header->num_triangles = LittleLong(header->num_triangles);
3035 header->ofs_triangles = LittleLong(header->ofs_triangles);
3036 header->ofs_neighbors = LittleLong(header->ofs_neighbors);
3037 header->num_joints = LittleLong(header->num_joints);
3038 header->ofs_joints = LittleLong(header->ofs_joints);
3039 header->num_poses = LittleLong(header->num_poses);
3040 header->ofs_poses = LittleLong(header->ofs_poses);
3041 header->num_anims = LittleLong(header->num_anims);
3042 header->ofs_anims = LittleLong(header->ofs_anims);
3043 header->num_frames = LittleLong(header->num_frames);
3044 header->num_framechannels = LittleLong(header->num_framechannels);
3045 header->ofs_frames = LittleLong(header->ofs_frames);
3046 header->ofs_bounds = LittleLong(header->ofs_bounds);
3047 header->num_comment = LittleLong(header->num_comment);
3048 header->ofs_comment = LittleLong(header->ofs_comment);
3049 header->num_extensions = LittleLong(header->num_extensions);
3050 header->ofs_extensions = LittleLong(header->ofs_extensions);
3052 if (header->num_triangles < 1 || header->num_vertexes < 3 || header->num_vertexarrays < 1 || header->num_meshes < 1)
3054 Con_Printf("%s has no geometry\n", loadmodel->name);
3057 if (header->num_frames < 1 || header->num_anims < 1)
3059 Con_Printf("%s has no animations\n", loadmodel->name);
3063 if (pbase + header->ofs_text + header->num_text > pend ||
3064 pbase + header->ofs_meshes + header->num_meshes*sizeof(iqmmesh_t) > pend ||
3065 pbase + header->ofs_vertexarrays + header->num_vertexarrays*sizeof(iqmvertexarray_t) > pend ||
3066 pbase + header->ofs_triangles + header->num_triangles*sizeof(int[3]) > pend ||
3067 (header->ofs_neighbors && pbase + header->ofs_neighbors + header->num_triangles*sizeof(int[3]) > pend) ||
3068 pbase + header->ofs_joints + header->num_joints*sizeof(iqmjoint_t) > pend ||
3069 pbase + header->ofs_poses + header->num_poses*sizeof(iqmpose_t) > pend ||
3070 pbase + header->ofs_anims + header->num_anims*sizeof(iqmanim_t) > pend ||
3071 pbase + header->ofs_frames + header->num_frames*header->num_framechannels*sizeof(unsigned short) > pend ||
3072 (header->ofs_bounds && pbase + header->ofs_bounds + header->num_frames*sizeof(iqmbounds_t) > pend) ||
3073 pbase + header->ofs_comment + header->num_comment > pend)
3075 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3079 va = (iqmvertexarray_t *)(pbase + header->ofs_vertexarrays);
3080 for (i = 0;i < (int)header->num_vertexarrays;i++)
3083 va[i].type = LittleLong(va[i].type);
3084 va[i].flags = LittleLong(va[i].flags);
3085 va[i].format = LittleLong(va[i].format);
3086 va[i].size = LittleLong(va[i].size);
3087 va[i].offset = LittleLong(va[i].offset);
3088 vsize = header->num_vertexes*va[i].size;
3089 switch (va[i].format)
3091 case IQM_FLOAT: vsize *= sizeof(float); break;
3092 case IQM_UBYTE: vsize *= sizeof(unsigned char); break;
3095 if (pbase + va[i].offset + vsize > pend)
3100 if (va[i].format == IQM_FLOAT && va[i].size == 3)
3101 vposition = (float *)(pbase + va[i].offset);
3104 if (va[i].format == IQM_FLOAT && va[i].size == 2)
3105 vtexcoord = (float *)(pbase + va[i].offset);
3108 if (va[i].format == IQM_FLOAT && va[i].size == 3)
3109 vnormal = (float *)(pbase + va[i].offset);
3112 if (va[i].format == IQM_FLOAT && va[i].size == 4)
3113 vtangent = (float *)(pbase + va[i].offset);
3115 case IQM_BLENDINDEXES:
3116 if (va[i].format == IQM_UBYTE && va[i].size == 4)
3117 vblendindexes = (unsigned char *)(pbase + va[i].offset);
3119 case IQM_BLENDWEIGHTS:
3120 if (va[i].format == IQM_UBYTE && va[i].size == 4)
3121 vblendweights = (unsigned char *)(pbase + va[i].offset);
3125 if (!vposition || !vtexcoord || !vblendindexes || !vblendweights)
3127 Con_Printf("%s is missing vertex array data\n", loadmodel->name);
3131 text = header->num_text && header->ofs_text ? (const char *)(pbase + header->ofs_text) : "";
3133 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
3134 loadmodel->DrawSky = NULL;
3135 loadmodel->DrawAddWaterPlanes = NULL;
3136 loadmodel->Draw = R_Q1BSP_Draw;
3137 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
3138 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
3139 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
3140 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
3141 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
3142 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
3143 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
3144 loadmodel->DrawLight = R_Q1BSP_DrawLight;
3145 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
3146 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
3147 loadmodel->PointSuperContents = NULL;
3149 // load external .skin files if present
3150 skinfiles = Mod_LoadSkinFiles();
3151 if (loadmodel->numskins < 1)
3152 loadmodel->numskins = 1;
3154 loadmodel->numframes = header->num_anims;
3155 loadmodel->num_bones = header->num_joints;
3156 loadmodel->num_poses = header->num_frames;
3157 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = header->num_meshes;
3158 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3159 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3161 meshvertices = header->num_vertexes;
3162 meshtriangles = header->num_triangles;
3164 // do most allocations as one merged chunk
3165 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));
3166 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
3167 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
3168 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
3169 loadmodel->surfmesh.num_vertices = meshvertices;
3170 loadmodel->surfmesh.num_triangles = meshtriangles;
3171 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3172 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3173 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
3174 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3175 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3176 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
3177 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
3178 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
3179 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
3180 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
3181 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
3182 loadmodel->surfmesh.num_blends = 0;
3183 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
3184 if (meshvertices <= 65536)
3185 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
3186 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
3187 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
3189 for (i = 0;i < loadmodel->numskins;i++)
3191 loadmodel->skinscenes[i].firstframe = i;
3192 loadmodel->skinscenes[i].framecount = 1;
3193 loadmodel->skinscenes[i].loop = true;
3194 loadmodel->skinscenes[i].framerate = 10;
3197 // load the bone info
3198 joint = (iqmjoint_t *) (pbase + header->ofs_joints);
3199 for (i = 0;i < loadmodel->num_bones;i++)
3201 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3202 joint[i].name = LittleLong(joint[i].name);
3203 joint[i].parent = LittleLong(joint[i].parent);
3204 for (j = 0;j < 3;j++)
3206 joint[i].origin[j] = LittleFloat(joint[i].origin[j]);
3207 joint[i].rotation[j] = LittleFloat(joint[i].rotation[j]);
3208 joint[i].scale[j] = LittleFloat(joint[i].scale[j]);
3210 strlcpy(loadmodel->data_bones[i].name, &text[joint[i].name], sizeof(loadmodel->data_bones[i].name));
3211 loadmodel->data_bones[i].parent = joint[i].parent;
3212 if (loadmodel->data_bones[i].parent >= i)
3213 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3214 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]);
3215 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3216 if (loadmodel->data_bones[i].parent >= 0)
3218 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3219 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3220 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3222 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3225 // set up the animscenes based on the anims
3226 anim = (iqmanim_t *) (pbase + header->ofs_anims);
3227 for (i = 0;i < (int)header->num_anims;i++)
3229 anim[i].name = LittleLong(anim[i].name);
3230 anim[i].first_frame = LittleLong(anim[i].first_frame);
3231 anim[i].num_frames = LittleLong(anim[i].num_frames);
3232 anim[i].framerate = LittleFloat(anim[i].framerate);
3233 anim[i].flags = LittleLong(anim[i].flags);
3234 strlcpy(loadmodel->animscenes[i].name, &text[anim[i].name], sizeof(loadmodel->animscenes[i].name));
3235 loadmodel->animscenes[i].firstframe = anim[i].first_frame;
3236 loadmodel->animscenes[i].framecount = anim[i].num_frames;
3237 loadmodel->animscenes[i].loop = ((anim[i].flags & IQM_LOOP) != 0);
3238 loadmodel->animscenes[i].framerate = anim[i].framerate;
3241 pose = (iqmpose_t *) (pbase + header->ofs_poses);
3243 for (i = 0;i < (int)header->num_poses;i++)
3246 pose[i].parent = LittleLong(pose[i].parent);
3247 pose[i].channelmask = LittleLong(pose[i].channelmask);
3248 pose[i].channeloffset[0] = LittleFloat(pose[i].channeloffset[0]);
3249 pose[i].channeloffset[1] = LittleFloat(pose[i].channeloffset[1]);
3250 pose[i].channeloffset[2] = LittleFloat(pose[i].channeloffset[2]);
3251 pose[i].channeloffset[3] = LittleFloat(pose[i].channeloffset[3]);
3252 pose[i].channeloffset[4] = LittleFloat(pose[i].channeloffset[4]);
3253 pose[i].channeloffset[5] = LittleFloat(pose[i].channeloffset[5]);
3254 pose[i].channeloffset[6] = LittleFloat(pose[i].channeloffset[6]);
3255 pose[i].channeloffset[7] = LittleFloat(pose[i].channeloffset[7]);
3256 pose[i].channeloffset[8] = LittleFloat(pose[i].channeloffset[8]);
3257 pose[i].channelscale[0] = LittleFloat(pose[i].channelscale[0]);
3258 pose[i].channelscale[1] = LittleFloat(pose[i].channelscale[1]);
3259 pose[i].channelscale[2] = LittleFloat(pose[i].channelscale[2]);
3260 pose[i].channelscale[3] = LittleFloat(pose[i].channelscale[3]);
3261 pose[i].channelscale[4] = LittleFloat(pose[i].channelscale[4]);
3262 pose[i].channelscale[5] = LittleFloat(pose[i].channelscale[5]);
3263 pose[i].channelscale[6] = LittleFloat(pose[i].channelscale[6]);
3264 pose[i].channelscale[7] = LittleFloat(pose[i].channelscale[7]);
3265 pose[i].channelscale[8] = LittleFloat(pose[i].channelscale[8]);
3266 f = fabs(pose[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3267 f = fabs(pose[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3268 f = fabs(pose[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3269 f = fabs(pose[i].channeloffset[0] + 0xFFFF*pose[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3270 f = fabs(pose[i].channeloffset[1] + 0xFFFF*pose[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3271 f = fabs(pose[i].channeloffset[2] + 0xFFFF*pose[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3273 loadmodel->num_posescale = biggestorigin / 32767.0f;
3274 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3276 // load the pose data
3277 framedata = (unsigned short *) (pbase + header->ofs_frames);
3278 for (i = 0, k = 0;i < (int)header->num_frames;i++)
3280 for (j = 0;j < (int)header->num_poses;j++, k++)
3282 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));
3283 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));
3284 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));
3285 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));
3286 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));
3287 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));
3288 // skip scale data for now
3289 if(pose[j].channelmask&64) framedata++;
3290 if(pose[j].channelmask&128) framedata++;
3291 if(pose[j].channelmask&256) framedata++;
3295 // load bounding box data
3296 if (header->ofs_bounds)
3298 float xyradius = 0, radius = 0;
3299 bounds = (iqmbounds_t *) (pbase + header->ofs_bounds);
3300 VectorClear(loadmodel->normalmins);
3301 VectorClear(loadmodel->normalmaxs);
3302 for (i = 0; i < (int)header->num_frames;i++)
3304 bounds[i].mins[0] = LittleFloat(bounds[i].mins[0]);
3305 bounds[i].mins[1] = LittleFloat(bounds[i].mins[1]);
3306 bounds[i].mins[2] = LittleFloat(bounds[i].mins[2]);
3307 bounds[i].maxs[0] = LittleFloat(bounds[i].maxs[0]);
3308 bounds[i].maxs[1] = LittleFloat(bounds[i].maxs[1]);
3309 bounds[i].maxs[2] = LittleFloat(bounds[i].maxs[2]);
3310 bounds[i].xyradius = LittleFloat(bounds[i].xyradius);
3311 bounds[i].radius = LittleFloat(bounds[i].radius);
3314 VectorCopy(bounds[i].mins, loadmodel->normalmins);
3315 VectorCopy(bounds[i].maxs, loadmodel->normalmaxs);
3319 if (loadmodel->normalmins[0] > bounds[i].mins[0]) loadmodel->normalmins[0] = bounds[i].mins[0];
3320 if (loadmodel->normalmins[1] > bounds[i].mins[1]) loadmodel->normalmins[1] = bounds[i].mins[1];
3321 if (loadmodel->normalmins[2] > bounds[i].mins[2]) loadmodel->normalmins[2] = bounds[i].mins[2];
3322 if (loadmodel->normalmaxs[0] < bounds[i].maxs[0]) loadmodel->normalmaxs[0] = bounds[i].maxs[0];
3323 if (loadmodel->normalmaxs[1] < bounds[i].maxs[1]) loadmodel->normalmaxs[1] = bounds[i].maxs[1];
3324 if (loadmodel->normalmaxs[2] < bounds[i].maxs[2]) loadmodel->normalmaxs[2] = bounds[i].maxs[2];
3326 if (bounds[i].xyradius > xyradius)
3327 xyradius = bounds[i].xyradius;
3328 if (bounds[i].radius > radius)
3329 radius = bounds[i].radius;
3331 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -xyradius;
3332 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = xyradius;
3333 loadmodel->yawmins[2] = loadmodel->normalmins[2];
3334 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
3335 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
3336 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
3337 loadmodel->radius = radius;
3338 loadmodel->radius2 = radius * radius;
3341 // load triangle data
3342 inelements = (const int *) (pbase + header->ofs_triangles);
3343 outelements = loadmodel->surfmesh.data_element3i;
3344 for (i = 0;i < (int)header->num_triangles;i++)
3346 outelements[0] = LittleLong(inelements[0]);
3347 outelements[1] = LittleLong(inelements[1]);
3348 outelements[2] = LittleLong(inelements[2]);
3352 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, header->num_vertexes, __FILE__, __LINE__);
3354 if (header->ofs_neighbors)
3356 inelements = (const int *) (pbase + header->ofs_neighbors);
3357 outelements = loadmodel->surfmesh.data_neighbor3i;
3358 for (i = 0;i < (int)header->num_triangles;i++)
3360 outelements[0] = LittleLong(inelements[0]);
3361 outelements[1] = LittleLong(inelements[1]);
3362 outelements[2] = LittleLong(inelements[2]);
3369 outvertex = loadmodel->surfmesh.data_vertex3f;
3370 for (i = 0;i < (int)header->num_vertexes;i++)
3372 outvertex[0] = LittleFloat(vposition[0]);
3373 outvertex[1] = LittleFloat(vposition[1]);
3374 outvertex[2] = LittleFloat(vposition[2]);
3379 outtexcoord = loadmodel->surfmesh.data_texcoordtexture2f;
3380 for (i = 0;i < (int)header->num_vertexes;i++)
3382 outtexcoord[0] = LittleFloat(vtexcoord[0]);
3383 outtexcoord[1] = LittleFloat(vtexcoord[1]);
3390 outnormal = loadmodel->surfmesh.data_normal3f;
3391 for (i = 0;i < (int)header->num_vertexes;i++)
3393 outnormal[0] = LittleFloat(vnormal[0]);
3394 outnormal[1] = LittleFloat(vnormal[1]);
3395 outnormal[2] = LittleFloat(vnormal[2]);
3401 if(vnormal && vtangent)
3403 outnormal = loadmodel->surfmesh.data_normal3f;
3404 outsvector = loadmodel->surfmesh.data_svector3f;
3405 outtvector = loadmodel->surfmesh.data_tvector3f;
3406 for (i = 0;i < (int)header->num_vertexes;i++)
3408 outsvector[0] = LittleFloat(vtangent[0]);
3409 outsvector[1] = LittleFloat(vtangent[1]);
3410 outsvector[2] = LittleFloat(vtangent[2]);
3411 if(LittleFloat(vtangent[3]) < 0)
3412 CrossProduct(outsvector, outnormal, outtvector);
3414 CrossProduct(outnormal, outsvector, outtvector);
3422 for (i = 0; i < (int)header->num_vertexes;i++)
3424 blendweights_t weights;
3425 memcpy(weights.index, vblendindexes + i*4, 4);
3426 memcpy(weights.influence, vblendweights + i*4, 4);
3427 loadmodel->surfmesh.blends[i] = Mod_Skeletal_AddBlend(loadmodel, &weights);
3431 mesh = (iqmmesh_t *) (pbase + header->ofs_meshes);
3432 for (i = 0;i < (int)header->num_meshes;i++)
3434 msurface_t *surface;
3436 mesh[i].name = LittleLong(mesh[i].name);
3437 mesh[i].material = LittleLong(mesh[i].material);
3438 mesh[i].first_vertex = LittleLong(mesh[i].first_vertex);
3439 mesh[i].num_vertexes = LittleLong(mesh[i].num_vertexes);
3440 mesh[i].first_triangle = LittleLong(mesh[i].first_triangle);
3441 mesh[i].num_triangles = LittleLong(mesh[i].num_triangles);
3443 loadmodel->sortedmodelsurfaces[i] = i;
3444 surface = loadmodel->data_surfaces + i;
3445 surface->texture = loadmodel->data_textures + i;
3446 surface->num_firsttriangle = mesh[i].first_triangle;
3447 surface->num_triangles = mesh[i].num_triangles;
3448 surface->num_firstvertex = mesh[i].first_vertex;
3449 surface->num_vertices = mesh[i].num_vertexes;
3451 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, &text[mesh[i].name], &text[mesh[i].material]);
3454 Mod_FreeSkinFiles(skinfiles);
3455 Mod_MakeSortedSurfaces(loadmodel);
3457 // compute all the mesh information that was not loaded from the file
3458 if (loadmodel->surfmesh.data_element3s)
3459 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3460 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3462 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
3463 if (!vnormal || !vtangent)
3464 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);
3465 if (!header->ofs_neighbors)
3466 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3467 if (!header->ofs_bounds)
3468 Mod_Alias_CalculateBoundingBox();
3470 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
3472 if (!loadmodel->surfmesh.isanimated)
3474 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3475 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3476 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3477 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3478 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3479 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;