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_Skeletal_AnimateVertices_maxbonepose = 0;
44 static void *Mod_Skeletal_AnimateVertices_bonepose = NULL;
45 void Mod_Skeletal_FreeBuffers(void)
47 if(Mod_Skeletal_AnimateVertices_bonepose)
48 Mem_Free(Mod_Skeletal_AnimateVertices_bonepose);
49 Mod_Skeletal_AnimateVertices_maxbonepose = 0;
50 Mod_Skeletal_AnimateVertices_bonepose = NULL;
52 void *Mod_Skeletal_AnimateVertices_AllocBuffers(size_t nbytes)
54 if(Mod_Skeletal_AnimateVertices_maxbonepose < nbytes)
56 if(Mod_Skeletal_AnimateVertices_bonepose)
57 Mem_Free(Mod_Skeletal_AnimateVertices_bonepose);
58 Mod_Skeletal_AnimateVertices_bonepose = Z_Malloc(nbytes);
59 Mod_Skeletal_AnimateVertices_maxbonepose = nbytes;
61 return Mod_Skeletal_AnimateVertices_bonepose;
64 void Mod_Skeletal_AnimateVertices(const dp_model_t * RESTRICT model, const frameblend_t * RESTRICT frameblend, const skeleton_t *skeleton, float * RESTRICT vertex3f, float * RESTRICT normal3f, float * RESTRICT svector3f, float * RESTRICT tvector3f)
67 if(r_skeletal_use_sse_defined)
68 if(r_skeletal_use_sse.integer)
70 Mod_Skeletal_AnimateVertices_SSE(model, frameblend, skeleton, vertex3f, normal3f, svector3f, tvector3f);
74 Mod_Skeletal_AnimateVertices_Generic(model, frameblend, skeleton, vertex3f, normal3f, svector3f, tvector3f);
77 void Mod_AliasInit (void)
80 Cvar_RegisterVariable(&r_skeletal_debugbone);
81 Cvar_RegisterVariable(&r_skeletal_debugbonecomponent);
82 Cvar_RegisterVariable(&r_skeletal_debugbonevalue);
83 Cvar_RegisterVariable(&r_skeletal_debugtranslatex);
84 Cvar_RegisterVariable(&r_skeletal_debugtranslatey);
85 Cvar_RegisterVariable(&r_skeletal_debugtranslatez);
86 Cvar_RegisterVariable(&mod_alias_supporttagscale);
87 for (i = 0;i < 320;i++)
88 mod_md3_sin[i] = sin(i * M_PI * 2.0f / 256.0);
92 Con_Printf("Skeletal animation uses SSE code path\n");
93 r_skeletal_use_sse_defined = true;
94 Cvar_RegisterVariable(&r_skeletal_use_sse);
97 Con_Printf("Skeletal animation uses generic code path (SSE disabled or not detected)\n");
99 Con_Printf("Skeletal animation uses generic code path (SSE not compiled in)\n");
103 int Mod_Skeletal_AddBlend(dp_model_t *model, const blendweights_t *newweights)
106 blendweights_t *weights;
107 if(!newweights->influence[1])
108 return newweights->index[0];
109 weights = model->surfmesh.data_blendweights;
110 for (i = 0;i < model->surfmesh.num_blends;i++, weights++)
112 if (!memcmp(weights, newweights, sizeof(blendweights_t)))
113 return model->num_bones + i;
115 model->surfmesh.num_blends++;
116 memcpy(weights, newweights, sizeof(blendweights_t));
117 return model->num_bones + i;
120 int Mod_Skeletal_CompressBlend(dp_model_t *model, const int *newindex, const float *newinfluence)
124 blendweights_t newweights;
128 for (i = 0;i < 4;i++)
129 scale += newinfluence[i];
130 scale = 255.0f / scale;
132 for (i = 0;i < 4;i++)
134 newweights.index[i] = newindex[i];
135 newweights.influence[i] = (unsigned char)(newinfluence[i] * scale);
136 total += newweights.influence[i];
140 for (i = 0;i < 4;i++)
142 if(newweights.influence[i] > 0 && total > 255)
144 newweights.influence[i]--;
151 for (i = 0; i < 4;i++)
153 if(newweights.influence[i] < 255 && total < 255)
155 newweights.influence[i]++;
160 return Mod_Skeletal_AddBlend(model, &newweights);
163 void Mod_MD3_AnimateVertices(const dp_model_t * RESTRICT model, const frameblend_t * RESTRICT frameblend, const skeleton_t *skeleton, float * RESTRICT vertex3f, float * RESTRICT normal3f, float * RESTRICT svector3f, float * RESTRICT tvector3f)
166 int i, numblends, blendnum;
167 int numverts = model->surfmesh.num_vertices;
169 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
171 //VectorMA(translate, model->surfmesh.num_morphmdlframetranslate, frameblend[blendnum].lerp, translate);
172 if (frameblend[blendnum].lerp > 0)
173 numblends = blendnum + 1;
175 // special case for the first blend because it avoids some adds and the need to memset the arrays first
176 for (blendnum = 0;blendnum < numblends;blendnum++)
178 const md3vertex_t *verts = model->surfmesh.data_morphmd3vertex + numverts * frameblend[blendnum].subframe;
181 float scale = frameblend[blendnum].lerp * (1.0f / 64.0f);
184 for (i = 0;i < numverts;i++)
186 vertex3f[i * 3 + 0] = verts[i].origin[0] * scale;
187 vertex3f[i * 3 + 1] = verts[i].origin[1] * scale;
188 vertex3f[i * 3 + 2] = verts[i].origin[2] * scale;
193 for (i = 0;i < numverts;i++)
195 vertex3f[i * 3 + 0] += verts[i].origin[0] * scale;
196 vertex3f[i * 3 + 1] += verts[i].origin[1] * scale;
197 vertex3f[i * 3 + 2] += verts[i].origin[2] * scale;
201 // the yaw and pitch stored in md3 models are 8bit quantized angles
202 // (0-255), and as such a lookup table is very well suited to
203 // decoding them, and since cosine is equivalent to sine with an
204 // extra 45 degree rotation, this uses one lookup table for both
205 // sine and cosine with a +64 bias to get cosine.
208 float lerp = frameblend[blendnum].lerp;
211 for (i = 0;i < numverts;i++)
213 normal3f[i * 3 + 0] = mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
214 normal3f[i * 3 + 1] = mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
215 normal3f[i * 3 + 2] = mod_md3_sin[verts[i].pitch + 64] * lerp;
220 for (i = 0;i < numverts;i++)
222 normal3f[i * 3 + 0] += mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
223 normal3f[i * 3 + 1] += mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
224 normal3f[i * 3 + 2] += mod_md3_sin[verts[i].pitch + 64] * lerp;
230 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
231 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
234 for (i = 0;i < numverts;i++, texvecvert++)
236 VectorScale(texvecvert->svec, f, svector3f + i*3);
237 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
242 for (i = 0;i < numverts;i++, texvecvert++)
244 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
245 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
251 void Mod_MDL_AnimateVertices(const dp_model_t * RESTRICT model, const frameblend_t * RESTRICT frameblend, const skeleton_t *skeleton, float * RESTRICT vertex3f, float * RESTRICT normal3f, float * RESTRICT svector3f, float * RESTRICT tvector3f)
254 int i, numblends, blendnum;
255 int numverts = model->surfmesh.num_vertices;
257 VectorClear(translate);
259 // blend the frame translates to avoid redundantly doing so on each vertex
260 // (a bit of a brain twister but it works)
261 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
263 if (model->surfmesh.data_morphmd2framesize6f)
264 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6 + 3, translate);
266 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.num_morphmdlframetranslate, translate);
267 if (frameblend[blendnum].lerp > 0)
268 numblends = blendnum + 1;
270 // special case for the first blend because it avoids some adds and the need to memset the arrays first
271 for (blendnum = 0;blendnum < numblends;blendnum++)
273 const trivertx_t *verts = model->surfmesh.data_morphmdlvertex + numverts * frameblend[blendnum].subframe;
277 if (model->surfmesh.data_morphmd2framesize6f)
278 VectorScale(model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6, frameblend[blendnum].lerp, scale);
280 VectorScale(model->surfmesh.num_morphmdlframescale, frameblend[blendnum].lerp, scale);
283 for (i = 0;i < numverts;i++)
285 vertex3f[i * 3 + 0] = translate[0] + verts[i].v[0] * scale[0];
286 vertex3f[i * 3 + 1] = translate[1] + verts[i].v[1] * scale[1];
287 vertex3f[i * 3 + 2] = translate[2] + verts[i].v[2] * scale[2];
292 for (i = 0;i < numverts;i++)
294 vertex3f[i * 3 + 0] += verts[i].v[0] * scale[0];
295 vertex3f[i * 3 + 1] += verts[i].v[1] * scale[1];
296 vertex3f[i * 3 + 2] += verts[i].v[2] * scale[2];
300 // the vertex normals in mdl models are an index into a table of
301 // 162 unique values, this very crude quantization reduces the
302 // vertex normal to only one byte, which saves a lot of space but
303 // also makes lighting pretty coarse
306 float lerp = frameblend[blendnum].lerp;
309 for (i = 0;i < numverts;i++)
311 const float *vn = m_bytenormals[verts[i].lightnormalindex];
312 VectorScale(vn, lerp, normal3f + i*3);
317 for (i = 0;i < numverts;i++)
319 const float *vn = m_bytenormals[verts[i].lightnormalindex];
320 VectorMA(normal3f + i*3, lerp, vn, normal3f + i*3);
326 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
327 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
330 for (i = 0;i < numverts;i++, texvecvert++)
332 VectorScale(texvecvert->svec, f, svector3f + i*3);
333 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
338 for (i = 0;i < numverts;i++, texvecvert++)
340 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
341 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
348 int Mod_Alias_GetTagMatrix(const dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, int tagindex, matrix4x4_t *outmatrix)
351 matrix4x4_t parentbonematrix;
352 matrix4x4_t tempbonematrix;
353 matrix4x4_t bonematrix;
354 matrix4x4_t blendmatrix;
361 *outmatrix = identitymatrix;
362 if (skeleton && skeleton->relativetransforms)
364 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
366 *outmatrix = skeleton->relativetransforms[tagindex];
367 while ((tagindex = model->data_bones[tagindex].parent) >= 0)
370 Matrix4x4_Concat(outmatrix, &skeleton->relativetransforms[tagindex], &temp);
373 else if (model->num_bones)
375 if (tagindex < 0 || tagindex >= model->num_bones)
377 Matrix4x4_Clear(&blendmatrix);
378 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
380 lerp = frameblend[blendindex].lerp;
381 Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
382 parenttagindex = tagindex;
383 while ((parenttagindex = model->data_bones[parenttagindex].parent) >= 0)
385 Matrix4x4_FromBonePose6s(&parentbonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + parenttagindex));
386 tempbonematrix = bonematrix;
387 Matrix4x4_Concat(&bonematrix, &parentbonematrix, &tempbonematrix);
389 Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
391 *outmatrix = blendmatrix;
393 else if (model->num_tags)
395 if (tagindex < 0 || tagindex >= model->num_tags)
397 for (k = 0;k < 12;k++)
399 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
401 lerp = frameblend[blendindex].lerp;
402 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
403 for (k = 0;k < 12;k++)
404 blendtag[k] += input[k] * lerp;
406 Matrix4x4_FromArray12FloatGL(outmatrix, blendtag);
409 if(!mod_alias_supporttagscale.integer)
410 Matrix4x4_Normalize3(outmatrix, outmatrix);
415 int Mod_Alias_GetExtendedTagInfoForIndex(const dp_model_t *model, unsigned int skin, const frameblend_t *frameblend, const skeleton_t *skeleton, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
420 matrix4x4_t bonematrix;
421 matrix4x4_t blendmatrix;
425 if (skeleton && skeleton->relativetransforms)
427 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
429 *parentindex = skeleton->model->data_bones[tagindex].parent;
430 *tagname = skeleton->model->data_bones[tagindex].name;
431 *tag_localmatrix = skeleton->relativetransforms[tagindex];
434 else if (model->num_bones)
436 if (tagindex < 0 || tagindex >= model->num_bones)
438 *parentindex = model->data_bones[tagindex].parent;
439 *tagname = model->data_bones[tagindex].name;
440 Matrix4x4_Clear(&blendmatrix);
441 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
443 lerp = frameblend[blendindex].lerp;
444 Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
445 Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
447 *tag_localmatrix = blendmatrix;
450 else if (model->num_tags)
452 if (tagindex < 0 || tagindex >= model->num_tags)
455 *tagname = model->data_tags[tagindex].name;
456 for (k = 0;k < 12;k++)
458 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
460 lerp = frameblend[blendindex].lerp;
461 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
462 for (k = 0;k < 12;k++)
463 blendtag[k] += input[k] * lerp;
465 Matrix4x4_FromArray12FloatGL(tag_localmatrix, blendtag);
472 int Mod_Alias_GetTagIndexForName(const dp_model_t *model, unsigned int skin, const char *tagname)
475 if(skin >= (unsigned int)model->numskins)
477 if (model->num_bones)
478 for (i = 0;i < model->num_bones;i++)
479 if (!strcasecmp(tagname, model->data_bones[i].name))
482 for (i = 0;i < model->num_tags;i++)
483 if (!strcasecmp(tagname, model->data_tags[i].name))
488 static void Mod_BuildBaseBonePoses(void)
491 matrix4x4_t *basebonepose;
492 float *outinvmatrix = loadmodel->data_baseboneposeinverse;
493 matrix4x4_t bonematrix;
494 matrix4x4_t tempbonematrix;
495 if (!loadmodel->num_bones)
497 basebonepose = (matrix4x4_t *)Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(matrix4x4_t));
498 for (boneindex = 0;boneindex < loadmodel->num_bones;boneindex++)
500 Matrix4x4_FromBonePose6s(&bonematrix, loadmodel->num_posescale, loadmodel->data_poses6s + 6 * boneindex);
501 if (loadmodel->data_bones[boneindex].parent >= 0)
503 tempbonematrix = bonematrix;
504 Matrix4x4_Concat(&bonematrix, basebonepose + loadmodel->data_bones[boneindex].parent, &tempbonematrix);
506 basebonepose[boneindex] = bonematrix;
507 Matrix4x4_Invert_Simple(&tempbonematrix, basebonepose + boneindex);
508 Matrix4x4_ToArray12FloatD3D(&tempbonematrix, outinvmatrix + 12*boneindex);
510 Mem_Free(basebonepose);
513 static void Mod_Alias_CalculateBoundingBox(void)
516 qboolean firstvertex = true;
517 float dist, yawradius, radius;
520 frameblend_t frameblend[MAX_FRAMEBLENDS];
521 memset(frameblend, 0, sizeof(frameblend));
522 frameblend[0].lerp = 1;
523 vertex3f = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
524 VectorClear(loadmodel->normalmins);
525 VectorClear(loadmodel->normalmaxs);
528 for (frameblend[0].subframe = 0;frameblend[0].subframe < loadmodel->num_poses;frameblend[0].subframe++)
530 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, vertex3f, NULL, NULL, NULL);
531 for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
536 VectorCopy(v, loadmodel->normalmins);
537 VectorCopy(v, loadmodel->normalmaxs);
541 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
542 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
543 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
544 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
545 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
546 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
548 dist = v[0] * v[0] + v[1] * v[1];
549 if (yawradius < dist)
558 radius = sqrt(radius);
559 yawradius = sqrt(yawradius);
560 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
561 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
562 loadmodel->yawmins[2] = loadmodel->normalmins[2];
563 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
564 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
565 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
566 loadmodel->radius = radius;
567 loadmodel->radius2 = radius * radius;
570 static void Mod_Alias_MorphMesh_CompileFrames(void)
573 frameblend_t frameblend[MAX_FRAMEBLENDS];
574 unsigned char *datapointer;
575 memset(frameblend, 0, sizeof(frameblend));
576 frameblend[0].lerp = 1;
577 datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
578 loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
579 loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
580 loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
581 loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
582 loadmodel->surfmesh.data_morphtexvecvertex = (texvecvertex_t *)datapointer;datapointer += loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices * sizeof(texvecvertex_t);
583 // this counts down from the last frame to the first so that the final data in surfmesh is for frame zero (which is what the renderer expects to be there)
584 for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
586 frameblend[0].subframe = i;
587 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
588 Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, r_smoothnormals_areaweighting.integer != 0);
589 // encode the svector and tvector in 3 byte format for permanent storage
590 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
592 VectorScaleCast(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
593 VectorScaleCast(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
598 static void Mod_MDLMD2MD3_TraceLine(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask)
601 float segmentmins[3], segmentmaxs[3];
603 static int maxvertices = 0;
604 static float *vertex3f = NULL;
605 memset(trace, 0, sizeof(*trace));
607 trace->realfraction = 1;
608 trace->hitsupercontentsmask = hitsupercontentsmask;
609 if (maxvertices < model->surfmesh.num_vertices)
613 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
614 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
616 segmentmins[0] = min(start[0], end[0]) - 1;
617 segmentmins[1] = min(start[1], end[1]) - 1;
618 segmentmins[2] = min(start[2], end[2]) - 1;
619 segmentmaxs[0] = max(start[0], end[0]) + 1;
620 segmentmaxs[1] = max(start[1], end[1]) + 1;
621 segmentmaxs[2] = max(start[2], end[2]) + 1;
622 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
623 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
624 Collision_TraceLineTriangleMeshFloat(trace, start, end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs);
627 static int maxvertices = 0;
628 static float *vertex3f = NULL;
630 static void Mod_MDLMD2MD3_TraceBox(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask)
633 vec3_t shiftstart, shiftend;
634 float segmentmins[3], segmentmaxs[3];
636 colboxbrushf_t thisbrush_start, thisbrush_end;
637 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
639 if (VectorCompare(boxmins, boxmaxs))
641 VectorAdd(start, boxmins, shiftstart);
642 VectorAdd(end, boxmins, shiftend);
643 Mod_MDLMD2MD3_TraceLine(model, frameblend, skeleton, trace, shiftstart, shiftend, hitsupercontentsmask);
644 VectorSubtract(trace->endpos, boxmins, trace->endpos);
648 // box trace, performed as brush trace
649 memset(trace, 0, sizeof(*trace));
651 trace->realfraction = 1;
652 trace->hitsupercontentsmask = hitsupercontentsmask;
653 if (maxvertices < model->surfmesh.num_vertices)
657 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
658 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
660 segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
661 segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
662 segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
663 segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
664 segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
665 segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
666 VectorAdd(start, boxmins, boxstartmins);
667 VectorAdd(start, boxmaxs, boxstartmaxs);
668 VectorAdd(end, boxmins, boxendmins);
669 VectorAdd(end, boxmaxs, boxendmaxs);
670 Collision_BrushForBox(&thisbrush_start, boxstartmins, boxstartmaxs, 0, 0, NULL);
671 Collision_BrushForBox(&thisbrush_end, boxendmins, boxendmaxs, 0, 0, NULL);
672 if (maxvertices < model->surfmesh.num_vertices)
676 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
677 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
679 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
680 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
681 Collision_TraceBrushTriangleMeshFloat(trace, &thisbrush_start.brush, &thisbrush_end.brush, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs);
684 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
687 for (i = 0;i < inverts;i++)
689 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
691 j = vertremap[i]; // not onseam
694 j = vertremap[i+inverts]; // onseam
700 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
702 int i, f, pose, groupframes;
704 daliasframetype_t *pframetype;
705 daliasframe_t *pinframe;
706 daliasgroup_t *group;
707 daliasinterval_t *intervals;
710 scene = loadmodel->animscenes;
711 for (f = 0;f < loadmodel->numframes;f++)
713 pframetype = (daliasframetype_t *)datapointer;
714 datapointer += sizeof(daliasframetype_t);
715 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
717 // a single frame is still treated as a group
724 group = (daliasgroup_t *)datapointer;
725 datapointer += sizeof(daliasgroup_t);
726 groupframes = LittleLong (group->numframes);
728 // intervals (time per frame)
729 intervals = (daliasinterval_t *)datapointer;
730 datapointer += sizeof(daliasinterval_t) * groupframes;
732 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
733 if (interval < 0.01f)
735 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
740 // get scene name from first frame
741 pinframe = (daliasframe_t *)datapointer;
743 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
744 scene->firstframe = pose;
745 scene->framecount = groupframes;
746 scene->framerate = 1.0f / interval;
751 for (i = 0;i < groupframes;i++)
753 pinframe = (daliasframe_t *)datapointer;
754 datapointer += sizeof(daliasframe_t);
755 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
756 datapointer += sizeof(trivertx_t) * inverts;
762 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
764 if (cls.state == ca_dedicated)
768 skinframe = R_SkinFrame_LoadMissing();
769 memset(texture, 0, sizeof(*texture));
770 texture->currentframe = texture;
771 //texture->animated = false;
772 texture->numskinframes = 1;
773 texture->skinframerate = 1;
774 texture->skinframes[0] = skinframe;
775 texture->currentskinframe = skinframe;
776 //texture->backgroundnumskinframes = 0;
777 //texture->customblendfunc[0] = 0;
778 //texture->customblendfunc[1] = 0;
779 //texture->surfaceflags = 0;
780 //texture->supercontents = 0;
781 //texture->surfaceparms = 0;
782 //texture->textureflags = 0;
784 texture->basematerialflags = MATERIALFLAG_WALL;
785 if (texture->currentskinframe->hasalpha)
786 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
787 texture->currentmaterialflags = texture->basematerialflags;
788 texture->offsetmapping = OFFSETMAPPING_DEFAULT;
789 texture->offsetscale = 1;
790 texture->offsetbias = 0;
791 texture->specularscalemod = 1;
792 texture->specularpowermod = 1;
793 texture->surfaceflags = 0;
794 texture->supercontents = SUPERCONTENTS_SOLID;
795 if (!(texture->basematerialflags & MATERIALFLAG_BLENDED))
796 texture->supercontents |= SUPERCONTENTS_OPAQUE;
799 void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
802 static char stripbuf[MAX_QPATH];
803 skinfileitem_t *skinfileitem;
804 if(developer_extra.integer)
805 Con_DPrintf("Looking up texture for %s (default: %s)\n", meshname, shadername);
808 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
809 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
811 memset(skin, 0, sizeof(*skin));
813 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
815 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
816 if (!strcmp(skinfileitem->name, meshname))
818 Image_StripImageExtension(skinfileitem->replacement, stripbuf, sizeof(stripbuf));
819 if(developer_extra.integer)
820 Con_DPrintf("--> got %s from skin file\n", stripbuf);
821 Mod_LoadTextureFromQ3Shader(skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
827 // don't render unmentioned meshes
828 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
829 if(developer_extra.integer)
830 Con_DPrintf("--> skipping\n");
831 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
837 if(developer_extra.integer)
838 Con_DPrintf("--> using default\n");
839 Image_StripImageExtension(shadername, stripbuf, sizeof(stripbuf));
840 Mod_LoadTextureFromQ3Shader(skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
844 #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);
845 #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);
846 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
848 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
849 float scales, scalet, interval;
853 stvert_t *pinstverts;
854 dtriangle_t *pintriangles;
855 daliasskintype_t *pinskintype;
856 daliasskingroup_t *pinskingroup;
857 daliasskininterval_t *pinskinintervals;
858 daliasframetype_t *pinframetype;
859 daliasgroup_t *pinframegroup;
860 unsigned char *datapointer, *startframes, *startskins;
861 char name[MAX_QPATH];
862 skinframe_t *tempskinframe;
863 animscene_t *tempskinscenes;
864 texture_t *tempaliasskins;
866 int *vertonseam, *vertremap;
867 skinfile_t *skinfiles;
869 datapointer = (unsigned char *)buffer;
870 pinmodel = (mdl_t *)datapointer;
871 datapointer += sizeof(mdl_t);
873 version = LittleLong (pinmodel->version);
874 if (version != ALIAS_VERSION)
875 Host_Error ("%s has wrong version number (%i should be %i)",
876 loadmodel->name, version, ALIAS_VERSION);
878 loadmodel->modeldatatypestring = "MDL";
880 loadmodel->type = mod_alias;
881 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
882 loadmodel->DrawSky = NULL;
883 loadmodel->DrawAddWaterPlanes = NULL;
884 loadmodel->Draw = R_Q1BSP_Draw;
885 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
886 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
887 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
888 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
889 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
890 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
891 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
892 loadmodel->DrawLight = R_Q1BSP_DrawLight;
893 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
894 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
895 // FIXME add TraceBrush!
896 loadmodel->PointSuperContents = NULL;
898 loadmodel->num_surfaces = 1;
899 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
900 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
901 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
902 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
903 loadmodel->sortedmodelsurfaces[0] = 0;
905 loadmodel->numskins = LittleLong(pinmodel->numskins);
906 BOUNDI(loadmodel->numskins,0,65536);
907 skinwidth = LittleLong (pinmodel->skinwidth);
908 BOUNDI(skinwidth,0,65536);
909 skinheight = LittleLong (pinmodel->skinheight);
910 BOUNDI(skinheight,0,65536);
911 numverts = LittleLong(pinmodel->numverts);
912 BOUNDI(numverts,0,65536);
913 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
914 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
915 loadmodel->numframes = LittleLong(pinmodel->numframes);
916 BOUNDI(loadmodel->numframes,0,65536);
917 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
918 BOUNDI((int)loadmodel->synctype,0,2);
919 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
920 i = LittleLong (pinmodel->flags);
921 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
923 for (i = 0;i < 3;i++)
925 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
926 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
929 startskins = datapointer;
931 for (i = 0;i < loadmodel->numskins;i++)
933 pinskintype = (daliasskintype_t *)datapointer;
934 datapointer += sizeof(daliasskintype_t);
935 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
939 pinskingroup = (daliasskingroup_t *)datapointer;
940 datapointer += sizeof(daliasskingroup_t);
941 groupskins = LittleLong(pinskingroup->numskins);
942 datapointer += sizeof(daliasskininterval_t) * groupskins;
945 for (j = 0;j < groupskins;j++)
947 datapointer += skinwidth * skinheight;
952 pinstverts = (stvert_t *)datapointer;
953 datapointer += sizeof(stvert_t) * numverts;
955 pintriangles = (dtriangle_t *)datapointer;
956 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
958 startframes = datapointer;
959 loadmodel->surfmesh.num_morphframes = 0;
960 for (i = 0;i < loadmodel->numframes;i++)
962 pinframetype = (daliasframetype_t *)datapointer;
963 datapointer += sizeof(daliasframetype_t);
964 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
968 pinframegroup = (daliasgroup_t *)datapointer;
969 datapointer += sizeof(daliasgroup_t);
970 groupframes = LittleLong(pinframegroup->numframes);
971 datapointer += sizeof(daliasinterval_t) * groupframes;
974 for (j = 0;j < groupframes;j++)
976 datapointer += sizeof(daliasframe_t);
977 datapointer += sizeof(trivertx_t) * numverts;
978 loadmodel->surfmesh.num_morphframes++;
981 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
983 // store texture coordinates into temporary array, they will be stored
984 // after usage is determined (triangle data)
985 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
986 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
987 vertonseam = vertremap + numverts * 2;
989 scales = 1.0 / skinwidth;
990 scalet = 1.0 / skinheight;
991 for (i = 0;i < numverts;i++)
993 vertonseam[i] = LittleLong(pinstverts[i].onseam);
994 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
995 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
996 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
997 vertst[(i+numverts)*2+1] = vertst[i*2+1];
1000 // load triangle data
1001 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1003 // read the triangle elements
1004 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1005 for (j = 0;j < 3;j++)
1006 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1007 // validate (note numverts is used because this is the original data)
1008 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1009 // now butcher the elements according to vertonseam and tri->facesfront
1010 // and then compact the vertex set to remove duplicates
1011 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1012 if (!LittleLong(pintriangles[i].facesfront)) // backface
1013 for (j = 0;j < 3;j++)
1014 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1015 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1017 // (this uses vertremap to count usage to save some memory)
1018 for (i = 0;i < numverts*2;i++)
1020 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1021 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1022 // build remapping table and compact array
1023 loadmodel->surfmesh.num_vertices = 0;
1024 for (i = 0;i < numverts*2;i++)
1028 vertremap[i] = loadmodel->surfmesh.num_vertices;
1029 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1030 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1031 loadmodel->surfmesh.num_vertices++;
1034 vertremap[i] = -1; // not used at all
1036 // remap the elements to the new vertex set
1037 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1038 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1039 // store the texture coordinates
1040 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1041 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1043 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1044 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1047 // generate ushort elements array if possible
1048 if (loadmodel->surfmesh.num_vertices <= 65536)
1049 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1050 if (loadmodel->surfmesh.data_element3s)
1051 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1052 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1055 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1056 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1057 if (r_enableshadowvolumes.integer)
1059 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1061 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1062 if (loadmodel->surfmesh.data_neighbor3i)
1063 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1064 Mod_Alias_CalculateBoundingBox();
1065 Mod_Alias_MorphMesh_CompileFrames();
1068 Mem_Free(vertremap);
1071 skinfiles = Mod_LoadSkinFiles();
1074 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1075 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1076 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1077 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1078 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1079 Mod_FreeSkinFiles(skinfiles);
1080 for (i = 0;i < loadmodel->numskins;i++)
1082 loadmodel->skinscenes[i].firstframe = i;
1083 loadmodel->skinscenes[i].framecount = 1;
1084 loadmodel->skinscenes[i].loop = true;
1085 loadmodel->skinscenes[i].framerate = 10;
1090 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1091 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1092 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1093 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1095 datapointer = startskins;
1096 for (i = 0;i < loadmodel->numskins;i++)
1098 pinskintype = (daliasskintype_t *)datapointer;
1099 datapointer += sizeof(daliasskintype_t);
1101 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1108 pinskingroup = (daliasskingroup_t *)datapointer;
1109 datapointer += sizeof(daliasskingroup_t);
1111 groupskins = LittleLong (pinskingroup->numskins);
1113 pinskinintervals = (daliasskininterval_t *)datapointer;
1114 datapointer += sizeof(daliasskininterval_t) * groupskins;
1116 interval = LittleFloat(pinskinintervals[0].interval);
1117 if (interval < 0.01f)
1119 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1124 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1125 loadmodel->skinscenes[i].firstframe = totalskins;
1126 loadmodel->skinscenes[i].framecount = groupskins;
1127 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1128 loadmodel->skinscenes[i].loop = true;
1130 for (j = 0;j < groupskins;j++)
1133 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1135 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1136 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))
1137 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));
1138 datapointer += skinwidth * skinheight;
1142 // check for skins that don't exist in the model, but do exist as external images
1143 // (this was added because yummyluv kept pestering me about support for it)
1144 // TODO: support shaders here?
1145 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)))
1147 // expand the arrays to make room
1148 tempskinscenes = loadmodel->skinscenes;
1149 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1150 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1151 Mem_Free(tempskinscenes);
1153 tempaliasskins = loadmodel->data_textures;
1154 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1155 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1156 Mem_Free(tempaliasskins);
1158 // store the info about the new skin
1159 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1160 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1161 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1162 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1163 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1164 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1166 //increase skin counts
1167 loadmodel->numskins++;
1170 // fix up the pointers since they are pointing at the old textures array
1171 // FIXME: this is a hack!
1172 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1173 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1177 surface = loadmodel->data_surfaces;
1178 surface->texture = loadmodel->data_textures;
1179 surface->num_firsttriangle = 0;
1180 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1181 surface->num_firstvertex = 0;
1182 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1184 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1186 if (!loadmodel->surfmesh.isanimated)
1188 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1189 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1190 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1191 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1192 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1193 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1196 // because shaders can do somewhat unexpected things, check for unusual features now
1197 for (i = 0;i < loadmodel->num_textures;i++)
1199 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
1200 mod->DrawSky = R_Q1BSP_DrawSky;
1201 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
1202 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
1206 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1208 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1209 float iskinwidth, iskinheight;
1210 unsigned char *data;
1211 msurface_t *surface;
1213 unsigned char *base, *datapointer;
1214 md2frame_t *pinframe;
1216 md2triangle_t *intri;
1217 unsigned short *inst;
1218 struct md2verthash_s
1220 struct md2verthash_s *next;
1224 *hash, **md2verthash, *md2verthashdata;
1225 skinfile_t *skinfiles;
1227 pinmodel = (md2_t *)buffer;
1228 base = (unsigned char *)buffer;
1230 version = LittleLong (pinmodel->version);
1231 if (version != MD2ALIAS_VERSION)
1232 Host_Error ("%s has wrong version number (%i should be %i)",
1233 loadmodel->name, version, MD2ALIAS_VERSION);
1235 loadmodel->modeldatatypestring = "MD2";
1237 loadmodel->type = mod_alias;
1238 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1239 loadmodel->DrawSky = NULL;
1240 loadmodel->DrawAddWaterPlanes = NULL;
1241 loadmodel->Draw = R_Q1BSP_Draw;
1242 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1243 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1244 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1245 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1246 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1247 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1248 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1249 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1250 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1251 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1252 loadmodel->PointSuperContents = NULL;
1254 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1255 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1256 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1257 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1258 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1259 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1260 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1261 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1263 end = LittleLong(pinmodel->ofs_end);
1264 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1265 Host_Error ("%s is not a valid model", loadmodel->name);
1266 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1267 Host_Error ("%s is not a valid model", loadmodel->name);
1268 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1269 Host_Error ("%s is not a valid model", loadmodel->name);
1270 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1271 Host_Error ("%s is not a valid model", loadmodel->name);
1272 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1273 Host_Error ("%s is not a valid model", loadmodel->name);
1275 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1276 numxyz = LittleLong(pinmodel->num_xyz);
1277 numst = LittleLong(pinmodel->num_st);
1278 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1279 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1280 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1281 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1282 skinwidth = LittleLong(pinmodel->skinwidth);
1283 skinheight = LittleLong(pinmodel->skinheight);
1284 iskinwidth = 1.0f / skinwidth;
1285 iskinheight = 1.0f / skinheight;
1287 loadmodel->num_surfaces = 1;
1288 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1289 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->numframes * sizeof(animscene_t) + loadmodel->numframes * sizeof(float[6]) + loadmodel->surfmesh.num_triangles * sizeof(int[3]) + (r_enableshadowvolumes.integer ? loadmodel->surfmesh.num_triangles * sizeof(int[3]) : 0));
1290 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1291 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1292 loadmodel->sortedmodelsurfaces[0] = 0;
1293 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1294 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1295 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1296 if (r_enableshadowvolumes.integer)
1298 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1301 loadmodel->synctype = ST_RAND;
1304 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1305 skinfiles = Mod_LoadSkinFiles();
1308 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1309 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1310 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1311 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1312 Mod_FreeSkinFiles(skinfiles);
1314 else if (loadmodel->numskins)
1316 // skins found (most likely not a player model)
1317 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1318 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1319 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1320 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1321 Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
1325 // no skins (most likely a player model)
1326 loadmodel->numskins = 1;
1327 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1328 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1329 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1330 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1333 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1334 for (i = 0;i < loadmodel->numskins;i++)
1336 loadmodel->skinscenes[i].firstframe = i;
1337 loadmodel->skinscenes[i].framecount = 1;
1338 loadmodel->skinscenes[i].loop = true;
1339 loadmodel->skinscenes[i].framerate = 10;
1342 // load the triangles and stvert data
1343 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1344 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1345 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1346 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1347 // swap the triangle list
1348 loadmodel->surfmesh.num_vertices = 0;
1349 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1351 for (j = 0;j < 3;j++)
1353 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1354 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1357 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1362 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1365 hashindex = (xyz * 256 + st) & 65535;
1366 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1367 if (hash->xyz == xyz && hash->st == st)
1371 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1374 hash->next = md2verthash[hashindex];
1375 md2verthash[hashindex] = hash;
1377 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1381 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1382 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));
1383 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1384 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1385 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1388 hash = md2verthashdata + i;
1389 vertremap[i] = hash->xyz;
1390 sts = LittleShort(inst[hash->st*2+0]);
1391 stt = LittleShort(inst[hash->st*2+1]);
1392 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1394 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1398 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1399 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1402 Mem_Free(md2verthash);
1403 Mem_Free(md2verthashdata);
1405 // generate ushort elements array if possible
1406 if (loadmodel->surfmesh.num_vertices <= 65536)
1407 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1408 if (loadmodel->surfmesh.data_element3s)
1409 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1410 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1413 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1414 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1419 pinframe = (md2frame_t *)datapointer;
1420 datapointer += sizeof(md2frame_t);
1421 // store the frame scale/translate into the appropriate array
1422 for (j = 0;j < 3;j++)
1424 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1425 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1427 // convert the vertices
1428 v = (trivertx_t *)datapointer;
1429 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1430 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1431 out[k] = v[vertremap[k]];
1432 datapointer += numxyz * sizeof(trivertx_t);
1434 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1435 loadmodel->animscenes[i].firstframe = i;
1436 loadmodel->animscenes[i].framecount = 1;
1437 loadmodel->animscenes[i].framerate = 10;
1438 loadmodel->animscenes[i].loop = true;
1441 Mem_Free(vertremap);
1443 if (loadmodel->surfmesh.data_neighbor3i)
1444 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1445 Mod_Alias_CalculateBoundingBox();
1446 Mod_Alias_MorphMesh_CompileFrames();
1448 surface = loadmodel->data_surfaces;
1449 surface->texture = loadmodel->data_textures;
1450 surface->num_firsttriangle = 0;
1451 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1452 surface->num_firstvertex = 0;
1453 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1455 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1457 if (!loadmodel->surfmesh.isanimated)
1459 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1460 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1461 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1462 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1463 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1464 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1467 // because shaders can do somewhat unexpected things, check for unusual features now
1468 for (i = 0;i < loadmodel->num_textures;i++)
1470 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
1471 mod->DrawSky = R_Q1BSP_DrawSky;
1472 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
1473 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
1477 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1479 int i, j, k, version, meshvertices, meshtriangles;
1480 unsigned char *data;
1481 msurface_t *surface;
1482 md3modelheader_t *pinmodel;
1483 md3frameinfo_t *pinframe;
1486 skinfile_t *skinfiles;
1488 pinmodel = (md3modelheader_t *)buffer;
1490 if (memcmp(pinmodel->identifier, "IDP3", 4))
1491 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1492 version = LittleLong (pinmodel->version);
1493 if (version != MD3VERSION)
1494 Host_Error ("%s has wrong version number (%i should be %i)",
1495 loadmodel->name, version, MD3VERSION);
1497 skinfiles = Mod_LoadSkinFiles();
1498 if (loadmodel->numskins < 1)
1499 loadmodel->numskins = 1;
1501 loadmodel->modeldatatypestring = "MD3";
1503 loadmodel->type = mod_alias;
1504 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1505 loadmodel->DrawSky = NULL;
1506 loadmodel->DrawAddWaterPlanes = NULL;
1507 loadmodel->Draw = R_Q1BSP_Draw;
1508 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1509 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1510 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1511 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1512 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1513 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1514 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1515 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1516 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1517 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1518 loadmodel->PointSuperContents = NULL;
1519 loadmodel->synctype = ST_RAND;
1520 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1521 i = LittleLong (pinmodel->flags);
1522 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1524 // set up some global info about the model
1525 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1526 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1528 // make skinscenes for the skins (no groups)
1529 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1530 for (i = 0;i < loadmodel->numskins;i++)
1532 loadmodel->skinscenes[i].firstframe = i;
1533 loadmodel->skinscenes[i].framecount = 1;
1534 loadmodel->skinscenes[i].loop = true;
1535 loadmodel->skinscenes[i].framerate = 10;
1539 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1540 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1542 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1543 loadmodel->animscenes[i].firstframe = i;
1544 loadmodel->animscenes[i].framecount = 1;
1545 loadmodel->animscenes[i].framerate = 10;
1546 loadmodel->animscenes[i].loop = true;
1550 loadmodel->num_tagframes = loadmodel->numframes;
1551 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1552 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1553 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1555 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1556 for (j = 0;j < 9;j++)
1557 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1558 for (j = 0;j < 3;j++)
1559 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1560 //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);
1566 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)))
1568 if (memcmp(pinmesh->identifier, "IDP3", 4))
1569 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1570 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1571 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1572 meshvertices += LittleLong(pinmesh->num_vertices);
1573 meshtriangles += LittleLong(pinmesh->num_triangles);
1576 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1577 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1578 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1579 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (r_enableshadowvolumes.integer ? meshtriangles * sizeof(int[3]) : 0) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshvertices * sizeof(float[2]) + meshvertices * loadmodel->numframes * sizeof(md3vertex_t));
1580 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1581 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1582 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1583 loadmodel->surfmesh.num_vertices = meshvertices;
1584 loadmodel->surfmesh.num_triangles = meshtriangles;
1585 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1586 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1587 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1588 if (r_enableshadowvolumes.integer)
1590 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1592 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1593 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1594 if (meshvertices <= 65536)
1596 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1601 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)))
1603 if (memcmp(pinmesh->identifier, "IDP3", 4))
1604 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1605 loadmodel->sortedmodelsurfaces[i] = i;
1606 surface = loadmodel->data_surfaces + i;
1607 surface->texture = loadmodel->data_textures + i;
1608 surface->num_firsttriangle = meshtriangles;
1609 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1610 surface->num_firstvertex = meshvertices;
1611 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1612 meshvertices += surface->num_vertices;
1613 meshtriangles += surface->num_triangles;
1615 for (j = 0;j < surface->num_triangles * 3;j++)
1616 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1617 for (j = 0;j < surface->num_vertices;j++)
1619 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1620 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1622 for (j = 0;j < loadmodel->numframes;j++)
1624 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1625 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1626 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1628 out->origin[0] = LittleShort(in->origin[0]);
1629 out->origin[1] = LittleShort(in->origin[1]);
1630 out->origin[2] = LittleShort(in->origin[2]);
1631 out->pitch = in->pitch;
1636 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1638 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1640 if (loadmodel->surfmesh.data_element3s)
1641 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1642 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1643 if (loadmodel->surfmesh.data_neighbor3i)
1644 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1645 Mod_Alias_MorphMesh_CompileFrames();
1646 Mod_Alias_CalculateBoundingBox();
1647 Mod_FreeSkinFiles(skinfiles);
1648 Mod_MakeSortedSurfaces(loadmodel);
1650 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1651 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1653 if (!loadmodel->surfmesh.isanimated)
1655 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1656 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1657 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1658 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1659 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1660 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1663 // because shaders can do somewhat unexpected things, check for unusual features now
1664 for (i = 0;i < loadmodel->num_textures;i++)
1666 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
1667 mod->DrawSky = R_Q1BSP_DrawSky;
1668 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
1669 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
1673 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1675 zymtype1header_t *pinmodel, *pheader;
1676 unsigned char *pbase;
1677 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1678 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose, f, biggestorigin, tempvec[3], modelscale;
1679 zymvertex_t *verts, *vertdata;
1683 skinfile_t *skinfiles;
1684 unsigned char *data;
1685 msurface_t *surface;
1687 pinmodel = (zymtype1header_t *)buffer;
1688 pbase = (unsigned char *)buffer;
1689 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1690 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1691 if (BigLong(pinmodel->type) != 1)
1692 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1694 loadmodel->modeldatatypestring = "ZYM";
1696 loadmodel->type = mod_alias;
1697 loadmodel->synctype = ST_RAND;
1701 pheader->type = BigLong(pinmodel->type);
1702 pheader->filesize = BigLong(pinmodel->filesize);
1703 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1704 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1705 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1706 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1707 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1708 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1709 pheader->radius = BigFloat(pinmodel->radius);
1710 pheader->numverts = BigLong(pinmodel->numverts);
1711 pheader->numtris = BigLong(pinmodel->numtris);
1712 pheader->numshaders = BigLong(pinmodel->numshaders);
1713 pheader->numbones = BigLong(pinmodel->numbones);
1714 pheader->numscenes = BigLong(pinmodel->numscenes);
1715 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1716 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1717 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1718 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1719 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1720 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1721 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1722 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1723 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1724 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1725 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1726 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1727 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1728 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1729 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1730 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1731 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1732 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1734 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1736 Con_Printf("%s has no geometry\n", loadmodel->name);
1739 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1741 Con_Printf("%s has no animations\n", loadmodel->name);
1745 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1746 loadmodel->DrawSky = NULL;
1747 loadmodel->DrawAddWaterPlanes = NULL;
1748 loadmodel->Draw = R_Q1BSP_Draw;
1749 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1750 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1751 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1752 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1753 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1754 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1755 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1756 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1757 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1758 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1759 loadmodel->PointSuperContents = NULL;
1761 loadmodel->numframes = pheader->numscenes;
1762 loadmodel->num_surfaces = pheader->numshaders;
1764 skinfiles = Mod_LoadSkinFiles();
1765 if (loadmodel->numskins < 1)
1766 loadmodel->numskins = 1;
1768 // make skinscenes for the skins (no groups)
1769 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1770 for (i = 0;i < loadmodel->numskins;i++)
1772 loadmodel->skinscenes[i].firstframe = i;
1773 loadmodel->skinscenes[i].framecount = 1;
1774 loadmodel->skinscenes[i].loop = true;
1775 loadmodel->skinscenes[i].framerate = 10;
1779 modelradius = pheader->radius;
1780 for (i = 0;i < 3;i++)
1782 loadmodel->normalmins[i] = pheader->mins[i];
1783 loadmodel->normalmaxs[i] = pheader->maxs[i];
1784 loadmodel->rotatedmins[i] = -modelradius;
1785 loadmodel->rotatedmaxs[i] = modelradius;
1787 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1788 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1789 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1790 if (loadmodel->yawmaxs[0] > modelradius)
1791 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1792 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1793 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1794 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1795 loadmodel->radius = modelradius;
1796 loadmodel->radius2 = modelradius * modelradius;
1798 // go through the lumps, swapping things
1800 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1801 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1802 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1803 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1804 for (i = 0;i < pheader->numscenes;i++)
1806 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1807 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1808 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1809 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1810 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1811 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1812 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1813 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1814 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1815 if (loadmodel->animscenes[i].framerate < 0)
1816 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1820 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1821 loadmodel->num_bones = pheader->numbones;
1822 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1823 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1824 for (i = 0;i < pheader->numbones;i++)
1826 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1827 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1828 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1829 if (loadmodel->data_bones[i].parent >= i)
1830 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1833 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1834 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1835 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1836 for (i = 0;i < pheader->numverts;i++)
1838 vertbonecounts[i] = BigLong(bonecount[i]);
1839 if (vertbonecounts[i] != 1)
1840 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1843 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1845 meshvertices = pheader->numverts;
1846 meshtriangles = pheader->numtris;
1848 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1849 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1850 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1851 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (r_enableshadowvolumes.integer ? meshtriangles * sizeof(int[3]) : 0) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshvertices * sizeof(float[14]) + meshvertices * sizeof(unsigned short) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]) + loadmodel->num_bones * sizeof(float[12]));
1852 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1853 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1854 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1855 loadmodel->surfmesh.num_vertices = meshvertices;
1856 loadmodel->surfmesh.num_triangles = meshtriangles;
1857 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1858 if (r_enableshadowvolumes.integer)
1860 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1862 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1863 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1864 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1865 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1866 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1867 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1868 loadmodel->surfmesh.num_blends = 0;
1869 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
1870 if (loadmodel->surfmesh.num_vertices <= 65536)
1872 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1874 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
1875 loadmodel->surfmesh.data_blendweights = NULL;
1877 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1878 poses = (float *) (pheader->lump_poses.start + pbase);
1879 // figure out scale of model from root bone, for compatibility with old zmodel versions
1880 tempvec[0] = BigFloat(poses[0]);
1881 tempvec[1] = BigFloat(poses[1]);
1882 tempvec[2] = BigFloat(poses[2]);
1883 modelscale = VectorLength(tempvec);
1885 for (i = 0;i < loadmodel->num_bones * numposes * 12;i++)
1887 f = fabs(BigFloat(poses[i]));
1888 biggestorigin = max(biggestorigin, f);
1890 loadmodel->num_posescale = biggestorigin / 32767.0f;
1891 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
1892 for (i = 0;i < numposes;i++)
1894 const float *frameposes = (float *) (pheader->lump_poses.start + pbase) + 12*i*loadmodel->num_bones;
1895 for (j = 0;j < loadmodel->num_bones;j++)
1898 matrix4x4_t posematrix;
1899 for (k = 0;k < 12;k++)
1900 pose[k] = BigFloat(frameposes[j*12+k]);
1901 //if (j < loadmodel->num_bones)
1902 // 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));
1903 // scale child bones to match the root scale
1904 if (loadmodel->data_bones[j].parent >= 0)
1906 pose[3] *= modelscale;
1907 pose[7] *= modelscale;
1908 pose[11] *= modelscale;
1910 // normalize rotation matrix
1911 VectorNormalize(pose + 0);
1912 VectorNormalize(pose + 4);
1913 VectorNormalize(pose + 8);
1914 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
1915 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
1919 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1920 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1921 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1922 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1923 // (converting from weight-blending skeletal animation to
1924 // deformation-based skeletal animation)
1925 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1926 for (i = 0;i < loadmodel->num_bones;i++)
1929 for (k = 0;k < 12;k++)
1930 m[k] = BigFloat(poses[i*12+k]);
1931 if (loadmodel->data_bones[i].parent >= 0)
1932 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1934 for (k = 0;k < 12;k++)
1935 bonepose[12*i+k] = m[k];
1937 for (j = 0;j < pheader->numverts;j++)
1939 // this format really should have had a per vertexweight weight value...
1940 // but since it does not, the weighting is completely ignored and
1941 // only one weight is allowed per vertex
1942 int boneindex = BigLong(vertdata[j].bonenum);
1943 const float *m = bonepose + 12 * boneindex;
1944 float relativeorigin[3];
1945 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1946 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1947 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1948 // transform the vertex bone weight into the base mesh
1949 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1950 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1951 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1952 // store the weight as the primary weight on this vertex
1953 loadmodel->surfmesh.blends[j] = boneindex;
1956 // normals and tangents are calculated after elements are loaded
1958 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1959 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1960 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1961 for (i = 0;i < pheader->numverts;i++)
1963 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1964 // flip T coordinate for OpenGL
1965 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1968 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1969 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1970 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1972 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1973 //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)
1974 // byteswap, validate, and swap winding order of tris
1975 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1976 if (pheader->lump_render.length != count)
1977 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1978 renderlist = (int *) (pheader->lump_render.start + pbase);
1979 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1981 for (i = 0;i < loadmodel->num_surfaces;i++)
1983 int firstvertex, lastvertex;
1984 if (renderlist >= renderlistend)
1985 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1986 count = BigLong(*renderlist);renderlist++;
1987 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1988 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1990 loadmodel->sortedmodelsurfaces[i] = i;
1991 surface = loadmodel->data_surfaces + i;
1992 surface->texture = loadmodel->data_textures + i;
1993 surface->num_firsttriangle = meshtriangles;
1994 surface->num_triangles = count;
1995 meshtriangles += surface->num_triangles;
1997 // load the elements
1998 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
1999 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
2001 outelements[j*3+2] = BigLong(renderlist[0]);
2002 outelements[j*3+1] = BigLong(renderlist[1]);
2003 outelements[j*3+0] = BigLong(renderlist[2]);
2005 // validate the elements and find the used vertex range
2006 firstvertex = meshvertices;
2008 for (j = 0;j < surface->num_triangles * 3;j++)
2010 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
2011 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
2012 firstvertex = min(firstvertex, outelements[j]);
2013 lastvertex = max(lastvertex, outelements[j]);
2015 surface->num_firstvertex = firstvertex;
2016 surface->num_vertices = lastvertex + 1 - firstvertex;
2018 // since zym models do not have named sections, reuse their shader
2019 // name as the section name
2020 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
2021 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
2023 Mod_FreeSkinFiles(skinfiles);
2024 Mem_Free(vertbonecounts);
2026 Mod_MakeSortedSurfaces(loadmodel);
2028 // compute all the mesh information that was not loaded from the file
2029 if (loadmodel->surfmesh.data_element3s)
2030 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2031 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2032 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2033 Mod_BuildBaseBonePoses();
2034 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, r_smoothnormals_areaweighting.integer != 0);
2035 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);
2036 if (loadmodel->surfmesh.data_neighbor3i)
2037 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2039 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2041 if (!loadmodel->surfmesh.isanimated)
2043 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2044 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2045 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2046 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2047 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2048 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2051 // because shaders can do somewhat unexpected things, check for unusual features now
2052 for (i = 0;i < loadmodel->num_textures;i++)
2054 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
2055 mod->DrawSky = R_Q1BSP_DrawSky;
2056 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
2057 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
2061 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2063 dpmheader_t *pheader;
2067 unsigned char *pbase;
2068 int i, j, k, meshvertices, meshtriangles;
2069 skinfile_t *skinfiles;
2070 unsigned char *data;
2072 float biggestorigin, tempvec[3], modelscale;
2076 pheader = (dpmheader_t *)buffer;
2077 pbase = (unsigned char *)buffer;
2078 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2079 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2080 if (BigLong(pheader->type) != 2)
2081 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2083 loadmodel->modeldatatypestring = "DPM";
2085 loadmodel->type = mod_alias;
2086 loadmodel->synctype = ST_RAND;
2089 pheader->type = BigLong(pheader->type);
2090 pheader->filesize = BigLong(pheader->filesize);
2091 pheader->mins[0] = BigFloat(pheader->mins[0]);
2092 pheader->mins[1] = BigFloat(pheader->mins[1]);
2093 pheader->mins[2] = BigFloat(pheader->mins[2]);
2094 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2095 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2096 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2097 pheader->yawradius = BigFloat(pheader->yawradius);
2098 pheader->allradius = BigFloat(pheader->allradius);
2099 pheader->num_bones = BigLong(pheader->num_bones);
2100 pheader->num_meshs = BigLong(pheader->num_meshs);
2101 pheader->num_frames = BigLong(pheader->num_frames);
2102 pheader->ofs_bones = BigLong(pheader->ofs_bones);
2103 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2104 pheader->ofs_frames = BigLong(pheader->ofs_frames);
2106 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2108 Con_Printf("%s has no geometry\n", loadmodel->name);
2111 if (pheader->num_frames < 1)
2113 Con_Printf("%s has no frames\n", loadmodel->name);
2117 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2118 loadmodel->DrawSky = NULL;
2119 loadmodel->DrawAddWaterPlanes = NULL;
2120 loadmodel->Draw = R_Q1BSP_Draw;
2121 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2122 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2123 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2124 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2125 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2126 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2127 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2128 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2129 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2130 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2131 loadmodel->PointSuperContents = NULL;
2134 for (i = 0;i < 3;i++)
2136 loadmodel->normalmins[i] = pheader->mins[i];
2137 loadmodel->normalmaxs[i] = pheader->maxs[i];
2138 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2139 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2140 loadmodel->rotatedmins[i] = -pheader->allradius;
2141 loadmodel->rotatedmaxs[i] = pheader->allradius;
2143 loadmodel->radius = pheader->allradius;
2144 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2146 // load external .skin files if present
2147 skinfiles = Mod_LoadSkinFiles();
2148 if (loadmodel->numskins < 1)
2149 loadmodel->numskins = 1;
2154 // gather combined statistics from the meshes
2155 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2156 for (i = 0;i < (int)pheader->num_meshs;i++)
2158 int numverts = BigLong(dpmmesh->num_verts);
2159 meshvertices += numverts;
2160 meshtriangles += BigLong(dpmmesh->num_tris);
2164 loadmodel->numframes = pheader->num_frames;
2165 loadmodel->num_bones = pheader->num_bones;
2166 loadmodel->num_poses = loadmodel->numframes;
2167 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2168 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2169 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2170 // do most allocations as one merged chunk
2171 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + (r_enableshadowvolumes.integer ? meshtriangles * sizeof(int[3]) : 0) + meshvertices * (sizeof(float[14]) + sizeof(unsigned short)) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
2172 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2173 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2174 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2175 loadmodel->surfmesh.num_vertices = meshvertices;
2176 loadmodel->surfmesh.num_triangles = meshtriangles;
2177 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2178 if (r_enableshadowvolumes.integer)
2180 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2182 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2183 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2184 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2185 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2186 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2187 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2188 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2189 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2190 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2191 loadmodel->surfmesh.num_blends = 0;
2192 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2193 if (meshvertices <= 65536)
2195 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2197 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2198 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
2200 for (i = 0;i < loadmodel->numskins;i++)
2202 loadmodel->skinscenes[i].firstframe = i;
2203 loadmodel->skinscenes[i].framecount = 1;
2204 loadmodel->skinscenes[i].loop = true;
2205 loadmodel->skinscenes[i].framerate = 10;
2208 // load the bone info
2209 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2210 for (i = 0;i < loadmodel->num_bones;i++)
2212 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2213 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2214 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2215 if (loadmodel->data_bones[i].parent >= i)
2216 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2220 frames = (dpmframe_t *) (pbase + pheader->ofs_frames);
2221 // figure out scale of model from root bone, for compatibility with old dpmodel versions
2222 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2223 tempvec[0] = BigFloat(poses[0]);
2224 tempvec[1] = BigFloat(poses[1]);
2225 tempvec[2] = BigFloat(poses[2]);
2226 modelscale = VectorLength(tempvec);
2228 for (i = 0;i < loadmodel->numframes;i++)
2230 memcpy(loadmodel->animscenes[i].name, frames[i].name, sizeof(frames[i].name));
2231 loadmodel->animscenes[i].firstframe = i;
2232 loadmodel->animscenes[i].framecount = 1;
2233 loadmodel->animscenes[i].loop = true;
2234 loadmodel->animscenes[i].framerate = 10;
2235 // load the bone poses for this frame
2236 poses = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2237 for (j = 0;j < loadmodel->num_bones*12;j++)
2239 f = fabs(BigFloat(poses[j]));
2240 biggestorigin = max(biggestorigin, f);
2242 // stuff not processed here: mins, maxs, yawradius, allradius
2244 loadmodel->num_posescale = biggestorigin / 32767.0f;
2245 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2246 for (i = 0;i < loadmodel->numframes;i++)
2248 const float *frameposes = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2249 for (j = 0;j < loadmodel->num_bones;j++)
2252 matrix4x4_t posematrix;
2253 for (k = 0;k < 12;k++)
2254 pose[k] = BigFloat(frameposes[j*12+k]);
2255 // scale child bones to match the root scale
2256 if (loadmodel->data_bones[j].parent >= 0)
2258 pose[3] *= modelscale;
2259 pose[7] *= modelscale;
2260 pose[11] *= modelscale;
2262 // normalize rotation matrix
2263 VectorNormalize(pose + 0);
2264 VectorNormalize(pose + 4);
2265 VectorNormalize(pose + 8);
2266 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2267 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
2271 // load the meshes now
2272 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2275 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2276 // (converting from weight-blending skeletal animation to
2277 // deformation-based skeletal animation)
2278 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2279 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2280 for (i = 0;i < loadmodel->num_bones;i++)
2283 for (k = 0;k < 12;k++)
2284 m[k] = BigFloat(poses[i*12+k]);
2285 if (loadmodel->data_bones[i].parent >= 0)
2286 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2288 for (k = 0;k < 12;k++)
2289 bonepose[12*i+k] = m[k];
2291 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2293 const int *inelements;
2295 const float *intexcoord;
2296 msurface_t *surface;
2298 loadmodel->sortedmodelsurfaces[i] = i;
2299 surface = loadmodel->data_surfaces + i;
2300 surface->texture = loadmodel->data_textures + i;
2301 surface->num_firsttriangle = meshtriangles;
2302 surface->num_triangles = BigLong(dpmmesh->num_tris);
2303 surface->num_firstvertex = meshvertices;
2304 surface->num_vertices = BigLong(dpmmesh->num_verts);
2305 meshvertices += surface->num_vertices;
2306 meshtriangles += surface->num_triangles;
2308 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2309 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2310 for (j = 0;j < surface->num_triangles;j++)
2312 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2313 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2314 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2315 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2320 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2321 for (j = 0;j < surface->num_vertices*2;j++)
2322 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2324 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2325 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2327 int weightindex[4] = { 0, 0, 0, 0 };
2328 float weightinfluence[4] = { 0, 0, 0, 0 };
2330 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2331 data += sizeof(dpmvertex_t);
2332 for (k = 0;k < numweights;k++)
2334 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2335 int boneindex = BigLong(vert->bonenum);
2336 const float *m = bonepose + 12 * boneindex;
2337 float influence = BigFloat(vert->influence);
2338 float relativeorigin[3], relativenormal[3];
2339 relativeorigin[0] = BigFloat(vert->origin[0]);
2340 relativeorigin[1] = BigFloat(vert->origin[1]);
2341 relativeorigin[2] = BigFloat(vert->origin[2]);
2342 relativenormal[0] = BigFloat(vert->normal[0]);
2343 relativenormal[1] = BigFloat(vert->normal[1]);
2344 relativenormal[2] = BigFloat(vert->normal[2]);
2345 // blend the vertex bone weights into the base mesh
2346 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2347 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2348 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2349 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2350 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2351 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2354 // store the first (and often only) weight
2355 weightinfluence[0] = influence;
2356 weightindex[0] = boneindex;
2360 // sort the new weight into this vertex's weight table
2361 // (which only accepts up to 4 bones per vertex)
2362 for (l = 0;l < 4;l++)
2364 if (weightinfluence[l] < influence)
2366 // move weaker influence weights out of the way first
2368 for (l2 = 3;l2 > l;l2--)
2370 weightinfluence[l2] = weightinfluence[l2-1];
2371 weightindex[l2] = weightindex[l2-1];
2373 // store the new weight
2374 weightinfluence[l] = influence;
2375 weightindex[l] = boneindex;
2380 data += sizeof(dpmbonevert_t);
2382 loadmodel->surfmesh.blends[j] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
2385 // since dpm models do not have named sections, reuse their shader name as the section name
2386 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2388 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2390 if (loadmodel->surfmesh.num_blends < meshvertices)
2391 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2393 Mod_FreeSkinFiles(skinfiles);
2394 Mod_MakeSortedSurfaces(loadmodel);
2396 // compute all the mesh information that was not loaded from the file
2397 if (loadmodel->surfmesh.data_element3s)
2398 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2399 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2400 Mod_BuildBaseBonePoses();
2401 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);
2402 if (loadmodel->surfmesh.data_neighbor3i)
2403 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2405 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2407 if (!loadmodel->surfmesh.isanimated)
2409 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2410 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2411 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2412 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2413 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2414 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2417 // because shaders can do somewhat unexpected things, check for unusual features now
2418 for (i = 0;i < loadmodel->num_textures;i++)
2420 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
2421 mod->DrawSky = R_Q1BSP_DrawSky;
2422 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
2423 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
2427 // no idea why PSK/PSA files contain weird quaternions but they do...
2428 #define PSKQUATNEGATIONS
2429 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2431 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2432 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2433 fs_offset_t filesize;
2438 pskboneinfo_t *bones;
2439 pskrawweights_t *rawweights;
2440 //pskboneinfo_t *animbones;
2441 pskaniminfo_t *anims;
2442 pskanimkeys_t *animkeys;
2443 void *animfilebuffer, *animbuffer, *animbufferend;
2444 unsigned char *data;
2446 skinfile_t *skinfiles;
2447 char animname[MAX_QPATH];
2449 float biggestorigin;
2451 pchunk = (pskchunk_t *)buffer;
2452 if (strcmp(pchunk->id, "ACTRHEAD"))
2453 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2455 loadmodel->modeldatatypestring = "PSK";
2457 loadmodel->type = mod_alias;
2458 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2459 loadmodel->DrawSky = NULL;
2460 loadmodel->DrawAddWaterPlanes = NULL;
2461 loadmodel->Draw = R_Q1BSP_Draw;
2462 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2463 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2464 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2465 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2466 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2467 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2468 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2469 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2470 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2471 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2472 loadmodel->PointSuperContents = NULL;
2473 loadmodel->synctype = ST_RAND;
2475 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2476 strlcat(animname, ".psa", sizeof(animname));
2477 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2478 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2479 if (animbuffer == NULL)
2480 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2499 while (buffer < bufferend)
2501 pchunk = (pskchunk_t *)buffer;
2502 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2503 version = LittleLong(pchunk->version);
2504 recordsize = LittleLong(pchunk->recordsize);
2505 numrecords = LittleLong(pchunk->numrecords);
2506 if (developer_extra.integer)
2507 Con_DPrintf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2508 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2509 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);
2510 if (!strcmp(pchunk->id, "ACTRHEAD"))
2514 else if (!strcmp(pchunk->id, "PNTS0000"))
2517 if (recordsize != sizeof(*p))
2518 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2519 // byteswap in place and keep the pointer
2520 numpnts = numrecords;
2521 pnts = (pskpnts_t *)buffer;
2522 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2524 p->origin[0] = LittleFloat(p->origin[0]);
2525 p->origin[1] = LittleFloat(p->origin[1]);
2526 p->origin[2] = LittleFloat(p->origin[2]);
2530 else if (!strcmp(pchunk->id, "VTXW0000"))
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 numvtxw = numrecords;
2537 vtxw = (pskvtxw_t *)buffer;
2538 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2540 p->pntsindex = LittleShort(p->pntsindex);
2541 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2542 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2543 if (p->pntsindex >= numpnts)
2545 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2551 else if (!strcmp(pchunk->id, "FACE0000"))
2554 if (recordsize != sizeof(*p))
2555 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2556 // byteswap in place and keep the pointer
2557 numfaces = numrecords;
2558 faces = (pskface_t *)buffer;
2559 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2561 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2562 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2563 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2564 p->group = LittleLong(p->group);
2565 if (p->vtxwindex[0] >= numvtxw)
2567 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2568 p->vtxwindex[0] = 0;
2570 if (p->vtxwindex[1] >= numvtxw)
2572 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2573 p->vtxwindex[1] = 0;
2575 if (p->vtxwindex[2] >= numvtxw)
2577 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2578 p->vtxwindex[2] = 0;
2583 else if (!strcmp(pchunk->id, "MATT0000"))
2586 if (recordsize != sizeof(*p))
2587 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2588 // byteswap in place and keep the pointer
2589 nummatts = numrecords;
2590 matts = (pskmatt_t *)buffer;
2591 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2597 else if (!strcmp(pchunk->id, "REFSKELT"))
2600 if (recordsize != sizeof(*p))
2601 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2602 // byteswap in place and keep the pointer
2603 numbones = numrecords;
2604 bones = (pskboneinfo_t *)buffer;
2605 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2607 p->numchildren = LittleLong(p->numchildren);
2608 p->parent = LittleLong(p->parent);
2609 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2610 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2611 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2612 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2613 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2614 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2615 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2616 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2617 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2618 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2619 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2620 #ifdef PSKQUATNEGATIONS
2623 p->basepose.quat[0] *= -1;
2624 p->basepose.quat[1] *= -1;
2625 p->basepose.quat[2] *= -1;
2629 p->basepose.quat[0] *= 1;
2630 p->basepose.quat[1] *= -1;
2631 p->basepose.quat[2] *= 1;
2634 if (p->parent < 0 || p->parent >= numbones)
2636 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2642 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2645 if (recordsize != sizeof(*p))
2646 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2647 // byteswap in place and keep the pointer
2648 numrawweights = numrecords;
2649 rawweights = (pskrawweights_t *)buffer;
2650 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2652 p->weight = LittleFloat(p->weight);
2653 p->pntsindex = LittleLong(p->pntsindex);
2654 p->boneindex = LittleLong(p->boneindex);
2655 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2657 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2660 if (p->boneindex < 0 || p->boneindex >= numbones)
2662 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2670 while (animbuffer < animbufferend)
2672 pchunk = (pskchunk_t *)animbuffer;
2673 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2674 version = LittleLong(pchunk->version);
2675 recordsize = LittleLong(pchunk->recordsize);
2676 numrecords = LittleLong(pchunk->numrecords);
2677 if (developer_extra.integer)
2678 Con_DPrintf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2679 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2680 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);
2681 if (!strcmp(pchunk->id, "ANIMHEAD"))
2685 else if (!strcmp(pchunk->id, "BONENAMES"))
2688 if (recordsize != sizeof(*p))
2689 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2690 // byteswap in place and keep the pointer
2691 numanimbones = numrecords;
2692 //animbones = (pskboneinfo_t *)animbuffer;
2693 // NOTE: supposedly psa does not need to match the psk model, the
2694 // bones missing from the psa would simply use their base
2695 // positions from the psk, but this is hard for me to implement
2696 // and people can easily make animations that match.
2697 if (numanimbones != numbones)
2698 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2699 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2701 p->numchildren = LittleLong(p->numchildren);
2702 p->parent = LittleLong(p->parent);
2703 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2704 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2705 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2706 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2707 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2708 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2709 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2710 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2711 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2712 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2713 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2714 #ifdef PSKQUATNEGATIONS
2717 p->basepose.quat[0] *= -1;
2718 p->basepose.quat[1] *= -1;
2719 p->basepose.quat[2] *= -1;
2723 p->basepose.quat[0] *= 1;
2724 p->basepose.quat[1] *= -1;
2725 p->basepose.quat[2] *= 1;
2728 if (p->parent < 0 || p->parent >= numanimbones)
2730 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2733 // check that bones are the same as in the base
2734 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2735 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2739 else if (!strcmp(pchunk->id, "ANIMINFO"))
2742 if (recordsize != sizeof(*p))
2743 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2744 // byteswap in place and keep the pointer
2745 numanims = numrecords;
2746 anims = (pskaniminfo_t *)animbuffer;
2747 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2749 p->numbones = LittleLong(p->numbones);
2750 p->playtime = LittleFloat(p->playtime);
2751 p->fps = LittleFloat(p->fps);
2752 p->firstframe = LittleLong(p->firstframe);
2753 p->numframes = LittleLong(p->numframes);
2754 if (p->numbones != numbones)
2755 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2759 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2762 if (recordsize != sizeof(*p))
2763 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2764 numanimkeys = numrecords;
2765 animkeys = (pskanimkeys_t *)animbuffer;
2766 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2768 p->origin[0] = LittleFloat(p->origin[0]);
2769 p->origin[1] = LittleFloat(p->origin[1]);
2770 p->origin[2] = LittleFloat(p->origin[2]);
2771 p->quat[0] = LittleFloat(p->quat[0]);
2772 p->quat[1] = LittleFloat(p->quat[1]);
2773 p->quat[2] = LittleFloat(p->quat[2]);
2774 p->quat[3] = LittleFloat(p->quat[3]);
2775 p->frametime = LittleFloat(p->frametime);
2776 #ifdef PSKQUATNEGATIONS
2777 if (index % numbones)
2792 // TODO: allocate bonepose stuff
2795 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2798 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2799 Host_Error("%s: missing required chunks", loadmodel->name);
2801 loadmodel->numframes = 0;
2802 for (index = 0;index < numanims;index++)
2803 loadmodel->numframes += anims[index].numframes;
2805 if (numanimkeys != numbones * loadmodel->numframes)
2806 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2808 meshvertices = numvtxw;
2809 meshtriangles = numfaces;
2811 // load external .skin files if present
2812 skinfiles = Mod_LoadSkinFiles();
2813 if (loadmodel->numskins < 1)
2814 loadmodel->numskins = 1;
2815 loadmodel->num_bones = numbones;
2816 loadmodel->num_poses = loadmodel->numframes;
2817 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2818 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2819 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2820 loadmodel->surfmesh.num_vertices = meshvertices;
2821 loadmodel->surfmesh.num_triangles = meshtriangles;
2822 // do most allocations as one merged chunk
2823 size = loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + loadmodel->surfmesh.num_triangles * sizeof(int[3]) + (r_enableshadowvolumes.integer ? loadmodel->surfmesh.num_triangles * sizeof(int[3]) : 0) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[2]) + loadmodel->surfmesh.num_vertices * sizeof(unsigned short) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t) + ((loadmodel->surfmesh.num_vertices <= 65536) ? (loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3])) : 0);
2824 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2825 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2826 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2827 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2828 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2829 if (r_enableshadowvolumes.integer)
2831 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2833 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2834 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2835 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2836 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2837 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2838 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2839 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2840 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2841 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2842 loadmodel->surfmesh.num_blends = 0;
2843 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2844 if (loadmodel->surfmesh.num_vertices <= 65536)
2846 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2848 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2849 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(blendweights_t));
2851 for (i = 0;i < loadmodel->numskins;i++)
2853 loadmodel->skinscenes[i].firstframe = i;
2854 loadmodel->skinscenes[i].framecount = 1;
2855 loadmodel->skinscenes[i].loop = true;
2856 loadmodel->skinscenes[i].framerate = 10;
2860 for (index = 0, i = 0;index < nummatts;index++)
2862 // since psk models do not have named sections, reuse their shader name as the section name
2863 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2864 loadmodel->sortedmodelsurfaces[index] = index;
2865 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2866 loadmodel->data_surfaces[index].num_firstvertex = 0;
2867 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2870 // copy over the vertex locations and texcoords
2871 for (index = 0;index < numvtxw;index++)
2873 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2874 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2875 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2876 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2877 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2880 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2881 for (index = 0;index < numfaces;index++)
2882 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2883 for (index = 0, i = 0;index < nummatts;index++)
2885 loadmodel->data_surfaces[index].num_firsttriangle = i;
2886 i += loadmodel->data_surfaces[index].num_triangles;
2887 loadmodel->data_surfaces[index].num_triangles = 0;
2889 for (index = 0;index < numfaces;index++)
2891 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2892 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2893 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2894 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2897 // copy over the bones
2898 for (index = 0;index < numbones;index++)
2900 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2901 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2902 if (loadmodel->data_bones[index].parent >= index)
2903 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2906 // sort the psk point weights into the vertex weight tables
2907 // (which only accept up to 4 bones per vertex)
2908 for (index = 0;index < numvtxw;index++)
2910 int weightindex[4] = { 0, 0, 0, 0 };
2911 float weightinfluence[4] = { 0, 0, 0, 0 };
2913 for (j = 0;j < numrawweights;j++)
2915 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2917 int boneindex = rawweights[j].boneindex;
2918 float influence = rawweights[j].weight;
2919 for (l = 0;l < 4;l++)
2921 if (weightinfluence[l] < influence)
2923 // move lower influence weights out of the way first
2925 for (l2 = 3;l2 > l;l2--)
2927 weightinfluence[l2] = weightinfluence[l2-1];
2928 weightindex[l2] = weightindex[l2-1];
2930 // store the new weight
2931 weightinfluence[l] = influence;
2932 weightindex[l] = boneindex;
2938 loadmodel->surfmesh.blends[index] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
2940 if (loadmodel->surfmesh.num_blends < loadmodel->surfmesh.num_vertices)
2941 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2943 // set up the animscenes based on the anims
2944 for (index = 0, i = 0;index < numanims;index++)
2946 for (j = 0;j < anims[index].numframes;j++, i++)
2948 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2949 loadmodel->animscenes[i].firstframe = i;
2950 loadmodel->animscenes[i].framecount = 1;
2951 loadmodel->animscenes[i].loop = true;
2952 loadmodel->animscenes[i].framerate = anims[index].fps;
2956 // calculate the scaling value for bone origins so they can be compressed to short
2958 for (index = 0;index < numanimkeys;index++)
2960 pskanimkeys_t *k = animkeys + index;
2961 biggestorigin = max(biggestorigin, fabs(k->origin[0]));
2962 biggestorigin = max(biggestorigin, fabs(k->origin[1]));
2963 biggestorigin = max(biggestorigin, fabs(k->origin[2]));
2965 loadmodel->num_posescale = biggestorigin / 32767.0f;
2966 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2968 // load the poses from the animkeys
2969 for (index = 0;index < numanimkeys;index++)
2971 pskanimkeys_t *k = animkeys + index;
2973 Vector4Copy(k->quat, quat);
2975 Vector4Negate(quat, quat);
2976 Vector4Normalize2(quat, quat);
2977 // compress poses to the short[6] format for longterm storage
2978 loadmodel->data_poses6s[index*6+0] = k->origin[0] * loadmodel->num_poseinvscale;
2979 loadmodel->data_poses6s[index*6+1] = k->origin[1] * loadmodel->num_poseinvscale;
2980 loadmodel->data_poses6s[index*6+2] = k->origin[2] * loadmodel->num_poseinvscale;
2981 loadmodel->data_poses6s[index*6+3] = quat[0] * 32767.0f;
2982 loadmodel->data_poses6s[index*6+4] = quat[1] * 32767.0f;
2983 loadmodel->data_poses6s[index*6+5] = quat[2] * 32767.0f;
2985 Mod_FreeSkinFiles(skinfiles);
2986 Mem_Free(animfilebuffer);
2987 Mod_MakeSortedSurfaces(loadmodel);
2989 // compute all the mesh information that was not loaded from the file
2990 // TODO: honor smoothing groups somehow?
2991 if (loadmodel->surfmesh.data_element3s)
2992 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2993 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2994 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2995 Mod_BuildBaseBonePoses();
2996 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, r_smoothnormals_areaweighting.integer != 0);
2997 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);
2998 if (loadmodel->surfmesh.data_neighbor3i)
2999 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3000 Mod_Alias_CalculateBoundingBox();
3002 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
3004 if (!loadmodel->surfmesh.isanimated)
3006 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3007 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3008 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3009 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3010 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3011 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
3014 // because shaders can do somewhat unexpected things, check for unusual features now
3015 for (i = 0;i < loadmodel->num_textures;i++)
3017 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
3018 mod->DrawSky = R_Q1BSP_DrawSky;
3019 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
3020 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
3024 void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
3026 unsigned char *data;
3028 const unsigned char *pbase, *pend;
3030 skinfile_t *skinfiles;
3031 int i, j, k, meshvertices, meshtriangles;
3032 float biggestorigin;
3033 const unsigned int *inelements;
3035 const int *inneighbors;
3037 float *outvertex, *outnormal, *outtexcoord, *outsvector, *outtvector;
3038 // this pointers into the file data are read only through Little* functions so they can be unaligned memory
3039 const float *vnormal = NULL;
3040 const float *vposition = NULL;
3041 const float *vtangent = NULL;
3042 const float *vtexcoord = NULL;
3043 const unsigned char *vblendindexes = NULL;
3044 const unsigned char *vblendweights = NULL;
3045 const unsigned short *framedata = NULL;
3046 // temporary memory allocations (because the data in the file may be misaligned)
3047 iqmanim_t *anims = NULL;
3048 iqmbounds_t *bounds = NULL;
3049 iqmjoint1_t *joint1 = NULL;
3050 iqmjoint_t *joint = NULL;
3051 iqmmesh_t *meshes = NULL;
3052 iqmpose1_t *pose1 = NULL;
3053 iqmpose_t *pose = NULL;
3054 iqmvertexarray_t *vas = NULL;
3056 pbase = (unsigned char *)buffer;
3057 pend = (unsigned char *)bufferend;
3059 if (pbase + sizeof(iqmheader_t) > pend)
3060 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model %d", loadmodel->name, (int)(pend - pbase));
3062 // copy struct (otherwise it may be misaligned)
3063 // LordHavoc: okay it's definitely not misaligned here, but for consistency...
3064 memcpy(&header, pbase, sizeof(iqmheader_t));
3066 if (memcmp(header.id, "INTERQUAKEMODEL", 16))
3067 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model", loadmodel->name);
3068 if (LittleLong(header.version) != 1 && LittleLong(header.version) != 2)
3069 Host_Error ("Mod_INTERQUAKEMODEL_Load: only version 1 and 2 models are currently supported (name = %s)", loadmodel->name);
3071 loadmodel->modeldatatypestring = "IQM";
3073 loadmodel->type = mod_alias;
3074 loadmodel->synctype = ST_RAND;
3077 header.version = LittleLong(header.version);
3078 header.filesize = LittleLong(header.filesize);
3079 header.flags = LittleLong(header.flags);
3080 header.num_text = LittleLong(header.num_text);
3081 header.ofs_text = LittleLong(header.ofs_text);
3082 header.num_meshes = LittleLong(header.num_meshes);
3083 header.ofs_meshes = LittleLong(header.ofs_meshes);
3084 header.num_vertexarrays = LittleLong(header.num_vertexarrays);
3085 header.num_vertexes = LittleLong(header.num_vertexes);
3086 header.ofs_vertexarrays = LittleLong(header.ofs_vertexarrays);
3087 header.num_triangles = LittleLong(header.num_triangles);
3088 header.ofs_triangles = LittleLong(header.ofs_triangles);
3089 header.ofs_neighbors = LittleLong(header.ofs_neighbors);
3090 header.num_joints = LittleLong(header.num_joints);
3091 header.ofs_joints = LittleLong(header.ofs_joints);
3092 header.num_poses = LittleLong(header.num_poses);
3093 header.ofs_poses = LittleLong(header.ofs_poses);
3094 header.num_anims = LittleLong(header.num_anims);
3095 header.ofs_anims = LittleLong(header.ofs_anims);
3096 header.num_frames = LittleLong(header.num_frames);
3097 header.num_framechannels = LittleLong(header.num_framechannels);
3098 header.ofs_frames = LittleLong(header.ofs_frames);
3099 header.ofs_bounds = LittleLong(header.ofs_bounds);
3100 header.num_comment = LittleLong(header.num_comment);
3101 header.ofs_comment = LittleLong(header.ofs_comment);
3102 header.num_extensions = LittleLong(header.num_extensions);
3103 header.ofs_extensions = LittleLong(header.ofs_extensions);
3105 if (header.num_triangles < 1 || header.num_vertexes < 3 || header.num_vertexarrays < 1 || header.num_meshes < 1)
3107 Con_Printf("%s has no geometry\n", loadmodel->name);
3111 if (header.version == 1)
3113 if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint1_t) > pend ||
3114 pbase + header.ofs_poses + header.num_poses*sizeof(iqmpose1_t) > pend)
3116 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3122 if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint_t) > pend ||
3123 pbase + header.ofs_poses + header.num_poses*sizeof(iqmpose_t) > pend)
3125 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3129 if (pbase + header.ofs_text + header.num_text > pend ||
3130 pbase + header.ofs_meshes + header.num_meshes*sizeof(iqmmesh_t) > pend ||
3131 pbase + header.ofs_vertexarrays + header.num_vertexarrays*sizeof(iqmvertexarray_t) > pend ||
3132 pbase + header.ofs_triangles + header.num_triangles*sizeof(int[3]) > pend ||
3133 (header.ofs_neighbors && pbase + header.ofs_neighbors + header.num_triangles*sizeof(int[3]) > pend) ||
3134 pbase + header.ofs_anims + header.num_anims*sizeof(iqmanim_t) > pend ||
3135 pbase + header.ofs_frames + header.num_frames*header.num_framechannels*sizeof(unsigned short) > pend ||
3136 (header.ofs_bounds && pbase + header.ofs_bounds + header.num_frames*sizeof(iqmbounds_t) > pend) ||
3137 pbase + header.ofs_comment + header.num_comment > pend)
3139 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3143 // copy structs to make them aligned in memory (otherwise we crash on Sparc and PowerPC and others)
3144 if (header.num_vertexarrays)
3145 vas = (iqmvertexarray_t *)(pbase + header.ofs_vertexarrays);
3146 if (header.num_anims)
3147 anims = (iqmanim_t *)(pbase + header.ofs_anims);
3148 if (header.ofs_bounds)
3149 bounds = (iqmbounds_t *)(pbase + header.ofs_bounds);
3150 if (header.num_meshes)
3151 meshes = (iqmmesh_t *)(pbase + header.ofs_meshes);
3153 for (i = 0;i < (int)header.num_vertexarrays;i++)
3155 iqmvertexarray_t va;
3157 va.type = LittleLong(vas[i].type);
3158 va.flags = LittleLong(vas[i].flags);
3159 va.format = LittleLong(vas[i].format);
3160 va.size = LittleLong(vas[i].size);
3161 va.offset = LittleLong(vas[i].offset);
3162 vsize = header.num_vertexes*va.size;
3165 case IQM_FLOAT: vsize *= sizeof(float); break;
3166 case IQM_UBYTE: vsize *= sizeof(unsigned char); break;
3169 if (pbase + va.offset + vsize > pend)
3171 // no need to copy the vertex data for alignment because LittleLong/LittleShort will be invoked on reading them, and the destination is aligned
3175 if (va.format == IQM_FLOAT && va.size == 3)
3176 vposition = (const float *)(pbase + va.offset);
3179 if (va.format == IQM_FLOAT && va.size == 2)
3180 vtexcoord = (const float *)(pbase + va.offset);
3183 if (va.format == IQM_FLOAT && va.size == 3)
3184 vnormal = (const float *)(pbase + va.offset);
3187 if (va.format == IQM_FLOAT && va.size == 4)
3188 vtangent = (const float *)(pbase + va.offset);
3190 case IQM_BLENDINDEXES:
3191 if (va.format == IQM_UBYTE && va.size == 4)
3192 vblendindexes = (const unsigned char *)(pbase + va.offset);
3194 case IQM_BLENDWEIGHTS:
3195 if (va.format == IQM_UBYTE && va.size == 4)
3196 vblendweights = (const unsigned char *)(pbase + va.offset);
3200 if (header.num_vertexes > 0 && (!vposition || !vtexcoord || ((header.num_frames > 0 || header.num_anims > 0) && (!vblendindexes || !vblendweights))))
3202 Con_Printf("%s is missing vertex array data\n", loadmodel->name);
3206 text = header.num_text && header.ofs_text ? (const char *)(pbase + header.ofs_text) : "";
3208 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
3209 loadmodel->DrawSky = NULL;
3210 loadmodel->DrawAddWaterPlanes = NULL;
3211 loadmodel->Draw = R_Q1BSP_Draw;
3212 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
3213 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
3214 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
3215 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
3216 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
3217 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
3218 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
3219 loadmodel->DrawLight = R_Q1BSP_DrawLight;
3220 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
3221 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
3222 loadmodel->PointSuperContents = NULL;
3224 // load external .skin files if present
3225 skinfiles = Mod_LoadSkinFiles();
3226 if (loadmodel->numskins < 1)
3227 loadmodel->numskins = 1;
3229 loadmodel->numframes = max(header.num_anims, 1);
3230 loadmodel->num_bones = header.num_joints;
3231 loadmodel->num_poses = max(header.num_frames, 1);
3232 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = header.num_meshes;
3233 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3234 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3236 meshvertices = header.num_vertexes;
3237 meshtriangles = header.num_triangles;
3239 // do most allocations as one merged chunk
3240 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + (r_enableshadowvolumes.integer ? meshtriangles * sizeof(int[3]) : 0) + meshvertices * sizeof(float[14]) + (vblendindexes && vblendweights ? meshvertices * sizeof(unsigned short) : 0) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
3241 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
3242 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
3243 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
3244 loadmodel->surfmesh.num_vertices = meshvertices;
3245 loadmodel->surfmesh.num_triangles = meshtriangles;
3246 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3247 if (r_enableshadowvolumes.integer)
3249 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3251 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
3252 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3253 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3254 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
3255 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
3256 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
3257 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
3258 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
3259 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
3260 if (vblendindexes && vblendweights)
3262 loadmodel->surfmesh.num_blends = 0;
3263 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
3265 if (meshvertices <= 65536)
3267 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
3269 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
3270 if (vblendindexes && vblendweights)
3271 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
3273 for (i = 0;i < loadmodel->numskins;i++)
3275 loadmodel->skinscenes[i].firstframe = i;
3276 loadmodel->skinscenes[i].framecount = 1;
3277 loadmodel->skinscenes[i].loop = true;
3278 loadmodel->skinscenes[i].framerate = 10;
3281 // load the bone info
3282 if (header.version == 1)
3284 iqmjoint1_t *injoint1 = (iqmjoint1_t *)(pbase + header.ofs_joints);
3285 if (loadmodel->num_bones)
3286 joint1 = (iqmjoint1_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(iqmjoint1_t));
3287 for (i = 0;i < loadmodel->num_bones;i++)
3289 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3290 joint1[i].name = LittleLong(injoint1[i].name);
3291 joint1[i].parent = LittleLong(injoint1[i].parent);
3292 for (j = 0;j < 3;j++)
3294 joint1[i].origin[j] = LittleFloat(injoint1[i].origin[j]);
3295 joint1[i].rotation[j] = LittleFloat(injoint1[i].rotation[j]);
3296 joint1[i].scale[j] = LittleFloat(injoint1[i].scale[j]);
3298 strlcpy(loadmodel->data_bones[i].name, &text[joint1[i].name], sizeof(loadmodel->data_bones[i].name));
3299 loadmodel->data_bones[i].parent = joint1[i].parent;
3300 if (loadmodel->data_bones[i].parent >= i)
3301 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3302 Matrix4x4_FromDoom3Joint(&relbase, joint1[i].origin[0], joint1[i].origin[1], joint1[i].origin[2], joint1[i].rotation[0], joint1[i].rotation[1], joint1[i].rotation[2]);
3303 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3304 if (loadmodel->data_bones[i].parent >= 0)
3306 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3307 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3308 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3310 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3315 iqmjoint_t *injoint = (iqmjoint_t *)(pbase + header.ofs_joints);
3316 if (header.num_joints)
3317 joint = (iqmjoint_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(iqmjoint_t));
3318 for (i = 0;i < loadmodel->num_bones;i++)
3320 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3321 joint[i].name = LittleLong(injoint[i].name);
3322 joint[i].parent = LittleLong(injoint[i].parent);
3323 for (j = 0;j < 3;j++)
3325 joint[i].origin[j] = LittleFloat(injoint[i].origin[j]);
3326 joint[i].rotation[j] = LittleFloat(injoint[i].rotation[j]);
3327 joint[i].scale[j] = LittleFloat(injoint[i].scale[j]);
3329 joint[i].rotation[3] = LittleFloat(injoint[i].rotation[3]);
3330 strlcpy(loadmodel->data_bones[i].name, &text[joint[i].name], sizeof(loadmodel->data_bones[i].name));
3331 loadmodel->data_bones[i].parent = joint[i].parent;
3332 if (loadmodel->data_bones[i].parent >= i)
3333 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3334 if (joint[i].rotation[3] > 0)
3335 Vector4Negate(joint[i].rotation, joint[i].rotation);
3336 Vector4Normalize2(joint[i].rotation, joint[i].rotation);
3337 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]);
3338 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3339 if (loadmodel->data_bones[i].parent >= 0)
3341 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3342 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3343 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3345 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3349 // set up the animscenes based on the anims
3350 for (i = 0;i < (int)header.num_anims;i++)
3353 anim.name = LittleLong(anims[i].name);
3354 anim.first_frame = LittleLong(anims[i].first_frame);
3355 anim.num_frames = LittleLong(anims[i].num_frames);
3356 anim.framerate = LittleFloat(anims[i].framerate);
3357 anim.flags = LittleLong(anims[i].flags);
3358 strlcpy(loadmodel->animscenes[i].name, &text[anim.name], sizeof(loadmodel->animscenes[i].name));
3359 loadmodel->animscenes[i].firstframe = anim.first_frame;
3360 loadmodel->animscenes[i].framecount = anim.num_frames;
3361 loadmodel->animscenes[i].loop = ((anim.flags & IQM_LOOP) != 0);
3362 loadmodel->animscenes[i].framerate = anim.framerate;
3364 if (header.num_anims <= 0)
3366 strlcpy(loadmodel->animscenes[0].name, "static", sizeof(loadmodel->animscenes[0].name));
3367 loadmodel->animscenes[0].firstframe = 0;
3368 loadmodel->animscenes[0].framecount = 1;
3369 loadmodel->animscenes[0].loop = true;
3370 loadmodel->animscenes[0].framerate = 10;
3374 if (header.version == 1)
3376 iqmpose1_t *inpose1 = (iqmpose1_t *)(pbase + header.ofs_poses);
3377 if (header.num_poses)
3378 pose1 = (iqmpose1_t *)Mem_Alloc(loadmodel->mempool, header.num_poses * sizeof(iqmpose1_t));
3379 for (i = 0;i < (int)header.num_poses;i++)
3382 pose1[i].parent = LittleLong(inpose1[i].parent);
3383 pose1[i].channelmask = LittleLong(inpose1[i].channelmask);
3384 for (j = 0;j < 9;j++)
3386 pose1[i].channeloffset[j] = LittleFloat(inpose1[i].channeloffset[j]);
3387 pose1[i].channelscale[j] = LittleFloat(inpose1[i].channelscale[j]);
3389 f = fabs(pose1[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3390 f = fabs(pose1[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3391 f = fabs(pose1[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3392 f = fabs(pose1[i].channeloffset[0] + 0xFFFF*pose1[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3393 f = fabs(pose1[i].channeloffset[1] + 0xFFFF*pose1[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3394 f = fabs(pose1[i].channeloffset[2] + 0xFFFF*pose1[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3396 if (header.num_frames <= 0)
3398 for (i = 0;i < loadmodel->num_bones;i++)
3401 f = fabs(joint1[i].origin[0]); biggestorigin = max(biggestorigin, f);
3402 f = fabs(joint1[i].origin[1]); biggestorigin = max(biggestorigin, f);
3403 f = fabs(joint1[i].origin[2]); biggestorigin = max(biggestorigin, f);
3409 iqmpose_t *inpose = (iqmpose_t *)(pbase + header.ofs_poses);
3410 if (header.num_poses)
3411 pose = (iqmpose_t *)Mem_Alloc(loadmodel->mempool, header.num_poses * sizeof(iqmpose_t));
3412 for (i = 0;i < (int)header.num_poses;i++)
3415 pose[i].parent = LittleLong(inpose[i].parent);
3416 pose[i].channelmask = LittleLong(inpose[i].channelmask);
3417 for (j = 0;j < 10;j++)
3419 pose[i].channeloffset[j] = LittleFloat(inpose[i].channeloffset[j]);
3420 pose[i].channelscale[j] = LittleFloat(inpose[i].channelscale[j]);
3422 f = fabs(pose[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3423 f = fabs(pose[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3424 f = fabs(pose[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3425 f = fabs(pose[i].channeloffset[0] + 0xFFFF*pose[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3426 f = fabs(pose[i].channeloffset[1] + 0xFFFF*pose[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3427 f = fabs(pose[i].channeloffset[2] + 0xFFFF*pose[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3429 if (header.num_frames <= 0)
3431 for (i = 0;i < loadmodel->num_bones;i++)
3434 f = fabs(joint[i].origin[0]); biggestorigin = max(biggestorigin, f);
3435 f = fabs(joint[i].origin[1]); biggestorigin = max(biggestorigin, f);
3436 f = fabs(joint[i].origin[2]); biggestorigin = max(biggestorigin, f);
3440 loadmodel->num_posescale = biggestorigin / 32767.0f;
3441 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3443 // load the pose data
3444 // this unaligned memory access is safe (LittleShort reads as bytes)
3445 framedata = (const unsigned short *)(pbase + header.ofs_frames);
3446 if (header.version == 1)
3448 for (i = 0, k = 0;i < (int)header.num_frames;i++)
3450 for (j = 0;j < (int)header.num_poses;j++, k++)
3452 loadmodel->data_poses6s[k*6 + 0] = loadmodel->num_poseinvscale * (pose1[j].channeloffset[0] + (pose1[j].channelmask&1 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[0] : 0));
3453 loadmodel->data_poses6s[k*6 + 1] = loadmodel->num_poseinvscale * (pose1[j].channeloffset[1] + (pose1[j].channelmask&2 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[1] : 0));
3454 loadmodel->data_poses6s[k*6 + 2] = loadmodel->num_poseinvscale * (pose1[j].channeloffset[2] + (pose1[j].channelmask&4 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[2] : 0));
3455 loadmodel->data_poses6s[k*6 + 3] = 32767.0f * (pose1[j].channeloffset[3] + (pose1[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[3] : 0));
3456 loadmodel->data_poses6s[k*6 + 4] = 32767.0f * (pose1[j].channeloffset[4] + (pose1[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[4] : 0));
3457 loadmodel->data_poses6s[k*6 + 5] = 32767.0f * (pose1[j].channeloffset[5] + (pose1[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[5] : 0));
3458 // skip scale data for now
3459 if(pose1[j].channelmask&64) framedata++;
3460 if(pose1[j].channelmask&128) framedata++;
3461 if(pose1[j].channelmask&256) framedata++;
3464 if (header.num_frames <= 0)
3466 for (i = 0;i < loadmodel->num_bones;i++)
3468 loadmodel->data_poses6s[i*6 + 0] = loadmodel->num_poseinvscale * joint1[i].origin[0];
3469 loadmodel->data_poses6s[i*6 + 1] = loadmodel->num_poseinvscale * joint1[i].origin[1];
3470 loadmodel->data_poses6s[i*6 + 2] = loadmodel->num_poseinvscale * joint1[i].origin[2];
3471 loadmodel->data_poses6s[i*6 + 3] = 32767.0f * joint1[i].rotation[0];
3472 loadmodel->data_poses6s[i*6 + 4] = 32767.0f * joint1[i].rotation[1];
3473 loadmodel->data_poses6s[i*6 + 5] = 32767.0f * joint1[i].rotation[2];
3479 for (i = 0, k = 0;i < (int)header.num_frames;i++)
3481 for (j = 0;j < (int)header.num_poses;j++, k++)
3484 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));
3485 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));
3486 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));
3487 rot[0] = pose[j].channeloffset[3] + (pose[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[3] : 0);
3488 rot[1] = pose[j].channeloffset[4] + (pose[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[4] : 0);
3489 rot[2] = pose[j].channeloffset[5] + (pose[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[5] : 0);
3490 rot[3] = pose[j].channeloffset[6] + (pose[j].channelmask&64 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[6] : 0);
3492 Vector4Negate(rot, rot);
3493 Vector4Normalize2(rot, rot);
3494 loadmodel->data_poses6s[k*6 + 3] = 32767.0f * rot[0];
3495 loadmodel->data_poses6s[k*6 + 4] = 32767.0f * rot[1];
3496 loadmodel->data_poses6s[k*6 + 5] = 32767.0f * rot[2];
3497 // skip scale data for now
3498 if(pose[j].channelmask&128) framedata++;
3499 if(pose[j].channelmask&256) framedata++;
3500 if(pose[j].channelmask&512) framedata++;
3503 if (header.num_frames <= 0)
3505 for (i = 0;i < loadmodel->num_bones;i++)
3507 loadmodel->data_poses6s[i*6 + 0] = loadmodel->num_poseinvscale * joint[i].origin[0];
3508 loadmodel->data_poses6s[i*6 + 1] = loadmodel->num_poseinvscale * joint[i].origin[1];
3509 loadmodel->data_poses6s[i*6 + 2] = loadmodel->num_poseinvscale * joint[i].origin[2];
3510 loadmodel->data_poses6s[i*6 + 3] = 32767.0f * joint[i].rotation[0];
3511 loadmodel->data_poses6s[i*6 + 4] = 32767.0f * joint[i].rotation[1];
3512 loadmodel->data_poses6s[i*6 + 5] = 32767.0f * joint[i].rotation[2];
3517 // load bounding box data
3518 if (header.ofs_bounds)
3520 float xyradius = 0, radius = 0;
3521 VectorClear(loadmodel->normalmins);
3522 VectorClear(loadmodel->normalmaxs);
3523 for (i = 0; i < (int)header.num_frames;i++)
3526 bound.mins[0] = LittleFloat(bounds[i].mins[0]);
3527 bound.mins[1] = LittleFloat(bounds[i].mins[1]);
3528 bound.mins[2] = LittleFloat(bounds[i].mins[2]);
3529 bound.maxs[0] = LittleFloat(bounds[i].maxs[0]);
3530 bound.maxs[1] = LittleFloat(bounds[i].maxs[1]);
3531 bound.maxs[2] = LittleFloat(bounds[i].maxs[2]);
3532 bound.xyradius = LittleFloat(bounds[i].xyradius);
3533 bound.radius = LittleFloat(bounds[i].radius);
3536 VectorCopy(bound.mins, loadmodel->normalmins);
3537 VectorCopy(bound.maxs, loadmodel->normalmaxs);
3541 if (loadmodel->normalmins[0] > bound.mins[0]) loadmodel->normalmins[0] = bound.mins[0];
3542 if (loadmodel->normalmins[1] > bound.mins[1]) loadmodel->normalmins[1] = bound.mins[1];
3543 if (loadmodel->normalmins[2] > bound.mins[2]) loadmodel->normalmins[2] = bound.mins[2];
3544 if (loadmodel->normalmaxs[0] < bound.maxs[0]) loadmodel->normalmaxs[0] = bound.maxs[0];
3545 if (loadmodel->normalmaxs[1] < bound.maxs[1]) loadmodel->normalmaxs[1] = bound.maxs[1];
3546 if (loadmodel->normalmaxs[2] < bound.maxs[2]) loadmodel->normalmaxs[2] = bound.maxs[2];
3548 if (bound.xyradius > xyradius)
3549 xyradius = bound.xyradius;
3550 if (bound.radius > radius)
3551 radius = bound.radius;
3553 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -xyradius;
3554 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = xyradius;
3555 loadmodel->yawmins[2] = loadmodel->normalmins[2];
3556 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
3557 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
3558 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
3559 loadmodel->radius = radius;
3560 loadmodel->radius2 = radius * radius;
3563 // load triangle data
3564 // this unaligned memory access is safe (LittleLong reads as bytes)
3565 inelements = (const unsigned int *)(pbase + header.ofs_triangles);
3566 outelements = loadmodel->surfmesh.data_element3i;
3567 for (i = 0;i < (int)header.num_triangles;i++)
3569 outelements[0] = LittleLong(inelements[0]);
3570 outelements[1] = LittleLong(inelements[1]);
3571 outelements[2] = LittleLong(inelements[2]);
3575 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, header.num_vertexes, __FILE__, __LINE__);
3577 if (header.ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
3579 // this unaligned memory access is safe (LittleLong reads as bytes)
3580 inneighbors = (const int *)(pbase + header.ofs_neighbors);
3581 outneighbors = loadmodel->surfmesh.data_neighbor3i;
3582 for (i = 0;i < (int)header.num_triangles;i++)
3584 outneighbors[0] = LittleLong(inneighbors[0]);
3585 outneighbors[1] = LittleLong(inneighbors[1]);
3586 outneighbors[2] = LittleLong(inneighbors[2]);
3593 // this unaligned memory access is safe (LittleFloat reads as bytes)
3594 outvertex = loadmodel->surfmesh.data_vertex3f;
3595 for (i = 0;i < (int)header.num_vertexes;i++)
3597 outvertex[0] = LittleFloat(vposition[0]);
3598 outvertex[1] = LittleFloat(vposition[1]);
3599 outvertex[2] = LittleFloat(vposition[2]);
3604 outtexcoord = loadmodel->surfmesh.data_texcoordtexture2f;
3605 // this unaligned memory access is safe (LittleFloat reads as bytes)
3606 for (i = 0;i < (int)header.num_vertexes;i++)
3608 outtexcoord[0] = LittleFloat(vtexcoord[0]);
3609 outtexcoord[1] = LittleFloat(vtexcoord[1]);
3614 // this unaligned memory access is safe (LittleFloat reads as bytes)
3617 outnormal = loadmodel->surfmesh.data_normal3f;
3618 for (i = 0;i < (int)header.num_vertexes;i++)
3620 outnormal[0] = LittleFloat(vnormal[0]);
3621 outnormal[1] = LittleFloat(vnormal[1]);
3622 outnormal[2] = LittleFloat(vnormal[2]);
3628 // this unaligned memory access is safe (LittleFloat reads as bytes)
3629 if(vnormal && vtangent)
3631 outnormal = loadmodel->surfmesh.data_normal3f;
3632 outsvector = loadmodel->surfmesh.data_svector3f;
3633 outtvector = loadmodel->surfmesh.data_tvector3f;
3634 for (i = 0;i < (int)header.num_vertexes;i++)
3636 outsvector[0] = LittleFloat(vtangent[0]);
3637 outsvector[1] = LittleFloat(vtangent[1]);
3638 outsvector[2] = LittleFloat(vtangent[2]);
3639 if(LittleFloat(vtangent[3]) < 0)
3640 CrossProduct(outsvector, outnormal, outtvector);
3642 CrossProduct(outnormal, outsvector, outtvector);
3650 // this unaligned memory access is safe (all bytes)
3651 if (vblendindexes && vblendweights)
3653 for (i = 0; i < (int)header.num_vertexes;i++)
3655 blendweights_t weights;
3656 memcpy(weights.index, vblendindexes + i*4, 4);
3657 memcpy(weights.influence, vblendweights + i*4, 4);
3658 loadmodel->surfmesh.blends[i] = Mod_Skeletal_AddBlend(loadmodel, &weights);
3663 for (i = 0;i < (int)header.num_meshes;i++)
3666 msurface_t *surface;
3668 mesh.name = LittleLong(meshes[i].name);
3669 mesh.material = LittleLong(meshes[i].material);
3670 mesh.first_vertex = LittleLong(meshes[i].first_vertex);
3671 mesh.num_vertexes = LittleLong(meshes[i].num_vertexes);
3672 mesh.first_triangle = LittleLong(meshes[i].first_triangle);
3673 mesh.num_triangles = LittleLong(meshes[i].num_triangles);
3675 loadmodel->sortedmodelsurfaces[i] = i;
3676 surface = loadmodel->data_surfaces + i;
3677 surface->texture = loadmodel->data_textures + i;
3678 surface->num_firsttriangle = mesh.first_triangle;
3679 surface->num_triangles = mesh.num_triangles;
3680 surface->num_firstvertex = mesh.first_vertex;
3681 surface->num_vertices = mesh.num_vertexes;
3683 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, &text[mesh.name], &text[mesh.material]);
3686 Mod_FreeSkinFiles(skinfiles);
3687 Mod_MakeSortedSurfaces(loadmodel);
3689 // compute all the mesh information that was not loaded from the file
3690 if (loadmodel->surfmesh.data_element3s)
3691 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3692 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3694 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, r_smoothnormals_areaweighting.integer != 0);
3695 if (!vnormal || !vtangent)
3696 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);
3697 if (!header.ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
3698 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3699 if (!header.ofs_bounds)
3700 Mod_Alias_CalculateBoundingBox();
3702 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
3704 if (!loadmodel->surfmesh.isanimated)
3706 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3707 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3708 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3709 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3710 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3711 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
3714 if (joint ) Mem_Free(joint );joint = NULL;
3715 if (joint1 ) Mem_Free(joint1 );joint1 = NULL;
3716 if (pose ) Mem_Free(pose );pose = NULL;
3717 if (pose1 ) Mem_Free(pose1 );pose1 = NULL;
3719 // because shaders can do somewhat unexpected things, check for unusual features now
3720 for (i = 0;i < loadmodel->num_textures;i++)
3722 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
3723 mod->DrawSky = R_Q1BSP_DrawSky;
3724 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
3725 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;