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->AnimateVertices = Mod_MDL_AnimateVertices;
895 loadmodel->DrawSky = NULL;
896 loadmodel->DrawAddWaterPlanes = NULL;
897 loadmodel->Draw = R_Q1BSP_Draw;
898 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
899 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
900 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
901 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
902 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
903 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
904 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
905 loadmodel->DrawLight = R_Q1BSP_DrawLight;
906 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
907 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
908 // FIXME add TraceBrush!
909 loadmodel->PointSuperContents = NULL;
911 loadmodel->num_surfaces = 1;
912 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
913 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
914 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
915 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
916 loadmodel->sortedmodelsurfaces[0] = 0;
918 loadmodel->numskins = LittleLong(pinmodel->numskins);
919 BOUNDI(loadmodel->numskins,0,65536);
920 skinwidth = LittleLong (pinmodel->skinwidth);
921 BOUNDI(skinwidth,0,65536);
922 skinheight = LittleLong (pinmodel->skinheight);
923 BOUNDI(skinheight,0,65536);
924 numverts = LittleLong(pinmodel->numverts);
925 BOUNDI(numverts,0,65536);
926 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
927 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
928 loadmodel->numframes = LittleLong(pinmodel->numframes);
929 BOUNDI(loadmodel->numframes,0,65536);
930 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
931 BOUNDI((int)loadmodel->synctype,0,2);
932 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
933 i = LittleLong (pinmodel->flags);
934 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
936 for (i = 0;i < 3;i++)
938 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
939 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
942 startskins = datapointer;
944 for (i = 0;i < loadmodel->numskins;i++)
946 pinskintype = (daliasskintype_t *)datapointer;
947 datapointer += sizeof(daliasskintype_t);
948 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
952 pinskingroup = (daliasskingroup_t *)datapointer;
953 datapointer += sizeof(daliasskingroup_t);
954 groupskins = LittleLong(pinskingroup->numskins);
955 datapointer += sizeof(daliasskininterval_t) * groupskins;
958 for (j = 0;j < groupskins;j++)
960 datapointer += skinwidth * skinheight;
965 pinstverts = (stvert_t *)datapointer;
966 datapointer += sizeof(stvert_t) * numverts;
968 pintriangles = (dtriangle_t *)datapointer;
969 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
971 startframes = datapointer;
972 loadmodel->surfmesh.num_morphframes = 0;
973 for (i = 0;i < loadmodel->numframes;i++)
975 pinframetype = (daliasframetype_t *)datapointer;
976 datapointer += sizeof(daliasframetype_t);
977 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
981 pinframegroup = (daliasgroup_t *)datapointer;
982 datapointer += sizeof(daliasgroup_t);
983 groupframes = LittleLong(pinframegroup->numframes);
984 datapointer += sizeof(daliasinterval_t) * groupframes;
987 for (j = 0;j < groupframes;j++)
989 datapointer += sizeof(daliasframe_t);
990 datapointer += sizeof(trivertx_t) * numverts;
991 loadmodel->surfmesh.num_morphframes++;
994 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
996 // store texture coordinates into temporary array, they will be stored
997 // after usage is determined (triangle data)
998 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
999 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
1000 vertonseam = vertremap + numverts * 2;
1002 scales = 1.0 / skinwidth;
1003 scalet = 1.0 / skinheight;
1004 for (i = 0;i < numverts;i++)
1006 vertonseam[i] = LittleLong(pinstverts[i].onseam);
1007 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
1008 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
1009 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
1010 vertst[(i+numverts)*2+1] = vertst[i*2+1];
1013 // load triangle data
1014 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1016 // read the triangle elements
1017 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1018 for (j = 0;j < 3;j++)
1019 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1020 // validate (note numverts is used because this is the original data)
1021 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1022 // now butcher the elements according to vertonseam and tri->facesfront
1023 // and then compact the vertex set to remove duplicates
1024 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1025 if (!LittleLong(pintriangles[i].facesfront)) // backface
1026 for (j = 0;j < 3;j++)
1027 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1028 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1030 // (this uses vertremap to count usage to save some memory)
1031 for (i = 0;i < numverts*2;i++)
1033 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1034 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1035 // build remapping table and compact array
1036 loadmodel->surfmesh.num_vertices = 0;
1037 for (i = 0;i < numverts*2;i++)
1041 vertremap[i] = loadmodel->surfmesh.num_vertices;
1042 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1043 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1044 loadmodel->surfmesh.num_vertices++;
1047 vertremap[i] = -1; // not used at all
1049 // remap the elements to the new vertex set
1050 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1051 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1052 // store the texture coordinates
1053 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1054 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1056 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1057 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1060 // generate ushort elements array if possible
1061 if (loadmodel->surfmesh.num_vertices <= 65536)
1062 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1063 if (loadmodel->surfmesh.data_element3s)
1064 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1065 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1068 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1069 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1070 if (r_enableshadowvolumes.integer)
1072 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1074 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1075 if (loadmodel->surfmesh.data_neighbor3i)
1076 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1077 Mod_Alias_CalculateBoundingBox();
1078 Mod_Alias_MorphMesh_CompileFrames();
1081 Mem_Free(vertremap);
1084 skinfiles = Mod_LoadSkinFiles();
1087 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1088 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1089 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1090 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1091 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1092 Mod_FreeSkinFiles(skinfiles);
1093 for (i = 0;i < loadmodel->numskins;i++)
1095 loadmodel->skinscenes[i].firstframe = i;
1096 loadmodel->skinscenes[i].framecount = 1;
1097 loadmodel->skinscenes[i].loop = true;
1098 loadmodel->skinscenes[i].framerate = 10;
1103 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1104 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1105 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1106 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1108 datapointer = startskins;
1109 for (i = 0;i < loadmodel->numskins;i++)
1111 pinskintype = (daliasskintype_t *)datapointer;
1112 datapointer += sizeof(daliasskintype_t);
1114 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1121 pinskingroup = (daliasskingroup_t *)datapointer;
1122 datapointer += sizeof(daliasskingroup_t);
1124 groupskins = LittleLong (pinskingroup->numskins);
1126 pinskinintervals = (daliasskininterval_t *)datapointer;
1127 datapointer += sizeof(daliasskininterval_t) * groupskins;
1129 interval = LittleFloat(pinskinintervals[0].interval);
1130 if (interval < 0.01f)
1132 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1137 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1138 loadmodel->skinscenes[i].firstframe = totalskins;
1139 loadmodel->skinscenes[i].framecount = groupskins;
1140 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1141 loadmodel->skinscenes[i].loop = true;
1143 for (j = 0;j < groupskins;j++)
1146 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1148 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1149 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))
1150 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));
1151 datapointer += skinwidth * skinheight;
1155 // check for skins that don't exist in the model, but do exist as external images
1156 // (this was added because yummyluv kept pestering me about support for it)
1157 // TODO: support shaders here?
1158 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)))
1160 // expand the arrays to make room
1161 tempskinscenes = loadmodel->skinscenes;
1162 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1163 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1164 Mem_Free(tempskinscenes);
1166 tempaliasskins = loadmodel->data_textures;
1167 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1168 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1169 Mem_Free(tempaliasskins);
1171 // store the info about the new skin
1172 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1173 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1174 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1175 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1176 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1177 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1179 //increase skin counts
1180 loadmodel->numskins++;
1183 // fix up the pointers since they are pointing at the old textures array
1184 // FIXME: this is a hack!
1185 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1186 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1190 surface = loadmodel->data_surfaces;
1191 surface->texture = loadmodel->data_textures;
1192 surface->num_firsttriangle = 0;
1193 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1194 surface->num_firstvertex = 0;
1195 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1197 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
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->AnimateVertices = Mod_MDL_AnimateVertices;
1252 loadmodel->DrawSky = NULL;
1253 loadmodel->DrawAddWaterPlanes = NULL;
1254 loadmodel->Draw = R_Q1BSP_Draw;
1255 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1256 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1257 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1258 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1259 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1260 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1261 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1262 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1263 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1264 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1265 loadmodel->PointSuperContents = NULL;
1267 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1268 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1269 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1270 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1271 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1272 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1273 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1274 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1276 end = LittleLong(pinmodel->ofs_end);
1277 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1278 Host_Error ("%s is not a valid model", loadmodel->name);
1279 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1280 Host_Error ("%s is not a valid model", loadmodel->name);
1281 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1282 Host_Error ("%s is not a valid model", loadmodel->name);
1283 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1284 Host_Error ("%s is not a valid model", loadmodel->name);
1285 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1286 Host_Error ("%s is not a valid model", loadmodel->name);
1288 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1289 numxyz = LittleLong(pinmodel->num_xyz);
1290 numst = LittleLong(pinmodel->num_st);
1291 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1292 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1293 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1294 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1295 skinwidth = LittleLong(pinmodel->skinwidth);
1296 skinheight = LittleLong(pinmodel->skinheight);
1297 iskinwidth = 1.0f / skinwidth;
1298 iskinheight = 1.0f / skinheight;
1300 loadmodel->num_surfaces = 1;
1301 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1302 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));
1303 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1304 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1305 loadmodel->sortedmodelsurfaces[0] = 0;
1306 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1307 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1308 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1309 if (r_enableshadowvolumes.integer)
1311 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1314 loadmodel->synctype = ST_RAND;
1317 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1318 skinfiles = Mod_LoadSkinFiles();
1321 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1322 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1323 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1324 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1325 Mod_FreeSkinFiles(skinfiles);
1327 else if (loadmodel->numskins)
1329 // skins found (most likely not a player model)
1330 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1331 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1332 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1333 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1334 Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
1338 // no skins (most likely a player model)
1339 loadmodel->numskins = 1;
1340 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1341 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1342 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1343 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1346 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1347 for (i = 0;i < loadmodel->numskins;i++)
1349 loadmodel->skinscenes[i].firstframe = i;
1350 loadmodel->skinscenes[i].framecount = 1;
1351 loadmodel->skinscenes[i].loop = true;
1352 loadmodel->skinscenes[i].framerate = 10;
1355 // load the triangles and stvert data
1356 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1357 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1358 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1359 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1360 // swap the triangle list
1361 loadmodel->surfmesh.num_vertices = 0;
1362 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1364 for (j = 0;j < 3;j++)
1366 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1367 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1370 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1375 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1378 hashindex = (xyz * 256 + st) & 65535;
1379 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1380 if (hash->xyz == xyz && hash->st == st)
1384 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1387 hash->next = md2verthash[hashindex];
1388 md2verthash[hashindex] = hash;
1390 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1394 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1395 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));
1396 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1397 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1398 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1401 hash = md2verthashdata + i;
1402 vertremap[i] = hash->xyz;
1403 sts = LittleShort(inst[hash->st*2+0]);
1404 stt = LittleShort(inst[hash->st*2+1]);
1405 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1407 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1411 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1412 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1415 Mem_Free(md2verthash);
1416 Mem_Free(md2verthashdata);
1418 // generate ushort elements array if possible
1419 if (loadmodel->surfmesh.num_vertices <= 65536)
1420 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1421 if (loadmodel->surfmesh.data_element3s)
1422 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1423 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1426 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1427 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1432 pinframe = (md2frame_t *)datapointer;
1433 datapointer += sizeof(md2frame_t);
1434 // store the frame scale/translate into the appropriate array
1435 for (j = 0;j < 3;j++)
1437 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1438 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1440 // convert the vertices
1441 v = (trivertx_t *)datapointer;
1442 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1443 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1444 out[k] = v[vertremap[k]];
1445 datapointer += numxyz * sizeof(trivertx_t);
1447 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1448 loadmodel->animscenes[i].firstframe = i;
1449 loadmodel->animscenes[i].framecount = 1;
1450 loadmodel->animscenes[i].framerate = 10;
1451 loadmodel->animscenes[i].loop = true;
1454 Mem_Free(vertremap);
1456 if (loadmodel->surfmesh.data_neighbor3i)
1457 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1458 Mod_Alias_CalculateBoundingBox();
1459 Mod_Alias_MorphMesh_CompileFrames();
1461 surface = loadmodel->data_surfaces;
1462 surface->texture = loadmodel->data_textures;
1463 surface->num_firsttriangle = 0;
1464 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1465 surface->num_firstvertex = 0;
1466 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1468 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
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->AnimateVertices = Mod_MD3_AnimateVertices;
1518 loadmodel->DrawSky = NULL;
1519 loadmodel->DrawAddWaterPlanes = NULL;
1520 loadmodel->Draw = R_Q1BSP_Draw;
1521 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1522 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1523 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1524 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1525 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1526 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1527 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1528 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1529 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1530 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1531 loadmodel->PointSuperContents = NULL;
1532 loadmodel->synctype = ST_RAND;
1533 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1534 i = LittleLong (pinmodel->flags);
1535 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1537 // set up some global info about the model
1538 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1539 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1541 // make skinscenes for the skins (no groups)
1542 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1543 for (i = 0;i < loadmodel->numskins;i++)
1545 loadmodel->skinscenes[i].firstframe = i;
1546 loadmodel->skinscenes[i].framecount = 1;
1547 loadmodel->skinscenes[i].loop = true;
1548 loadmodel->skinscenes[i].framerate = 10;
1552 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1553 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1555 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1556 loadmodel->animscenes[i].firstframe = i;
1557 loadmodel->animscenes[i].framecount = 1;
1558 loadmodel->animscenes[i].framerate = 10;
1559 loadmodel->animscenes[i].loop = true;
1563 loadmodel->num_tagframes = loadmodel->numframes;
1564 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1565 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1566 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1568 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1569 for (j = 0;j < 9;j++)
1570 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1571 for (j = 0;j < 3;j++)
1572 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1573 //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);
1579 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)))
1581 if (memcmp(pinmesh->identifier, "IDP3", 4))
1582 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1583 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1584 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1585 meshvertices += LittleLong(pinmesh->num_vertices);
1586 meshtriangles += LittleLong(pinmesh->num_triangles);
1589 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1590 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1591 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1592 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));
1593 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1594 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1595 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1596 loadmodel->surfmesh.num_vertices = meshvertices;
1597 loadmodel->surfmesh.num_triangles = meshtriangles;
1598 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1599 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1600 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1601 if (r_enableshadowvolumes.integer)
1603 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1605 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1606 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1607 if (meshvertices <= 65536)
1609 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1614 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)))
1616 if (memcmp(pinmesh->identifier, "IDP3", 4))
1617 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1618 loadmodel->sortedmodelsurfaces[i] = i;
1619 surface = loadmodel->data_surfaces + i;
1620 surface->texture = loadmodel->data_textures + i;
1621 surface->num_firsttriangle = meshtriangles;
1622 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1623 surface->num_firstvertex = meshvertices;
1624 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1625 meshvertices += surface->num_vertices;
1626 meshtriangles += surface->num_triangles;
1628 for (j = 0;j < surface->num_triangles * 3;j++)
1629 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1630 for (j = 0;j < surface->num_vertices;j++)
1632 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1633 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1635 for (j = 0;j < loadmodel->numframes;j++)
1637 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1638 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1639 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1641 out->origin[0] = LittleShort(in->origin[0]);
1642 out->origin[1] = LittleShort(in->origin[1]);
1643 out->origin[2] = LittleShort(in->origin[2]);
1644 out->pitch = in->pitch;
1649 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1651 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1653 if (loadmodel->surfmesh.data_element3s)
1654 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1655 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1656 if (loadmodel->surfmesh.data_neighbor3i)
1657 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1658 Mod_Alias_MorphMesh_CompileFrames();
1659 Mod_Alias_CalculateBoundingBox();
1660 Mod_FreeSkinFiles(skinfiles);
1661 Mod_MakeSortedSurfaces(loadmodel);
1663 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1664 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1666 if (!loadmodel->surfmesh.isanimated)
1668 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1669 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1670 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1671 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1672 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1673 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1676 // because shaders can do somewhat unexpected things, check for unusual features now
1677 for (i = 0;i < loadmodel->num_textures;i++)
1679 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
1680 mod->DrawSky = R_Q1BSP_DrawSky;
1681 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
1682 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
1686 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1688 zymtype1header_t *pinmodel, *pheader;
1689 unsigned char *pbase;
1690 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1691 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose, f, biggestorigin, tempvec[3], modelscale;
1692 zymvertex_t *verts, *vertdata;
1696 skinfile_t *skinfiles;
1697 unsigned char *data;
1698 msurface_t *surface;
1700 pinmodel = (zymtype1header_t *)buffer;
1701 pbase = (unsigned char *)buffer;
1702 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1703 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1704 if (BigLong(pinmodel->type) != 1)
1705 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1707 loadmodel->modeldatatypestring = "ZYM";
1709 loadmodel->type = mod_alias;
1710 loadmodel->synctype = ST_RAND;
1714 pheader->type = BigLong(pinmodel->type);
1715 pheader->filesize = BigLong(pinmodel->filesize);
1716 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1717 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1718 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1719 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1720 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1721 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1722 pheader->radius = BigFloat(pinmodel->radius);
1723 pheader->numverts = BigLong(pinmodel->numverts);
1724 pheader->numtris = BigLong(pinmodel->numtris);
1725 pheader->numshaders = BigLong(pinmodel->numshaders);
1726 pheader->numbones = BigLong(pinmodel->numbones);
1727 pheader->numscenes = BigLong(pinmodel->numscenes);
1728 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1729 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1730 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1731 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1732 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1733 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1734 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1735 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1736 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1737 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1738 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1739 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1740 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1741 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1742 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1743 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1744 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1745 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1747 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1749 Con_Printf("%s has no geometry\n", loadmodel->name);
1752 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1754 Con_Printf("%s has no animations\n", loadmodel->name);
1758 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1759 loadmodel->DrawSky = NULL;
1760 loadmodel->DrawAddWaterPlanes = NULL;
1761 loadmodel->Draw = R_Q1BSP_Draw;
1762 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1763 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1764 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1765 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1766 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1767 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1768 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1769 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1770 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1771 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1772 loadmodel->PointSuperContents = NULL;
1774 loadmodel->numframes = pheader->numscenes;
1775 loadmodel->num_surfaces = pheader->numshaders;
1777 skinfiles = Mod_LoadSkinFiles();
1778 if (loadmodel->numskins < 1)
1779 loadmodel->numskins = 1;
1781 // make skinscenes for the skins (no groups)
1782 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1783 for (i = 0;i < loadmodel->numskins;i++)
1785 loadmodel->skinscenes[i].firstframe = i;
1786 loadmodel->skinscenes[i].framecount = 1;
1787 loadmodel->skinscenes[i].loop = true;
1788 loadmodel->skinscenes[i].framerate = 10;
1792 modelradius = pheader->radius;
1793 for (i = 0;i < 3;i++)
1795 loadmodel->normalmins[i] = pheader->mins[i];
1796 loadmodel->normalmaxs[i] = pheader->maxs[i];
1797 loadmodel->rotatedmins[i] = -modelradius;
1798 loadmodel->rotatedmaxs[i] = modelradius;
1800 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1801 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1802 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1803 if (loadmodel->yawmaxs[0] > modelradius)
1804 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1805 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1806 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1807 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1808 loadmodel->radius = modelradius;
1809 loadmodel->radius2 = modelradius * modelradius;
1811 // go through the lumps, swapping things
1813 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1814 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1815 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1816 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1817 for (i = 0;i < pheader->numscenes;i++)
1819 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1820 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1821 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1822 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1823 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1824 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1825 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1826 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1827 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1828 if (loadmodel->animscenes[i].framerate < 0)
1829 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1833 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1834 loadmodel->num_bones = pheader->numbones;
1835 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1836 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1837 for (i = 0;i < pheader->numbones;i++)
1839 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1840 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1841 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1842 if (loadmodel->data_bones[i].parent >= i)
1843 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1846 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1847 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1848 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1849 for (i = 0;i < pheader->numverts;i++)
1851 vertbonecounts[i] = BigLong(bonecount[i]);
1852 if (vertbonecounts[i] != 1)
1853 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1856 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1858 meshvertices = pheader->numverts;
1859 meshtriangles = pheader->numtris;
1861 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1862 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1863 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1864 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]));
1865 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1866 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1867 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1868 loadmodel->surfmesh.num_vertices = meshvertices;
1869 loadmodel->surfmesh.num_triangles = meshtriangles;
1870 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1871 if (r_enableshadowvolumes.integer)
1873 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1875 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1876 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1877 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1878 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1879 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1880 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1881 loadmodel->surfmesh.num_blends = 0;
1882 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
1883 if (loadmodel->surfmesh.num_vertices <= 65536)
1885 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1887 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
1888 loadmodel->surfmesh.data_blendweights = NULL;
1890 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1891 poses = (float *) (pheader->lump_poses.start + pbase);
1892 // figure out scale of model from root bone, for compatibility with old zmodel versions
1893 tempvec[0] = BigFloat(poses[0]);
1894 tempvec[1] = BigFloat(poses[1]);
1895 tempvec[2] = BigFloat(poses[2]);
1896 modelscale = VectorLength(tempvec);
1898 for (i = 0;i < loadmodel->num_bones * numposes * 12;i++)
1900 f = fabs(BigFloat(poses[i]));
1901 biggestorigin = max(biggestorigin, f);
1903 loadmodel->num_posescale = biggestorigin / 32767.0f;
1904 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
1905 for (i = 0;i < numposes;i++)
1907 const float *frameposes = (float *) (pheader->lump_poses.start + pbase) + 12*i*loadmodel->num_bones;
1908 for (j = 0;j < loadmodel->num_bones;j++)
1911 matrix4x4_t posematrix;
1912 for (k = 0;k < 12;k++)
1913 pose[k] = BigFloat(frameposes[j*12+k]);
1914 //if (j < loadmodel->num_bones)
1915 // 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));
1916 // scale child bones to match the root scale
1917 if (loadmodel->data_bones[j].parent >= 0)
1919 pose[3] *= modelscale;
1920 pose[7] *= modelscale;
1921 pose[11] *= modelscale;
1923 // normalize rotation matrix
1924 VectorNormalize(pose + 0);
1925 VectorNormalize(pose + 4);
1926 VectorNormalize(pose + 8);
1927 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
1928 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
1932 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1933 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1934 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1935 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1936 // (converting from weight-blending skeletal animation to
1937 // deformation-based skeletal animation)
1938 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1939 for (i = 0;i < loadmodel->num_bones;i++)
1942 for (k = 0;k < 12;k++)
1943 m[k] = BigFloat(poses[i*12+k]);
1944 if (loadmodel->data_bones[i].parent >= 0)
1945 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1947 for (k = 0;k < 12;k++)
1948 bonepose[12*i+k] = m[k];
1950 for (j = 0;j < pheader->numverts;j++)
1952 // this format really should have had a per vertexweight weight value...
1953 // but since it does not, the weighting is completely ignored and
1954 // only one weight is allowed per vertex
1955 int boneindex = BigLong(vertdata[j].bonenum);
1956 const float *m = bonepose + 12 * boneindex;
1957 float relativeorigin[3];
1958 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1959 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1960 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1961 // transform the vertex bone weight into the base mesh
1962 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1963 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1964 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1965 // store the weight as the primary weight on this vertex
1966 loadmodel->surfmesh.blends[j] = boneindex;
1969 // normals and tangents are calculated after elements are loaded
1971 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1972 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1973 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1974 for (i = 0;i < pheader->numverts;i++)
1976 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1977 // flip T coordinate for OpenGL
1978 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1981 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1982 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1983 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1985 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1986 //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)
1987 // byteswap, validate, and swap winding order of tris
1988 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1989 if (pheader->lump_render.length != count)
1990 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1991 renderlist = (int *) (pheader->lump_render.start + pbase);
1992 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1994 for (i = 0;i < loadmodel->num_surfaces;i++)
1996 int firstvertex, lastvertex;
1997 if (renderlist >= renderlistend)
1998 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1999 count = BigLong(*renderlist);renderlist++;
2000 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
2001 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2003 loadmodel->sortedmodelsurfaces[i] = i;
2004 surface = loadmodel->data_surfaces + i;
2005 surface->texture = loadmodel->data_textures + i;
2006 surface->num_firsttriangle = meshtriangles;
2007 surface->num_triangles = count;
2008 meshtriangles += surface->num_triangles;
2010 // load the elements
2011 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2012 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
2014 outelements[j*3+2] = BigLong(renderlist[0]);
2015 outelements[j*3+1] = BigLong(renderlist[1]);
2016 outelements[j*3+0] = BigLong(renderlist[2]);
2018 // validate the elements and find the used vertex range
2019 firstvertex = meshvertices;
2021 for (j = 0;j < surface->num_triangles * 3;j++)
2023 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
2024 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
2025 firstvertex = min(firstvertex, outelements[j]);
2026 lastvertex = max(lastvertex, outelements[j]);
2028 surface->num_firstvertex = firstvertex;
2029 surface->num_vertices = lastvertex + 1 - firstvertex;
2031 // since zym models do not have named sections, reuse their shader
2032 // name as the section name
2033 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
2034 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
2036 Mod_FreeSkinFiles(skinfiles);
2037 Mem_Free(vertbonecounts);
2039 Mod_MakeSortedSurfaces(loadmodel);
2041 // compute all the mesh information that was not loaded from the file
2042 if (loadmodel->surfmesh.data_element3s)
2043 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2044 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2045 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2046 Mod_BuildBaseBonePoses();
2047 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);
2048 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);
2049 if (loadmodel->surfmesh.data_neighbor3i)
2050 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2052 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2054 if (!loadmodel->surfmesh.isanimated)
2056 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2057 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2058 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2059 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2060 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2061 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2064 // because shaders can do somewhat unexpected things, check for unusual features now
2065 for (i = 0;i < loadmodel->num_textures;i++)
2067 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
2068 mod->DrawSky = R_Q1BSP_DrawSky;
2069 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
2070 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
2074 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2076 dpmheader_t *pheader;
2080 unsigned char *pbase;
2081 int i, j, k, meshvertices, meshtriangles;
2082 skinfile_t *skinfiles;
2083 unsigned char *data;
2085 float biggestorigin, tempvec[3], modelscale;
2089 pheader = (dpmheader_t *)buffer;
2090 pbase = (unsigned char *)buffer;
2091 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2092 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2093 if (BigLong(pheader->type) != 2)
2094 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2096 loadmodel->modeldatatypestring = "DPM";
2098 loadmodel->type = mod_alias;
2099 loadmodel->synctype = ST_RAND;
2102 pheader->type = BigLong(pheader->type);
2103 pheader->filesize = BigLong(pheader->filesize);
2104 pheader->mins[0] = BigFloat(pheader->mins[0]);
2105 pheader->mins[1] = BigFloat(pheader->mins[1]);
2106 pheader->mins[2] = BigFloat(pheader->mins[2]);
2107 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2108 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2109 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2110 pheader->yawradius = BigFloat(pheader->yawradius);
2111 pheader->allradius = BigFloat(pheader->allradius);
2112 pheader->num_bones = BigLong(pheader->num_bones);
2113 pheader->num_meshs = BigLong(pheader->num_meshs);
2114 pheader->num_frames = BigLong(pheader->num_frames);
2115 pheader->ofs_bones = BigLong(pheader->ofs_bones);
2116 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2117 pheader->ofs_frames = BigLong(pheader->ofs_frames);
2119 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2121 Con_Printf("%s has no geometry\n", loadmodel->name);
2124 if (pheader->num_frames < 1)
2126 Con_Printf("%s has no frames\n", loadmodel->name);
2130 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2131 loadmodel->DrawSky = NULL;
2132 loadmodel->DrawAddWaterPlanes = NULL;
2133 loadmodel->Draw = R_Q1BSP_Draw;
2134 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2135 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2136 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2137 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2138 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2139 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2140 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2141 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2142 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2143 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2144 loadmodel->PointSuperContents = NULL;
2147 for (i = 0;i < 3;i++)
2149 loadmodel->normalmins[i] = pheader->mins[i];
2150 loadmodel->normalmaxs[i] = pheader->maxs[i];
2151 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2152 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2153 loadmodel->rotatedmins[i] = -pheader->allradius;
2154 loadmodel->rotatedmaxs[i] = pheader->allradius;
2156 loadmodel->radius = pheader->allradius;
2157 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2159 // load external .skin files if present
2160 skinfiles = Mod_LoadSkinFiles();
2161 if (loadmodel->numskins < 1)
2162 loadmodel->numskins = 1;
2167 // gather combined statistics from the meshes
2168 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2169 for (i = 0;i < (int)pheader->num_meshs;i++)
2171 int numverts = BigLong(dpmmesh->num_verts);
2172 meshvertices += numverts;
2173 meshtriangles += BigLong(dpmmesh->num_tris);
2177 loadmodel->numframes = pheader->num_frames;
2178 loadmodel->num_bones = pheader->num_bones;
2179 loadmodel->num_poses = loadmodel->numframes;
2180 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2181 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2182 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2183 // do most allocations as one merged chunk
2184 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));
2185 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2186 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2187 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2188 loadmodel->surfmesh.num_vertices = meshvertices;
2189 loadmodel->surfmesh.num_triangles = meshtriangles;
2190 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2191 if (r_enableshadowvolumes.integer)
2193 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2195 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2196 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2197 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2198 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2199 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2200 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2201 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2202 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2203 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2204 loadmodel->surfmesh.num_blends = 0;
2205 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2206 if (meshvertices <= 65536)
2208 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2210 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2211 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
2213 for (i = 0;i < loadmodel->numskins;i++)
2215 loadmodel->skinscenes[i].firstframe = i;
2216 loadmodel->skinscenes[i].framecount = 1;
2217 loadmodel->skinscenes[i].loop = true;
2218 loadmodel->skinscenes[i].framerate = 10;
2221 // load the bone info
2222 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2223 for (i = 0;i < loadmodel->num_bones;i++)
2225 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2226 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2227 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2228 if (loadmodel->data_bones[i].parent >= i)
2229 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2233 frames = (dpmframe_t *) (pbase + pheader->ofs_frames);
2234 // figure out scale of model from root bone, for compatibility with old dpmodel versions
2235 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2236 tempvec[0] = BigFloat(poses[0]);
2237 tempvec[1] = BigFloat(poses[1]);
2238 tempvec[2] = BigFloat(poses[2]);
2239 modelscale = VectorLength(tempvec);
2241 for (i = 0;i < loadmodel->numframes;i++)
2243 memcpy(loadmodel->animscenes[i].name, frames[i].name, sizeof(frames[i].name));
2244 loadmodel->animscenes[i].firstframe = i;
2245 loadmodel->animscenes[i].framecount = 1;
2246 loadmodel->animscenes[i].loop = true;
2247 loadmodel->animscenes[i].framerate = 10;
2248 // load the bone poses for this frame
2249 poses = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2250 for (j = 0;j < loadmodel->num_bones*12;j++)
2252 f = fabs(BigFloat(poses[j]));
2253 biggestorigin = max(biggestorigin, f);
2255 // stuff not processed here: mins, maxs, yawradius, allradius
2257 loadmodel->num_posescale = biggestorigin / 32767.0f;
2258 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2259 for (i = 0;i < loadmodel->numframes;i++)
2261 const float *frameposes = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2262 for (j = 0;j < loadmodel->num_bones;j++)
2265 matrix4x4_t posematrix;
2266 for (k = 0;k < 12;k++)
2267 pose[k] = BigFloat(frameposes[j*12+k]);
2268 // scale child bones to match the root scale
2269 if (loadmodel->data_bones[j].parent >= 0)
2271 pose[3] *= modelscale;
2272 pose[7] *= modelscale;
2273 pose[11] *= modelscale;
2275 // normalize rotation matrix
2276 VectorNormalize(pose + 0);
2277 VectorNormalize(pose + 4);
2278 VectorNormalize(pose + 8);
2279 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2280 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
2284 // load the meshes now
2285 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2288 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2289 // (converting from weight-blending skeletal animation to
2290 // deformation-based skeletal animation)
2291 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2292 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2293 for (i = 0;i < loadmodel->num_bones;i++)
2296 for (k = 0;k < 12;k++)
2297 m[k] = BigFloat(poses[i*12+k]);
2298 if (loadmodel->data_bones[i].parent >= 0)
2299 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2301 for (k = 0;k < 12;k++)
2302 bonepose[12*i+k] = m[k];
2304 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2306 const int *inelements;
2308 const float *intexcoord;
2309 msurface_t *surface;
2311 loadmodel->sortedmodelsurfaces[i] = i;
2312 surface = loadmodel->data_surfaces + i;
2313 surface->texture = loadmodel->data_textures + i;
2314 surface->num_firsttriangle = meshtriangles;
2315 surface->num_triangles = BigLong(dpmmesh->num_tris);
2316 surface->num_firstvertex = meshvertices;
2317 surface->num_vertices = BigLong(dpmmesh->num_verts);
2318 meshvertices += surface->num_vertices;
2319 meshtriangles += surface->num_triangles;
2321 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2322 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2323 for (j = 0;j < surface->num_triangles;j++)
2325 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2326 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2327 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2328 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2333 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2334 for (j = 0;j < surface->num_vertices*2;j++)
2335 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2337 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2338 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2340 int weightindex[4] = { 0, 0, 0, 0 };
2341 float weightinfluence[4] = { 0, 0, 0, 0 };
2343 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2344 data += sizeof(dpmvertex_t);
2345 for (k = 0;k < numweights;k++)
2347 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2348 int boneindex = BigLong(vert->bonenum);
2349 const float *m = bonepose + 12 * boneindex;
2350 float influence = BigFloat(vert->influence);
2351 float relativeorigin[3], relativenormal[3];
2352 relativeorigin[0] = BigFloat(vert->origin[0]);
2353 relativeorigin[1] = BigFloat(vert->origin[1]);
2354 relativeorigin[2] = BigFloat(vert->origin[2]);
2355 relativenormal[0] = BigFloat(vert->normal[0]);
2356 relativenormal[1] = BigFloat(vert->normal[1]);
2357 relativenormal[2] = BigFloat(vert->normal[2]);
2358 // blend the vertex bone weights into the base mesh
2359 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2360 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2361 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2362 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2363 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2364 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2367 // store the first (and often only) weight
2368 weightinfluence[0] = influence;
2369 weightindex[0] = boneindex;
2373 // sort the new weight into this vertex's weight table
2374 // (which only accepts up to 4 bones per vertex)
2375 for (l = 0;l < 4;l++)
2377 if (weightinfluence[l] < influence)
2379 // move weaker influence weights out of the way first
2381 for (l2 = 3;l2 > l;l2--)
2383 weightinfluence[l2] = weightinfluence[l2-1];
2384 weightindex[l2] = weightindex[l2-1];
2386 // store the new weight
2387 weightinfluence[l] = influence;
2388 weightindex[l] = boneindex;
2393 data += sizeof(dpmbonevert_t);
2395 loadmodel->surfmesh.blends[j] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
2398 // since dpm models do not have named sections, reuse their shader name as the section name
2399 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2401 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2403 if (loadmodel->surfmesh.num_blends < meshvertices)
2404 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2406 Mod_FreeSkinFiles(skinfiles);
2407 Mod_MakeSortedSurfaces(loadmodel);
2409 // compute all the mesh information that was not loaded from the file
2410 if (loadmodel->surfmesh.data_element3s)
2411 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2412 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2413 Mod_BuildBaseBonePoses();
2414 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);
2415 if (loadmodel->surfmesh.data_neighbor3i)
2416 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2418 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2420 if (!loadmodel->surfmesh.isanimated)
2422 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2423 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2424 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2425 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2426 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2427 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2430 // because shaders can do somewhat unexpected things, check for unusual features now
2431 for (i = 0;i < loadmodel->num_textures;i++)
2433 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
2434 mod->DrawSky = R_Q1BSP_DrawSky;
2435 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
2436 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
2440 // no idea why PSK/PSA files contain weird quaternions but they do...
2441 #define PSKQUATNEGATIONS
2442 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2444 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2445 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2446 fs_offset_t filesize;
2451 pskboneinfo_t *bones;
2452 pskrawweights_t *rawweights;
2453 //pskboneinfo_t *animbones;
2454 pskaniminfo_t *anims;
2455 pskanimkeys_t *animkeys;
2456 void *animfilebuffer, *animbuffer, *animbufferend;
2457 unsigned char *data;
2459 skinfile_t *skinfiles;
2460 char animname[MAX_QPATH];
2462 float biggestorigin;
2464 pchunk = (pskchunk_t *)buffer;
2465 if (strcmp(pchunk->id, "ACTRHEAD"))
2466 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2468 loadmodel->modeldatatypestring = "PSK";
2470 loadmodel->type = mod_alias;
2471 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2472 loadmodel->DrawSky = NULL;
2473 loadmodel->DrawAddWaterPlanes = NULL;
2474 loadmodel->Draw = R_Q1BSP_Draw;
2475 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2476 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2477 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2478 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2479 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2480 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2481 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2482 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2483 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2484 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2485 loadmodel->PointSuperContents = NULL;
2486 loadmodel->synctype = ST_RAND;
2488 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2489 strlcat(animname, ".psa", sizeof(animname));
2490 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2491 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2492 if (animbuffer == NULL)
2493 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2512 while (buffer < bufferend)
2514 pchunk = (pskchunk_t *)buffer;
2515 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2516 version = LittleLong(pchunk->version);
2517 recordsize = LittleLong(pchunk->recordsize);
2518 numrecords = LittleLong(pchunk->numrecords);
2519 if (developer_extra.integer)
2520 Con_DPrintf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2521 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2522 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);
2523 if (!strcmp(pchunk->id, "ACTRHEAD"))
2527 else if (!strcmp(pchunk->id, "PNTS0000"))
2530 if (recordsize != sizeof(*p))
2531 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2532 // byteswap in place and keep the pointer
2533 numpnts = numrecords;
2534 pnts = (pskpnts_t *)buffer;
2535 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2537 p->origin[0] = LittleFloat(p->origin[0]);
2538 p->origin[1] = LittleFloat(p->origin[1]);
2539 p->origin[2] = LittleFloat(p->origin[2]);
2543 else if (!strcmp(pchunk->id, "VTXW0000"))
2546 if (recordsize != sizeof(*p))
2547 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2548 // byteswap in place and keep the pointer
2549 numvtxw = numrecords;
2550 vtxw = (pskvtxw_t *)buffer;
2551 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2553 p->pntsindex = LittleShort(p->pntsindex);
2554 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2555 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2556 if (p->pntsindex >= numpnts)
2558 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2564 else if (!strcmp(pchunk->id, "FACE0000"))
2567 if (recordsize != sizeof(*p))
2568 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2569 // byteswap in place and keep the pointer
2570 numfaces = numrecords;
2571 faces = (pskface_t *)buffer;
2572 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2574 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2575 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2576 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2577 p->group = LittleLong(p->group);
2578 if (p->vtxwindex[0] >= numvtxw)
2580 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2581 p->vtxwindex[0] = 0;
2583 if (p->vtxwindex[1] >= numvtxw)
2585 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2586 p->vtxwindex[1] = 0;
2588 if (p->vtxwindex[2] >= numvtxw)
2590 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2591 p->vtxwindex[2] = 0;
2596 else if (!strcmp(pchunk->id, "MATT0000"))
2599 if (recordsize != sizeof(*p))
2600 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2601 // byteswap in place and keep the pointer
2602 nummatts = numrecords;
2603 matts = (pskmatt_t *)buffer;
2604 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2610 else if (!strcmp(pchunk->id, "REFSKELT"))
2613 if (recordsize != sizeof(*p))
2614 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2615 // byteswap in place and keep the pointer
2616 numbones = numrecords;
2617 bones = (pskboneinfo_t *)buffer;
2618 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2620 p->numchildren = LittleLong(p->numchildren);
2621 p->parent = LittleLong(p->parent);
2622 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2623 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2624 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2625 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2626 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2627 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2628 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2629 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2630 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2631 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2632 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2633 #ifdef PSKQUATNEGATIONS
2636 p->basepose.quat[0] *= -1;
2637 p->basepose.quat[1] *= -1;
2638 p->basepose.quat[2] *= -1;
2642 p->basepose.quat[0] *= 1;
2643 p->basepose.quat[1] *= -1;
2644 p->basepose.quat[2] *= 1;
2647 if (p->parent < 0 || p->parent >= numbones)
2649 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2655 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2658 if (recordsize != sizeof(*p))
2659 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2660 // byteswap in place and keep the pointer
2661 numrawweights = numrecords;
2662 rawweights = (pskrawweights_t *)buffer;
2663 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2665 p->weight = LittleFloat(p->weight);
2666 p->pntsindex = LittleLong(p->pntsindex);
2667 p->boneindex = LittleLong(p->boneindex);
2668 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2670 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2673 if (p->boneindex < 0 || p->boneindex >= numbones)
2675 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2683 while (animbuffer < animbufferend)
2685 pchunk = (pskchunk_t *)animbuffer;
2686 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2687 version = LittleLong(pchunk->version);
2688 recordsize = LittleLong(pchunk->recordsize);
2689 numrecords = LittleLong(pchunk->numrecords);
2690 if (developer_extra.integer)
2691 Con_DPrintf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2692 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2693 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);
2694 if (!strcmp(pchunk->id, "ANIMHEAD"))
2698 else if (!strcmp(pchunk->id, "BONENAMES"))
2701 if (recordsize != sizeof(*p))
2702 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2703 // byteswap in place and keep the pointer
2704 numanimbones = numrecords;
2705 //animbones = (pskboneinfo_t *)animbuffer;
2706 // NOTE: supposedly psa does not need to match the psk model, the
2707 // bones missing from the psa would simply use their base
2708 // positions from the psk, but this is hard for me to implement
2709 // and people can easily make animations that match.
2710 if (numanimbones != numbones)
2711 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2712 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2714 p->numchildren = LittleLong(p->numchildren);
2715 p->parent = LittleLong(p->parent);
2716 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2717 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2718 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2719 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2720 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2721 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2722 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2723 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2724 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2725 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2726 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2727 #ifdef PSKQUATNEGATIONS
2730 p->basepose.quat[0] *= -1;
2731 p->basepose.quat[1] *= -1;
2732 p->basepose.quat[2] *= -1;
2736 p->basepose.quat[0] *= 1;
2737 p->basepose.quat[1] *= -1;
2738 p->basepose.quat[2] *= 1;
2741 if (p->parent < 0 || p->parent >= numanimbones)
2743 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2746 // check that bones are the same as in the base
2747 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2748 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2752 else if (!strcmp(pchunk->id, "ANIMINFO"))
2755 if (recordsize != sizeof(*p))
2756 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2757 // byteswap in place and keep the pointer
2758 numanims = numrecords;
2759 anims = (pskaniminfo_t *)animbuffer;
2760 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2762 p->numbones = LittleLong(p->numbones);
2763 p->playtime = LittleFloat(p->playtime);
2764 p->fps = LittleFloat(p->fps);
2765 p->firstframe = LittleLong(p->firstframe);
2766 p->numframes = LittleLong(p->numframes);
2767 if (p->numbones != numbones)
2768 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2772 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2775 if (recordsize != sizeof(*p))
2776 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2777 numanimkeys = numrecords;
2778 animkeys = (pskanimkeys_t *)animbuffer;
2779 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2781 p->origin[0] = LittleFloat(p->origin[0]);
2782 p->origin[1] = LittleFloat(p->origin[1]);
2783 p->origin[2] = LittleFloat(p->origin[2]);
2784 p->quat[0] = LittleFloat(p->quat[0]);
2785 p->quat[1] = LittleFloat(p->quat[1]);
2786 p->quat[2] = LittleFloat(p->quat[2]);
2787 p->quat[3] = LittleFloat(p->quat[3]);
2788 p->frametime = LittleFloat(p->frametime);
2789 #ifdef PSKQUATNEGATIONS
2790 if (index % numbones)
2805 // TODO: allocate bonepose stuff
2808 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2811 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2812 Host_Error("%s: missing required chunks", loadmodel->name);
2814 loadmodel->numframes = 0;
2815 for (index = 0;index < numanims;index++)
2816 loadmodel->numframes += anims[index].numframes;
2818 if (numanimkeys != numbones * loadmodel->numframes)
2819 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2821 meshvertices = numvtxw;
2822 meshtriangles = numfaces;
2824 // load external .skin files if present
2825 skinfiles = Mod_LoadSkinFiles();
2826 if (loadmodel->numskins < 1)
2827 loadmodel->numskins = 1;
2828 loadmodel->num_bones = numbones;
2829 loadmodel->num_poses = loadmodel->numframes;
2830 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2831 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2832 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2833 loadmodel->surfmesh.num_vertices = meshvertices;
2834 loadmodel->surfmesh.num_triangles = meshtriangles;
2835 // do most allocations as one merged chunk
2836 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);
2837 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2838 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2839 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2840 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2841 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2842 if (r_enableshadowvolumes.integer)
2844 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2846 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2847 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2848 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2849 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2850 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2851 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2852 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2853 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2854 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2855 loadmodel->surfmesh.num_blends = 0;
2856 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2857 if (loadmodel->surfmesh.num_vertices <= 65536)
2859 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2861 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2862 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(blendweights_t));
2864 for (i = 0;i < loadmodel->numskins;i++)
2866 loadmodel->skinscenes[i].firstframe = i;
2867 loadmodel->skinscenes[i].framecount = 1;
2868 loadmodel->skinscenes[i].loop = true;
2869 loadmodel->skinscenes[i].framerate = 10;
2873 for (index = 0, i = 0;index < nummatts;index++)
2875 // since psk models do not have named sections, reuse their shader name as the section name
2876 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2877 loadmodel->sortedmodelsurfaces[index] = index;
2878 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2879 loadmodel->data_surfaces[index].num_firstvertex = 0;
2880 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2883 // copy over the vertex locations and texcoords
2884 for (index = 0;index < numvtxw;index++)
2886 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2887 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2888 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2889 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2890 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2893 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2894 for (index = 0;index < numfaces;index++)
2895 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2896 for (index = 0, i = 0;index < nummatts;index++)
2898 loadmodel->data_surfaces[index].num_firsttriangle = i;
2899 i += loadmodel->data_surfaces[index].num_triangles;
2900 loadmodel->data_surfaces[index].num_triangles = 0;
2902 for (index = 0;index < numfaces;index++)
2904 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2905 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2906 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2907 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2910 // copy over the bones
2911 for (index = 0;index < numbones;index++)
2913 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2914 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2915 if (loadmodel->data_bones[index].parent >= index)
2916 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2919 // sort the psk point weights into the vertex weight tables
2920 // (which only accept up to 4 bones per vertex)
2921 for (index = 0;index < numvtxw;index++)
2923 int weightindex[4] = { 0, 0, 0, 0 };
2924 float weightinfluence[4] = { 0, 0, 0, 0 };
2926 for (j = 0;j < numrawweights;j++)
2928 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2930 int boneindex = rawweights[j].boneindex;
2931 float influence = rawweights[j].weight;
2932 for (l = 0;l < 4;l++)
2934 if (weightinfluence[l] < influence)
2936 // move lower influence weights out of the way first
2938 for (l2 = 3;l2 > l;l2--)
2940 weightinfluence[l2] = weightinfluence[l2-1];
2941 weightindex[l2] = weightindex[l2-1];
2943 // store the new weight
2944 weightinfluence[l] = influence;
2945 weightindex[l] = boneindex;
2951 loadmodel->surfmesh.blends[index] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
2953 if (loadmodel->surfmesh.num_blends < loadmodel->surfmesh.num_vertices)
2954 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2956 // set up the animscenes based on the anims
2957 for (index = 0, i = 0;index < numanims;index++)
2959 for (j = 0;j < anims[index].numframes;j++, i++)
2961 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2962 loadmodel->animscenes[i].firstframe = i;
2963 loadmodel->animscenes[i].framecount = 1;
2964 loadmodel->animscenes[i].loop = true;
2965 loadmodel->animscenes[i].framerate = anims[index].fps;
2969 // calculate the scaling value for bone origins so they can be compressed to short
2971 for (index = 0;index < numanimkeys;index++)
2973 pskanimkeys_t *k = animkeys + index;
2974 biggestorigin = max(biggestorigin, fabs(k->origin[0]));
2975 biggestorigin = max(biggestorigin, fabs(k->origin[1]));
2976 biggestorigin = max(biggestorigin, fabs(k->origin[2]));
2978 loadmodel->num_posescale = biggestorigin / 32767.0f;
2979 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2981 // load the poses from the animkeys
2982 for (index = 0;index < numanimkeys;index++)
2984 pskanimkeys_t *k = animkeys + index;
2986 Vector4Copy(k->quat, quat);
2988 Vector4Negate(quat, quat);
2989 Vector4Normalize2(quat, quat);
2990 // compress poses to the short[6] format for longterm storage
2991 loadmodel->data_poses6s[index*6+0] = k->origin[0] * loadmodel->num_poseinvscale;
2992 loadmodel->data_poses6s[index*6+1] = k->origin[1] * loadmodel->num_poseinvscale;
2993 loadmodel->data_poses6s[index*6+2] = k->origin[2] * loadmodel->num_poseinvscale;
2994 loadmodel->data_poses6s[index*6+3] = quat[0] * 32767.0f;
2995 loadmodel->data_poses6s[index*6+4] = quat[1] * 32767.0f;
2996 loadmodel->data_poses6s[index*6+5] = quat[2] * 32767.0f;
2998 Mod_FreeSkinFiles(skinfiles);
2999 Mem_Free(animfilebuffer);
3000 Mod_MakeSortedSurfaces(loadmodel);
3002 // compute all the mesh information that was not loaded from the file
3003 // TODO: honor smoothing groups somehow?
3004 if (loadmodel->surfmesh.data_element3s)
3005 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3006 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3007 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
3008 Mod_BuildBaseBonePoses();
3009 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);
3010 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);
3011 if (loadmodel->surfmesh.data_neighbor3i)
3012 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3013 Mod_Alias_CalculateBoundingBox();
3015 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
3017 if (!loadmodel->surfmesh.isanimated)
3019 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3020 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3021 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3022 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3023 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3024 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
3027 // because shaders can do somewhat unexpected things, check for unusual features now
3028 for (i = 0;i < loadmodel->num_textures;i++)
3030 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
3031 mod->DrawSky = R_Q1BSP_DrawSky;
3032 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
3033 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
3037 void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
3039 unsigned char *data;
3041 const unsigned char *pbase, *pend;
3043 skinfile_t *skinfiles;
3044 int i, j, k, meshvertices, meshtriangles;
3045 float biggestorigin;
3046 const unsigned int *inelements;
3048 const int *inneighbors;
3050 float *outvertex, *outnormal, *outtexcoord, *outsvector, *outtvector;
3051 // this pointers into the file data are read only through Little* functions so they can be unaligned memory
3052 const float *vnormal = NULL;
3053 const float *vposition = NULL;
3054 const float *vtangent = NULL;
3055 const float *vtexcoord = NULL;
3056 const unsigned char *vblendindexes = NULL;
3057 const unsigned char *vblendweights = NULL;
3058 const unsigned short *framedata = NULL;
3059 // temporary memory allocations (because the data in the file may be misaligned)
3060 iqmanim_t *anims = NULL;
3061 iqmbounds_t *bounds = NULL;
3062 iqmjoint1_t *joint1 = NULL;
3063 iqmjoint_t *joint = NULL;
3064 iqmmesh_t *meshes = NULL;
3065 iqmpose1_t *pose1 = NULL;
3066 iqmpose_t *pose = NULL;
3067 iqmvertexarray_t *vas = NULL;
3069 pbase = (unsigned char *)buffer;
3070 pend = (unsigned char *)bufferend;
3072 if (pbase + sizeof(iqmheader_t) > pend)
3073 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model %d", loadmodel->name, (int)(pend - pbase));
3075 // copy struct (otherwise it may be misaligned)
3076 // LordHavoc: okay it's definitely not misaligned here, but for consistency...
3077 memcpy(&header, pbase, sizeof(iqmheader_t));
3079 if (memcmp(header.id, "INTERQUAKEMODEL", 16))
3080 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model", loadmodel->name);
3081 if (LittleLong(header.version) != 1 && LittleLong(header.version) != 2)
3082 Host_Error ("Mod_INTERQUAKEMODEL_Load: only version 1 and 2 models are currently supported (name = %s)", loadmodel->name);
3084 loadmodel->modeldatatypestring = "IQM";
3086 loadmodel->type = mod_alias;
3087 loadmodel->synctype = ST_RAND;
3090 header.version = LittleLong(header.version);
3091 header.filesize = LittleLong(header.filesize);
3092 header.flags = LittleLong(header.flags);
3093 header.num_text = LittleLong(header.num_text);
3094 header.ofs_text = LittleLong(header.ofs_text);
3095 header.num_meshes = LittleLong(header.num_meshes);
3096 header.ofs_meshes = LittleLong(header.ofs_meshes);
3097 header.num_vertexarrays = LittleLong(header.num_vertexarrays);
3098 header.num_vertexes = LittleLong(header.num_vertexes);
3099 header.ofs_vertexarrays = LittleLong(header.ofs_vertexarrays);
3100 header.num_triangles = LittleLong(header.num_triangles);
3101 header.ofs_triangles = LittleLong(header.ofs_triangles);
3102 header.ofs_neighbors = LittleLong(header.ofs_neighbors);
3103 header.num_joints = LittleLong(header.num_joints);
3104 header.ofs_joints = LittleLong(header.ofs_joints);
3105 header.num_poses = LittleLong(header.num_poses);
3106 header.ofs_poses = LittleLong(header.ofs_poses);
3107 header.num_anims = LittleLong(header.num_anims);
3108 header.ofs_anims = LittleLong(header.ofs_anims);
3109 header.num_frames = LittleLong(header.num_frames);
3110 header.num_framechannels = LittleLong(header.num_framechannels);
3111 header.ofs_frames = LittleLong(header.ofs_frames);
3112 header.ofs_bounds = LittleLong(header.ofs_bounds);
3113 header.num_comment = LittleLong(header.num_comment);
3114 header.ofs_comment = LittleLong(header.ofs_comment);
3115 header.num_extensions = LittleLong(header.num_extensions);
3116 header.ofs_extensions = LittleLong(header.ofs_extensions);
3118 if (header.num_triangles < 1 || header.num_vertexes < 3 || header.num_vertexarrays < 1 || header.num_meshes < 1)
3120 Con_Printf("%s has no geometry\n", loadmodel->name);
3124 if (header.version == 1)
3126 if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint1_t) > pend ||
3127 pbase + header.ofs_poses + header.num_poses*sizeof(iqmpose1_t) > pend)
3129 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3135 if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint_t) > pend ||
3136 pbase + header.ofs_poses + header.num_poses*sizeof(iqmpose_t) > pend)
3138 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3142 if (pbase + header.ofs_text + header.num_text > pend ||
3143 pbase + header.ofs_meshes + header.num_meshes*sizeof(iqmmesh_t) > pend ||
3144 pbase + header.ofs_vertexarrays + header.num_vertexarrays*sizeof(iqmvertexarray_t) > pend ||
3145 pbase + header.ofs_triangles + header.num_triangles*sizeof(int[3]) > pend ||
3146 (header.ofs_neighbors && pbase + header.ofs_neighbors + header.num_triangles*sizeof(int[3]) > pend) ||
3147 pbase + header.ofs_anims + header.num_anims*sizeof(iqmanim_t) > pend ||
3148 pbase + header.ofs_frames + header.num_frames*header.num_framechannels*sizeof(unsigned short) > pend ||
3149 (header.ofs_bounds && pbase + header.ofs_bounds + header.num_frames*sizeof(iqmbounds_t) > pend) ||
3150 pbase + header.ofs_comment + header.num_comment > pend)
3152 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3156 // copy structs to make them aligned in memory (otherwise we crash on Sparc and PowerPC and others)
3157 if (header.num_vertexarrays)
3158 vas = (iqmvertexarray_t *)(pbase + header.ofs_vertexarrays);
3159 if (header.num_anims)
3160 anims = (iqmanim_t *)(pbase + header.ofs_anims);
3161 if (header.ofs_bounds)
3162 bounds = (iqmbounds_t *)(pbase + header.ofs_bounds);
3163 if (header.num_meshes)
3164 meshes = (iqmmesh_t *)(pbase + header.ofs_meshes);
3166 for (i = 0;i < (int)header.num_vertexarrays;i++)
3168 iqmvertexarray_t va;
3170 va.type = LittleLong(vas[i].type);
3171 va.flags = LittleLong(vas[i].flags);
3172 va.format = LittleLong(vas[i].format);
3173 va.size = LittleLong(vas[i].size);
3174 va.offset = LittleLong(vas[i].offset);
3175 vsize = header.num_vertexes*va.size;
3178 case IQM_FLOAT: vsize *= sizeof(float); break;
3179 case IQM_UBYTE: vsize *= sizeof(unsigned char); break;
3182 if (pbase + va.offset + vsize > pend)
3184 // no need to copy the vertex data for alignment because LittleLong/LittleShort will be invoked on reading them, and the destination is aligned
3188 if (va.format == IQM_FLOAT && va.size == 3)
3189 vposition = (const float *)(pbase + va.offset);
3192 if (va.format == IQM_FLOAT && va.size == 2)
3193 vtexcoord = (const float *)(pbase + va.offset);
3196 if (va.format == IQM_FLOAT && va.size == 3)
3197 vnormal = (const float *)(pbase + va.offset);
3200 if (va.format == IQM_FLOAT && va.size == 4)
3201 vtangent = (const float *)(pbase + va.offset);
3203 case IQM_BLENDINDEXES:
3204 if (va.format == IQM_UBYTE && va.size == 4)
3205 vblendindexes = (const unsigned char *)(pbase + va.offset);
3207 case IQM_BLENDWEIGHTS:
3208 if (va.format == IQM_UBYTE && va.size == 4)
3209 vblendweights = (const unsigned char *)(pbase + va.offset);
3213 if (header.num_vertexes > 0 && (!vposition || !vtexcoord || ((header.num_frames > 0 || header.num_anims > 0) && (!vblendindexes || !vblendweights))))
3215 Con_Printf("%s is missing vertex array data\n", loadmodel->name);
3219 text = header.num_text && header.ofs_text ? (const char *)(pbase + header.ofs_text) : "";
3221 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
3222 loadmodel->DrawSky = NULL;
3223 loadmodel->DrawAddWaterPlanes = NULL;
3224 loadmodel->Draw = R_Q1BSP_Draw;
3225 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
3226 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
3227 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
3228 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
3229 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
3230 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
3231 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
3232 loadmodel->DrawLight = R_Q1BSP_DrawLight;
3233 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
3234 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
3235 loadmodel->PointSuperContents = NULL;
3237 // load external .skin files if present
3238 skinfiles = Mod_LoadSkinFiles();
3239 if (loadmodel->numskins < 1)
3240 loadmodel->numskins = 1;
3242 loadmodel->numframes = max(header.num_anims, 1);
3243 loadmodel->num_bones = header.num_joints;
3244 loadmodel->num_poses = max(header.num_frames, 1);
3245 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = header.num_meshes;
3246 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3247 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3249 meshvertices = header.num_vertexes;
3250 meshtriangles = header.num_triangles;
3252 // do most allocations as one merged chunk
3253 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));
3254 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
3255 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
3256 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
3257 loadmodel->surfmesh.num_vertices = meshvertices;
3258 loadmodel->surfmesh.num_triangles = meshtriangles;
3259 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3260 if (r_enableshadowvolumes.integer)
3262 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3264 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
3265 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3266 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3267 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
3268 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
3269 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
3270 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
3271 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
3272 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
3273 if (vblendindexes && vblendweights)
3275 loadmodel->surfmesh.num_blends = 0;
3276 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
3278 if (meshvertices <= 65536)
3280 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
3282 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
3283 if (vblendindexes && vblendweights)
3284 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
3286 for (i = 0;i < loadmodel->numskins;i++)
3288 loadmodel->skinscenes[i].firstframe = i;
3289 loadmodel->skinscenes[i].framecount = 1;
3290 loadmodel->skinscenes[i].loop = true;
3291 loadmodel->skinscenes[i].framerate = 10;
3294 // load the bone info
3295 if (header.version == 1)
3297 iqmjoint1_t *injoint1 = (iqmjoint1_t *)(pbase + header.ofs_joints);
3298 if (loadmodel->num_bones)
3299 joint1 = (iqmjoint1_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(iqmjoint1_t));
3300 for (i = 0;i < loadmodel->num_bones;i++)
3302 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3303 joint1[i].name = LittleLong(injoint1[i].name);
3304 joint1[i].parent = LittleLong(injoint1[i].parent);
3305 for (j = 0;j < 3;j++)
3307 joint1[i].origin[j] = LittleFloat(injoint1[i].origin[j]);
3308 joint1[i].rotation[j] = LittleFloat(injoint1[i].rotation[j]);
3309 joint1[i].scale[j] = LittleFloat(injoint1[i].scale[j]);
3311 strlcpy(loadmodel->data_bones[i].name, &text[joint1[i].name], sizeof(loadmodel->data_bones[i].name));
3312 loadmodel->data_bones[i].parent = joint1[i].parent;
3313 if (loadmodel->data_bones[i].parent >= i)
3314 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3315 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]);
3316 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3317 if (loadmodel->data_bones[i].parent >= 0)
3319 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3320 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3321 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3323 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3328 iqmjoint_t *injoint = (iqmjoint_t *)(pbase + header.ofs_joints);
3329 if (header.num_joints)
3330 joint = (iqmjoint_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(iqmjoint_t));
3331 for (i = 0;i < loadmodel->num_bones;i++)
3333 matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3334 joint[i].name = LittleLong(injoint[i].name);
3335 joint[i].parent = LittleLong(injoint[i].parent);
3336 for (j = 0;j < 3;j++)
3338 joint[i].origin[j] = LittleFloat(injoint[i].origin[j]);
3339 joint[i].rotation[j] = LittleFloat(injoint[i].rotation[j]);
3340 joint[i].scale[j] = LittleFloat(injoint[i].scale[j]);
3342 joint[i].rotation[3] = LittleFloat(injoint[i].rotation[3]);
3343 strlcpy(loadmodel->data_bones[i].name, &text[joint[i].name], sizeof(loadmodel->data_bones[i].name));
3344 loadmodel->data_bones[i].parent = joint[i].parent;
3345 if (loadmodel->data_bones[i].parent >= i)
3346 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3347 if (joint[i].rotation[3] > 0)
3348 Vector4Negate(joint[i].rotation, joint[i].rotation);
3349 Vector4Normalize2(joint[i].rotation, joint[i].rotation);
3350 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]);
3351 Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3352 if (loadmodel->data_bones[i].parent >= 0)
3354 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3355 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3356 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3358 else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3362 // set up the animscenes based on the anims
3363 for (i = 0;i < (int)header.num_anims;i++)
3366 anim.name = LittleLong(anims[i].name);
3367 anim.first_frame = LittleLong(anims[i].first_frame);
3368 anim.num_frames = LittleLong(anims[i].num_frames);
3369 anim.framerate = LittleFloat(anims[i].framerate);
3370 anim.flags = LittleLong(anims[i].flags);
3371 strlcpy(loadmodel->animscenes[i].name, &text[anim.name], sizeof(loadmodel->animscenes[i].name));
3372 loadmodel->animscenes[i].firstframe = anim.first_frame;
3373 loadmodel->animscenes[i].framecount = anim.num_frames;
3374 loadmodel->animscenes[i].loop = ((anim.flags & IQM_LOOP) != 0);
3375 loadmodel->animscenes[i].framerate = anim.framerate;
3377 if (header.num_anims <= 0)
3379 strlcpy(loadmodel->animscenes[0].name, "static", sizeof(loadmodel->animscenes[0].name));
3380 loadmodel->animscenes[0].firstframe = 0;
3381 loadmodel->animscenes[0].framecount = 1;
3382 loadmodel->animscenes[0].loop = true;
3383 loadmodel->animscenes[0].framerate = 10;
3387 if (header.version == 1)
3389 iqmpose1_t *inpose1 = (iqmpose1_t *)(pbase + header.ofs_poses);
3390 if (header.num_poses)
3391 pose1 = (iqmpose1_t *)Mem_Alloc(loadmodel->mempool, header.num_poses * sizeof(iqmpose1_t));
3392 for (i = 0;i < (int)header.num_poses;i++)
3395 pose1[i].parent = LittleLong(inpose1[i].parent);
3396 pose1[i].channelmask = LittleLong(inpose1[i].channelmask);
3397 for (j = 0;j < 9;j++)
3399 pose1[i].channeloffset[j] = LittleFloat(inpose1[i].channeloffset[j]);
3400 pose1[i].channelscale[j] = LittleFloat(inpose1[i].channelscale[j]);
3402 f = fabs(pose1[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3403 f = fabs(pose1[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3404 f = fabs(pose1[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3405 f = fabs(pose1[i].channeloffset[0] + 0xFFFF*pose1[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3406 f = fabs(pose1[i].channeloffset[1] + 0xFFFF*pose1[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3407 f = fabs(pose1[i].channeloffset[2] + 0xFFFF*pose1[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3409 if (header.num_frames <= 0)
3411 for (i = 0;i < loadmodel->num_bones;i++)
3414 f = fabs(joint1[i].origin[0]); biggestorigin = max(biggestorigin, f);
3415 f = fabs(joint1[i].origin[1]); biggestorigin = max(biggestorigin, f);
3416 f = fabs(joint1[i].origin[2]); biggestorigin = max(biggestorigin, f);
3422 iqmpose_t *inpose = (iqmpose_t *)(pbase + header.ofs_poses);
3423 if (header.num_poses)
3424 pose = (iqmpose_t *)Mem_Alloc(loadmodel->mempool, header.num_poses * sizeof(iqmpose_t));
3425 for (i = 0;i < (int)header.num_poses;i++)
3428 pose[i].parent = LittleLong(inpose[i].parent);
3429 pose[i].channelmask = LittleLong(inpose[i].channelmask);
3430 for (j = 0;j < 10;j++)
3432 pose[i].channeloffset[j] = LittleFloat(inpose[i].channeloffset[j]);
3433 pose[i].channelscale[j] = LittleFloat(inpose[i].channelscale[j]);
3435 f = fabs(pose[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3436 f = fabs(pose[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3437 f = fabs(pose[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3438 f = fabs(pose[i].channeloffset[0] + 0xFFFF*pose[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3439 f = fabs(pose[i].channeloffset[1] + 0xFFFF*pose[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3440 f = fabs(pose[i].channeloffset[2] + 0xFFFF*pose[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3442 if (header.num_frames <= 0)
3444 for (i = 0;i < loadmodel->num_bones;i++)
3447 f = fabs(joint[i].origin[0]); biggestorigin = max(biggestorigin, f);
3448 f = fabs(joint[i].origin[1]); biggestorigin = max(biggestorigin, f);
3449 f = fabs(joint[i].origin[2]); biggestorigin = max(biggestorigin, f);
3453 loadmodel->num_posescale = biggestorigin / 32767.0f;
3454 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3456 // load the pose data
3457 // this unaligned memory access is safe (LittleShort reads as bytes)
3458 framedata = (const unsigned short *)(pbase + header.ofs_frames);
3459 if (header.version == 1)
3461 for (i = 0, k = 0;i < (int)header.num_frames;i++)
3463 for (j = 0;j < (int)header.num_poses;j++, k++)
3465 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));
3466 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));
3467 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));
3468 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));
3469 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));
3470 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));
3471 // skip scale data for now
3472 if(pose1[j].channelmask&64) framedata++;
3473 if(pose1[j].channelmask&128) framedata++;
3474 if(pose1[j].channelmask&256) framedata++;
3477 if (header.num_frames <= 0)
3479 for (i = 0;i < loadmodel->num_bones;i++)
3481 loadmodel->data_poses6s[i*6 + 0] = loadmodel->num_poseinvscale * joint1[i].origin[0];
3482 loadmodel->data_poses6s[i*6 + 1] = loadmodel->num_poseinvscale * joint1[i].origin[1];
3483 loadmodel->data_poses6s[i*6 + 2] = loadmodel->num_poseinvscale * joint1[i].origin[2];
3484 loadmodel->data_poses6s[i*6 + 3] = 32767.0f * joint1[i].rotation[0];
3485 loadmodel->data_poses6s[i*6 + 4] = 32767.0f * joint1[i].rotation[1];
3486 loadmodel->data_poses6s[i*6 + 5] = 32767.0f * joint1[i].rotation[2];
3492 for (i = 0, k = 0;i < (int)header.num_frames;i++)
3494 for (j = 0;j < (int)header.num_poses;j++, k++)
3497 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));
3498 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));
3499 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));
3500 rot[0] = pose[j].channeloffset[3] + (pose[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[3] : 0);
3501 rot[1] = pose[j].channeloffset[4] + (pose[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[4] : 0);
3502 rot[2] = pose[j].channeloffset[5] + (pose[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[5] : 0);
3503 rot[3] = pose[j].channeloffset[6] + (pose[j].channelmask&64 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[6] : 0);
3505 Vector4Negate(rot, rot);
3506 Vector4Normalize2(rot, rot);
3507 loadmodel->data_poses6s[k*6 + 3] = 32767.0f * rot[0];
3508 loadmodel->data_poses6s[k*6 + 4] = 32767.0f * rot[1];
3509 loadmodel->data_poses6s[k*6 + 5] = 32767.0f * rot[2];
3510 // skip scale data for now
3511 if(pose[j].channelmask&128) framedata++;
3512 if(pose[j].channelmask&256) framedata++;
3513 if(pose[j].channelmask&512) framedata++;
3516 if (header.num_frames <= 0)
3518 for (i = 0;i < loadmodel->num_bones;i++)
3520 loadmodel->data_poses6s[i*6 + 0] = loadmodel->num_poseinvscale * joint[i].origin[0];
3521 loadmodel->data_poses6s[i*6 + 1] = loadmodel->num_poseinvscale * joint[i].origin[1];
3522 loadmodel->data_poses6s[i*6 + 2] = loadmodel->num_poseinvscale * joint[i].origin[2];
3523 loadmodel->data_poses6s[i*6 + 3] = 32767.0f * joint[i].rotation[0];
3524 loadmodel->data_poses6s[i*6 + 4] = 32767.0f * joint[i].rotation[1];
3525 loadmodel->data_poses6s[i*6 + 5] = 32767.0f * joint[i].rotation[2];
3530 // load bounding box data
3531 if (header.ofs_bounds)
3533 float xyradius = 0, radius = 0;
3534 VectorClear(loadmodel->normalmins);
3535 VectorClear(loadmodel->normalmaxs);
3536 for (i = 0; i < (int)header.num_frames;i++)
3539 bound.mins[0] = LittleFloat(bounds[i].mins[0]);
3540 bound.mins[1] = LittleFloat(bounds[i].mins[1]);
3541 bound.mins[2] = LittleFloat(bounds[i].mins[2]);
3542 bound.maxs[0] = LittleFloat(bounds[i].maxs[0]);
3543 bound.maxs[1] = LittleFloat(bounds[i].maxs[1]);
3544 bound.maxs[2] = LittleFloat(bounds[i].maxs[2]);
3545 bound.xyradius = LittleFloat(bounds[i].xyradius);
3546 bound.radius = LittleFloat(bounds[i].radius);
3549 VectorCopy(bound.mins, loadmodel->normalmins);
3550 VectorCopy(bound.maxs, loadmodel->normalmaxs);
3554 if (loadmodel->normalmins[0] > bound.mins[0]) loadmodel->normalmins[0] = bound.mins[0];
3555 if (loadmodel->normalmins[1] > bound.mins[1]) loadmodel->normalmins[1] = bound.mins[1];
3556 if (loadmodel->normalmins[2] > bound.mins[2]) loadmodel->normalmins[2] = bound.mins[2];
3557 if (loadmodel->normalmaxs[0] < bound.maxs[0]) loadmodel->normalmaxs[0] = bound.maxs[0];
3558 if (loadmodel->normalmaxs[1] < bound.maxs[1]) loadmodel->normalmaxs[1] = bound.maxs[1];
3559 if (loadmodel->normalmaxs[2] < bound.maxs[2]) loadmodel->normalmaxs[2] = bound.maxs[2];
3561 if (bound.xyradius > xyradius)
3562 xyradius = bound.xyradius;
3563 if (bound.radius > radius)
3564 radius = bound.radius;
3566 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -xyradius;
3567 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = xyradius;
3568 loadmodel->yawmins[2] = loadmodel->normalmins[2];
3569 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
3570 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
3571 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
3572 loadmodel->radius = radius;
3573 loadmodel->radius2 = radius * radius;
3576 // load triangle data
3577 // this unaligned memory access is safe (LittleLong reads as bytes)
3578 inelements = (const unsigned int *)(pbase + header.ofs_triangles);
3579 outelements = loadmodel->surfmesh.data_element3i;
3580 for (i = 0;i < (int)header.num_triangles;i++)
3582 outelements[0] = LittleLong(inelements[0]);
3583 outelements[1] = LittleLong(inelements[1]);
3584 outelements[2] = LittleLong(inelements[2]);
3588 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, header.num_vertexes, __FILE__, __LINE__);
3590 if (header.ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
3592 // this unaligned memory access is safe (LittleLong reads as bytes)
3593 inneighbors = (const int *)(pbase + header.ofs_neighbors);
3594 outneighbors = loadmodel->surfmesh.data_neighbor3i;
3595 for (i = 0;i < (int)header.num_triangles;i++)
3597 outneighbors[0] = LittleLong(inneighbors[0]);
3598 outneighbors[1] = LittleLong(inneighbors[1]);
3599 outneighbors[2] = LittleLong(inneighbors[2]);
3606 // this unaligned memory access is safe (LittleFloat reads as bytes)
3607 outvertex = loadmodel->surfmesh.data_vertex3f;
3608 for (i = 0;i < (int)header.num_vertexes;i++)
3610 outvertex[0] = LittleFloat(vposition[0]);
3611 outvertex[1] = LittleFloat(vposition[1]);
3612 outvertex[2] = LittleFloat(vposition[2]);
3617 outtexcoord = loadmodel->surfmesh.data_texcoordtexture2f;
3618 // this unaligned memory access is safe (LittleFloat reads as bytes)
3619 for (i = 0;i < (int)header.num_vertexes;i++)
3621 outtexcoord[0] = LittleFloat(vtexcoord[0]);
3622 outtexcoord[1] = LittleFloat(vtexcoord[1]);
3627 // this unaligned memory access is safe (LittleFloat reads as bytes)
3630 outnormal = loadmodel->surfmesh.data_normal3f;
3631 for (i = 0;i < (int)header.num_vertexes;i++)
3633 outnormal[0] = LittleFloat(vnormal[0]);
3634 outnormal[1] = LittleFloat(vnormal[1]);
3635 outnormal[2] = LittleFloat(vnormal[2]);
3641 // this unaligned memory access is safe (LittleFloat reads as bytes)
3642 if(vnormal && vtangent)
3644 outnormal = loadmodel->surfmesh.data_normal3f;
3645 outsvector = loadmodel->surfmesh.data_svector3f;
3646 outtvector = loadmodel->surfmesh.data_tvector3f;
3647 for (i = 0;i < (int)header.num_vertexes;i++)
3649 outsvector[0] = LittleFloat(vtangent[0]);
3650 outsvector[1] = LittleFloat(vtangent[1]);
3651 outsvector[2] = LittleFloat(vtangent[2]);
3652 if(LittleFloat(vtangent[3]) < 0)
3653 CrossProduct(outsvector, outnormal, outtvector);
3655 CrossProduct(outnormal, outsvector, outtvector);
3663 // this unaligned memory access is safe (all bytes)
3664 if (vblendindexes && vblendweights)
3666 for (i = 0; i < (int)header.num_vertexes;i++)
3668 blendweights_t weights;
3669 memcpy(weights.index, vblendindexes + i*4, 4);
3670 memcpy(weights.influence, vblendweights + i*4, 4);
3671 loadmodel->surfmesh.blends[i] = Mod_Skeletal_AddBlend(loadmodel, &weights);
3676 for (i = 0;i < (int)header.num_meshes;i++)
3679 msurface_t *surface;
3681 mesh.name = LittleLong(meshes[i].name);
3682 mesh.material = LittleLong(meshes[i].material);
3683 mesh.first_vertex = LittleLong(meshes[i].first_vertex);
3684 mesh.num_vertexes = LittleLong(meshes[i].num_vertexes);
3685 mesh.first_triangle = LittleLong(meshes[i].first_triangle);
3686 mesh.num_triangles = LittleLong(meshes[i].num_triangles);
3688 loadmodel->sortedmodelsurfaces[i] = i;
3689 surface = loadmodel->data_surfaces + i;
3690 surface->texture = loadmodel->data_textures + i;
3691 surface->num_firsttriangle = mesh.first_triangle;
3692 surface->num_triangles = mesh.num_triangles;
3693 surface->num_firstvertex = mesh.first_vertex;
3694 surface->num_vertices = mesh.num_vertexes;
3696 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, &text[mesh.name], &text[mesh.material]);
3699 Mod_FreeSkinFiles(skinfiles);
3700 Mod_MakeSortedSurfaces(loadmodel);
3702 // compute all the mesh information that was not loaded from the file
3703 if (loadmodel->surfmesh.data_element3s)
3704 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3705 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3707 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);
3708 if (!vnormal || !vtangent)
3709 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);
3710 if (!header.ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
3711 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3712 if (!header.ofs_bounds)
3713 Mod_Alias_CalculateBoundingBox();
3715 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
3717 if (!loadmodel->surfmesh.isanimated)
3719 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3720 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3721 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3722 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3723 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3724 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
3727 if (joint ) Mem_Free(joint );joint = NULL;
3728 if (joint1 ) Mem_Free(joint1 );joint1 = NULL;
3729 if (pose ) Mem_Free(pose );pose = NULL;
3730 if (pose1 ) Mem_Free(pose1 );pose1 = NULL;
3732 // because shaders can do somewhat unexpected things, check for unusual features now
3733 for (i = 0;i < loadmodel->num_textures;i++)
3735 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
3736 mod->DrawSky = R_Q1BSP_DrawSky;
3737 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
3738 mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;