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 (!model->surfmesh.num_vertices)
70 if (!model->num_bones)
72 if (vertex3f) memcpy(vertex3f, model->surfmesh.data_vertex3f, model->surfmesh.num_vertices*sizeof(float[3]));
73 if (normal3f) memcpy(normal3f, model->surfmesh.data_normal3f, model->surfmesh.num_vertices*sizeof(float[3]));
74 if (svector3f) memcpy(svector3f, model->surfmesh.data_svector3f, model->surfmesh.num_vertices*sizeof(float[3]));
75 if (tvector3f) memcpy(tvector3f, model->surfmesh.data_tvector3f, model->surfmesh.num_vertices*sizeof(float[3]));
80 if(r_skeletal_use_sse_defined)
81 if(r_skeletal_use_sse.integer)
83 Mod_Skeletal_AnimateVertices_SSE(model, frameblend, skeleton, vertex3f, normal3f, svector3f, tvector3f);
87 Mod_Skeletal_AnimateVertices_Generic(model, frameblend, skeleton, vertex3f, normal3f, svector3f, tvector3f);
90 void Mod_AliasInit (void)
93 Cvar_RegisterVariable(&r_skeletal_debugbone);
94 Cvar_RegisterVariable(&r_skeletal_debugbonecomponent);
95 Cvar_RegisterVariable(&r_skeletal_debugbonevalue);
96 Cvar_RegisterVariable(&r_skeletal_debugtranslatex);
97 Cvar_RegisterVariable(&r_skeletal_debugtranslatey);
98 Cvar_RegisterVariable(&r_skeletal_debugtranslatez);
99 Cvar_RegisterVariable(&mod_alias_supporttagscale);
100 for (i = 0;i < 320;i++)
101 mod_md3_sin[i] = sin(i * M_PI * 2.0f / 256.0);
105 Con_Printf("Skeletal animation uses SSE code path\n");
106 r_skeletal_use_sse_defined = true;
107 Cvar_RegisterVariable(&r_skeletal_use_sse);
110 Con_Printf("Skeletal animation uses generic code path (SSE disabled or not detected)\n");
112 Con_Printf("Skeletal animation uses generic code path (SSE not compiled in)\n");
116 int Mod_Skeletal_AddBlend(dp_model_t *model, const blendweights_t *newweights)
119 blendweights_t *weights;
120 if(!newweights->influence[1])
121 return newweights->index[0];
122 weights = model->surfmesh.data_blendweights;
123 for (i = 0;i < model->surfmesh.num_blends;i++, weights++)
125 if (!memcmp(weights, newweights, sizeof(blendweights_t)))
126 return model->num_bones + i;
128 model->surfmesh.num_blends++;
129 memcpy(weights, newweights, sizeof(blendweights_t));
130 return model->num_bones + i;
133 int Mod_Skeletal_CompressBlend(dp_model_t *model, const int *newindex, const float *newinfluence)
137 blendweights_t newweights;
141 for (i = 0;i < 4;i++)
142 scale += newinfluence[i];
143 scale = 255.0f / scale;
145 for (i = 0;i < 4;i++)
147 newweights.index[i] = newindex[i];
148 newweights.influence[i] = (unsigned char)(newinfluence[i] * scale);
149 total += newweights.influence[i];
153 for (i = 0;i < 4;i++)
155 if(newweights.influence[i] > 0 && total > 255)
157 newweights.influence[i]--;
164 for (i = 0; i < 4;i++)
166 if(newweights.influence[i] < 255 && total < 255)
168 newweights.influence[i]++;
173 return Mod_Skeletal_AddBlend(model, &newweights);
176 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)
179 int i, numblends, blendnum;
180 int numverts = model->surfmesh.num_vertices;
182 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
184 //VectorMA(translate, model->surfmesh.num_morphmdlframetranslate, frameblend[blendnum].lerp, translate);
185 if (frameblend[blendnum].lerp > 0)
186 numblends = blendnum + 1;
188 // special case for the first blend because it avoids some adds and the need to memset the arrays first
189 for (blendnum = 0;blendnum < numblends;blendnum++)
191 const md3vertex_t *verts = model->surfmesh.data_morphmd3vertex + numverts * frameblend[blendnum].subframe;
194 float scale = frameblend[blendnum].lerp * (1.0f / 64.0f);
197 for (i = 0;i < numverts;i++)
199 vertex3f[i * 3 + 0] = verts[i].origin[0] * scale;
200 vertex3f[i * 3 + 1] = verts[i].origin[1] * scale;
201 vertex3f[i * 3 + 2] = verts[i].origin[2] * scale;
206 for (i = 0;i < numverts;i++)
208 vertex3f[i * 3 + 0] += verts[i].origin[0] * scale;
209 vertex3f[i * 3 + 1] += verts[i].origin[1] * scale;
210 vertex3f[i * 3 + 2] += verts[i].origin[2] * scale;
214 // the yaw and pitch stored in md3 models are 8bit quantized angles
215 // (0-255), and as such a lookup table is very well suited to
216 // decoding them, and since cosine is equivalent to sine with an
217 // extra 45 degree rotation, this uses one lookup table for both
218 // sine and cosine with a +64 bias to get cosine.
221 float lerp = frameblend[blendnum].lerp;
224 for (i = 0;i < numverts;i++)
226 normal3f[i * 3 + 0] = mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
227 normal3f[i * 3 + 1] = mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
228 normal3f[i * 3 + 2] = mod_md3_sin[verts[i].pitch + 64] * lerp;
233 for (i = 0;i < numverts;i++)
235 normal3f[i * 3 + 0] += mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
236 normal3f[i * 3 + 1] += mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
237 normal3f[i * 3 + 2] += mod_md3_sin[verts[i].pitch + 64] * lerp;
243 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
244 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
247 for (i = 0;i < numverts;i++, texvecvert++)
249 VectorScale(texvecvert->svec, f, svector3f + i*3);
250 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
255 for (i = 0;i < numverts;i++, texvecvert++)
257 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
258 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
264 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)
267 int i, numblends, blendnum;
268 int numverts = model->surfmesh.num_vertices;
270 VectorClear(translate);
272 // blend the frame translates to avoid redundantly doing so on each vertex
273 // (a bit of a brain twister but it works)
274 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
276 if (model->surfmesh.data_morphmd2framesize6f)
277 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6 + 3, translate);
279 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.num_morphmdlframetranslate, translate);
280 if (frameblend[blendnum].lerp > 0)
281 numblends = blendnum + 1;
283 // special case for the first blend because it avoids some adds and the need to memset the arrays first
284 for (blendnum = 0;blendnum < numblends;blendnum++)
286 const trivertx_t *verts = model->surfmesh.data_morphmdlvertex + numverts * frameblend[blendnum].subframe;
290 if (model->surfmesh.data_morphmd2framesize6f)
291 VectorScale(model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6, frameblend[blendnum].lerp, scale);
293 VectorScale(model->surfmesh.num_morphmdlframescale, frameblend[blendnum].lerp, scale);
296 for (i = 0;i < numverts;i++)
298 vertex3f[i * 3 + 0] = translate[0] + verts[i].v[0] * scale[0];
299 vertex3f[i * 3 + 1] = translate[1] + verts[i].v[1] * scale[1];
300 vertex3f[i * 3 + 2] = translate[2] + verts[i].v[2] * scale[2];
305 for (i = 0;i < numverts;i++)
307 vertex3f[i * 3 + 0] += verts[i].v[0] * scale[0];
308 vertex3f[i * 3 + 1] += verts[i].v[1] * scale[1];
309 vertex3f[i * 3 + 2] += verts[i].v[2] * scale[2];
313 // the vertex normals in mdl models are an index into a table of
314 // 162 unique values, this very crude quantization reduces the
315 // vertex normal to only one byte, which saves a lot of space but
316 // also makes lighting pretty coarse
319 float lerp = frameblend[blendnum].lerp;
322 for (i = 0;i < numverts;i++)
324 const float *vn = m_bytenormals[verts[i].lightnormalindex];
325 VectorScale(vn, lerp, normal3f + i*3);
330 for (i = 0;i < numverts;i++)
332 const float *vn = m_bytenormals[verts[i].lightnormalindex];
333 VectorMA(normal3f + i*3, lerp, vn, normal3f + i*3);
339 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
340 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
343 for (i = 0;i < numverts;i++, texvecvert++)
345 VectorScale(texvecvert->svec, f, svector3f + i*3);
346 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
351 for (i = 0;i < numverts;i++, texvecvert++)
353 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
354 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
361 int Mod_Alias_GetTagMatrix(const dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, int tagindex, matrix4x4_t *outmatrix)
364 matrix4x4_t parentbonematrix;
365 matrix4x4_t tempbonematrix;
366 matrix4x4_t bonematrix;
367 matrix4x4_t blendmatrix;
374 *outmatrix = identitymatrix;
375 if (skeleton && skeleton->relativetransforms)
377 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
379 *outmatrix = skeleton->relativetransforms[tagindex];
380 while ((tagindex = model->data_bones[tagindex].parent) >= 0)
383 Matrix4x4_Concat(outmatrix, &skeleton->relativetransforms[tagindex], &temp);
386 else if (model->num_bones)
388 if (tagindex < 0 || tagindex >= model->num_bones)
390 Matrix4x4_Clear(&blendmatrix);
391 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
393 lerp = frameblend[blendindex].lerp;
394 Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
395 parenttagindex = tagindex;
396 while ((parenttagindex = model->data_bones[parenttagindex].parent) >= 0)
398 Matrix4x4_FromBonePose6s(&parentbonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + parenttagindex));
399 tempbonematrix = bonematrix;
400 Matrix4x4_Concat(&bonematrix, &parentbonematrix, &tempbonematrix);
402 Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
404 *outmatrix = blendmatrix;
406 else if (model->num_tags)
408 if (tagindex < 0 || tagindex >= model->num_tags)
410 for (k = 0;k < 12;k++)
412 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
414 lerp = frameblend[blendindex].lerp;
415 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
416 for (k = 0;k < 12;k++)
417 blendtag[k] += input[k] * lerp;
419 Matrix4x4_FromArray12FloatGL(outmatrix, blendtag);
422 if(!mod_alias_supporttagscale.integer)
423 Matrix4x4_Normalize3(outmatrix, outmatrix);
428 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)
433 matrix4x4_t bonematrix;
434 matrix4x4_t blendmatrix;
438 if (skeleton && skeleton->relativetransforms)
440 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
442 *parentindex = skeleton->model->data_bones[tagindex].parent;
443 *tagname = skeleton->model->data_bones[tagindex].name;
444 *tag_localmatrix = skeleton->relativetransforms[tagindex];
447 else if (model->num_bones)
449 if (tagindex < 0 || tagindex >= model->num_bones)
451 *parentindex = model->data_bones[tagindex].parent;
452 *tagname = model->data_bones[tagindex].name;
453 Matrix4x4_Clear(&blendmatrix);
454 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
456 lerp = frameblend[blendindex].lerp;
457 Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
458 Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
460 *tag_localmatrix = blendmatrix;
463 else if (model->num_tags)
465 if (tagindex < 0 || tagindex >= model->num_tags)
468 *tagname = model->data_tags[tagindex].name;
469 for (k = 0;k < 12;k++)
471 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
473 lerp = frameblend[blendindex].lerp;
474 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
475 for (k = 0;k < 12;k++)
476 blendtag[k] += input[k] * lerp;
478 Matrix4x4_FromArray12FloatGL(tag_localmatrix, blendtag);
485 int Mod_Alias_GetTagIndexForName(const dp_model_t *model, unsigned int skin, const char *tagname)
488 if(skin >= (unsigned int)model->numskins)
490 if (model->num_bones)
491 for (i = 0;i < model->num_bones;i++)
492 if (!strcasecmp(tagname, model->data_bones[i].name))
495 for (i = 0;i < model->num_tags;i++)
496 if (!strcasecmp(tagname, model->data_tags[i].name))
501 static void Mod_BuildBaseBonePoses(void)
504 matrix4x4_t *basebonepose;
505 float *outinvmatrix = loadmodel->data_baseboneposeinverse;
506 matrix4x4_t bonematrix;
507 matrix4x4_t tempbonematrix;
508 if (!loadmodel->num_bones)
510 basebonepose = (matrix4x4_t *)Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(matrix4x4_t));
511 for (boneindex = 0;boneindex < loadmodel->num_bones;boneindex++)
513 Matrix4x4_FromBonePose6s(&bonematrix, loadmodel->num_posescale, loadmodel->data_poses6s + 6 * boneindex);
514 if (loadmodel->data_bones[boneindex].parent >= 0)
516 tempbonematrix = bonematrix;
517 Matrix4x4_Concat(&bonematrix, basebonepose + loadmodel->data_bones[boneindex].parent, &tempbonematrix);
519 basebonepose[boneindex] = bonematrix;
520 Matrix4x4_Invert_Simple(&tempbonematrix, basebonepose + boneindex);
521 Matrix4x4_ToArray12FloatD3D(&tempbonematrix, outinvmatrix + 12*boneindex);
523 Mem_Free(basebonepose);
526 static void Mod_Alias_CalculateBoundingBox(void)
529 qboolean firstvertex = true;
530 float dist, yawradius, radius;
533 frameblend_t frameblend[MAX_FRAMEBLENDS];
534 memset(frameblend, 0, sizeof(frameblend));
535 frameblend[0].lerp = 1;
536 vertex3f = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
537 VectorClear(loadmodel->normalmins);
538 VectorClear(loadmodel->normalmaxs);
541 for (frameblend[0].subframe = 0;frameblend[0].subframe < loadmodel->num_poses;frameblend[0].subframe++)
543 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, vertex3f, NULL, NULL, NULL);
544 for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
549 VectorCopy(v, loadmodel->normalmins);
550 VectorCopy(v, loadmodel->normalmaxs);
554 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
555 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
556 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
557 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
558 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
559 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
561 dist = v[0] * v[0] + v[1] * v[1];
562 if (yawradius < dist)
571 radius = sqrt(radius);
572 yawradius = sqrt(yawradius);
573 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
574 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
575 loadmodel->yawmins[2] = loadmodel->normalmins[2];
576 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
577 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
578 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
579 loadmodel->radius = radius;
580 loadmodel->radius2 = radius * radius;
583 static void Mod_Alias_MorphMesh_CompileFrames(void)
586 frameblend_t frameblend[MAX_FRAMEBLENDS];
587 unsigned char *datapointer;
588 memset(frameblend, 0, sizeof(frameblend));
589 frameblend[0].lerp = 1;
590 datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
591 loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
592 loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
593 loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
594 loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
595 loadmodel->surfmesh.data_morphtexvecvertex = (texvecvertex_t *)datapointer;datapointer += loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices * sizeof(texvecvertex_t);
596 // 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)
597 for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
599 frameblend[0].subframe = i;
600 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
601 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);
602 // encode the svector and tvector in 3 byte format for permanent storage
603 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
605 VectorScaleCast(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
606 VectorScaleCast(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
611 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)
614 float segmentmins[3], segmentmaxs[3];
616 static int maxvertices = 0;
617 static float *vertex3f = NULL;
618 memset(trace, 0, sizeof(*trace));
620 trace->realfraction = 1;
621 trace->hitsupercontentsmask = hitsupercontentsmask;
622 if (maxvertices < model->surfmesh.num_vertices)
626 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
627 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
629 segmentmins[0] = min(start[0], end[0]) - 1;
630 segmentmins[1] = min(start[1], end[1]) - 1;
631 segmentmins[2] = min(start[2], end[2]) - 1;
632 segmentmaxs[0] = max(start[0], end[0]) + 1;
633 segmentmaxs[1] = max(start[1], end[1]) + 1;
634 segmentmaxs[2] = max(start[2], end[2]) + 1;
635 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
636 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
637 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);
640 static int maxvertices = 0;
641 static float *vertex3f = NULL;
643 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)
646 vec3_t shiftstart, shiftend;
647 float segmentmins[3], segmentmaxs[3];
649 colboxbrushf_t thisbrush_start, thisbrush_end;
650 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
652 if (VectorCompare(boxmins, boxmaxs))
654 VectorAdd(start, boxmins, shiftstart);
655 VectorAdd(end, boxmins, shiftend);
656 Mod_MDLMD2MD3_TraceLine(model, frameblend, skeleton, trace, shiftstart, shiftend, hitsupercontentsmask);
657 VectorSubtract(trace->endpos, boxmins, trace->endpos);
661 // box trace, performed as brush trace
662 memset(trace, 0, sizeof(*trace));
664 trace->realfraction = 1;
665 trace->hitsupercontentsmask = hitsupercontentsmask;
666 if (maxvertices < model->surfmesh.num_vertices)
670 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
671 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
673 segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
674 segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
675 segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
676 segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
677 segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
678 segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
679 VectorAdd(start, boxmins, boxstartmins);
680 VectorAdd(start, boxmaxs, boxstartmaxs);
681 VectorAdd(end, boxmins, boxendmins);
682 VectorAdd(end, boxmaxs, boxendmaxs);
683 Collision_BrushForBox(&thisbrush_start, boxstartmins, boxstartmaxs, 0, 0, NULL);
684 Collision_BrushForBox(&thisbrush_end, boxendmins, boxendmaxs, 0, 0, NULL);
685 if (maxvertices < model->surfmesh.num_vertices)
689 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
690 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
692 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
693 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
694 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);
697 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
700 for (i = 0;i < inverts;i++)
702 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
704 j = vertremap[i]; // not onseam
707 j = vertremap[i+inverts]; // onseam
713 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
715 int i, f, pose, groupframes;
717 daliasframetype_t *pframetype;
718 daliasframe_t *pinframe;
719 daliasgroup_t *group;
720 daliasinterval_t *intervals;
723 scene = loadmodel->animscenes;
724 for (f = 0;f < loadmodel->numframes;f++)
726 pframetype = (daliasframetype_t *)datapointer;
727 datapointer += sizeof(daliasframetype_t);
728 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
730 // a single frame is still treated as a group
737 group = (daliasgroup_t *)datapointer;
738 datapointer += sizeof(daliasgroup_t);
739 groupframes = LittleLong (group->numframes);
741 // intervals (time per frame)
742 intervals = (daliasinterval_t *)datapointer;
743 datapointer += sizeof(daliasinterval_t) * groupframes;
745 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
746 if (interval < 0.01f)
748 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
753 // get scene name from first frame
754 pinframe = (daliasframe_t *)datapointer;
756 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
757 scene->firstframe = pose;
758 scene->framecount = groupframes;
759 scene->framerate = 1.0f / interval;
764 for (i = 0;i < groupframes;i++)
766 pinframe = (daliasframe_t *)datapointer;
767 datapointer += sizeof(daliasframe_t);
768 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
769 datapointer += sizeof(trivertx_t) * inverts;
775 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
777 if (cls.state == ca_dedicated)
781 skinframe = R_SkinFrame_LoadMissing();
782 memset(texture, 0, sizeof(*texture));
783 texture->currentframe = texture;
784 //texture->animated = false;
785 texture->numskinframes = 1;
786 texture->skinframerate = 1;
787 texture->skinframes[0] = skinframe;
788 texture->currentskinframe = skinframe;
789 //texture->backgroundnumskinframes = 0;
790 //texture->customblendfunc[0] = 0;
791 //texture->customblendfunc[1] = 0;
792 //texture->surfaceflags = 0;
793 //texture->supercontents = 0;
794 //texture->surfaceparms = 0;
795 //texture->textureflags = 0;
797 texture->basematerialflags = MATERIALFLAG_WALL;
798 if (texture->currentskinframe->hasalpha)
799 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
800 texture->currentmaterialflags = texture->basematerialflags;
801 texture->offsetmapping = OFFSETMAPPING_DEFAULT;
802 texture->offsetscale = 1;
803 texture->offsetbias = 0;
804 texture->specularscalemod = 1;
805 texture->specularpowermod = 1;
806 texture->surfaceflags = 0;
807 texture->supercontents = SUPERCONTENTS_SOLID;
808 if (!(texture->basematerialflags & MATERIALFLAG_BLENDED))
809 texture->supercontents |= SUPERCONTENTS_OPAQUE;
812 void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
815 static char stripbuf[MAX_QPATH];
816 skinfileitem_t *skinfileitem;
817 if(developer_extra.integer)
818 Con_DPrintf("Looking up texture for %s (default: %s)\n", meshname, shadername);
821 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
822 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
824 memset(skin, 0, sizeof(*skin));
826 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
828 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
829 if (!strcmp(skinfileitem->name, meshname))
831 Image_StripImageExtension(skinfileitem->replacement, stripbuf, sizeof(stripbuf));
832 if(developer_extra.integer)
833 Con_DPrintf("--> got %s from skin file\n", stripbuf);
834 Mod_LoadTextureFromQ3Shader(skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
840 // don't render unmentioned meshes
841 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
842 if(developer_extra.integer)
843 Con_DPrintf("--> skipping\n");
844 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
850 if(developer_extra.integer)
851 Con_DPrintf("--> using default\n");
852 Image_StripImageExtension(shadername, stripbuf, sizeof(stripbuf));
853 Mod_LoadTextureFromQ3Shader(skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
857 #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);
858 #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);
859 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
861 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
862 float scales, scalet, interval;
866 stvert_t *pinstverts;
867 dtriangle_t *pintriangles;
868 daliasskintype_t *pinskintype;
869 daliasskingroup_t *pinskingroup;
870 daliasskininterval_t *pinskinintervals;
871 daliasframetype_t *pinframetype;
872 daliasgroup_t *pinframegroup;
873 unsigned char *datapointer, *startframes, *startskins;
874 char name[MAX_QPATH];
875 skinframe_t *tempskinframe;
876 animscene_t *tempskinscenes;
877 texture_t *tempaliasskins;
879 int *vertonseam, *vertremap;
880 skinfile_t *skinfiles;
882 datapointer = (unsigned char *)buffer;
883 pinmodel = (mdl_t *)datapointer;
884 datapointer += sizeof(mdl_t);
886 version = LittleLong (pinmodel->version);
887 if (version != ALIAS_VERSION)
888 Host_Error ("%s has wrong version number (%i should be %i)",
889 loadmodel->name, version, ALIAS_VERSION);
891 loadmodel->modeldatatypestring = "MDL";
893 loadmodel->type = mod_alias;
894 loadmodel->DrawSky = NULL;
895 loadmodel->DrawAddWaterPlanes = NULL;
896 loadmodel->Draw = R_Q1BSP_Draw;
897 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
898 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
899 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
900 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
901 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
902 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
903 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
904 loadmodel->DrawLight = R_Q1BSP_DrawLight;
905 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
906 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
907 // FIXME add TraceBrush!
908 loadmodel->PointSuperContents = NULL;
910 loadmodel->num_surfaces = 1;
911 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
912 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
913 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
914 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
915 loadmodel->sortedmodelsurfaces[0] = 0;
917 loadmodel->numskins = LittleLong(pinmodel->numskins);
918 BOUNDI(loadmodel->numskins,0,65536);
919 skinwidth = LittleLong (pinmodel->skinwidth);
920 BOUNDI(skinwidth,0,65536);
921 skinheight = LittleLong (pinmodel->skinheight);
922 BOUNDI(skinheight,0,65536);
923 numverts = LittleLong(pinmodel->numverts);
924 BOUNDI(numverts,0,65536);
925 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
926 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
927 loadmodel->numframes = LittleLong(pinmodel->numframes);
928 BOUNDI(loadmodel->numframes,0,65536);
929 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
930 BOUNDI((int)loadmodel->synctype,0,2);
931 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
932 i = LittleLong (pinmodel->flags);
933 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
935 for (i = 0;i < 3;i++)
937 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
938 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
941 startskins = datapointer;
943 for (i = 0;i < loadmodel->numskins;i++)
945 pinskintype = (daliasskintype_t *)datapointer;
946 datapointer += sizeof(daliasskintype_t);
947 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
951 pinskingroup = (daliasskingroup_t *)datapointer;
952 datapointer += sizeof(daliasskingroup_t);
953 groupskins = LittleLong(pinskingroup->numskins);
954 datapointer += sizeof(daliasskininterval_t) * groupskins;
957 for (j = 0;j < groupskins;j++)
959 datapointer += skinwidth * skinheight;
964 pinstverts = (stvert_t *)datapointer;
965 datapointer += sizeof(stvert_t) * numverts;
967 pintriangles = (dtriangle_t *)datapointer;
968 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
970 startframes = datapointer;
971 loadmodel->surfmesh.num_morphframes = 0;
972 for (i = 0;i < loadmodel->numframes;i++)
974 pinframetype = (daliasframetype_t *)datapointer;
975 datapointer += sizeof(daliasframetype_t);
976 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
980 pinframegroup = (daliasgroup_t *)datapointer;
981 datapointer += sizeof(daliasgroup_t);
982 groupframes = LittleLong(pinframegroup->numframes);
983 datapointer += sizeof(daliasinterval_t) * groupframes;
986 for (j = 0;j < groupframes;j++)
988 datapointer += sizeof(daliasframe_t);
989 datapointer += sizeof(trivertx_t) * numverts;
990 loadmodel->surfmesh.num_morphframes++;
993 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
995 // store texture coordinates into temporary array, they will be stored
996 // after usage is determined (triangle data)
997 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
998 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
999 vertonseam = vertremap + numverts * 2;
1001 scales = 1.0 / skinwidth;
1002 scalet = 1.0 / skinheight;
1003 for (i = 0;i < numverts;i++)
1005 vertonseam[i] = LittleLong(pinstverts[i].onseam);
1006 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
1007 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
1008 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
1009 vertst[(i+numverts)*2+1] = vertst[i*2+1];
1012 // load triangle data
1013 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1015 // read the triangle elements
1016 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1017 for (j = 0;j < 3;j++)
1018 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1019 // validate (note numverts is used because this is the original data)
1020 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1021 // now butcher the elements according to vertonseam and tri->facesfront
1022 // and then compact the vertex set to remove duplicates
1023 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1024 if (!LittleLong(pintriangles[i].facesfront)) // backface
1025 for (j = 0;j < 3;j++)
1026 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1027 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1029 // (this uses vertremap to count usage to save some memory)
1030 for (i = 0;i < numverts*2;i++)
1032 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1033 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1034 // build remapping table and compact array
1035 loadmodel->surfmesh.num_vertices = 0;
1036 for (i = 0;i < numverts*2;i++)
1040 vertremap[i] = loadmodel->surfmesh.num_vertices;
1041 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1042 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1043 loadmodel->surfmesh.num_vertices++;
1046 vertremap[i] = -1; // not used at all
1048 // remap the elements to the new vertex set
1049 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1050 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1051 // store the texture coordinates
1052 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1053 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1055 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1056 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1059 // generate ushort elements array if possible
1060 if (loadmodel->surfmesh.num_vertices <= 65536)
1061 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1062 if (loadmodel->surfmesh.data_element3s)
1063 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1064 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1067 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1068 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1069 if (r_enableshadowvolumes.integer)
1071 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1073 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1074 if (loadmodel->surfmesh.data_neighbor3i)
1075 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1076 Mod_Alias_CalculateBoundingBox();
1077 Mod_Alias_MorphMesh_CompileFrames();
1080 Mem_Free(vertremap);
1083 skinfiles = Mod_LoadSkinFiles();
1086 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1087 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1088 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1089 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1090 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1091 Mod_FreeSkinFiles(skinfiles);
1092 for (i = 0;i < loadmodel->numskins;i++)
1094 loadmodel->skinscenes[i].firstframe = i;
1095 loadmodel->skinscenes[i].framecount = 1;
1096 loadmodel->skinscenes[i].loop = true;
1097 loadmodel->skinscenes[i].framerate = 10;
1102 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1103 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1104 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1105 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1107 datapointer = startskins;
1108 for (i = 0;i < loadmodel->numskins;i++)
1110 pinskintype = (daliasskintype_t *)datapointer;
1111 datapointer += sizeof(daliasskintype_t);
1113 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1120 pinskingroup = (daliasskingroup_t *)datapointer;
1121 datapointer += sizeof(daliasskingroup_t);
1123 groupskins = LittleLong (pinskingroup->numskins);
1125 pinskinintervals = (daliasskininterval_t *)datapointer;
1126 datapointer += sizeof(daliasskininterval_t) * groupskins;
1128 interval = LittleFloat(pinskinintervals[0].interval);
1129 if (interval < 0.01f)
1131 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1136 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1137 loadmodel->skinscenes[i].firstframe = totalskins;
1138 loadmodel->skinscenes[i].framecount = groupskins;
1139 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1140 loadmodel->skinscenes[i].loop = true;
1142 for (j = 0;j < groupskins;j++)
1145 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1147 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1148 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))
1149 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));
1150 datapointer += skinwidth * skinheight;
1154 // check for skins that don't exist in the model, but do exist as external images
1155 // (this was added because yummyluv kept pestering me about support for it)
1156 // TODO: support shaders here?
1157 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)))
1159 // expand the arrays to make room
1160 tempskinscenes = loadmodel->skinscenes;
1161 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1162 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1163 Mem_Free(tempskinscenes);
1165 tempaliasskins = loadmodel->data_textures;
1166 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1167 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1168 Mem_Free(tempaliasskins);
1170 // store the info about the new skin
1171 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1172 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1173 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1174 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1175 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1176 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1178 //increase skin counts
1179 loadmodel->numskins++;
1182 // fix up the pointers since they are pointing at the old textures array
1183 // FIXME: this is a hack!
1184 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1185 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1189 surface = loadmodel->data_surfaces;
1190 surface->texture = loadmodel->data_textures;
1191 surface->num_firsttriangle = 0;
1192 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1193 surface->num_firstvertex = 0;
1194 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1196 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1197 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_MDL_AnimateVertices : NULL;
1199 if (!loadmodel->surfmesh.isanimated)
1201 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1202 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1203 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1204 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1205 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1206 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1209 // because shaders can do somewhat unexpected things, check for unusual features now
1210 for (i = 0;i < loadmodel->num_textures;i++)
1212 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
1213 mod->DrawSky = R_Q1BSP_DrawSky;
1214 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
1215 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
1219 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1221 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1222 float iskinwidth, iskinheight;
1223 unsigned char *data;
1224 msurface_t *surface;
1226 unsigned char *base, *datapointer;
1227 md2frame_t *pinframe;
1229 md2triangle_t *intri;
1230 unsigned short *inst;
1231 struct md2verthash_s
1233 struct md2verthash_s *next;
1237 *hash, **md2verthash, *md2verthashdata;
1238 skinfile_t *skinfiles;
1240 pinmodel = (md2_t *)buffer;
1241 base = (unsigned char *)buffer;
1243 version = LittleLong (pinmodel->version);
1244 if (version != MD2ALIAS_VERSION)
1245 Host_Error ("%s has wrong version number (%i should be %i)",
1246 loadmodel->name, version, MD2ALIAS_VERSION);
1248 loadmodel->modeldatatypestring = "MD2";
1250 loadmodel->type = mod_alias;
1251 loadmodel->DrawSky = NULL;
1252 loadmodel->DrawAddWaterPlanes = NULL;
1253 loadmodel->Draw = R_Q1BSP_Draw;
1254 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1255 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1256 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1257 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1258 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1259 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1260 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1261 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1262 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1263 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1264 loadmodel->PointSuperContents = NULL;
1266 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1267 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1268 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1269 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1270 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1271 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1272 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1273 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1275 end = LittleLong(pinmodel->ofs_end);
1276 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1277 Host_Error ("%s is not a valid model", loadmodel->name);
1278 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1279 Host_Error ("%s is not a valid model", loadmodel->name);
1280 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1281 Host_Error ("%s is not a valid model", loadmodel->name);
1282 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1283 Host_Error ("%s is not a valid model", loadmodel->name);
1284 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1285 Host_Error ("%s is not a valid model", loadmodel->name);
1287 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1288 numxyz = LittleLong(pinmodel->num_xyz);
1289 numst = LittleLong(pinmodel->num_st);
1290 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1291 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1292 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1293 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1294 skinwidth = LittleLong(pinmodel->skinwidth);
1295 skinheight = LittleLong(pinmodel->skinheight);
1296 iskinwidth = 1.0f / skinwidth;
1297 iskinheight = 1.0f / skinheight;
1299 loadmodel->num_surfaces = 1;
1300 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1301 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));
1302 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1303 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1304 loadmodel->sortedmodelsurfaces[0] = 0;
1305 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1306 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1307 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1308 if (r_enableshadowvolumes.integer)
1310 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1313 loadmodel->synctype = ST_RAND;
1316 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1317 skinfiles = Mod_LoadSkinFiles();
1320 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1321 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1322 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1323 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1324 Mod_FreeSkinFiles(skinfiles);
1326 else if (loadmodel->numskins)
1328 // skins found (most likely not a player model)
1329 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1330 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1331 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1332 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1333 Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
1337 // no skins (most likely a player model)
1338 loadmodel->numskins = 1;
1339 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1340 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1341 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1342 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1345 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1346 for (i = 0;i < loadmodel->numskins;i++)
1348 loadmodel->skinscenes[i].firstframe = i;
1349 loadmodel->skinscenes[i].framecount = 1;
1350 loadmodel->skinscenes[i].loop = true;
1351 loadmodel->skinscenes[i].framerate = 10;
1354 // load the triangles and stvert data
1355 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1356 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1357 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1358 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1359 // swap the triangle list
1360 loadmodel->surfmesh.num_vertices = 0;
1361 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1363 for (j = 0;j < 3;j++)
1365 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1366 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1369 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1374 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1377 hashindex = (xyz * 256 + st) & 65535;
1378 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1379 if (hash->xyz == xyz && hash->st == st)
1383 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1386 hash->next = md2verthash[hashindex];
1387 md2verthash[hashindex] = hash;
1389 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1393 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1394 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));
1395 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1396 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1397 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1400 hash = md2verthashdata + i;
1401 vertremap[i] = hash->xyz;
1402 sts = LittleShort(inst[hash->st*2+0]);
1403 stt = LittleShort(inst[hash->st*2+1]);
1404 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1406 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1410 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1411 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1414 Mem_Free(md2verthash);
1415 Mem_Free(md2verthashdata);
1417 // generate ushort elements array if possible
1418 if (loadmodel->surfmesh.num_vertices <= 65536)
1419 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1420 if (loadmodel->surfmesh.data_element3s)
1421 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1422 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1425 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1426 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1431 pinframe = (md2frame_t *)datapointer;
1432 datapointer += sizeof(md2frame_t);
1433 // store the frame scale/translate into the appropriate array
1434 for (j = 0;j < 3;j++)
1436 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1437 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1439 // convert the vertices
1440 v = (trivertx_t *)datapointer;
1441 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1442 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1443 out[k] = v[vertremap[k]];
1444 datapointer += numxyz * sizeof(trivertx_t);
1446 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1447 loadmodel->animscenes[i].firstframe = i;
1448 loadmodel->animscenes[i].framecount = 1;
1449 loadmodel->animscenes[i].framerate = 10;
1450 loadmodel->animscenes[i].loop = true;
1453 Mem_Free(vertremap);
1455 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1456 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_MDL_AnimateVertices : NULL;
1458 if (loadmodel->surfmesh.data_neighbor3i)
1459 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1460 Mod_Alias_CalculateBoundingBox();
1461 Mod_Alias_MorphMesh_CompileFrames();
1463 surface = loadmodel->data_surfaces;
1464 surface->texture = loadmodel->data_textures;
1465 surface->num_firsttriangle = 0;
1466 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1467 surface->num_firstvertex = 0;
1468 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1470 if (!loadmodel->surfmesh.isanimated)
1472 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1473 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1474 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1475 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1476 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1477 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1480 // because shaders can do somewhat unexpected things, check for unusual features now
1481 for (i = 0;i < loadmodel->num_textures;i++)
1483 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
1484 mod->DrawSky = R_Q1BSP_DrawSky;
1485 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
1486 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
1490 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1492 int i, j, k, version, meshvertices, meshtriangles;
1493 unsigned char *data;
1494 msurface_t *surface;
1495 md3modelheader_t *pinmodel;
1496 md3frameinfo_t *pinframe;
1499 skinfile_t *skinfiles;
1501 pinmodel = (md3modelheader_t *)buffer;
1503 if (memcmp(pinmodel->identifier, "IDP3", 4))
1504 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1505 version = LittleLong (pinmodel->version);
1506 if (version != MD3VERSION)
1507 Host_Error ("%s has wrong version number (%i should be %i)",
1508 loadmodel->name, version, MD3VERSION);
1510 skinfiles = Mod_LoadSkinFiles();
1511 if (loadmodel->numskins < 1)
1512 loadmodel->numskins = 1;
1514 loadmodel->modeldatatypestring = "MD3";
1516 loadmodel->type = mod_alias;
1517 loadmodel->DrawSky = NULL;
1518 loadmodel->DrawAddWaterPlanes = NULL;
1519 loadmodel->Draw = R_Q1BSP_Draw;
1520 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1521 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1522 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1523 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1524 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1525 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1526 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1527 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1528 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1529 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1530 loadmodel->PointSuperContents = NULL;
1531 loadmodel->synctype = ST_RAND;
1532 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1533 i = LittleLong (pinmodel->flags);
1534 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1536 // set up some global info about the model
1537 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1538 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1540 // make skinscenes for the skins (no groups)
1541 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1542 for (i = 0;i < loadmodel->numskins;i++)
1544 loadmodel->skinscenes[i].firstframe = i;
1545 loadmodel->skinscenes[i].framecount = 1;
1546 loadmodel->skinscenes[i].loop = true;
1547 loadmodel->skinscenes[i].framerate = 10;
1551 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1552 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1554 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1555 loadmodel->animscenes[i].firstframe = i;
1556 loadmodel->animscenes[i].framecount = 1;
1557 loadmodel->animscenes[i].framerate = 10;
1558 loadmodel->animscenes[i].loop = true;
1562 loadmodel->num_tagframes = loadmodel->numframes;
1563 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1564 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1565 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1567 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1568 for (j = 0;j < 9;j++)
1569 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1570 for (j = 0;j < 3;j++)
1571 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1572 //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);
1578 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)))
1580 if (memcmp(pinmesh->identifier, "IDP3", 4))
1581 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1582 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1583 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1584 meshvertices += LittleLong(pinmesh->num_vertices);
1585 meshtriangles += LittleLong(pinmesh->num_triangles);
1588 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1589 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1590 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1591 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1592 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_MD3_AnimateVertices : NULL;
1593 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));
1594 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1595 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1596 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1597 loadmodel->surfmesh.num_vertices = meshvertices;
1598 loadmodel->surfmesh.num_triangles = meshtriangles;
1599 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1600 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1601 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1602 if (r_enableshadowvolumes.integer)
1604 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1606 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1607 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1608 if (meshvertices <= 65536)
1610 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1615 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)))
1617 if (memcmp(pinmesh->identifier, "IDP3", 4))
1618 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1619 loadmodel->sortedmodelsurfaces[i] = i;
1620 surface = loadmodel->data_surfaces + i;
1621 surface->texture = loadmodel->data_textures + i;
1622 surface->num_firsttriangle = meshtriangles;
1623 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1624 surface->num_firstvertex = meshvertices;
1625 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1626 meshvertices += surface->num_vertices;
1627 meshtriangles += surface->num_triangles;
1629 for (j = 0;j < surface->num_triangles * 3;j++)
1630 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1631 for (j = 0;j < surface->num_vertices;j++)
1633 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1634 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1636 for (j = 0;j < loadmodel->numframes;j++)
1638 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1639 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1640 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1642 out->origin[0] = LittleShort(in->origin[0]);
1643 out->origin[1] = LittleShort(in->origin[1]);
1644 out->origin[2] = LittleShort(in->origin[2]);
1645 out->pitch = in->pitch;
1650 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1652 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1654 if (loadmodel->surfmesh.data_element3s)
1655 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1656 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1657 if (loadmodel->surfmesh.data_neighbor3i)
1658 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1659 Mod_Alias_MorphMesh_CompileFrames();
1660 Mod_Alias_CalculateBoundingBox();
1661 Mod_FreeSkinFiles(skinfiles);
1662 Mod_MakeSortedSurfaces(loadmodel);
1664 if (!loadmodel->surfmesh.isanimated)
1666 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1667 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1668 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1669 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1670 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1671 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1674 // because shaders can do somewhat unexpected things, check for unusual features now
1675 for (i = 0;i < loadmodel->num_textures;i++)
1677 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
1678 mod->DrawSky = R_Q1BSP_DrawSky;
1679 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
1680 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
1684 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1686 zymtype1header_t *pinmodel, *pheader;
1687 unsigned char *pbase;
1688 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1689 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose, f, biggestorigin, tempvec[3], modelscale;
1690 zymvertex_t *verts, *vertdata;
1694 skinfile_t *skinfiles;
1695 unsigned char *data;
1696 msurface_t *surface;
1698 pinmodel = (zymtype1header_t *)buffer;
1699 pbase = (unsigned char *)buffer;
1700 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1701 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1702 if (BigLong(pinmodel->type) != 1)
1703 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1705 loadmodel->modeldatatypestring = "ZYM";
1707 loadmodel->type = mod_alias;
1708 loadmodel->synctype = ST_RAND;
1712 pheader->type = BigLong(pinmodel->type);
1713 pheader->filesize = BigLong(pinmodel->filesize);
1714 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1715 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1716 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1717 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1718 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1719 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1720 pheader->radius = BigFloat(pinmodel->radius);
1721 pheader->numverts = BigLong(pinmodel->numverts);
1722 pheader->numtris = BigLong(pinmodel->numtris);
1723 pheader->numshaders = BigLong(pinmodel->numshaders);
1724 pheader->numbones = BigLong(pinmodel->numbones);
1725 pheader->numscenes = BigLong(pinmodel->numscenes);
1726 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1727 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1728 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1729 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1730 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1731 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1732 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1733 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1734 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1735 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1736 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1737 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1738 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1739 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1740 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1741 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1742 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1743 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1745 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1747 Con_Printf("%s has no geometry\n", loadmodel->name);
1750 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1752 Con_Printf("%s has no animations\n", loadmodel->name);
1756 loadmodel->DrawSky = NULL;
1757 loadmodel->DrawAddWaterPlanes = NULL;
1758 loadmodel->Draw = R_Q1BSP_Draw;
1759 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1760 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1761 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1762 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1763 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1764 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1765 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1766 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1767 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1768 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1769 loadmodel->PointSuperContents = NULL;
1771 loadmodel->numframes = pheader->numscenes;
1772 loadmodel->num_surfaces = pheader->numshaders;
1774 skinfiles = Mod_LoadSkinFiles();
1775 if (loadmodel->numskins < 1)
1776 loadmodel->numskins = 1;
1778 // make skinscenes for the skins (no groups)
1779 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1780 for (i = 0;i < loadmodel->numskins;i++)
1782 loadmodel->skinscenes[i].firstframe = i;
1783 loadmodel->skinscenes[i].framecount = 1;
1784 loadmodel->skinscenes[i].loop = true;
1785 loadmodel->skinscenes[i].framerate = 10;
1789 modelradius = pheader->radius;
1790 for (i = 0;i < 3;i++)
1792 loadmodel->normalmins[i] = pheader->mins[i];
1793 loadmodel->normalmaxs[i] = pheader->maxs[i];
1794 loadmodel->rotatedmins[i] = -modelradius;
1795 loadmodel->rotatedmaxs[i] = modelradius;
1797 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1798 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1799 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1800 if (loadmodel->yawmaxs[0] > modelradius)
1801 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1802 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1803 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1804 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1805 loadmodel->radius = modelradius;
1806 loadmodel->radius2 = modelradius * modelradius;
1808 // go through the lumps, swapping things
1810 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1811 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1812 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1813 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1814 for (i = 0;i < pheader->numscenes;i++)
1816 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1817 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1818 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1819 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1820 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1821 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1822 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1823 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1824 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1825 if (loadmodel->animscenes[i].framerate < 0)
1826 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1830 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1831 loadmodel->num_bones = pheader->numbones;
1832 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1833 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1834 for (i = 0;i < pheader->numbones;i++)
1836 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1837 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1838 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1839 if (loadmodel->data_bones[i].parent >= i)
1840 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1843 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1844 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1845 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1846 for (i = 0;i < pheader->numverts;i++)
1848 vertbonecounts[i] = BigLong(bonecount[i]);
1849 if (vertbonecounts[i] != 1)
1850 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1853 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1855 meshvertices = pheader->numverts;
1856 meshtriangles = pheader->numtris;
1858 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1859 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
1860 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1861 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1862 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1863 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]));
1864 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1865 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1866 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1867 loadmodel->surfmesh.num_vertices = meshvertices;
1868 loadmodel->surfmesh.num_triangles = meshtriangles;
1869 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1870 if (r_enableshadowvolumes.integer)
1872 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1874 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1875 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1876 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1877 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1878 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1879 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1880 loadmodel->surfmesh.num_blends = 0;
1881 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
1882 if (loadmodel->surfmesh.num_vertices <= 65536)
1884 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1886 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
1887 loadmodel->surfmesh.data_blendweights = NULL;
1889 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1890 poses = (float *) (pheader->lump_poses.start + pbase);
1891 // figure out scale of model from root bone, for compatibility with old zmodel versions
1892 tempvec[0] = BigFloat(poses[0]);
1893 tempvec[1] = BigFloat(poses[1]);
1894 tempvec[2] = BigFloat(poses[2]);
1895 modelscale = VectorLength(tempvec);
1897 for (i = 0;i < loadmodel->num_bones * numposes * 12;i++)
1899 f = fabs(BigFloat(poses[i]));
1900 biggestorigin = max(biggestorigin, f);
1902 loadmodel->num_posescale = biggestorigin / 32767.0f;
1903 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
1904 for (i = 0;i < numposes;i++)
1906 const float *frameposes = (float *) (pheader->lump_poses.start + pbase) + 12*i*loadmodel->num_bones;
1907 for (j = 0;j < loadmodel->num_bones;j++)
1910 matrix4x4_t posematrix;
1911 for (k = 0;k < 12;k++)
1912 pose[k] = BigFloat(frameposes[j*12+k]);
1913 //if (j < loadmodel->num_bones)
1914 // 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));
1915 // scale child bones to match the root scale
1916 if (loadmodel->data_bones[j].parent >= 0)
1918 pose[3] *= modelscale;
1919 pose[7] *= modelscale;
1920 pose[11] *= modelscale;
1922 // normalize rotation matrix
1923 VectorNormalize(pose + 0);
1924 VectorNormalize(pose + 4);
1925 VectorNormalize(pose + 8);
1926 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
1927 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
1931 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1932 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1933 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1934 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1935 // (converting from weight-blending skeletal animation to
1936 // deformation-based skeletal animation)
1937 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1938 for (i = 0;i < loadmodel->num_bones;i++)
1941 for (k = 0;k < 12;k++)
1942 m[k] = BigFloat(poses[i*12+k]);
1943 if (loadmodel->data_bones[i].parent >= 0)
1944 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1946 for (k = 0;k < 12;k++)
1947 bonepose[12*i+k] = m[k];
1949 for (j = 0;j < pheader->numverts;j++)
1951 // this format really should have had a per vertexweight weight value...
1952 // but since it does not, the weighting is completely ignored and
1953 // only one weight is allowed per vertex
1954 int boneindex = BigLong(vertdata[j].bonenum);
1955 const float *m = bonepose + 12 * boneindex;
1956 float relativeorigin[3];
1957 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1958 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1959 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1960 // transform the vertex bone weight into the base mesh
1961 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1962 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1963 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1964 // store the weight as the primary weight on this vertex
1965 loadmodel->surfmesh.blends[j] = boneindex;
1968 // normals and tangents are calculated after elements are loaded
1970 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1971 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1972 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1973 for (i = 0;i < pheader->numverts;i++)
1975 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1976 // flip T coordinate for OpenGL
1977 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1980 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1981 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1982 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1984 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1985 //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)
1986 // byteswap, validate, and swap winding order of tris
1987 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1988 if (pheader->lump_render.length != count)
1989 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1990 renderlist = (int *) (pheader->lump_render.start + pbase);
1991 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1993 for (i = 0;i < loadmodel->num_surfaces;i++)
1995 int firstvertex, lastvertex;
1996 if (renderlist >= renderlistend)
1997 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1998 count = BigLong(*renderlist);renderlist++;
1999 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
2000 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2002 loadmodel->sortedmodelsurfaces[i] = i;
2003 surface = loadmodel->data_surfaces + i;
2004 surface->texture = loadmodel->data_textures + i;
2005 surface->num_firsttriangle = meshtriangles;
2006 surface->num_triangles = count;
2007 meshtriangles += surface->num_triangles;
2009 // load the elements
2010 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2011 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
2013 outelements[j*3+2] = BigLong(renderlist[0]);
2014 outelements[j*3+1] = BigLong(renderlist[1]);
2015 outelements[j*3+0] = BigLong(renderlist[2]);
2017 // validate the elements and find the used vertex range
2018 firstvertex = meshvertices;
2020 for (j = 0;j < surface->num_triangles * 3;j++)
2022 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
2023 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
2024 firstvertex = min(firstvertex, outelements[j]);
2025 lastvertex = max(lastvertex, outelements[j]);
2027 surface->num_firstvertex = firstvertex;
2028 surface->num_vertices = lastvertex + 1 - firstvertex;
2030 // since zym models do not have named sections, reuse their shader
2031 // name as the section name
2032 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
2033 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
2035 Mod_FreeSkinFiles(skinfiles);
2036 Mem_Free(vertbonecounts);
2038 Mod_MakeSortedSurfaces(loadmodel);
2040 // compute all the mesh information that was not loaded from the file
2041 if (loadmodel->surfmesh.data_element3s)
2042 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2043 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2044 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2045 Mod_BuildBaseBonePoses();
2046 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);
2047 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);
2048 if (loadmodel->surfmesh.data_neighbor3i)
2049 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2051 if (!loadmodel->surfmesh.isanimated)
2053 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2054 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2055 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2056 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2057 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2058 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2061 // because shaders can do somewhat unexpected things, check for unusual features now
2062 for (i = 0;i < loadmodel->num_textures;i++)
2064 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
2065 mod->DrawSky = R_Q1BSP_DrawSky;
2066 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
2067 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
2071 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2073 dpmheader_t *pheader;
2077 unsigned char *pbase;
2078 int i, j, k, meshvertices, meshtriangles;
2079 skinfile_t *skinfiles;
2080 unsigned char *data;
2082 float biggestorigin, tempvec[3], modelscale;
2086 pheader = (dpmheader_t *)buffer;
2087 pbase = (unsigned char *)buffer;
2088 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2089 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2090 if (BigLong(pheader->type) != 2)
2091 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2093 loadmodel->modeldatatypestring = "DPM";
2095 loadmodel->type = mod_alias;
2096 loadmodel->synctype = ST_RAND;
2099 pheader->type = BigLong(pheader->type);
2100 pheader->filesize = BigLong(pheader->filesize);
2101 pheader->mins[0] = BigFloat(pheader->mins[0]);
2102 pheader->mins[1] = BigFloat(pheader->mins[1]);
2103 pheader->mins[2] = BigFloat(pheader->mins[2]);
2104 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2105 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2106 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2107 pheader->yawradius = BigFloat(pheader->yawradius);
2108 pheader->allradius = BigFloat(pheader->allradius);
2109 pheader->num_bones = BigLong(pheader->num_bones);
2110 pheader->num_meshs = BigLong(pheader->num_meshs);
2111 pheader->num_frames = BigLong(pheader->num_frames);
2112 pheader->ofs_bones = BigLong(pheader->ofs_bones);
2113 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2114 pheader->ofs_frames = BigLong(pheader->ofs_frames);
2116 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2118 Con_Printf("%s has no geometry\n", loadmodel->name);
2121 if (pheader->num_frames < 1)
2123 Con_Printf("%s has no frames\n", loadmodel->name);
2127 loadmodel->DrawSky = NULL;
2128 loadmodel->DrawAddWaterPlanes = NULL;
2129 loadmodel->Draw = R_Q1BSP_Draw;
2130 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2131 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2132 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2133 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2134 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2135 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2136 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2137 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2138 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2139 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2140 loadmodel->PointSuperContents = NULL;
2143 for (i = 0;i < 3;i++)
2145 loadmodel->normalmins[i] = pheader->mins[i];
2146 loadmodel->normalmaxs[i] = pheader->maxs[i];
2147 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2148 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2149 loadmodel->rotatedmins[i] = -pheader->allradius;
2150 loadmodel->rotatedmaxs[i] = pheader->allradius;
2152 loadmodel->radius = pheader->allradius;
2153 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2155 // load external .skin files if present
2156 skinfiles = Mod_LoadSkinFiles();
2157 if (loadmodel->numskins < 1)
2158 loadmodel->numskins = 1;
2163 // gather combined statistics from the meshes
2164 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2165 for (i = 0;i < (int)pheader->num_meshs;i++)
2167 int numverts = BigLong(dpmmesh->num_verts);
2168 meshvertices += numverts;
2169 meshtriangles += BigLong(dpmmesh->num_tris);
2173 loadmodel->numframes = pheader->num_frames;
2174 loadmodel->num_bones = pheader->num_bones;
2175 loadmodel->num_poses = loadmodel->numframes;
2176 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2177 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2178 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2179 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2180 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
2181 // do most allocations as one merged chunk
2182 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));
2183 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2184 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2185 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2186 loadmodel->surfmesh.num_vertices = meshvertices;
2187 loadmodel->surfmesh.num_triangles = meshtriangles;
2188 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2189 if (r_enableshadowvolumes.integer)
2191 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2193 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2194 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2195 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2196 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2197 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2198 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2199 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2200 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2201 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2202 loadmodel->surfmesh.num_blends = 0;
2203 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2204 if (meshvertices <= 65536)
2206 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2208 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2209 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
2211 for (i = 0;i < loadmodel->numskins;i++)
2213 loadmodel->skinscenes[i].firstframe = i;
2214 loadmodel->skinscenes[i].framecount = 1;
2215 loadmodel->skinscenes[i].loop = true;
2216 loadmodel->skinscenes[i].framerate = 10;
2219 // load the bone info
2220 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2221 for (i = 0;i < loadmodel->num_bones;i++)
2223 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2224 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2225 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2226 if (loadmodel->data_bones[i].parent >= i)
2227 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2231 frames = (dpmframe_t *) (pbase + pheader->ofs_frames);
2232 // figure out scale of model from root bone, for compatibility with old dpmodel versions
2233 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2234 tempvec[0] = BigFloat(poses[0]);
2235 tempvec[1] = BigFloat(poses[1]);
2236 tempvec[2] = BigFloat(poses[2]);
2237 modelscale = VectorLength(tempvec);
2239 for (i = 0;i < loadmodel->numframes;i++)
2241 memcpy(loadmodel->animscenes[i].name, frames[i].name, sizeof(frames[i].name));
2242 loadmodel->animscenes[i].firstframe = i;
2243 loadmodel->animscenes[i].framecount = 1;
2244 loadmodel->animscenes[i].loop = true;
2245 loadmodel->animscenes[i].framerate = 10;
2246 // load the bone poses for this frame
2247 poses = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2248 for (j = 0;j < loadmodel->num_bones*12;j++)
2250 f = fabs(BigFloat(poses[j]));
2251 biggestorigin = max(biggestorigin, f);
2253 // stuff not processed here: mins, maxs, yawradius, allradius
2255 loadmodel->num_posescale = biggestorigin / 32767.0f;
2256 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2257 for (i = 0;i < loadmodel->numframes;i++)
2259 const float *frameposes = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2260 for (j = 0;j < loadmodel->num_bones;j++)
2263 matrix4x4_t posematrix;
2264 for (k = 0;k < 12;k++)
2265 pose[k] = BigFloat(frameposes[j*12+k]);
2266 // scale child bones to match the root scale
2267 if (loadmodel->data_bones[j].parent >= 0)
2269 pose[3] *= modelscale;
2270 pose[7] *= modelscale;
2271 pose[11] *= modelscale;
2273 // normalize rotation matrix
2274 VectorNormalize(pose + 0);
2275 VectorNormalize(pose + 4);
2276 VectorNormalize(pose + 8);
2277 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2278 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
2282 // load the meshes now
2283 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2286 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2287 // (converting from weight-blending skeletal animation to
2288 // deformation-based skeletal animation)
2289 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2290 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2291 for (i = 0;i < loadmodel->num_bones;i++)
2294 for (k = 0;k < 12;k++)
2295 m[k] = BigFloat(poses[i*12+k]);
2296 if (loadmodel->data_bones[i].parent >= 0)
2297 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2299 for (k = 0;k < 12;k++)
2300 bonepose[12*i+k] = m[k];
2302 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2304 const int *inelements;
2306 const float *intexcoord;
2307 msurface_t *surface;
2309 loadmodel->sortedmodelsurfaces[i] = i;
2310 surface = loadmodel->data_surfaces + i;
2311 surface->texture = loadmodel->data_textures + i;
2312 surface->num_firsttriangle = meshtriangles;
2313 surface->num_triangles = BigLong(dpmmesh->num_tris);
2314 surface->num_firstvertex = meshvertices;
2315 surface->num_vertices = BigLong(dpmmesh->num_verts);
2316 meshvertices += surface->num_vertices;
2317 meshtriangles += surface->num_triangles;
2319 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2320 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2321 for (j = 0;j < surface->num_triangles;j++)
2323 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2324 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2325 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2326 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2331 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2332 for (j = 0;j < surface->num_vertices*2;j++)
2333 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2335 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2336 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2338 int weightindex[4] = { 0, 0, 0, 0 };
2339 float weightinfluence[4] = { 0, 0, 0, 0 };
2341 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2342 data += sizeof(dpmvertex_t);
2343 for (k = 0;k < numweights;k++)
2345 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2346 int boneindex = BigLong(vert->bonenum);
2347 const float *m = bonepose + 12 * boneindex;
2348 float influence = BigFloat(vert->influence);
2349 float relativeorigin[3], relativenormal[3];
2350 relativeorigin[0] = BigFloat(vert->origin[0]);
2351 relativeorigin[1] = BigFloat(vert->origin[1]);
2352 relativeorigin[2] = BigFloat(vert->origin[2]);
2353 relativenormal[0] = BigFloat(vert->normal[0]);
2354 relativenormal[1] = BigFloat(vert->normal[1]);
2355 relativenormal[2] = BigFloat(vert->normal[2]);
2356 // blend the vertex bone weights into the base mesh
2357 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2358 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2359 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2360 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2361 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2362 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2365 // store the first (and often only) weight
2366 weightinfluence[0] = influence;
2367 weightindex[0] = boneindex;
2371 // sort the new weight into this vertex's weight table
2372 // (which only accepts up to 4 bones per vertex)
2373 for (l = 0;l < 4;l++)
2375 if (weightinfluence[l] < influence)
2377 // move weaker influence weights out of the way first
2379 for (l2 = 3;l2 > l;l2--)
2381 weightinfluence[l2] = weightinfluence[l2-1];
2382 weightindex[l2] = weightindex[l2-1];
2384 // store the new weight
2385 weightinfluence[l] = influence;
2386 weightindex[l] = boneindex;
2391 data += sizeof(dpmbonevert_t);
2393 loadmodel->surfmesh.blends[j] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
2396 // since dpm models do not have named sections, reuse their shader name as the section name
2397 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2399 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2401 if (loadmodel->surfmesh.num_blends < meshvertices)
2402 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2404 Mod_FreeSkinFiles(skinfiles);
2405 Mod_MakeSortedSurfaces(loadmodel);
2407 // compute all the mesh information that was not loaded from the file
2408 if (loadmodel->surfmesh.data_element3s)
2409 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2410 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2411 Mod_BuildBaseBonePoses();
2412 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);
2413 if (loadmodel->surfmesh.data_neighbor3i)
2414 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2416 if (!loadmodel->surfmesh.isanimated)
2418 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2419 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2420 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2421 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2422 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2423 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2426 // because shaders can do somewhat unexpected things, check for unusual features now
2427 for (i = 0;i < loadmodel->num_textures;i++)
2429 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
2430 mod->DrawSky = R_Q1BSP_DrawSky;
2431 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
2432 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
2436 // no idea why PSK/PSA files contain weird quaternions but they do...
2437 #define PSKQUATNEGATIONS
2438 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2440 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2441 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2442 fs_offset_t filesize;
2447 pskboneinfo_t *bones;
2448 pskrawweights_t *rawweights;
2449 //pskboneinfo_t *animbones;
2450 pskaniminfo_t *anims;
2451 pskanimkeys_t *animkeys;
2452 void *animfilebuffer, *animbuffer, *animbufferend;
2453 unsigned char *data;
2455 skinfile_t *skinfiles;
2456 char animname[MAX_QPATH];
2458 float biggestorigin;
2460 pchunk = (pskchunk_t *)buffer;
2461 if (strcmp(pchunk->id, "ACTRHEAD"))
2462 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2464 loadmodel->modeldatatypestring = "PSK";
2466 loadmodel->type = mod_alias;
2467 loadmodel->DrawSky = NULL;
2468 loadmodel->DrawAddWaterPlanes = NULL;
2469 loadmodel->Draw = R_Q1BSP_Draw;
2470 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2471 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2472 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2473 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2474 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2475 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2476 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2477 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2478 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2479 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2480 loadmodel->PointSuperContents = NULL;
2481 loadmodel->synctype = ST_RAND;
2483 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2484 strlcat(animname, ".psa", sizeof(animname));
2485 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2486 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2487 if (animbuffer == NULL)
2488 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2507 while (buffer < bufferend)
2509 pchunk = (pskchunk_t *)buffer;
2510 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2511 version = LittleLong(pchunk->version);
2512 recordsize = LittleLong(pchunk->recordsize);
2513 numrecords = LittleLong(pchunk->numrecords);
2514 if (developer_extra.integer)
2515 Con_DPrintf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2516 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2517 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);
2518 if (!strcmp(pchunk->id, "ACTRHEAD"))
2522 else if (!strcmp(pchunk->id, "PNTS0000"))
2525 if (recordsize != sizeof(*p))
2526 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2527 // byteswap in place and keep the pointer
2528 numpnts = numrecords;
2529 pnts = (pskpnts_t *)buffer;
2530 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2532 p->origin[0] = LittleFloat(p->origin[0]);
2533 p->origin[1] = LittleFloat(p->origin[1]);
2534 p->origin[2] = LittleFloat(p->origin[2]);
2538 else if (!strcmp(pchunk->id, "VTXW0000"))
2541 if (recordsize != sizeof(*p))
2542 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2543 // byteswap in place and keep the pointer
2544 numvtxw = numrecords;
2545 vtxw = (pskvtxw_t *)buffer;
2546 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2548 p->pntsindex = LittleShort(p->pntsindex);
2549 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2550 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2551 if (p->pntsindex >= numpnts)
2553 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2559 else if (!strcmp(pchunk->id, "FACE0000"))
2562 if (recordsize != sizeof(*p))
2563 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2564 // byteswap in place and keep the pointer
2565 numfaces = numrecords;
2566 faces = (pskface_t *)buffer;
2567 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2569 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2570 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2571 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2572 p->group = LittleLong(p->group);
2573 if (p->vtxwindex[0] >= numvtxw)
2575 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2576 p->vtxwindex[0] = 0;
2578 if (p->vtxwindex[1] >= numvtxw)
2580 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2581 p->vtxwindex[1] = 0;
2583 if (p->vtxwindex[2] >= numvtxw)
2585 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2586 p->vtxwindex[2] = 0;
2591 else if (!strcmp(pchunk->id, "MATT0000"))
2594 if (recordsize != sizeof(*p))
2595 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2596 // byteswap in place and keep the pointer
2597 nummatts = numrecords;
2598 matts = (pskmatt_t *)buffer;
2599 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2605 else if (!strcmp(pchunk->id, "REFSKELT"))
2608 if (recordsize != sizeof(*p))
2609 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2610 // byteswap in place and keep the pointer
2611 numbones = numrecords;
2612 bones = (pskboneinfo_t *)buffer;
2613 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2615 p->numchildren = LittleLong(p->numchildren);
2616 p->parent = LittleLong(p->parent);
2617 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2618 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2619 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2620 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2621 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2622 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2623 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2624 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2625 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2626 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2627 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2628 #ifdef PSKQUATNEGATIONS
2631 p->basepose.quat[0] *= -1;
2632 p->basepose.quat[1] *= -1;
2633 p->basepose.quat[2] *= -1;
2637 p->basepose.quat[0] *= 1;
2638 p->basepose.quat[1] *= -1;
2639 p->basepose.quat[2] *= 1;
2642 if (p->parent < 0 || p->parent >= numbones)
2644 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2650 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2653 if (recordsize != sizeof(*p))
2654 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2655 // byteswap in place and keep the pointer
2656 numrawweights = numrecords;
2657 rawweights = (pskrawweights_t *)buffer;
2658 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2660 p->weight = LittleFloat(p->weight);
2661 p->pntsindex = LittleLong(p->pntsindex);
2662 p->boneindex = LittleLong(p->boneindex);
2663 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2665 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2668 if (p->boneindex < 0 || p->boneindex >= numbones)
2670 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2678 while (animbuffer < animbufferend)
2680 pchunk = (pskchunk_t *)animbuffer;
2681 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2682 version = LittleLong(pchunk->version);
2683 recordsize = LittleLong(pchunk->recordsize);
2684 numrecords = LittleLong(pchunk->numrecords);
2685 if (developer_extra.integer)
2686 Con_DPrintf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2687 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2688 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);
2689 if (!strcmp(pchunk->id, "ANIMHEAD"))
2693 else if (!strcmp(pchunk->id, "BONENAMES"))
2696 if (recordsize != sizeof(*p))
2697 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2698 // byteswap in place and keep the pointer
2699 numanimbones = numrecords;
2700 //animbones = (pskboneinfo_t *)animbuffer;
2701 // NOTE: supposedly psa does not need to match the psk model, the
2702 // bones missing from the psa would simply use their base
2703 // positions from the psk, but this is hard for me to implement
2704 // and people can easily make animations that match.
2705 if (numanimbones != numbones)
2706 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2707 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2709 p->numchildren = LittleLong(p->numchildren);
2710 p->parent = LittleLong(p->parent);
2711 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2712 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2713 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2714 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2715 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2716 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2717 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2718 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2719 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2720 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2721 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2722 #ifdef PSKQUATNEGATIONS
2725 p->basepose.quat[0] *= -1;
2726 p->basepose.quat[1] *= -1;
2727 p->basepose.quat[2] *= -1;
2731 p->basepose.quat[0] *= 1;
2732 p->basepose.quat[1] *= -1;
2733 p->basepose.quat[2] *= 1;
2736 if (p->parent < 0 || p->parent >= numanimbones)
2738 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2741 // check that bones are the same as in the base
2742 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2743 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2747 else if (!strcmp(pchunk->id, "ANIMINFO"))
2750 if (recordsize != sizeof(*p))
2751 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2752 // byteswap in place and keep the pointer
2753 numanims = numrecords;
2754 anims = (pskaniminfo_t *)animbuffer;
2755 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2757 p->numbones = LittleLong(p->numbones);
2758 p->playtime = LittleFloat(p->playtime);
2759 p->fps = LittleFloat(p->fps);
2760 p->firstframe = LittleLong(p->firstframe);
2761 p->numframes = LittleLong(p->numframes);
2762 if (p->numbones != numbones)
2763 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2767 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2770 if (recordsize != sizeof(*p))
2771 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2772 numanimkeys = numrecords;
2773 animkeys = (pskanimkeys_t *)animbuffer;
2774 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2776 p->origin[0] = LittleFloat(p->origin[0]);
2777 p->origin[1] = LittleFloat(p->origin[1]);
2778 p->origin[2] = LittleFloat(p->origin[2]);
2779 p->quat[0] = LittleFloat(p->quat[0]);
2780 p->quat[1] = LittleFloat(p->quat[1]);
2781 p->quat[2] = LittleFloat(p->quat[2]);
2782 p->quat[3] = LittleFloat(p->quat[3]);
2783 p->frametime = LittleFloat(p->frametime);
2784 #ifdef PSKQUATNEGATIONS
2785 if (index % numbones)
2800 // TODO: allocate bonepose stuff
2803 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2806 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2807 Host_Error("%s: missing required chunks", loadmodel->name);
2809 loadmodel->numframes = 0;
2810 for (index = 0;index < numanims;index++)
2811 loadmodel->numframes += anims[index].numframes;
2813 if (numanimkeys != numbones * loadmodel->numframes)
2814 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2816 meshvertices = numvtxw;
2817 meshtriangles = numfaces;
2819 // load external .skin files if present
2820 skinfiles = Mod_LoadSkinFiles();
2821 if (loadmodel->numskins < 1)
2822 loadmodel->numskins = 1;
2823 loadmodel->num_bones = numbones;
2824 loadmodel->num_poses = loadmodel->numframes;
2825 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2826 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2827 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2828 loadmodel->surfmesh.num_vertices = meshvertices;
2829 loadmodel->surfmesh.num_triangles = meshtriangles;
2830 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2831 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
2832 // do most allocations as one merged chunk
2833 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);
2834 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2835 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2836 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2837 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2838 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2839 if (r_enableshadowvolumes.integer)
2841 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2843 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2844 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2845 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2846 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2847 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2848 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2849 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2850 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2851 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2852 loadmodel->surfmesh.num_blends = 0;
2853 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2854 if (loadmodel->surfmesh.num_vertices <= 65536)
2856 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2858 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2859 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(blendweights_t));
2861 for (i = 0;i < loadmodel->numskins;i++)
2863 loadmodel->skinscenes[i].firstframe = i;
2864 loadmodel->skinscenes[i].framecount = 1;
2865 loadmodel->skinscenes[i].loop = true;
2866 loadmodel->skinscenes[i].framerate = 10;
2870 for (index = 0, i = 0;index < nummatts;index++)
2872 // since psk models do not have named sections, reuse their shader name as the section name
2873 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2874 loadmodel->sortedmodelsurfaces[index] = index;
2875 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2876 loadmodel->data_surfaces[index].num_firstvertex = 0;
2877 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2880 // copy over the vertex locations and texcoords
2881 for (index = 0;index < numvtxw;index++)
2883 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2884 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2885 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2886 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2887 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2890 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2891 for (index = 0;index < numfaces;index++)
2892 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2893 for (index = 0, i = 0;index < nummatts;index++)
2895 loadmodel->data_surfaces[index].num_firsttriangle = i;
2896 i += loadmodel->data_surfaces[index].num_triangles;
2897 loadmodel->data_surfaces[index].num_triangles = 0;
2899 for (index = 0;index < numfaces;index++)
2901 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2902 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2903 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2904 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2907 // copy over the bones
2908 for (index = 0;index < numbones;index++)
2910 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2911 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2912 if (loadmodel->data_bones[index].parent >= index)
2913 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2916 // sort the psk point weights into the vertex weight tables
2917 // (which only accept up to 4 bones per vertex)
2918 for (index = 0;index < numvtxw;index++)
2920 int weightindex[4] = { 0, 0, 0, 0 };
2921 float weightinfluence[4] = { 0, 0, 0, 0 };
2923 for (j = 0;j < numrawweights;j++)
2925 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2927 int boneindex = rawweights[j].boneindex;
2928 float influence = rawweights[j].weight;
2929 for (l = 0;l < 4;l++)
2931 if (weightinfluence[l] < influence)
2933 // move lower influence weights out of the way first
2935 for (l2 = 3;l2 > l;l2--)
2937 weightinfluence[l2] = weightinfluence[l2-1];
2938 weightindex[l2] = weightindex[l2-1];
2940 // store the new weight
2941 weightinfluence[l] = influence;
2942 weightindex[l] = boneindex;
2948 loadmodel->surfmesh.blends[index] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
2950 if (loadmodel->surfmesh.num_blends < loadmodel->surfmesh.num_vertices)
2951 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2953 // set up the animscenes based on the anims
2954 for (index = 0, i = 0;index < numanims;index++)
2956 for (j = 0;j < anims[index].numframes;j++, i++)
2958 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2959 loadmodel->animscenes[i].firstframe = i;
2960 loadmodel->animscenes[i].framecount = 1;
2961 loadmodel->animscenes[i].loop = true;
2962 loadmodel->animscenes[i].framerate = anims[index].fps;
2966 // calculate the scaling value for bone origins so they can be compressed to short
2968 for (index = 0;index < numanimkeys;index++)
2970 pskanimkeys_t *k = animkeys + index;
2971 biggestorigin = max(biggestorigin, fabs(k->origin[0]));
2972 biggestorigin = max(biggestorigin, fabs(k->origin[1]));
2973 biggestorigin = max(biggestorigin, fabs(k->origin[2]));
2975 loadmodel->num_posescale = biggestorigin / 32767.0f;
2976 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2978 // load the poses from the animkeys
2979 for (index = 0;index < numanimkeys;index++)
2981 pskanimkeys_t *k = animkeys + index;
2983 Vector4Copy(k->quat, quat);
2985 Vector4Negate(quat, quat);
2986 Vector4Normalize2(quat, quat);
2987 // compress poses to the short[6] format for longterm storage
2988 loadmodel->data_poses6s[index*6+0] = k->origin[0] * loadmodel->num_poseinvscale;
2989 loadmodel->data_poses6s[index*6+1] = k->origin[1] * loadmodel->num_poseinvscale;
2990 loadmodel->data_poses6s[index*6+2] = k->origin[2] * loadmodel->num_poseinvscale;
2991 loadmodel->data_poses6s[index*6+3] = quat[0] * 32767.0f;
2992 loadmodel->data_poses6s[index*6+4] = quat[1] * 32767.0f;
2993 loadmodel->data_poses6s[index*6+5] = quat[2] * 32767.0f;
2995 Mod_FreeSkinFiles(skinfiles);
2996 Mem_Free(animfilebuffer);
2997 Mod_MakeSortedSurfaces(loadmodel);
2999 // compute all the mesh information that was not loaded from the file
3000 // TODO: honor smoothing groups somehow?
3001 if (loadmodel->surfmesh.data_element3s)
3002 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3003 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3004 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
3005 Mod_BuildBaseBonePoses();
3006 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);
3007 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);
3008 if (loadmodel->surfmesh.data_neighbor3i)
3009 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3010 Mod_Alias_CalculateBoundingBox();
3012 if (!loadmodel->surfmesh.isanimated)
3014 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3015 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3016 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3017 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3018 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3019 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
3022 // because shaders can do somewhat unexpected things, check for unusual features now
3023 for (i = 0;i < loadmodel->num_textures;i++)
3025 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
3026 mod->DrawSky = R_Q1BSP_DrawSky;
3027 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
3028 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
3032 void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
3034 unsigned char *data;
3036 const unsigned char *pbase, *pend;
3038 skinfile_t *skinfiles;
3039 int i, j, k, meshvertices, meshtriangles;
3040 float biggestorigin;
3041 const unsigned int *inelements;
3043 const int *inneighbors;
3045 float *outvertex, *outnormal, *outtexcoord, *outsvector, *outtvector;
3046 // this pointers into the file data are read only through Little* functions so they can be unaligned memory
3047 const float *vnormal = NULL;
3048 const float *vposition = NULL;
3049 const float *vtangent = NULL;
3050 const float *vtexcoord = NULL;
3051 const unsigned char *vblendindexes = NULL;
3052 const unsigned char *vblendweights = NULL;
3053 const unsigned short *framedata = NULL;
3054 // temporary memory allocations (because the data in the file may be misaligned)
3055 iqmanim_t *anims = NULL;
3056 iqmbounds_t *bounds = NULL;
3057 iqmjoint1_t *joint1 = NULL;
3058 iqmjoint_t *joint = NULL;
3059 iqmmesh_t *meshes = NULL;
3060 iqmpose1_t *pose1 = NULL;
3061 iqmpose_t *pose = NULL;
3062 iqmvertexarray_t *vas = NULL;
3064 pbase = (unsigned char *)buffer;
3065 pend = (unsigned char *)bufferend;
3067 if (pbase + sizeof(iqmheader_t) > pend)
3068 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model %d", loadmodel->name, (int)(pend - pbase));
3070 // copy struct (otherwise it may be misaligned)
3071 // LordHavoc: okay it's definitely not misaligned here, but for consistency...
3072 memcpy(&header, pbase, sizeof(iqmheader_t));
3074 if (memcmp(header.id, "INTERQUAKEMODEL", 16))
3075 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model", loadmodel->name);
3076 if (LittleLong(header.version) != 1 && LittleLong(header.version) != 2)
3077 Host_Error ("Mod_INTERQUAKEMODEL_Load: only version 1 and 2 models are currently supported (name = %s)", loadmodel->name);
3079 loadmodel->modeldatatypestring = "IQM";
3081 loadmodel->type = mod_alias;
3082 loadmodel->synctype = ST_RAND;
3085 header.version = LittleLong(header.version);
3086 header.filesize = LittleLong(header.filesize);
3087 header.flags = LittleLong(header.flags);
3088 header.num_text = LittleLong(header.num_text);
3089 header.ofs_text = LittleLong(header.ofs_text);
3090 header.num_meshes = LittleLong(header.num_meshes);
3091 header.ofs_meshes = LittleLong(header.ofs_meshes);
3092 header.num_vertexarrays = LittleLong(header.num_vertexarrays);
3093 header.num_vertexes = LittleLong(header.num_vertexes);
3094 header.ofs_vertexarrays = LittleLong(header.ofs_vertexarrays);
3095 header.num_triangles = LittleLong(header.num_triangles);
3096 header.ofs_triangles = LittleLong(header.ofs_triangles);
3097 header.ofs_neighbors = LittleLong(header.ofs_neighbors);
3098 header.num_joints = LittleLong(header.num_joints);
3099 header.ofs_joints = LittleLong(header.ofs_joints);
3100 header.num_poses = LittleLong(header.num_poses);
3101 header.ofs_poses = LittleLong(header.ofs_poses);
3102 header.num_anims = LittleLong(header.num_anims);
3103 header.ofs_anims = LittleLong(header.ofs_anims);
3104 header.num_frames = LittleLong(header.num_frames);
3105 header.num_framechannels = LittleLong(header.num_framechannels);
3106 header.ofs_frames = LittleLong(header.ofs_frames);
3107 header.ofs_bounds = LittleLong(header.ofs_bounds);
3108 header.num_comment = LittleLong(header.num_comment);
3109 header.ofs_comment = LittleLong(header.ofs_comment);
3110 header.num_extensions = LittleLong(header.num_extensions);
3111 header.ofs_extensions = LittleLong(header.ofs_extensions);
3113 if (header.version == 1)
3115 if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint1_t) > pend ||
3116 pbase + header.ofs_poses + header.num_poses*sizeof(iqmpose1_t) > pend)
3118 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3124 if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint_t) > pend ||
3125 pbase + header.ofs_poses + header.num_poses*sizeof(iqmpose_t) > pend)
3127 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3131 if (pbase + header.ofs_text + header.num_text > pend ||
3132 pbase + header.ofs_meshes + header.num_meshes*sizeof(iqmmesh_t) > pend ||
3133 pbase + header.ofs_vertexarrays + header.num_vertexarrays*sizeof(iqmvertexarray_t) > pend ||
3134 pbase + header.ofs_triangles + header.num_triangles*sizeof(int[3]) > pend ||
3135 (header.ofs_neighbors && pbase + header.ofs_neighbors + header.num_triangles*sizeof(int[3]) > pend) ||
3136 pbase + header.ofs_anims + header.num_anims*sizeof(iqmanim_t) > pend ||
3137 pbase + header.ofs_frames + header.num_frames*header.num_framechannels*sizeof(unsigned short) > pend ||
3138 (header.ofs_bounds && pbase + header.ofs_bounds + header.num_frames*sizeof(iqmbounds_t) > pend) ||
3139 pbase + header.ofs_comment + header.num_comment > pend)
3141 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3145 // copy structs to make them aligned in memory (otherwise we crash on Sparc and PowerPC and others)
3146 if (header.num_vertexarrays)
3147 vas = (iqmvertexarray_t *)(pbase + header.ofs_vertexarrays);
3148 if (header.num_anims)
3149 anims = (iqmanim_t *)(pbase + header.ofs_anims);
3150 if (header.ofs_bounds)
3151 bounds = (iqmbounds_t *)(pbase + header.ofs_bounds);
3152 if (header.num_meshes)
3153 meshes = (iqmmesh_t *)(pbase + header.ofs_meshes);
3155 for (i = 0;i < (int)header.num_vertexarrays;i++)
3157 iqmvertexarray_t va;
3159 va.type = LittleLong(vas[i].type);
3160 va.flags = LittleLong(vas[i].flags);
3161 va.format = LittleLong(vas[i].format);
3162 va.size = LittleLong(vas[i].size);
3163 va.offset = LittleLong(vas[i].offset);
3164 vsize = header.num_vertexes*va.size;
3167 case IQM_FLOAT: vsize *= sizeof(float); break;
3168 case IQM_UBYTE: vsize *= sizeof(unsigned char); break;
3171 if (pbase + va.offset + vsize > pend)
3173 // no need to copy the vertex data for alignment because LittleLong/LittleShort will be invoked on reading them, and the destination is aligned
3177 if (va.format == IQM_FLOAT && va.size == 3)
3178 vposition = (const float *)(pbase + va.offset);
3181 if (va.format == IQM_FLOAT && va.size == 2)
3182 vtexcoord = (const float *)(pbase + va.offset);
3185 if (va.format == IQM_FLOAT && va.size == 3)
3186 vnormal = (const float *)(pbase + va.offset);
3189 if (va.format == IQM_FLOAT && va.size == 4)
3190 vtangent = (const float *)(pbase + va.offset);
3192 case IQM_BLENDINDEXES:
3193 if (va.format == IQM_UBYTE && va.size == 4)
3194 vblendindexes = (const unsigned char *)(pbase + va.offset);
3196 case IQM_BLENDWEIGHTS:
3197 if (va.format == IQM_UBYTE && va.size == 4)
3198 vblendweights = (const unsigned char *)(pbase + va.offset);
3202 if (header.num_vertexes > 0 && (!vposition || !vtexcoord || ((header.num_frames > 0 || header.num_anims > 0) && (!vblendindexes || !vblendweights))))
3204 Con_Printf("%s is missing vertex array data\n", loadmodel->name);
3208 text = header.num_text && header.ofs_text ? (const char *)(pbase + header.ofs_text) : "";
3210 loadmodel->DrawSky = NULL;
3211 loadmodel->DrawAddWaterPlanes = NULL;
3212 loadmodel->Draw = R_Q1BSP_Draw;
3213 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
3214 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
3215 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
3216 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
3217 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
3218 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
3219 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
3220 loadmodel->DrawLight = R_Q1BSP_DrawLight;
3221 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
3222 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
3223 loadmodel->PointSuperContents = NULL;
3225 // load external .skin files if present
3226 skinfiles = Mod_LoadSkinFiles();
3227 if (loadmodel->numskins < 1)
3228 loadmodel->numskins = 1;
3230 loadmodel->numframes = max(header.num_anims, 1);
3231 loadmodel->num_bones = header.num_joints;
3232 loadmodel->num_poses = max(header.num_frames, 1);
3233 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = header.num_meshes;
3234 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3235 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3236 loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
3237 loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
3239 meshvertices = header.num_vertexes;
3240 meshtriangles = header.num_triangles;
3242 // do most allocations as one merged chunk
3243 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));
3244 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
3245 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
3246 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
3247 loadmodel->surfmesh.num_vertices = meshvertices;
3248 loadmodel->surfmesh.num_triangles = meshtriangles;
3249 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3250 if (r_enableshadowvolumes.integer)
3252 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3254 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
3255 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3256 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3257 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
3258 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
3259 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
3260 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
3261 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
3262 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
3263 if (vblendindexes && vblendweights)
3265 loadmodel->surfmesh.num_blends = 0;
3266 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
3268 if (meshvertices <= 65536)
3270 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
3272 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
3273 if (vblendindexes && vblendweights)
3274 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
3276 for (i = 0;i < loadmodel->numskins;i++)
3278 loadmodel->skinscenes[i].firstframe = i;
3279 loadmodel->skinscenes[i].framecount = 1;
3280 loadmodel->skinscenes[i].loop = true;
3281 loadmodel->skinscenes[i].framerate = 10;
3284 // load the bone info
3285 if (header.version == 1)
3287 iqmjoint1_t *injoint1 = (iqmjoint1_t *)(pbase + header.ofs_joints);
3288 if (loadmodel->num_bones)
3289 joint1 = (iqmjoint1_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(iqmjoint1_t));
3290 for (i = 0;i < loadmodel->num_bones;i++)
3292 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3293 joint1[i].name = LittleLong(injoint1[i].name);
3294 joint1[i].parent = LittleLong(injoint1[i].parent);
3295 for (j = 0;j < 3;j++)
3297 joint1[i].origin[j] = LittleFloat(injoint1[i].origin[j]);
3298 joint1[i].rotation[j] = LittleFloat(injoint1[i].rotation[j]);
3299 joint1[i].scale[j] = LittleFloat(injoint1[i].scale[j]);
3301 strlcpy(loadmodel->data_bones[i].name, &text[joint1[i].name], sizeof(loadmodel->data_bones[i].name));
3302 loadmodel->data_bones[i].parent = joint1[i].parent;
3303 if (loadmodel->data_bones[i].parent >= i)
3304 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3305 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]);
3306 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3307 if (loadmodel->data_bones[i].parent >= 0)
3309 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3310 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3311 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3313 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3318 iqmjoint_t *injoint = (iqmjoint_t *)(pbase + header.ofs_joints);
3319 if (header.num_joints)
3320 joint = (iqmjoint_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(iqmjoint_t));
3321 for (i = 0;i < loadmodel->num_bones;i++)
3323 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3324 joint[i].name = LittleLong(injoint[i].name);
3325 joint[i].parent = LittleLong(injoint[i].parent);
3326 for (j = 0;j < 3;j++)
3328 joint[i].origin[j] = LittleFloat(injoint[i].origin[j]);
3329 joint[i].rotation[j] = LittleFloat(injoint[i].rotation[j]);
3330 joint[i].scale[j] = LittleFloat(injoint[i].scale[j]);
3332 joint[i].rotation[3] = LittleFloat(injoint[i].rotation[3]);
3333 strlcpy(loadmodel->data_bones[i].name, &text[joint[i].name], sizeof(loadmodel->data_bones[i].name));
3334 loadmodel->data_bones[i].parent = joint[i].parent;
3335 if (loadmodel->data_bones[i].parent >= i)
3336 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3337 if (joint[i].rotation[3] > 0)
3338 Vector4Negate(joint[i].rotation, joint[i].rotation);
3339 Vector4Normalize2(joint[i].rotation, joint[i].rotation);
3340 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]);
3341 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3342 if (loadmodel->data_bones[i].parent >= 0)
3344 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3345 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3346 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3348 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3352 // set up the animscenes based on the anims
3353 for (i = 0;i < (int)header.num_anims;i++)
3356 anim.name = LittleLong(anims[i].name);
3357 anim.first_frame = LittleLong(anims[i].first_frame);
3358 anim.num_frames = LittleLong(anims[i].num_frames);
3359 anim.framerate = LittleFloat(anims[i].framerate);
3360 anim.flags = LittleLong(anims[i].flags);
3361 strlcpy(loadmodel->animscenes[i].name, &text[anim.name], sizeof(loadmodel->animscenes[i].name));
3362 loadmodel->animscenes[i].firstframe = anim.first_frame;
3363 loadmodel->animscenes[i].framecount = anim.num_frames;
3364 loadmodel->animscenes[i].loop = ((anim.flags & IQM_LOOP) != 0);
3365 loadmodel->animscenes[i].framerate = anim.framerate;
3367 if (header.num_anims <= 0)
3369 strlcpy(loadmodel->animscenes[0].name, "static", sizeof(loadmodel->animscenes[0].name));
3370 loadmodel->animscenes[0].firstframe = 0;
3371 loadmodel->animscenes[0].framecount = 1;
3372 loadmodel->animscenes[0].loop = true;
3373 loadmodel->animscenes[0].framerate = 10;
3377 if (header.version == 1)
3379 iqmpose1_t *inpose1 = (iqmpose1_t *)(pbase + header.ofs_poses);
3380 if (header.num_poses)
3381 pose1 = (iqmpose1_t *)Mem_Alloc(loadmodel->mempool, header.num_poses * sizeof(iqmpose1_t));
3382 for (i = 0;i < (int)header.num_poses;i++)
3385 pose1[i].parent = LittleLong(inpose1[i].parent);
3386 pose1[i].channelmask = LittleLong(inpose1[i].channelmask);
3387 for (j = 0;j < 9;j++)
3389 pose1[i].channeloffset[j] = LittleFloat(inpose1[i].channeloffset[j]);
3390 pose1[i].channelscale[j] = LittleFloat(inpose1[i].channelscale[j]);
3392 f = fabs(pose1[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3393 f = fabs(pose1[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3394 f = fabs(pose1[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3395 f = fabs(pose1[i].channeloffset[0] + 0xFFFF*pose1[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3396 f = fabs(pose1[i].channeloffset[1] + 0xFFFF*pose1[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3397 f = fabs(pose1[i].channeloffset[2] + 0xFFFF*pose1[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3399 if (header.num_frames <= 0)
3401 for (i = 0;i < loadmodel->num_bones;i++)
3404 f = fabs(joint1[i].origin[0]); biggestorigin = max(biggestorigin, f);
3405 f = fabs(joint1[i].origin[1]); biggestorigin = max(biggestorigin, f);
3406 f = fabs(joint1[i].origin[2]); biggestorigin = max(biggestorigin, f);
3412 iqmpose_t *inpose = (iqmpose_t *)(pbase + header.ofs_poses);
3413 if (header.num_poses)
3414 pose = (iqmpose_t *)Mem_Alloc(loadmodel->mempool, header.num_poses * sizeof(iqmpose_t));
3415 for (i = 0;i < (int)header.num_poses;i++)
3418 pose[i].parent = LittleLong(inpose[i].parent);
3419 pose[i].channelmask = LittleLong(inpose[i].channelmask);
3420 for (j = 0;j < 10;j++)
3422 pose[i].channeloffset[j] = LittleFloat(inpose[i].channeloffset[j]);
3423 pose[i].channelscale[j] = LittleFloat(inpose[i].channelscale[j]);
3425 f = fabs(pose[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3426 f = fabs(pose[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3427 f = fabs(pose[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3428 f = fabs(pose[i].channeloffset[0] + 0xFFFF*pose[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3429 f = fabs(pose[i].channeloffset[1] + 0xFFFF*pose[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3430 f = fabs(pose[i].channeloffset[2] + 0xFFFF*pose[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3432 if (header.num_frames <= 0)
3434 for (i = 0;i < loadmodel->num_bones;i++)
3437 f = fabs(joint[i].origin[0]); biggestorigin = max(biggestorigin, f);
3438 f = fabs(joint[i].origin[1]); biggestorigin = max(biggestorigin, f);
3439 f = fabs(joint[i].origin[2]); biggestorigin = max(biggestorigin, f);
3443 loadmodel->num_posescale = biggestorigin / 32767.0f;
3444 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3446 // load the pose data
3447 // this unaligned memory access is safe (LittleShort reads as bytes)
3448 framedata = (const unsigned short *)(pbase + header.ofs_frames);
3449 if (header.version == 1)
3451 for (i = 0, k = 0;i < (int)header.num_frames;i++)
3453 for (j = 0;j < (int)header.num_poses;j++, k++)
3455 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));
3456 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));
3457 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));
3458 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));
3459 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));
3460 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));
3461 // skip scale data for now
3462 if(pose1[j].channelmask&64) framedata++;
3463 if(pose1[j].channelmask&128) framedata++;
3464 if(pose1[j].channelmask&256) framedata++;
3467 if (header.num_frames <= 0)
3469 for (i = 0;i < loadmodel->num_bones;i++)
3471 loadmodel->data_poses6s[i*6 + 0] = loadmodel->num_poseinvscale * joint1[i].origin[0];
3472 loadmodel->data_poses6s[i*6 + 1] = loadmodel->num_poseinvscale * joint1[i].origin[1];
3473 loadmodel->data_poses6s[i*6 + 2] = loadmodel->num_poseinvscale * joint1[i].origin[2];
3474 loadmodel->data_poses6s[i*6 + 3] = 32767.0f * joint1[i].rotation[0];
3475 loadmodel->data_poses6s[i*6 + 4] = 32767.0f * joint1[i].rotation[1];
3476 loadmodel->data_poses6s[i*6 + 5] = 32767.0f * joint1[i].rotation[2];
3482 for (i = 0, k = 0;i < (int)header.num_frames;i++)
3484 for (j = 0;j < (int)header.num_poses;j++, k++)
3487 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));
3488 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));
3489 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));
3490 rot[0] = pose[j].channeloffset[3] + (pose[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[3] : 0);
3491 rot[1] = pose[j].channeloffset[4] + (pose[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[4] : 0);
3492 rot[2] = pose[j].channeloffset[5] + (pose[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[5] : 0);
3493 rot[3] = pose[j].channeloffset[6] + (pose[j].channelmask&64 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[6] : 0);
3495 Vector4Negate(rot, rot);
3496 Vector4Normalize2(rot, rot);
3497 loadmodel->data_poses6s[k*6 + 3] = 32767.0f * rot[0];
3498 loadmodel->data_poses6s[k*6 + 4] = 32767.0f * rot[1];
3499 loadmodel->data_poses6s[k*6 + 5] = 32767.0f * rot[2];
3500 // skip scale data for now
3501 if(pose[j].channelmask&128) framedata++;
3502 if(pose[j].channelmask&256) framedata++;
3503 if(pose[j].channelmask&512) framedata++;
3506 if (header.num_frames <= 0)
3508 for (i = 0;i < loadmodel->num_bones;i++)
3510 loadmodel->data_poses6s[i*6 + 0] = loadmodel->num_poseinvscale * joint[i].origin[0];
3511 loadmodel->data_poses6s[i*6 + 1] = loadmodel->num_poseinvscale * joint[i].origin[1];
3512 loadmodel->data_poses6s[i*6 + 2] = loadmodel->num_poseinvscale * joint[i].origin[2];
3513 loadmodel->data_poses6s[i*6 + 3] = 32767.0f * joint[i].rotation[0];
3514 loadmodel->data_poses6s[i*6 + 4] = 32767.0f * joint[i].rotation[1];
3515 loadmodel->data_poses6s[i*6 + 5] = 32767.0f * joint[i].rotation[2];
3520 // load bounding box data
3521 if (header.ofs_bounds)
3523 float xyradius = 0, radius = 0;
3524 VectorClear(loadmodel->normalmins);
3525 VectorClear(loadmodel->normalmaxs);
3526 for (i = 0; i < (int)header.num_frames;i++)
3529 bound.mins[0] = LittleFloat(bounds[i].mins[0]);
3530 bound.mins[1] = LittleFloat(bounds[i].mins[1]);
3531 bound.mins[2] = LittleFloat(bounds[i].mins[2]);
3532 bound.maxs[0] = LittleFloat(bounds[i].maxs[0]);
3533 bound.maxs[1] = LittleFloat(bounds[i].maxs[1]);
3534 bound.maxs[2] = LittleFloat(bounds[i].maxs[2]);
3535 bound.xyradius = LittleFloat(bounds[i].xyradius);
3536 bound.radius = LittleFloat(bounds[i].radius);
3539 VectorCopy(bound.mins, loadmodel->normalmins);
3540 VectorCopy(bound.maxs, loadmodel->normalmaxs);
3544 if (loadmodel->normalmins[0] > bound.mins[0]) loadmodel->normalmins[0] = bound.mins[0];
3545 if (loadmodel->normalmins[1] > bound.mins[1]) loadmodel->normalmins[1] = bound.mins[1];
3546 if (loadmodel->normalmins[2] > bound.mins[2]) loadmodel->normalmins[2] = bound.mins[2];
3547 if (loadmodel->normalmaxs[0] < bound.maxs[0]) loadmodel->normalmaxs[0] = bound.maxs[0];
3548 if (loadmodel->normalmaxs[1] < bound.maxs[1]) loadmodel->normalmaxs[1] = bound.maxs[1];
3549 if (loadmodel->normalmaxs[2] < bound.maxs[2]) loadmodel->normalmaxs[2] = bound.maxs[2];
3551 if (bound.xyradius > xyradius)
3552 xyradius = bound.xyradius;
3553 if (bound.radius > radius)
3554 radius = bound.radius;
3556 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -xyradius;
3557 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = xyradius;
3558 loadmodel->yawmins[2] = loadmodel->normalmins[2];
3559 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
3560 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
3561 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
3562 loadmodel->radius = radius;
3563 loadmodel->radius2 = radius * radius;
3566 // load triangle data
3567 // this unaligned memory access is safe (LittleLong reads as bytes)
3568 inelements = (const unsigned int *)(pbase + header.ofs_triangles);
3569 outelements = loadmodel->surfmesh.data_element3i;
3570 for (i = 0;i < (int)header.num_triangles;i++)
3572 outelements[0] = LittleLong(inelements[0]);
3573 outelements[1] = LittleLong(inelements[1]);
3574 outelements[2] = LittleLong(inelements[2]);
3578 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, header.num_vertexes, __FILE__, __LINE__);
3580 if (header.ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
3582 // this unaligned memory access is safe (LittleLong reads as bytes)
3583 inneighbors = (const int *)(pbase + header.ofs_neighbors);
3584 outneighbors = loadmodel->surfmesh.data_neighbor3i;
3585 for (i = 0;i < (int)header.num_triangles;i++)
3587 outneighbors[0] = LittleLong(inneighbors[0]);
3588 outneighbors[1] = LittleLong(inneighbors[1]);
3589 outneighbors[2] = LittleLong(inneighbors[2]);
3596 // this unaligned memory access is safe (LittleFloat reads as bytes)
3597 outvertex = loadmodel->surfmesh.data_vertex3f;
3598 for (i = 0;i < (int)header.num_vertexes;i++)
3600 outvertex[0] = LittleFloat(vposition[0]);
3601 outvertex[1] = LittleFloat(vposition[1]);
3602 outvertex[2] = LittleFloat(vposition[2]);
3607 outtexcoord = loadmodel->surfmesh.data_texcoordtexture2f;
3608 // this unaligned memory access is safe (LittleFloat reads as bytes)
3609 for (i = 0;i < (int)header.num_vertexes;i++)
3611 outtexcoord[0] = LittleFloat(vtexcoord[0]);
3612 outtexcoord[1] = LittleFloat(vtexcoord[1]);
3617 // this unaligned memory access is safe (LittleFloat reads as bytes)
3620 outnormal = loadmodel->surfmesh.data_normal3f;
3621 for (i = 0;i < (int)header.num_vertexes;i++)
3623 outnormal[0] = LittleFloat(vnormal[0]);
3624 outnormal[1] = LittleFloat(vnormal[1]);
3625 outnormal[2] = LittleFloat(vnormal[2]);
3631 // this unaligned memory access is safe (LittleFloat reads as bytes)
3632 if(vnormal && vtangent)
3634 outnormal = loadmodel->surfmesh.data_normal3f;
3635 outsvector = loadmodel->surfmesh.data_svector3f;
3636 outtvector = loadmodel->surfmesh.data_tvector3f;
3637 for (i = 0;i < (int)header.num_vertexes;i++)
3639 outsvector[0] = LittleFloat(vtangent[0]);
3640 outsvector[1] = LittleFloat(vtangent[1]);
3641 outsvector[2] = LittleFloat(vtangent[2]);
3642 if(LittleFloat(vtangent[3]) < 0)
3643 CrossProduct(outsvector, outnormal, outtvector);
3645 CrossProduct(outnormal, outsvector, outtvector);
3653 // this unaligned memory access is safe (all bytes)
3654 if (vblendindexes && vblendweights)
3656 for (i = 0; i < (int)header.num_vertexes;i++)
3658 blendweights_t weights;
3659 memcpy(weights.index, vblendindexes + i*4, 4);
3660 memcpy(weights.influence, vblendweights + i*4, 4);
3661 loadmodel->surfmesh.blends[i] = Mod_Skeletal_AddBlend(loadmodel, &weights);
3666 for (i = 0;i < (int)header.num_meshes;i++)
3669 msurface_t *surface;
3671 mesh.name = LittleLong(meshes[i].name);
3672 mesh.material = LittleLong(meshes[i].material);
3673 mesh.first_vertex = LittleLong(meshes[i].first_vertex);
3674 mesh.num_vertexes = LittleLong(meshes[i].num_vertexes);
3675 mesh.first_triangle = LittleLong(meshes[i].first_triangle);
3676 mesh.num_triangles = LittleLong(meshes[i].num_triangles);
3678 loadmodel->sortedmodelsurfaces[i] = i;
3679 surface = loadmodel->data_surfaces + i;
3680 surface->texture = loadmodel->data_textures + i;
3681 surface->num_firsttriangle = mesh.first_triangle;
3682 surface->num_triangles = mesh.num_triangles;
3683 surface->num_firstvertex = mesh.first_vertex;
3684 surface->num_vertices = mesh.num_vertexes;
3686 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, &text[mesh.name], &text[mesh.material]);
3689 Mod_FreeSkinFiles(skinfiles);
3690 Mod_MakeSortedSurfaces(loadmodel);
3692 // compute all the mesh information that was not loaded from the file
3693 if (loadmodel->surfmesh.data_element3s)
3694 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3695 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3697 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);
3698 if (!vnormal || !vtangent)
3699 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);
3700 if (!header.ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
3701 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3702 if (!header.ofs_bounds)
3703 Mod_Alias_CalculateBoundingBox();
3705 if (!loadmodel->surfmesh.isanimated && loadmodel->surfmesh.num_triangles >= 1)
3707 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3708 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3709 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3710 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3711 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3712 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
3715 if (joint ) Mem_Free(joint );joint = NULL;
3716 if (joint1 ) Mem_Free(joint1 );joint1 = NULL;
3717 if (pose ) Mem_Free(pose );pose = NULL;
3718 if (pose1 ) Mem_Free(pose1 );pose1 = NULL;
3720 // because shaders can do somewhat unexpected things, check for unusual features now
3721 for (i = 0;i < loadmodel->num_textures;i++)
3723 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
3724 mod->DrawSky = R_Q1BSP_DrawSky;
3725 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
3726 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;