]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - model_alias.c
added entity caching stats in graph
[xonotic/darkplaces.git] / model_alias.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
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.
8
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.
12
13 See the GNU General Public License for more details.
14
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.
18
19 */
20
21 #include "quakedef.h"
22 #include "image.h"
23 #include "r_shadow.h"
24 #include "mod_skeletal_animatevertices_generic.h"
25 #ifdef SSE_POSSIBLE
26 #include "mod_skeletal_animatevertices_sse.h"
27 #endif
28
29 #ifdef SSE_POSSIBLE
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"};
32 #endif
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"};
40 cvar_t mod_alias_force_animated = {0, "mod_alias_force_animated", "", "if set to an non-empty string, overrides the is-animated flag of any alias models (for benchmarking)"};
41
42 float mod_md3_sin[320];
43
44 static size_t Mod_Skeletal_AnimateVertices_maxbonepose = 0;
45 static void *Mod_Skeletal_AnimateVertices_bonepose = NULL;
46 void Mod_Skeletal_FreeBuffers(void)
47 {
48         if(Mod_Skeletal_AnimateVertices_bonepose)
49                 Mem_Free(Mod_Skeletal_AnimateVertices_bonepose);
50         Mod_Skeletal_AnimateVertices_maxbonepose = 0;
51         Mod_Skeletal_AnimateVertices_bonepose = NULL;
52 }
53 void *Mod_Skeletal_AnimateVertices_AllocBuffers(size_t nbytes)
54 {
55         if(Mod_Skeletal_AnimateVertices_maxbonepose < nbytes)
56         {
57                 if(Mod_Skeletal_AnimateVertices_bonepose)
58                         Mem_Free(Mod_Skeletal_AnimateVertices_bonepose);
59                 Mod_Skeletal_AnimateVertices_bonepose = Z_Malloc(nbytes);
60                 Mod_Skeletal_AnimateVertices_maxbonepose = nbytes;
61         }
62         return Mod_Skeletal_AnimateVertices_bonepose;
63 }
64
65 static 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)
66 {
67
68         if (!model->surfmesh.num_vertices)
69                 return;
70
71         if (!model->num_bones)
72         {
73                 if (vertex3f) memcpy(vertex3f, model->surfmesh.data_vertex3f, model->surfmesh.num_vertices*sizeof(float[3]));
74                 if (normal3f) memcpy(normal3f, model->surfmesh.data_normal3f, model->surfmesh.num_vertices*sizeof(float[3]));
75                 if (svector3f) memcpy(svector3f, model->surfmesh.data_svector3f, model->surfmesh.num_vertices*sizeof(float[3]));
76                 if (tvector3f) memcpy(tvector3f, model->surfmesh.data_tvector3f, model->surfmesh.num_vertices*sizeof(float[3]));
77                 return;
78         }
79
80 #ifdef SSE_POSSIBLE
81         if(r_skeletal_use_sse_defined)
82                 if(r_skeletal_use_sse.integer)
83                 {
84                         Mod_Skeletal_AnimateVertices_SSE(model, frameblend, skeleton, vertex3f, normal3f, svector3f, tvector3f);
85                         return;
86                 }
87 #endif
88         Mod_Skeletal_AnimateVertices_Generic(model, frameblend, skeleton, vertex3f, normal3f, svector3f, tvector3f);
89 }
90
91 void Mod_AliasInit (void)
92 {
93         int i;
94         Cvar_RegisterVariable(&r_skeletal_debugbone);
95         Cvar_RegisterVariable(&r_skeletal_debugbonecomponent);
96         Cvar_RegisterVariable(&r_skeletal_debugbonevalue);
97         Cvar_RegisterVariable(&r_skeletal_debugtranslatex);
98         Cvar_RegisterVariable(&r_skeletal_debugtranslatey);
99         Cvar_RegisterVariable(&r_skeletal_debugtranslatez);
100         Cvar_RegisterVariable(&mod_alias_supporttagscale);
101         Cvar_RegisterVariable(&mod_alias_force_animated);
102         for (i = 0;i < 320;i++)
103                 mod_md3_sin[i] = sin(i * M_PI * 2.0f / 256.0);
104 #ifdef SSE_POSSIBLE
105         if(Sys_HaveSSE())
106         {
107                 Con_Printf("Skeletal animation uses SSE code path\n");
108                 r_skeletal_use_sse_defined = true;
109                 Cvar_RegisterVariable(&r_skeletal_use_sse);
110         }
111         else
112                 Con_Printf("Skeletal animation uses generic code path (SSE disabled or not detected)\n");
113 #else
114         Con_Printf("Skeletal animation uses generic code path (SSE not compiled in)\n");
115 #endif
116 }
117
118 static int Mod_Skeletal_AddBlend(dp_model_t *model, const blendweights_t *newweights)
119 {
120         int i;
121         blendweights_t *weights;
122         if(!newweights->influence[1])
123                 return newweights->index[0];
124         weights = model->surfmesh.data_blendweights;
125         for (i = 0;i < model->surfmesh.num_blends;i++, weights++)
126         {
127                 if (!memcmp(weights, newweights, sizeof(blendweights_t)))
128                         return model->num_bones + i;
129         }
130         model->surfmesh.num_blends++;
131         memcpy(weights, newweights, sizeof(blendweights_t));
132         return model->num_bones + i;
133 }
134
135 static int Mod_Skeletal_CompressBlend(dp_model_t *model, const int *newindex, const float *newinfluence)
136 {
137         int i, total;
138         float scale;
139         blendweights_t newweights;
140         if(!newinfluence[1])
141                 return newindex[0];
142         scale = 0;
143         for (i = 0;i < 4;i++)
144                 scale += newinfluence[i];
145         scale = 255.0f / scale;
146         total = 0;
147         for (i = 0;i < 4;i++)
148         {
149                 newweights.index[i] = newindex[i];
150                 newweights.influence[i] = (unsigned char)(newinfluence[i] * scale);
151                 total += newweights.influence[i];
152         }       
153         while (total > 255)
154         {
155                 for (i = 0;i < 4;i++)
156                 {
157                         if(newweights.influence[i] > 0 && total > 255) 
158                         { 
159                                 newweights.influence[i]--;
160                                 total--; 
161                         }
162                 }
163         }
164         while (total < 255)
165         {
166                 for (i = 0; i < 4;i++)
167                 {
168                         if(newweights.influence[i] < 255 && total < 255) 
169                         { 
170                                 newweights.influence[i]++; 
171                                 total++; 
172                         }
173                 }
174         }
175         return Mod_Skeletal_AddBlend(model, &newweights);
176 }
177
178 static 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 {
180         // vertex morph
181         int i, numblends, blendnum;
182         int numverts = model->surfmesh.num_vertices;
183         numblends = 0;
184         for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
185         {
186                 //VectorMA(translate, model->surfmesh.num_morphmdlframetranslate, frameblend[blendnum].lerp, translate);
187                 if (frameblend[blendnum].lerp > 0)
188                         numblends = blendnum + 1;
189         }
190         // special case for the first blend because it avoids some adds and the need to memset the arrays first
191         for (blendnum = 0;blendnum < numblends;blendnum++)
192         {
193                 const md3vertex_t *verts = model->surfmesh.data_morphmd3vertex + numverts * frameblend[blendnum].subframe;
194                 if (vertex3f)
195                 {
196                         float scale = frameblend[blendnum].lerp * (1.0f / 64.0f);
197                         if (blendnum == 0)
198                         {
199                                 for (i = 0;i < numverts;i++)
200                                 {
201                                         vertex3f[i * 3 + 0] = verts[i].origin[0] * scale;
202                                         vertex3f[i * 3 + 1] = verts[i].origin[1] * scale;
203                                         vertex3f[i * 3 + 2] = verts[i].origin[2] * scale;
204                                 }
205                         }
206                         else
207                         {
208                                 for (i = 0;i < numverts;i++)
209                                 {
210                                         vertex3f[i * 3 + 0] += verts[i].origin[0] * scale;
211                                         vertex3f[i * 3 + 1] += verts[i].origin[1] * scale;
212                                         vertex3f[i * 3 + 2] += verts[i].origin[2] * scale;
213                                 }
214                         }
215                 }
216                 // the yaw and pitch stored in md3 models are 8bit quantized angles
217                 // (0-255), and as such a lookup table is very well suited to
218                 // decoding them, and since cosine is equivalent to sine with an
219                 // extra 45 degree rotation, this uses one lookup table for both
220                 // sine and cosine with a +64 bias to get cosine.
221                 if (normal3f)
222                 {
223                         float lerp = frameblend[blendnum].lerp;
224                         if (blendnum == 0)
225                         {
226                                 for (i = 0;i < numverts;i++)
227                                 {
228                                         normal3f[i * 3 + 0] = mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch     ] * lerp;
229                                         normal3f[i * 3 + 1] = mod_md3_sin[verts[i].yaw     ] * mod_md3_sin[verts[i].pitch     ] * lerp;
230                                         normal3f[i * 3 + 2] =                                  mod_md3_sin[verts[i].pitch + 64] * lerp;
231                                 }
232                         }
233                         else
234                         {
235                                 for (i = 0;i < numverts;i++)
236                                 {
237                                         normal3f[i * 3 + 0] += mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch     ] * lerp;
238                                         normal3f[i * 3 + 1] += mod_md3_sin[verts[i].yaw     ] * mod_md3_sin[verts[i].pitch     ] * lerp;
239                                         normal3f[i * 3 + 2] +=                                  mod_md3_sin[verts[i].pitch + 64] * lerp;
240                                 }
241                         }
242                 }
243                 if (svector3f)
244                 {
245                         const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
246                         float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
247                         if (blendnum == 0)
248                         {
249                                 for (i = 0;i < numverts;i++, texvecvert++)
250                                 {
251                                         VectorScale(texvecvert->svec, f, svector3f + i*3);
252                                         VectorScale(texvecvert->tvec, f, tvector3f + i*3);
253                                 }
254                         }
255                         else
256                         {
257                                 for (i = 0;i < numverts;i++, texvecvert++)
258                                 {
259                                         VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
260                                         VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
261                                 }
262                         }
263                 }
264         }
265 }
266 static 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 {
268         // vertex morph
269         int i, numblends, blendnum;
270         int numverts = model->surfmesh.num_vertices;
271         float translate[3];
272         VectorClear(translate);
273         numblends = 0;
274         // blend the frame translates to avoid redundantly doing so on each vertex
275         // (a bit of a brain twister but it works)
276         for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
277         {
278                 if (model->surfmesh.data_morphmd2framesize6f)
279                         VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6 + 3, translate);
280                 else
281                         VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.num_morphmdlframetranslate, translate);
282                 if (frameblend[blendnum].lerp > 0)
283                         numblends = blendnum + 1;
284         }
285         // special case for the first blend because it avoids some adds and the need to memset the arrays first
286         for (blendnum = 0;blendnum < numblends;blendnum++)
287         {
288                 const trivertx_t *verts = model->surfmesh.data_morphmdlvertex + numverts * frameblend[blendnum].subframe;
289                 if (vertex3f)
290                 {
291                         float scale[3];
292                         if (model->surfmesh.data_morphmd2framesize6f)
293                                 VectorScale(model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6, frameblend[blendnum].lerp, scale);
294                         else
295                                 VectorScale(model->surfmesh.num_morphmdlframescale, frameblend[blendnum].lerp, scale);
296                         if (blendnum == 0)
297                         {
298                                 for (i = 0;i < numverts;i++)
299                                 {
300                                         vertex3f[i * 3 + 0] = translate[0] + verts[i].v[0] * scale[0];
301                                         vertex3f[i * 3 + 1] = translate[1] + verts[i].v[1] * scale[1];
302                                         vertex3f[i * 3 + 2] = translate[2] + verts[i].v[2] * scale[2];
303                                 }
304                         }
305                         else
306                         {
307                                 for (i = 0;i < numverts;i++)
308                                 {
309                                         vertex3f[i * 3 + 0] += verts[i].v[0] * scale[0];
310                                         vertex3f[i * 3 + 1] += verts[i].v[1] * scale[1];
311                                         vertex3f[i * 3 + 2] += verts[i].v[2] * scale[2];
312                                 }
313                         }
314                 }
315                 // the vertex normals in mdl models are an index into a table of
316                 // 162 unique values, this very crude quantization reduces the
317                 // vertex normal to only one byte, which saves a lot of space but
318                 // also makes lighting pretty coarse
319                 if (normal3f)
320                 {
321                         float lerp = frameblend[blendnum].lerp;
322                         if (blendnum == 0)
323                         {
324                                 for (i = 0;i < numverts;i++)
325                                 {
326                                         const float *vn = m_bytenormals[verts[i].lightnormalindex];
327                                         VectorScale(vn, lerp, normal3f + i*3);
328                                 }
329                         }
330                         else
331                         {
332                                 for (i = 0;i < numverts;i++)
333                                 {
334                                         const float *vn = m_bytenormals[verts[i].lightnormalindex];
335                                         VectorMA(normal3f + i*3, lerp, vn, normal3f + i*3);
336                                 }
337                         }
338                 }
339                 if (svector3f)
340                 {
341                         const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
342                         float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
343                         if (blendnum == 0)
344                         {
345                                 for (i = 0;i < numverts;i++, texvecvert++)
346                                 {
347                                         VectorScale(texvecvert->svec, f, svector3f + i*3);
348                                         VectorScale(texvecvert->tvec, f, tvector3f + i*3);
349                                 }
350                         }
351                         else
352                         {
353                                 for (i = 0;i < numverts;i++, texvecvert++)
354                                 {
355                                         VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
356                                         VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
357                                 }
358                         }
359                 }
360         }
361 }
362
363 int Mod_Alias_GetTagMatrix(const dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, int tagindex, matrix4x4_t *outmatrix)
364 {
365         matrix4x4_t temp;
366         matrix4x4_t parentbonematrix;
367         matrix4x4_t tempbonematrix;
368         matrix4x4_t bonematrix;
369         matrix4x4_t blendmatrix;
370         int blendindex;
371         int parenttagindex;
372         int k;
373         float lerp;
374         const float *input;
375         float blendtag[12];
376         *outmatrix = identitymatrix;
377         if (skeleton && skeleton->relativetransforms)
378         {
379                 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
380                         return 4;
381                 *outmatrix = skeleton->relativetransforms[tagindex];
382                 while ((tagindex = model->data_bones[tagindex].parent) >= 0)
383                 {
384                         temp = *outmatrix;
385                         Matrix4x4_Concat(outmatrix, &skeleton->relativetransforms[tagindex], &temp);
386                 }
387         }
388         else if (model->num_bones)
389         {
390                 if (tagindex < 0 || tagindex >= model->num_bones)
391                         return 4;
392                 Matrix4x4_Clear(&blendmatrix);
393                 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
394                 {
395                         lerp = frameblend[blendindex].lerp;
396                         Matrix4x4_FromBonePose7s(&bonematrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
397                         parenttagindex = tagindex;
398                         while ((parenttagindex = model->data_bones[parenttagindex].parent) >= 0)
399                         {
400                                 Matrix4x4_FromBonePose7s(&parentbonematrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + parenttagindex));
401                                 tempbonematrix = bonematrix;
402                                 Matrix4x4_Concat(&bonematrix, &parentbonematrix, &tempbonematrix);
403                         }
404                         Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
405                 }
406                 *outmatrix = blendmatrix;
407         }
408         else if (model->num_tags)
409         {
410                 if (tagindex < 0 || tagindex >= model->num_tags)
411                         return 4;
412                 for (k = 0;k < 12;k++)
413                         blendtag[k] = 0;
414                 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
415                 {
416                         lerp = frameblend[blendindex].lerp;
417                         input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
418                         for (k = 0;k < 12;k++)
419                                 blendtag[k] += input[k] * lerp;
420                 }
421                 Matrix4x4_FromArray12FloatGL(outmatrix, blendtag);
422         }
423
424         if(!mod_alias_supporttagscale.integer)
425                 Matrix4x4_Normalize3(outmatrix, outmatrix);
426
427         return 0;
428 }
429
430 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)
431 {
432         int blendindex;
433         int k;
434         float lerp;
435         matrix4x4_t bonematrix;
436         matrix4x4_t blendmatrix;
437         const float *input;
438         float blendtag[12];
439
440         if (skeleton && skeleton->relativetransforms)
441         {
442                 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
443                         return 1;
444                 *parentindex = skeleton->model->data_bones[tagindex].parent;
445                 *tagname = skeleton->model->data_bones[tagindex].name;
446                 *tag_localmatrix = skeleton->relativetransforms[tagindex];
447                 return 0;
448         }
449         else if (model->num_bones)
450         {
451                 if (tagindex < 0 || tagindex >= model->num_bones)
452                         return 1;
453                 *parentindex = model->data_bones[tagindex].parent;
454                 *tagname = model->data_bones[tagindex].name;
455                 Matrix4x4_Clear(&blendmatrix);
456                 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
457                 {
458                         lerp = frameblend[blendindex].lerp;
459                         Matrix4x4_FromBonePose7s(&bonematrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
460                         Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
461                 }
462                 *tag_localmatrix = blendmatrix;
463                 return 0;
464         }
465         else if (model->num_tags)
466         {
467                 if (tagindex < 0 || tagindex >= model->num_tags)
468                         return 1;
469                 *parentindex = -1;
470                 *tagname = model->data_tags[tagindex].name;
471                 for (k = 0;k < 12;k++)
472                         blendtag[k] = 0;
473                 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
474                 {
475                         lerp = frameblend[blendindex].lerp;
476                         input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
477                         for (k = 0;k < 12;k++)
478                                 blendtag[k] += input[k] * lerp;
479                 }
480                 Matrix4x4_FromArray12FloatGL(tag_localmatrix, blendtag);
481                 return 0;
482         }
483
484         return 2;
485 }
486
487 int Mod_Alias_GetTagIndexForName(const dp_model_t *model, unsigned int skin, const char *tagname)
488 {
489         int i;
490         if(skin >= (unsigned int)model->numskins)
491                 skin = 0;
492         if (model->num_bones)
493                 for (i = 0;i < model->num_bones;i++)
494                         if (!strcasecmp(tagname, model->data_bones[i].name))
495                                 return i + 1;
496         if (model->num_tags)
497                 for (i = 0;i < model->num_tags;i++)
498                         if (!strcasecmp(tagname, model->data_tags[i].name))
499                                 return i + 1;
500         return 0;
501 }
502
503 static void Mod_BuildBaseBonePoses(void)
504 {
505         int boneindex;
506         matrix4x4_t *basebonepose;
507         float *outinvmatrix = loadmodel->data_baseboneposeinverse;
508         matrix4x4_t bonematrix;
509         matrix4x4_t tempbonematrix;
510         if (!loadmodel->num_bones)
511                 return;
512         basebonepose = (matrix4x4_t *)Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(matrix4x4_t));
513         for (boneindex = 0;boneindex < loadmodel->num_bones;boneindex++)
514         {
515                 Matrix4x4_FromBonePose7s(&bonematrix, loadmodel->num_posescale, loadmodel->data_poses7s + 7 * boneindex);
516                 if (loadmodel->data_bones[boneindex].parent >= 0)
517                 {
518                         tempbonematrix = bonematrix;
519                         Matrix4x4_Concat(&bonematrix, basebonepose + loadmodel->data_bones[boneindex].parent, &tempbonematrix);
520                 }
521                 basebonepose[boneindex] = bonematrix;
522                 Matrix4x4_Invert_Simple(&tempbonematrix, basebonepose + boneindex);
523                 Matrix4x4_ToArray12FloatD3D(&tempbonematrix, outinvmatrix + 12*boneindex);
524         }
525         Mem_Free(basebonepose);
526 }
527
528 static qboolean Mod_Alias_CalculateBoundingBox(void)
529 {
530         int vnum;
531         qboolean firstvertex = true;
532         float dist, yawradius, radius;
533         float *v;
534         qboolean isanimated = false;
535         VectorClear(loadmodel->normalmins);
536         VectorClear(loadmodel->normalmaxs);
537         yawradius = 0;
538         radius = 0;
539         if (loadmodel->AnimateVertices)
540         {
541                 float *vertex3f, *refvertex3f;
542                 frameblend_t frameblend[MAX_FRAMEBLENDS];
543                 memset(frameblend, 0, sizeof(frameblend));
544                 frameblend[0].lerp = 1;
545                 vertex3f = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]) * 2);
546                 refvertex3f = NULL;
547                 for (frameblend[0].subframe = 0;frameblend[0].subframe < loadmodel->num_poses;frameblend[0].subframe++)
548                 {
549                         loadmodel->AnimateVertices(loadmodel, frameblend, NULL, vertex3f, NULL, NULL, NULL);
550                         if (!refvertex3f)
551                         {
552                                 // make a copy of the first frame for comparing all others
553                                 refvertex3f = vertex3f + loadmodel->surfmesh.num_vertices * 3;
554                                 memcpy(refvertex3f, vertex3f, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
555                         }
556                         else
557                         {
558                                 if (!isanimated && memcmp(refvertex3f, vertex3f, loadmodel->surfmesh.num_vertices * sizeof(float[3])))
559                                         isanimated = true;
560                         }
561                         for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
562                         {
563                                 if (firstvertex)
564                                 {
565                                         firstvertex = false;
566                                         VectorCopy(v, loadmodel->normalmins);
567                                         VectorCopy(v, loadmodel->normalmaxs);
568                                 }
569                                 else
570                                 {
571                                         if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
572                                         if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
573                                         if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
574                                         if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
575                                         if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
576                                         if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
577                                 }
578                                 dist = v[0] * v[0] + v[1] * v[1];
579                                 if (yawradius < dist)
580                                         yawradius = dist;
581                                 dist += v[2] * v[2];
582                                 if (radius < dist)
583                                         radius = dist;
584                         }
585                 }
586                 if (vertex3f)
587                         Mem_Free(vertex3f);
588         }
589         else
590         {
591                 for (vnum = 0, v = loadmodel->surfmesh.data_vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
592                 {
593                         if (firstvertex)
594                         {
595                                 firstvertex = false;
596                                 VectorCopy(v, loadmodel->normalmins);
597                                 VectorCopy(v, loadmodel->normalmaxs);
598                         }
599                         else
600                         {
601                                 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
602                                 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
603                                 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
604                                 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
605                                 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
606                                 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
607                         }
608                         dist = v[0] * v[0] + v[1] * v[1];
609                         if (yawradius < dist)
610                                 yawradius = dist;
611                         dist += v[2] * v[2];
612                         if (radius < dist)
613                                 radius = dist;
614                 }
615         }
616         radius = sqrt(radius);
617         yawradius = sqrt(yawradius);
618         loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
619         loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
620         loadmodel->yawmins[2] = loadmodel->normalmins[2];
621         loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
622         loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
623         loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
624         loadmodel->radius = radius;
625         loadmodel->radius2 = radius * radius;
626         return isanimated;
627 }
628
629 static void Mod_Alias_MorphMesh_CompileFrames(void)
630 {
631         int i, j;
632         frameblend_t frameblend[MAX_FRAMEBLENDS];
633         unsigned char *datapointer;
634         memset(frameblend, 0, sizeof(frameblend));
635         frameblend[0].lerp = 1;
636         datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
637         loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
638         loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
639         loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
640         loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
641         loadmodel->surfmesh.data_morphtexvecvertex = (texvecvertex_t *)datapointer;datapointer += loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices * sizeof(texvecvertex_t);
642         // 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)
643         for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
644         {
645                 frameblend[0].subframe = i;
646                 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
647                 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);
648                 // encode the svector and tvector in 3 byte format for permanent storage
649                 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
650                 {
651                         VectorScaleCast(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
652                         VectorScaleCast(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
653                 }
654         }
655 }
656
657 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)
658 {
659         int i;
660         float segmentmins[3], segmentmaxs[3];
661         msurface_t *surface;
662         float vertex3fbuf[1024*3];
663         float *vertex3f = vertex3fbuf;
664         memset(trace, 0, sizeof(*trace));
665         trace->fraction = 1;
666         trace->realfraction = 1;
667         trace->hitsupercontentsmask = hitsupercontentsmask;
668         if (model->surfmesh.num_vertices > 1024)
669                 vertex3f = (float *)Mem_Alloc(tempmempool, model->surfmesh.num_vertices * sizeof(float[3]));
670         segmentmins[0] = min(start[0], end[0]) - 1;
671         segmentmins[1] = min(start[1], end[1]) - 1;
672         segmentmins[2] = min(start[2], end[2]) - 1;
673         segmentmaxs[0] = max(start[0], end[0]) + 1;
674         segmentmaxs[1] = max(start[1], end[1]) + 1;
675         segmentmaxs[2] = max(start[2], end[2]) + 1;
676         model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
677         for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
678                 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);
679         if (vertex3f != vertex3fbuf)
680                 Mem_Free(vertex3f);
681 }
682
683 static void Mod_MDLMD2MD3_TraceBox(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask)
684 {
685         int i;
686         vec3_t shiftstart, shiftend;
687         float segmentmins[3], segmentmaxs[3];
688         msurface_t *surface;
689         float vertex3fbuf[1024*3];
690         float *vertex3f = vertex3fbuf;
691         colboxbrushf_t thisbrush_start, thisbrush_end;
692         vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
693
694         if (VectorCompare(boxmins, boxmaxs))
695         {
696                 VectorAdd(start, boxmins, shiftstart);
697                 VectorAdd(end, boxmins, shiftend);
698                 Mod_MDLMD2MD3_TraceLine(model, frameblend, skeleton, trace, shiftstart, shiftend, hitsupercontentsmask);
699                 VectorSubtract(trace->endpos, boxmins, trace->endpos);
700                 return;
701         }
702
703         // box trace, performed as brush trace
704         memset(trace, 0, sizeof(*trace));
705         trace->fraction = 1;
706         trace->realfraction = 1;
707         trace->hitsupercontentsmask = hitsupercontentsmask;
708         if (model->surfmesh.num_vertices > 1024)
709                 vertex3f = (float *)Mem_Alloc(tempmempool, model->surfmesh.num_vertices * sizeof(float[3]));
710         segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
711         segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
712         segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
713         segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
714         segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
715         segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
716         VectorAdd(start, boxmins, boxstartmins);
717         VectorAdd(start, boxmaxs, boxstartmaxs);
718         VectorAdd(end, boxmins, boxendmins);
719         VectorAdd(end, boxmaxs, boxendmaxs);
720         Collision_BrushForBox(&thisbrush_start, boxstartmins, boxstartmaxs, 0, 0, NULL);
721         Collision_BrushForBox(&thisbrush_end, boxendmins, boxendmaxs, 0, 0, NULL);
722         model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
723         for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
724                 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);
725         if (vertex3f != vertex3fbuf)
726                 Mem_Free(vertex3f);
727 }
728
729 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
730 {
731         int i, j;
732         for (i = 0;i < inverts;i++)
733         {
734                 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
735                         continue;
736                 j = vertremap[i]; // not onseam
737                 if (j >= 0)
738                         out[j] = v[i];
739                 j = vertremap[i+inverts]; // onseam
740                 if (j >= 0)
741                         out[j] = v[i];
742         }
743 }
744
745 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
746 {
747         int i, f, pose, groupframes;
748         float interval;
749         daliasframetype_t *pframetype;
750         daliasframe_t *pinframe;
751         daliasgroup_t *group;
752         daliasinterval_t *intervals;
753         animscene_t *scene;
754         pose = 0;
755         scene = loadmodel->animscenes;
756         for (f = 0;f < loadmodel->numframes;f++)
757         {
758                 pframetype = (daliasframetype_t *)datapointer;
759                 datapointer += sizeof(daliasframetype_t);
760                 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
761                 {
762                         // a single frame is still treated as a group
763                         interval = 0.1f;
764                         groupframes = 1;
765                 }
766                 else
767                 {
768                         // read group header
769                         group = (daliasgroup_t *)datapointer;
770                         datapointer += sizeof(daliasgroup_t);
771                         groupframes = LittleLong (group->numframes);
772
773                         // intervals (time per frame)
774                         intervals = (daliasinterval_t *)datapointer;
775                         datapointer += sizeof(daliasinterval_t) * groupframes;
776
777                         interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
778                         if (interval < 0.01f)
779                         {
780                                 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
781                                 interval = 0.1f;
782                         }
783                 }
784
785                 // get scene name from first frame
786                 pinframe = (daliasframe_t *)datapointer;
787
788                 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
789                 scene->firstframe = pose;
790                 scene->framecount = groupframes;
791                 scene->framerate = 1.0f / interval;
792                 scene->loop = true;
793                 scene++;
794
795                 // read frames
796                 for (i = 0;i < groupframes;i++)
797                 {
798                         datapointer += sizeof(daliasframe_t);
799                         Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
800                         datapointer += sizeof(trivertx_t) * inverts;
801                         pose++;
802                 }
803         }
804 }
805
806 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
807 {
808         if (cls.state == ca_dedicated)
809                 return;
810         // hack
811         if (!skinframe)
812                 skinframe = R_SkinFrame_LoadMissing();
813         memset(texture, 0, sizeof(*texture));
814         texture->currentframe = texture;
815         //texture->animated = false;
816         texture->numskinframes = 1;
817         texture->skinframerate = 1;
818         texture->skinframes[0] = skinframe;
819         texture->currentskinframe = skinframe;
820         //texture->backgroundnumskinframes = 0;
821         //texture->customblendfunc[0] = 0;
822         //texture->customblendfunc[1] = 0;
823         //texture->surfaceflags = 0;
824         //texture->supercontents = 0;
825         //texture->surfaceparms = 0;
826         //texture->textureflags = 0;
827
828         texture->basematerialflags = MATERIALFLAG_WALL;
829         if (texture->currentskinframe->hasalpha)
830                 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
831         texture->currentmaterialflags = texture->basematerialflags;
832         texture->offsetmapping = OFFSETMAPPING_DEFAULT;
833         texture->offsetscale = 1;
834         texture->offsetbias = 0;
835         texture->specularscalemod = 1;
836         texture->specularpowermod = 1;
837         texture->surfaceflags = 0;
838         texture->supercontents = SUPERCONTENTS_SOLID;
839         if (!(texture->basematerialflags & MATERIALFLAG_BLENDED))
840                 texture->supercontents |= SUPERCONTENTS_OPAQUE;
841         texture->transparentsort = TRANSPARENTSORT_DISTANCE;
842         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
843         // JUST GREP FOR "specularscalemod = 1".
844 }
845
846 void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
847 {
848         int i;
849         char stripbuf[MAX_QPATH];
850         skinfileitem_t *skinfileitem;
851         if(developer_extra.integer)
852                 Con_DPrintf("Looking up texture for %s (default: %s)\n", meshname, shadername);
853         if (skinfile)
854         {
855                 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
856                 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
857                 {
858                         memset(skin, 0, sizeof(*skin));
859                         // see if a mesh
860                         for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
861                         {
862                                 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
863                                 if (!strcmp(skinfileitem->name, meshname))
864                                 {
865                                         Image_StripImageExtension(skinfileitem->replacement, stripbuf, sizeof(stripbuf));
866                                         if(developer_extra.integer)
867                                                 Con_DPrintf("--> got %s from skin file\n", stripbuf);
868                                         Mod_LoadTextureFromQ3Shader(skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
869                                         break;
870                                 }
871                         }
872                         if (!skinfileitem)
873                         {
874                                 // don't render unmentioned meshes
875                                 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
876                                 if(developer_extra.integer)
877                                         Con_DPrintf("--> skipping\n");
878                                 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
879                         }
880                 }
881         }
882         else
883         {
884                 if(developer_extra.integer)
885                         Con_DPrintf("--> using default\n");
886                 Image_StripImageExtension(shadername, stripbuf, sizeof(stripbuf));
887                 Mod_LoadTextureFromQ3Shader(skin, stripbuf, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
888         }
889 }
890
891 #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);
892 #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);
893 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
894 {
895         int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
896         float scales, scalet, interval;
897         msurface_t *surface;
898         unsigned char *data;
899         mdl_t *pinmodel;
900         stvert_t *pinstverts;
901         dtriangle_t *pintriangles;
902         daliasskintype_t *pinskintype;
903         daliasskingroup_t *pinskingroup;
904         daliasskininterval_t *pinskinintervals;
905         daliasframetype_t *pinframetype;
906         daliasgroup_t *pinframegroup;
907         unsigned char *datapointer, *startframes, *startskins;
908         char name[MAX_QPATH];
909         skinframe_t *tempskinframe;
910         animscene_t *tempskinscenes;
911         texture_t *tempaliasskins;
912         float *vertst;
913         int *vertonseam, *vertremap;
914         skinfile_t *skinfiles;
915         char vabuf[1024];
916
917         datapointer = (unsigned char *)buffer;
918         pinmodel = (mdl_t *)datapointer;
919         datapointer += sizeof(mdl_t);
920
921         version = LittleLong (pinmodel->version);
922         if (version != ALIAS_VERSION)
923                 Host_Error ("%s has wrong version number (%i should be %i)",
924                                  loadmodel->name, version, ALIAS_VERSION);
925
926         loadmodel->modeldatatypestring = "MDL";
927
928         loadmodel->type = mod_alias;
929         loadmodel->DrawSky = NULL;
930         loadmodel->DrawAddWaterPlanes = NULL;
931         loadmodel->Draw = R_Q1BSP_Draw;
932         loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
933         loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
934         loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
935         loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
936         loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
937         loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
938         loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
939         loadmodel->DrawLight = R_Q1BSP_DrawLight;
940         loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
941         loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
942         // FIXME add TraceBrush!
943         loadmodel->PointSuperContents = NULL;
944         loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
945
946         loadmodel->num_surfaces = 1;
947         loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
948         data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
949         loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
950         loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
951         loadmodel->sortedmodelsurfaces[0] = 0;
952
953         loadmodel->numskins = LittleLong(pinmodel->numskins);
954         BOUNDI(loadmodel->numskins,0,65536);
955         skinwidth = LittleLong (pinmodel->skinwidth);
956         BOUNDI(skinwidth,0,65536);
957         skinheight = LittleLong (pinmodel->skinheight);
958         BOUNDI(skinheight,0,65536);
959         numverts = LittleLong(pinmodel->numverts);
960         BOUNDI(numverts,0,65536);
961         loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
962         BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
963         loadmodel->numframes = LittleLong(pinmodel->numframes);
964         BOUNDI(loadmodel->numframes,0,65536);
965         loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
966         BOUNDI((int)loadmodel->synctype,0,2);
967         // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
968         i = LittleLong (pinmodel->flags);
969         loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
970
971         for (i = 0;i < 3;i++)
972         {
973                 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
974                 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
975         }
976
977         startskins = datapointer;
978         totalskins = 0;
979         for (i = 0;i < loadmodel->numskins;i++)
980         {
981                 pinskintype = (daliasskintype_t *)datapointer;
982                 datapointer += sizeof(daliasskintype_t);
983                 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
984                         groupskins = 1;
985                 else
986                 {
987                         pinskingroup = (daliasskingroup_t *)datapointer;
988                         datapointer += sizeof(daliasskingroup_t);
989                         groupskins = LittleLong(pinskingroup->numskins);
990                         datapointer += sizeof(daliasskininterval_t) * groupskins;
991                 }
992
993                 for (j = 0;j < groupskins;j++)
994                 {
995                         datapointer += skinwidth * skinheight;
996                         totalskins++;
997                 }
998         }
999
1000         pinstverts = (stvert_t *)datapointer;
1001         datapointer += sizeof(stvert_t) * numverts;
1002
1003         pintriangles = (dtriangle_t *)datapointer;
1004         datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
1005
1006         startframes = datapointer;
1007         loadmodel->surfmesh.num_morphframes = 0;
1008         for (i = 0;i < loadmodel->numframes;i++)
1009         {
1010                 pinframetype = (daliasframetype_t *)datapointer;
1011                 datapointer += sizeof(daliasframetype_t);
1012                 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
1013                         groupframes = 1;
1014                 else
1015                 {
1016                         pinframegroup = (daliasgroup_t *)datapointer;
1017                         datapointer += sizeof(daliasgroup_t);
1018                         groupframes = LittleLong(pinframegroup->numframes);
1019                         datapointer += sizeof(daliasinterval_t) * groupframes;
1020                 }
1021
1022                 for (j = 0;j < groupframes;j++)
1023                 {
1024                         datapointer += sizeof(daliasframe_t);
1025                         datapointer += sizeof(trivertx_t) * numverts;
1026                         loadmodel->surfmesh.num_morphframes++;
1027                 }
1028         }
1029         loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1030
1031         // store texture coordinates into temporary array, they will be stored
1032         // after usage is determined (triangle data)
1033         vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
1034         vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
1035         vertonseam = vertremap + numverts * 2;
1036
1037         scales = 1.0 / skinwidth;
1038         scalet = 1.0 / skinheight;
1039         for (i = 0;i < numverts;i++)
1040         {
1041                 vertonseam[i] = LittleLong(pinstverts[i].onseam);
1042                 vertst[i*2+0] = LittleLong(pinstverts[i].s) * scales;
1043                 vertst[i*2+1] = LittleLong(pinstverts[i].t) * scalet;
1044                 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
1045                 vertst[(i+numverts)*2+1] = vertst[i*2+1];
1046         }
1047
1048 // load triangle data
1049         loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1050
1051         // read the triangle elements
1052         for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1053                 for (j = 0;j < 3;j++)
1054                         loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1055         // validate (note numverts is used because this is the original data)
1056         Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1057         // now butcher the elements according to vertonseam and tri->facesfront
1058         // and then compact the vertex set to remove duplicates
1059         for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1060                 if (!LittleLong(pintriangles[i].facesfront)) // backface
1061                         for (j = 0;j < 3;j++)
1062                                 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1063                                         loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1064         // count the usage
1065         // (this uses vertremap to count usage to save some memory)
1066         for (i = 0;i < numverts*2;i++)
1067                 vertremap[i] = 0;
1068         for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1069                 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1070         // build remapping table and compact array
1071         loadmodel->surfmesh.num_vertices = 0;
1072         for (i = 0;i < numverts*2;i++)
1073         {
1074                 if (vertremap[i])
1075                 {
1076                         vertremap[i] = loadmodel->surfmesh.num_vertices;
1077                         vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1078                         vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1079                         loadmodel->surfmesh.num_vertices++;
1080                 }
1081                 else
1082                         vertremap[i] = -1; // not used at all
1083         }
1084         // remap the elements to the new vertex set
1085         for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1086                 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1087         // store the texture coordinates
1088         loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1089         for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1090         {
1091                 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1092                 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1093         }
1094
1095         // generate ushort elements array if possible
1096         if (loadmodel->surfmesh.num_vertices <= 65536)
1097                 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1098         if (loadmodel->surfmesh.data_element3s)
1099                 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1100                         loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1101
1102 // load the frames
1103         loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1104         loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1105         if (r_enableshadowvolumes.integer)
1106         {
1107                 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1108         }
1109         Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1110         if (loadmodel->surfmesh.data_neighbor3i)
1111                 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1112         loadmodel->surfmesh.isanimated = Mod_Alias_CalculateBoundingBox();
1113         Mod_Alias_MorphMesh_CompileFrames();
1114
1115         Mem_Free(vertst);
1116         Mem_Free(vertremap);
1117
1118         // load the skins
1119         skinfiles = Mod_LoadSkinFiles();
1120         if (skinfiles)
1121         {
1122                 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1123                 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1124                 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1125                 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1126                 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1127                 Mod_FreeSkinFiles(skinfiles);
1128                 for (i = 0;i < loadmodel->numskins;i++)
1129                 {
1130                         loadmodel->skinscenes[i].firstframe = i;
1131                         loadmodel->skinscenes[i].framecount = 1;
1132                         loadmodel->skinscenes[i].loop = true;
1133                         loadmodel->skinscenes[i].framerate = 10;
1134                 }
1135         }
1136         else
1137         {
1138                 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1139                 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1140                 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1141                 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1142                 totalskins = 0;
1143                 datapointer = startskins;
1144                 for (i = 0;i < loadmodel->numskins;i++)
1145                 {
1146                         pinskintype = (daliasskintype_t *)datapointer;
1147                         datapointer += sizeof(daliasskintype_t);
1148
1149                         if (pinskintype->type == ALIAS_SKIN_SINGLE)
1150                         {
1151                                 groupskins = 1;
1152                                 interval = 0.1f;
1153                         }
1154                         else
1155                         {
1156                                 pinskingroup = (daliasskingroup_t *)datapointer;
1157                                 datapointer += sizeof(daliasskingroup_t);
1158
1159                                 groupskins = LittleLong (pinskingroup->numskins);
1160
1161                                 pinskinintervals = (daliasskininterval_t *)datapointer;
1162                                 datapointer += sizeof(daliasskininterval_t) * groupskins;
1163
1164                                 interval = LittleFloat(pinskinintervals[0].interval);
1165                                 if (interval < 0.01f)
1166                                 {
1167                                         Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1168                                         interval = 0.1f;
1169                                 }
1170                         }
1171
1172                         dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1173                         loadmodel->skinscenes[i].firstframe = totalskins;
1174                         loadmodel->skinscenes[i].framecount = groupskins;
1175                         loadmodel->skinscenes[i].framerate = 1.0f / interval;
1176                         loadmodel->skinscenes[i].loop = true;
1177
1178                         for (j = 0;j < groupskins;j++)
1179                         {
1180                                 if (groupskins > 1)
1181                                         dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1182                                 else
1183                                         dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1184                                 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))
1185                                         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));
1186                                 datapointer += skinwidth * skinheight;
1187                                 totalskins++;
1188                         }
1189                 }
1190                 // check for skins that don't exist in the model, but do exist as external images
1191                 // (this was added because yummyluv kept pestering me about support for it)
1192                 // TODO: support shaders here?
1193                 while ((tempskinframe = R_SkinFrame_LoadExternal(va(vabuf, sizeof(vabuf), "%s_%i", loadmodel->name, loadmodel->numskins), (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS, false)))
1194                 {
1195                         // expand the arrays to make room
1196                         tempskinscenes = loadmodel->skinscenes;
1197                         loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1198                         memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1199                         Mem_Free(tempskinscenes);
1200
1201                         tempaliasskins = loadmodel->data_textures;
1202                         loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1203                         memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1204                         Mem_Free(tempaliasskins);
1205
1206                         // store the info about the new skin
1207                         Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1208                         strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1209                         loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1210                         loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1211                         loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1212                         loadmodel->skinscenes[loadmodel->numskins].loop = true;
1213
1214                         //increase skin counts
1215                         loadmodel->numskins++;
1216                         totalskins++;
1217
1218                         // fix up the pointers since they are pointing at the old textures array
1219                         // FIXME: this is a hack!
1220                         for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1221                                 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1222                 }
1223         }
1224
1225         surface = loadmodel->data_surfaces;
1226         surface->texture = loadmodel->data_textures;
1227         surface->num_firsttriangle = 0;
1228         surface->num_triangles = loadmodel->surfmesh.num_triangles;
1229         surface->num_firstvertex = 0;
1230         surface->num_vertices = loadmodel->surfmesh.num_vertices;
1231
1232         if(mod_alias_force_animated.string[0])
1233                 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
1234
1235         if (!loadmodel->surfmesh.isanimated)
1236         {
1237                 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1238                 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1239                 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1240                 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1241                 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1242                 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1243         }
1244
1245         // because shaders can do somewhat unexpected things, check for unusual features now
1246         for (i = 0;i < loadmodel->num_textures;i++)
1247         {
1248                 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
1249                         mod->DrawSky = R_Q1BSP_DrawSky;
1250                 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
1251                         mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
1252         }
1253 }
1254
1255 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1256 {
1257         int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1258         float iskinwidth, iskinheight;
1259         unsigned char *data;
1260         msurface_t *surface;
1261         md2_t *pinmodel;
1262         unsigned char *base, *datapointer;
1263         md2frame_t *pinframe;
1264         char *inskin;
1265         md2triangle_t *intri;
1266         unsigned short *inst;
1267         struct md2verthash_s
1268         {
1269                 struct md2verthash_s *next;
1270                 unsigned short xyz;
1271                 unsigned short st;
1272         }
1273         *hash, **md2verthash, *md2verthashdata;
1274         skinfile_t *skinfiles;
1275
1276         pinmodel = (md2_t *)buffer;
1277         base = (unsigned char *)buffer;
1278
1279         version = LittleLong (pinmodel->version);
1280         if (version != MD2ALIAS_VERSION)
1281                 Host_Error ("%s has wrong version number (%i should be %i)",
1282                         loadmodel->name, version, MD2ALIAS_VERSION);
1283
1284         loadmodel->modeldatatypestring = "MD2";
1285
1286         loadmodel->type = mod_alias;
1287         loadmodel->DrawSky = NULL;
1288         loadmodel->DrawAddWaterPlanes = NULL;
1289         loadmodel->Draw = R_Q1BSP_Draw;
1290         loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1291         loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1292         loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1293         loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1294         loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1295         loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1296         loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1297         loadmodel->DrawLight = R_Q1BSP_DrawLight;
1298         loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1299         loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1300         loadmodel->PointSuperContents = NULL;
1301         loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1302
1303         if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1304                 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1305         if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1306                 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1307         if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1308                 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1309         if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1310                 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1311
1312         end = LittleLong(pinmodel->ofs_end);
1313         if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1314                 Host_Error ("%s is not a valid model", loadmodel->name);
1315         if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1316                 Host_Error ("%s is not a valid model", loadmodel->name);
1317         if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1318                 Host_Error ("%s is not a valid model", loadmodel->name);
1319         if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1320                 Host_Error ("%s is not a valid model", loadmodel->name);
1321         if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1322                 Host_Error ("%s is not a valid model", loadmodel->name);
1323
1324         loadmodel->numskins = LittleLong(pinmodel->num_skins);
1325         numxyz = LittleLong(pinmodel->num_xyz);
1326         numst = LittleLong(pinmodel->num_st);
1327         loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1328         loadmodel->numframes = LittleLong(pinmodel->num_frames);
1329         loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1330         loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1331         skinwidth = LittleLong(pinmodel->skinwidth);
1332         skinheight = LittleLong(pinmodel->skinheight);
1333         iskinwidth = 1.0f / skinwidth;
1334         iskinheight = 1.0f / skinheight;
1335
1336         loadmodel->num_surfaces = 1;
1337         loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1338         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));
1339         loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1340         loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1341         loadmodel->sortedmodelsurfaces[0] = 0;
1342         loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1343         loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1344         loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1345         if (r_enableshadowvolumes.integer)
1346         {
1347                 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1348         }
1349
1350         loadmodel->synctype = ST_RAND;
1351
1352         // load the skins
1353         inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1354         skinfiles = Mod_LoadSkinFiles();
1355         if (skinfiles)
1356         {
1357                 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1358                 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1359                 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1360                 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1361                 Mod_FreeSkinFiles(skinfiles);
1362         }
1363         else if (loadmodel->numskins)
1364         {
1365                 // skins found (most likely not a player model)
1366                 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1367                 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1368                 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1369                 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1370                         Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
1371         }
1372         else
1373         {
1374                 // no skins (most likely a player model)
1375                 loadmodel->numskins = 1;
1376                 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1377                 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1378                 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1379                 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1380         }
1381
1382         loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1383         for (i = 0;i < loadmodel->numskins;i++)
1384         {
1385                 loadmodel->skinscenes[i].firstframe = i;
1386                 loadmodel->skinscenes[i].framecount = 1;
1387                 loadmodel->skinscenes[i].loop = true;
1388                 loadmodel->skinscenes[i].framerate = 10;
1389         }
1390
1391         // load the triangles and stvert data
1392         inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1393         intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1394         md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1395         md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1396         // swap the triangle list
1397         loadmodel->surfmesh.num_vertices = 0;
1398         for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1399         {
1400                 for (j = 0;j < 3;j++)
1401                 {
1402                         xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1403                         st = (unsigned short) LittleShort (intri[i].index_st[j]);
1404                         if (xyz >= numxyz)
1405                         {
1406                                 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1407                                 xyz = 0;
1408                         }
1409                         if (st >= numst)
1410                         {
1411                                 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1412                                 st = 0;
1413                         }
1414                         hashindex = (xyz * 256 + st) & 65535;
1415                         for (hash = md2verthash[hashindex];hash;hash = hash->next)
1416                                 if (hash->xyz == xyz && hash->st == st)
1417                                         break;
1418                         if (hash == NULL)
1419                         {
1420                                 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1421                                 hash->xyz = xyz;
1422                                 hash->st = st;
1423                                 hash->next = md2verthash[hashindex];
1424                                 md2verthash[hashindex] = hash;
1425                         }
1426                         loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1427                 }
1428         }
1429
1430         vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1431         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));
1432         loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1433         loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1434         for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1435         {
1436                 int sts, stt;
1437                 hash = md2verthashdata + i;
1438                 vertremap[i] = hash->xyz;
1439                 sts = LittleShort(inst[hash->st*2+0]);
1440                 stt = LittleShort(inst[hash->st*2+1]);
1441                 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1442                 {
1443                         Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1444                         sts = 0;
1445                         stt = 0;
1446                 }
1447                 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1448                 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1449         }
1450
1451         Mem_Free(md2verthash);
1452         Mem_Free(md2verthashdata);
1453
1454         // generate ushort elements array if possible
1455         if (loadmodel->surfmesh.num_vertices <= 65536)
1456                 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1457         if (loadmodel->surfmesh.data_element3s)
1458                 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1459                         loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1460
1461         // load the frames
1462         datapointer = (base + LittleLong(pinmodel->ofs_frames));
1463         for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1464         {
1465                 int k;
1466                 trivertx_t *v;
1467                 trivertx_t *out;
1468                 pinframe = (md2frame_t *)datapointer;
1469                 datapointer += sizeof(md2frame_t);
1470                 // store the frame scale/translate into the appropriate array
1471                 for (j = 0;j < 3;j++)
1472                 {
1473                         loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1474                         loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1475                 }
1476                 // convert the vertices
1477                 v = (trivertx_t *)datapointer;
1478                 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1479                 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1480                         out[k] = v[vertremap[k]];
1481                 datapointer += numxyz * sizeof(trivertx_t);
1482
1483                 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1484                 loadmodel->animscenes[i].firstframe = i;
1485                 loadmodel->animscenes[i].framecount = 1;
1486                 loadmodel->animscenes[i].framerate = 10;
1487                 loadmodel->animscenes[i].loop = true;
1488         }
1489
1490         Mem_Free(vertremap);
1491
1492         if (loadmodel->surfmesh.data_neighbor3i)
1493                 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1494         loadmodel->surfmesh.isanimated = Mod_Alias_CalculateBoundingBox();
1495         Mod_Alias_MorphMesh_CompileFrames();
1496         if(mod_alias_force_animated.string[0])
1497                 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
1498
1499         surface = loadmodel->data_surfaces;
1500         surface->texture = loadmodel->data_textures;
1501         surface->num_firsttriangle = 0;
1502         surface->num_triangles = loadmodel->surfmesh.num_triangles;
1503         surface->num_firstvertex = 0;
1504         surface->num_vertices = loadmodel->surfmesh.num_vertices;
1505
1506         if (!loadmodel->surfmesh.isanimated)
1507         {
1508                 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1509                 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1510                 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1511                 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1512                 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1513                 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1514         }
1515
1516         // because shaders can do somewhat unexpected things, check for unusual features now
1517         for (i = 0;i < loadmodel->num_textures;i++)
1518         {
1519                 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
1520                         mod->DrawSky = R_Q1BSP_DrawSky;
1521                 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
1522                         mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
1523         }
1524 }
1525
1526 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1527 {
1528         int i, j, k, version, meshvertices, meshtriangles;
1529         unsigned char *data;
1530         msurface_t *surface;
1531         md3modelheader_t *pinmodel;
1532         md3frameinfo_t *pinframe;
1533         md3mesh_t *pinmesh;
1534         md3tag_t *pintag;
1535         skinfile_t *skinfiles;
1536
1537         pinmodel = (md3modelheader_t *)buffer;
1538
1539         if (memcmp(pinmodel->identifier, "IDP3", 4))
1540                 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1541         version = LittleLong (pinmodel->version);
1542         if (version != MD3VERSION)
1543                 Host_Error ("%s has wrong version number (%i should be %i)",
1544                         loadmodel->name, version, MD3VERSION);
1545
1546         skinfiles = Mod_LoadSkinFiles();
1547         if (loadmodel->numskins < 1)
1548                 loadmodel->numskins = 1;
1549
1550         loadmodel->modeldatatypestring = "MD3";
1551
1552         loadmodel->type = mod_alias;
1553         loadmodel->DrawSky = NULL;
1554         loadmodel->DrawAddWaterPlanes = NULL;
1555         loadmodel->Draw = R_Q1BSP_Draw;
1556         loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1557         loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1558         loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1559         loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1560         loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1561         loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1562         loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1563         loadmodel->DrawLight = R_Q1BSP_DrawLight;
1564         loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1565         loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1566         loadmodel->PointSuperContents = NULL;
1567         loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1568         loadmodel->synctype = ST_RAND;
1569         // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1570         i = LittleLong (pinmodel->flags);
1571         loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1572
1573         // set up some global info about the model
1574         loadmodel->numframes = LittleLong(pinmodel->num_frames);
1575         loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1576
1577         // make skinscenes for the skins (no groups)
1578         loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1579         for (i = 0;i < loadmodel->numskins;i++)
1580         {
1581                 loadmodel->skinscenes[i].firstframe = i;
1582                 loadmodel->skinscenes[i].framecount = 1;
1583                 loadmodel->skinscenes[i].loop = true;
1584                 loadmodel->skinscenes[i].framerate = 10;
1585         }
1586
1587         // load frameinfo
1588         loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1589         for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1590         {
1591                 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1592                 loadmodel->animscenes[i].firstframe = i;
1593                 loadmodel->animscenes[i].framecount = 1;
1594                 loadmodel->animscenes[i].framerate = 10;
1595                 loadmodel->animscenes[i].loop = true;
1596         }
1597
1598         // load tags
1599         loadmodel->num_tagframes = loadmodel->numframes;
1600         loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1601         loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1602         for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1603         {
1604                 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1605                 for (j = 0;j < 9;j++)
1606                         loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1607                 for (j = 0;j < 3;j++)
1608                         loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1609                 //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);
1610         }
1611
1612         // load meshes
1613         meshvertices = 0;
1614         meshtriangles = 0;
1615         for (i = 0, pinmesh = (md3mesh_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_meshes));i < loadmodel->num_surfaces;i++, pinmesh = (md3mesh_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_end)))
1616         {
1617                 if (memcmp(pinmesh->identifier, "IDP3", 4))
1618                         Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1619                 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1620                         Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1621                 meshvertices += LittleLong(pinmesh->num_vertices);
1622                 meshtriangles += LittleLong(pinmesh->num_triangles);
1623         }
1624
1625         loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1626         loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1627         loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1628         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));
1629         loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1630         loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1631         loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1632         loadmodel->surfmesh.num_vertices = meshvertices;
1633         loadmodel->surfmesh.num_triangles = meshtriangles;
1634         loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1635         loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1636         loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1637         if (r_enableshadowvolumes.integer)
1638         {
1639                 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1640         }
1641         loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1642         loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1643         if (meshvertices <= 65536)
1644         {
1645                 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1646         }
1647
1648         meshvertices = 0;
1649         meshtriangles = 0;
1650         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)))
1651         {
1652                 if (memcmp(pinmesh->identifier, "IDP3", 4))
1653                         Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1654                 loadmodel->sortedmodelsurfaces[i] = i;
1655                 surface = loadmodel->data_surfaces + i;
1656                 surface->texture = loadmodel->data_textures + i;
1657                 surface->num_firsttriangle = meshtriangles;
1658                 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1659                 surface->num_firstvertex = meshvertices;
1660                 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1661                 meshvertices += surface->num_vertices;
1662                 meshtriangles += surface->num_triangles;
1663
1664                 for (j = 0;j < surface->num_triangles * 3;j++)
1665                         loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1666                 for (j = 0;j < surface->num_vertices;j++)
1667                 {
1668                         loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1669                         loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1670                 }
1671                 for (j = 0;j < loadmodel->numframes;j++)
1672                 {
1673                         const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1674                         md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1675                         for (k = 0;k < surface->num_vertices;k++, in++, out++)
1676                         {
1677                                 out->origin[0] = LittleShort(in->origin[0]);
1678                                 out->origin[1] = LittleShort(in->origin[1]);
1679                                 out->origin[2] = LittleShort(in->origin[2]);
1680                                 out->pitch = in->pitch;
1681                                 out->yaw = in->yaw;
1682                         }
1683                 }
1684
1685                 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1686
1687                 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1688         }
1689         if (loadmodel->surfmesh.data_element3s)
1690                 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1691                         loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1692         if (loadmodel->surfmesh.data_neighbor3i)
1693                 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1694         Mod_Alias_MorphMesh_CompileFrames();
1695         loadmodel->surfmesh.isanimated = Mod_Alias_CalculateBoundingBox();
1696         Mod_FreeSkinFiles(skinfiles);
1697         Mod_MakeSortedSurfaces(loadmodel);
1698         if(mod_alias_force_animated.string[0])
1699                 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
1700
1701         if (!loadmodel->surfmesh.isanimated)
1702         {
1703                 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
1704                 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
1705                 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
1706                 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
1707                 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
1708                 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
1709         }
1710
1711         // because shaders can do somewhat unexpected things, check for unusual features now
1712         for (i = 0;i < loadmodel->num_textures;i++)
1713         {
1714                 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
1715                         mod->DrawSky = R_Q1BSP_DrawSky;
1716                 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
1717                         mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
1718         }
1719 }
1720
1721 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1722 {
1723         zymtype1header_t *pinmodel, *pheader;
1724         unsigned char *pbase;
1725         int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1726         float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose, f, biggestorigin, tempvec[3], modelscale;
1727         zymvertex_t *verts, *vertdata;
1728         zymscene_t *scene;
1729         zymbone_t *bone;
1730         char *shadername;
1731         skinfile_t *skinfiles;
1732         unsigned char *data;
1733         msurface_t *surface;
1734
1735         pinmodel = (zymtype1header_t *)buffer;
1736         pbase = (unsigned char *)buffer;
1737         if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1738                 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1739         if (BigLong(pinmodel->type) != 1)
1740                 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1741
1742         loadmodel->modeldatatypestring = "ZYM";
1743
1744         loadmodel->type = mod_alias;
1745         loadmodel->synctype = ST_RAND;
1746
1747         // byteswap header
1748         pheader = pinmodel;
1749         pheader->type = BigLong(pinmodel->type);
1750         pheader->filesize = BigLong(pinmodel->filesize);
1751         pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1752         pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1753         pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1754         pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1755         pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1756         pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1757         pheader->radius = BigFloat(pinmodel->radius);
1758         pheader->numverts = BigLong(pinmodel->numverts);
1759         pheader->numtris = BigLong(pinmodel->numtris);
1760         pheader->numshaders = BigLong(pinmodel->numshaders);
1761         pheader->numbones = BigLong(pinmodel->numbones);
1762         pheader->numscenes = BigLong(pinmodel->numscenes);
1763         pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1764         pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1765         pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1766         pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1767         pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1768         pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1769         pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1770         pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1771         pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1772         pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1773         pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1774         pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1775         pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1776         pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1777         pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1778         pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1779         pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1780         pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1781
1782         if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1783         {
1784                 Con_Printf("%s has no geometry\n", loadmodel->name);
1785                 return;
1786         }
1787         if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1788         {
1789                 Con_Printf("%s has no animations\n", loadmodel->name);
1790                 return;
1791         }
1792
1793         loadmodel->DrawSky = NULL;
1794         loadmodel->DrawAddWaterPlanes = NULL;
1795         loadmodel->Draw = R_Q1BSP_Draw;
1796         loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1797         loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1798         loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1799         loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1800         loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1801         loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1802         loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1803         loadmodel->DrawLight = R_Q1BSP_DrawLight;
1804         loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1805         loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1806         loadmodel->PointSuperContents = NULL;
1807         loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1808
1809         loadmodel->numframes = pheader->numscenes;
1810         loadmodel->num_surfaces = pheader->numshaders;
1811
1812         skinfiles = Mod_LoadSkinFiles();
1813         if (loadmodel->numskins < 1)
1814                 loadmodel->numskins = 1;
1815
1816         // make skinscenes for the skins (no groups)
1817         loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1818         for (i = 0;i < loadmodel->numskins;i++)
1819         {
1820                 loadmodel->skinscenes[i].firstframe = i;
1821                 loadmodel->skinscenes[i].framecount = 1;
1822                 loadmodel->skinscenes[i].loop = true;
1823                 loadmodel->skinscenes[i].framerate = 10;
1824         }
1825
1826         // model bbox
1827         // LordHavoc: actually we blow this away later with Mod_Alias_CalculateBoundingBox()
1828         modelradius = pheader->radius;
1829         for (i = 0;i < 3;i++)
1830         {
1831                 loadmodel->normalmins[i] = pheader->mins[i];
1832                 loadmodel->normalmaxs[i] = pheader->maxs[i];
1833                 loadmodel->rotatedmins[i] = -modelradius;
1834                 loadmodel->rotatedmaxs[i] = modelradius;
1835         }
1836         corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1837         corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1838         loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1839         if (loadmodel->yawmaxs[0] > modelradius)
1840                 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1841         loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1842         loadmodel->yawmins[2] = loadmodel->normalmins[2];
1843         loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1844         loadmodel->radius = modelradius;
1845         loadmodel->radius2 = modelradius * modelradius;
1846
1847         // go through the lumps, swapping things
1848
1849         //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1850         loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1851         scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1852         numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1853         for (i = 0;i < pheader->numscenes;i++)
1854         {
1855                 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1856                 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1857                 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1858                 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1859                 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1860                 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1861                         Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1862                 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1863                         Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1864                 if (loadmodel->animscenes[i].framerate < 0)
1865                         Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1866                 scene++;
1867         }
1868
1869         //zymlump_t lump_bones; // zymbone_t bone[numbones];
1870         loadmodel->num_bones = pheader->numbones;
1871         loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1872         bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1873         for (i = 0;i < pheader->numbones;i++)
1874         {
1875                 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1876                 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1877                 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1878                 if (loadmodel->data_bones[i].parent >= i)
1879                         Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1880         }
1881
1882         //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1883         vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1884         bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1885         for (i = 0;i < pheader->numverts;i++)
1886         {
1887                 vertbonecounts[i] = BigLong(bonecount[i]);
1888                 if (vertbonecounts[i] != 1)
1889                         Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1890         }
1891
1892         loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1893
1894         meshvertices = pheader->numverts;
1895         meshtriangles = pheader->numtris;
1896
1897         loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1898         loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1899         loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1900         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]) + sizeof(unsigned short) + sizeof(unsigned char[2][4])) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]) + loadmodel->num_bones * sizeof(float[12]));
1901         loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1902         loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1903         loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1904         loadmodel->surfmesh.num_vertices = meshvertices;
1905         loadmodel->surfmesh.num_triangles = meshtriangles;
1906         loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1907         if (r_enableshadowvolumes.integer)
1908         {
1909                 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1910         }
1911         loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1912         loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1913         loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1914         loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1915         loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1916         loadmodel->surfmesh.data_skeletalindex4ub = (unsigned char *)data;data += meshvertices * sizeof(unsigned char[4]);
1917         loadmodel->surfmesh.data_skeletalweight4ub = (unsigned char *)data;data += meshvertices * sizeof(unsigned char[4]);
1918         loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1919         loadmodel->surfmesh.num_blends = 0;
1920         loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
1921         if (loadmodel->surfmesh.num_vertices <= 65536)
1922         {
1923                 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1924         }
1925         loadmodel->data_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
1926         loadmodel->surfmesh.data_blendweights = NULL;
1927
1928         //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1929         poses = (float *) (pheader->lump_poses.start + pbase);
1930         // figure out scale of model from root bone, for compatibility with old zmodel versions
1931         tempvec[0] = BigFloat(poses[0]);
1932         tempvec[1] = BigFloat(poses[1]);
1933         tempvec[2] = BigFloat(poses[2]);
1934         modelscale = VectorLength(tempvec);
1935         biggestorigin = 0;
1936         for (i = 0;i < loadmodel->num_bones * numposes * 12;i++)
1937         {
1938                 f = fabs(BigFloat(poses[i]));
1939                 biggestorigin = max(biggestorigin, f);
1940         }
1941         loadmodel->num_posescale = biggestorigin / 32767.0f;
1942         loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
1943         for (i = 0;i < numposes;i++)
1944         {
1945                 const float *frameposes = (float *) (pheader->lump_poses.start + pbase) + 12*i*loadmodel->num_bones;
1946                 for (j = 0;j < loadmodel->num_bones;j++)
1947                 {
1948                         float pose[12];
1949                         matrix4x4_t posematrix;
1950                         for (k = 0;k < 12;k++)
1951                                 pose[k] = BigFloat(frameposes[j*12+k]);
1952                         //if (j < loadmodel->num_bones)
1953                         //      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));
1954                         // scale child bones to match the root scale
1955                         if (loadmodel->data_bones[j].parent >= 0)
1956                         {
1957                                 pose[3] *= modelscale;
1958                                 pose[7] *= modelscale;
1959                                 pose[11] *= modelscale;
1960                         }
1961                         // normalize rotation matrix
1962                         VectorNormalize(pose + 0);
1963                         VectorNormalize(pose + 4);
1964                         VectorNormalize(pose + 8);
1965                         Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
1966                         Matrix4x4_ToBonePose7s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses7s + 7*(i*loadmodel->num_bones+j));
1967                 }
1968         }
1969
1970         //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1971         verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1972         vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1973         // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1974         // (converting from weight-blending skeletal animation to
1975         //  deformation-based skeletal animation)
1976         bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1977         for (i = 0;i < loadmodel->num_bones;i++)
1978         {
1979                 float m[12];
1980                 for (k = 0;k < 12;k++)
1981                         m[k] = BigFloat(poses[i*12+k]);
1982                 if (loadmodel->data_bones[i].parent >= 0)
1983                         R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1984                 else
1985                         for (k = 0;k < 12;k++)
1986                                 bonepose[12*i+k] = m[k];
1987         }
1988         for (j = 0;j < pheader->numverts;j++)
1989         {
1990                 // this format really should have had a per vertexweight weight value...
1991                 // but since it does not, the weighting is completely ignored and
1992                 // only one weight is allowed per vertex
1993                 int boneindex = BigLong(vertdata[j].bonenum);
1994                 const float *m = bonepose + 12 * boneindex;
1995                 float relativeorigin[3];
1996                 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1997                 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1998                 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1999                 // transform the vertex bone weight into the base mesh
2000                 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
2001                 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
2002                 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
2003                 // store the weight as the primary weight on this vertex
2004                 loadmodel->surfmesh.blends[j] = boneindex;
2005                 loadmodel->surfmesh.data_skeletalindex4ub[j*4  ] = boneindex;
2006                 loadmodel->surfmesh.data_skeletalindex4ub[j*4+1] = 0;
2007                 loadmodel->surfmesh.data_skeletalindex4ub[j*4+2] = 0;
2008                 loadmodel->surfmesh.data_skeletalindex4ub[j*4+3] = 0;
2009                 loadmodel->surfmesh.data_skeletalweight4ub[j*4  ] = 255;
2010                 loadmodel->surfmesh.data_skeletalweight4ub[j*4+1] = 0;
2011                 loadmodel->surfmesh.data_skeletalweight4ub[j*4+2] = 0;
2012                 loadmodel->surfmesh.data_skeletalweight4ub[j*4+3] = 0;
2013         }
2014         Z_Free(bonepose);
2015         // normals and tangents are calculated after elements are loaded
2016
2017         //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
2018         outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
2019         intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
2020         for (i = 0;i < pheader->numverts;i++)
2021         {
2022                 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
2023                 // flip T coordinate for OpenGL
2024                 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
2025         }
2026
2027         //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
2028         //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
2029         //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
2030
2031         //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
2032         //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)
2033         // byteswap, validate, and swap winding order of tris
2034         count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
2035         if (pheader->lump_render.length != count)
2036                 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
2037         renderlist = (int *) (pheader->lump_render.start + pbase);
2038         renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
2039         meshtriangles = 0;
2040         for (i = 0;i < loadmodel->num_surfaces;i++)
2041         {
2042                 int firstvertex, lastvertex;
2043                 if (renderlist >= renderlistend)
2044                         Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2045                 count = BigLong(*renderlist);renderlist++;
2046                 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
2047                         Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
2048
2049                 loadmodel->sortedmodelsurfaces[i] = i;
2050                 surface = loadmodel->data_surfaces + i;
2051                 surface->texture = loadmodel->data_textures + i;
2052                 surface->num_firsttriangle = meshtriangles;
2053                 surface->num_triangles = count;
2054                 meshtriangles += surface->num_triangles;
2055
2056                 // load the elements
2057                 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2058                 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
2059                 {
2060                         outelements[j*3+2] = BigLong(renderlist[0]);
2061                         outelements[j*3+1] = BigLong(renderlist[1]);
2062                         outelements[j*3+0] = BigLong(renderlist[2]);
2063                 }
2064                 // validate the elements and find the used vertex range
2065                 firstvertex = meshvertices;
2066                 lastvertex = 0;
2067                 for (j = 0;j < surface->num_triangles * 3;j++)
2068                 {
2069                         if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
2070                                 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
2071                         firstvertex = min(firstvertex, outelements[j]);
2072                         lastvertex = max(lastvertex, outelements[j]);
2073                 }
2074                 surface->num_firstvertex = firstvertex;
2075                 surface->num_vertices = lastvertex + 1 - firstvertex;
2076
2077                 // since zym models do not have named sections, reuse their shader
2078                 // name as the section name
2079                 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
2080                 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
2081         }
2082         Mod_FreeSkinFiles(skinfiles);
2083         Mem_Free(vertbonecounts);
2084         Mem_Free(verts);
2085         Mod_MakeSortedSurfaces(loadmodel);
2086
2087         // compute all the mesh information that was not loaded from the file
2088         if (loadmodel->surfmesh.data_element3s)
2089                 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2090                         loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2091         Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2092         Mod_BuildBaseBonePoses();
2093         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);
2094         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);
2095         if (loadmodel->surfmesh.data_neighbor3i)
2096                 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2097         loadmodel->surfmesh.isanimated = Mod_Alias_CalculateBoundingBox();
2098         if(mod_alias_force_animated.string[0])
2099                 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
2100
2101         if (!loadmodel->surfmesh.isanimated)
2102         {
2103                 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2104                 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2105                 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2106                 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2107                 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2108                 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2109         }
2110
2111         // because shaders can do somewhat unexpected things, check for unusual features now
2112         for (i = 0;i < loadmodel->num_textures;i++)
2113         {
2114                 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
2115                         mod->DrawSky = R_Q1BSP_DrawSky;
2116                 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
2117                         mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
2118         }
2119 }
2120
2121 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2122 {
2123         dpmheader_t *pheader;
2124         dpmframe_t *frames;
2125         dpmbone_t *bone;
2126         dpmmesh_t *dpmmesh;
2127         unsigned char *pbase;
2128         int i, j, k, meshvertices, meshtriangles;
2129         skinfile_t *skinfiles;
2130         unsigned char *data;
2131         float *bonepose;
2132         float biggestorigin, tempvec[3], modelscale;
2133         float f;
2134         float *poses;
2135
2136         pheader = (dpmheader_t *)buffer;
2137         pbase = (unsigned char *)buffer;
2138         if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2139                 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2140         if (BigLong(pheader->type) != 2)
2141                 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2142
2143         loadmodel->modeldatatypestring = "DPM";
2144
2145         loadmodel->type = mod_alias;
2146         loadmodel->synctype = ST_RAND;
2147
2148         // byteswap header
2149         pheader->type = BigLong(pheader->type);
2150         pheader->filesize = BigLong(pheader->filesize);
2151         pheader->mins[0] = BigFloat(pheader->mins[0]);
2152         pheader->mins[1] = BigFloat(pheader->mins[1]);
2153         pheader->mins[2] = BigFloat(pheader->mins[2]);
2154         pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2155         pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2156         pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2157         pheader->yawradius = BigFloat(pheader->yawradius);
2158         pheader->allradius = BigFloat(pheader->allradius);
2159         pheader->num_bones = BigLong(pheader->num_bones);
2160         pheader->num_meshs = BigLong(pheader->num_meshs);
2161         pheader->num_frames = BigLong(pheader->num_frames);
2162         pheader->ofs_bones = BigLong(pheader->ofs_bones);
2163         pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2164         pheader->ofs_frames = BigLong(pheader->ofs_frames);
2165
2166         if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2167         {
2168                 Con_Printf("%s has no geometry\n", loadmodel->name);
2169                 return;
2170         }
2171         if (pheader->num_frames < 1)
2172         {
2173                 Con_Printf("%s has no frames\n", loadmodel->name);
2174                 return;
2175         }
2176
2177         loadmodel->DrawSky = NULL;
2178         loadmodel->DrawAddWaterPlanes = NULL;
2179         loadmodel->Draw = R_Q1BSP_Draw;
2180         loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2181         loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2182         loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2183         loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2184         loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2185         loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2186         loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2187         loadmodel->DrawLight = R_Q1BSP_DrawLight;
2188         loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2189         loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2190         loadmodel->PointSuperContents = NULL;
2191         loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2192
2193         // model bbox
2194         // LordHavoc: actually we blow this away later with Mod_Alias_CalculateBoundingBox()
2195         for (i = 0;i < 3;i++)
2196         {
2197                 loadmodel->normalmins[i] = pheader->mins[i];
2198                 loadmodel->normalmaxs[i] = pheader->maxs[i];
2199                 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2200                 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2201                 loadmodel->rotatedmins[i] = -pheader->allradius;
2202                 loadmodel->rotatedmaxs[i] = pheader->allradius;
2203         }
2204         loadmodel->radius = pheader->allradius;
2205         loadmodel->radius2 = pheader->allradius * pheader->allradius;
2206
2207         // load external .skin files if present
2208         skinfiles = Mod_LoadSkinFiles();
2209         if (loadmodel->numskins < 1)
2210                 loadmodel->numskins = 1;
2211
2212         meshvertices = 0;
2213         meshtriangles = 0;
2214
2215         // gather combined statistics from the meshes
2216         dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2217         for (i = 0;i < (int)pheader->num_meshs;i++)
2218         {
2219                 int numverts = BigLong(dpmmesh->num_verts);
2220                 meshvertices += numverts;
2221                 meshtriangles += BigLong(dpmmesh->num_tris);
2222                 dpmmesh++;
2223         }
2224
2225         loadmodel->numframes = pheader->num_frames;
2226         loadmodel->num_bones = pheader->num_bones;
2227         loadmodel->num_poses = loadmodel->numframes;
2228         loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2229         loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2230         loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2231         // do most allocations as one merged chunk
2232         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) + sizeof(unsigned char[2][4])) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
2233         loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2234         loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2235         loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2236         loadmodel->surfmesh.num_vertices = meshvertices;
2237         loadmodel->surfmesh.num_triangles = meshtriangles;
2238         loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2239         if (r_enableshadowvolumes.integer)
2240         {
2241                 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2242         }
2243         loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2244         loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2245         loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2246         loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2247         loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2248         loadmodel->surfmesh.data_skeletalindex4ub = (unsigned char *)data;data += meshvertices * sizeof(unsigned char[4]);
2249         loadmodel->surfmesh.data_skeletalweight4ub = (unsigned char *)data;data += meshvertices * sizeof(unsigned char[4]);
2250         loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2251         loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2252         loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2253         loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2254         loadmodel->surfmesh.num_blends = 0;
2255         loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2256         if (meshvertices <= 65536)
2257         {
2258                 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2259         }
2260         loadmodel->data_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
2261         loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
2262
2263         for (i = 0;i < loadmodel->numskins;i++)
2264         {
2265                 loadmodel->skinscenes[i].firstframe = i;
2266                 loadmodel->skinscenes[i].framecount = 1;
2267                 loadmodel->skinscenes[i].loop = true;
2268                 loadmodel->skinscenes[i].framerate = 10;
2269         }
2270
2271         // load the bone info
2272         bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2273         for (i = 0;i < loadmodel->num_bones;i++)
2274         {
2275                 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2276                 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2277                 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2278                 if (loadmodel->data_bones[i].parent >= i)
2279                         Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2280         }
2281
2282         // load the frames
2283         frames = (dpmframe_t *) (pbase + pheader->ofs_frames);
2284         // figure out scale of model from root bone, for compatibility with old dpmodel versions
2285         poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2286         tempvec[0] = BigFloat(poses[0]);
2287         tempvec[1] = BigFloat(poses[1]);
2288         tempvec[2] = BigFloat(poses[2]);
2289         modelscale = VectorLength(tempvec);
2290         biggestorigin = 0;
2291         for (i = 0;i < loadmodel->numframes;i++)
2292         {
2293                 memcpy(loadmodel->animscenes[i].name, frames[i].name, sizeof(frames[i].name));
2294                 loadmodel->animscenes[i].firstframe = i;
2295                 loadmodel->animscenes[i].framecount = 1;
2296                 loadmodel->animscenes[i].loop = true;
2297                 loadmodel->animscenes[i].framerate = 10;
2298                 // load the bone poses for this frame
2299                 poses = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2300                 for (j = 0;j < loadmodel->num_bones*12;j++)
2301                 {
2302                         f = fabs(BigFloat(poses[j]));
2303                         biggestorigin = max(biggestorigin, f);
2304                 }
2305                 // stuff not processed here: mins, maxs, yawradius, allradius
2306         }
2307         loadmodel->num_posescale = biggestorigin / 32767.0f;
2308         loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2309         for (i = 0;i < loadmodel->numframes;i++)
2310         {
2311                 const float *frameposes = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2312                 for (j = 0;j < loadmodel->num_bones;j++)
2313                 {
2314                         float pose[12];
2315                         matrix4x4_t posematrix;
2316                         for (k = 0;k < 12;k++)
2317                                 pose[k] = BigFloat(frameposes[j*12+k]);
2318                         // scale child bones to match the root scale
2319                         if (loadmodel->data_bones[j].parent >= 0)
2320                         {
2321                                 pose[3] *= modelscale;
2322                                 pose[7] *= modelscale;
2323                                 pose[11] *= modelscale;
2324                         }
2325                         // normalize rotation matrix
2326                         VectorNormalize(pose + 0);
2327                         VectorNormalize(pose + 4);
2328                         VectorNormalize(pose + 8);
2329                         Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2330                         Matrix4x4_ToBonePose7s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses7s + 7*(i*loadmodel->num_bones+j));
2331                 }
2332         }
2333
2334         // load the meshes now
2335         dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2336         meshvertices = 0;
2337         meshtriangles = 0;
2338         // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2339         // (converting from weight-blending skeletal animation to
2340         //  deformation-based skeletal animation)
2341         poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2342         bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2343         for (i = 0;i < loadmodel->num_bones;i++)
2344         {
2345                 float m[12];
2346                 for (k = 0;k < 12;k++)
2347                         m[k] = BigFloat(poses[i*12+k]);
2348                 if (loadmodel->data_bones[i].parent >= 0)
2349                         R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2350                 else
2351                         for (k = 0;k < 12;k++)
2352                                 bonepose[12*i+k] = m[k];
2353         }
2354         for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2355         {
2356                 const int *inelements;
2357                 int *outelements;
2358                 const float *intexcoord;
2359                 msurface_t *surface;
2360
2361                 loadmodel->sortedmodelsurfaces[i] = i;
2362                 surface = loadmodel->data_surfaces + i;
2363                 surface->texture = loadmodel->data_textures + i;
2364                 surface->num_firsttriangle = meshtriangles;
2365                 surface->num_triangles = BigLong(dpmmesh->num_tris);
2366                 surface->num_firstvertex = meshvertices;
2367                 surface->num_vertices = BigLong(dpmmesh->num_verts);
2368                 meshvertices += surface->num_vertices;
2369                 meshtriangles += surface->num_triangles;
2370
2371                 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2372                 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2373                 for (j = 0;j < surface->num_triangles;j++)
2374                 {
2375                         // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2376                         outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2377                         outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2378                         outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2379                         inelements += 3;
2380                         outelements += 3;
2381                 }
2382
2383                 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2384                 for (j = 0;j < surface->num_vertices*2;j++)
2385                         loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2386
2387                 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2388                 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2389                 {
2390                         int weightindex[4] = { 0, 0, 0, 0 };
2391                         float weightinfluence[4] = { 0, 0, 0, 0 };
2392                         int l;
2393                         int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2394                         data += sizeof(dpmvertex_t);
2395                         for (k = 0;k < numweights;k++)
2396                         {
2397                                 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2398                                 int boneindex = BigLong(vert->bonenum);
2399                                 const float *m = bonepose + 12 * boneindex;
2400                                 float influence = BigFloat(vert->influence);
2401                                 float relativeorigin[3], relativenormal[3];
2402                                 relativeorigin[0] = BigFloat(vert->origin[0]);
2403                                 relativeorigin[1] = BigFloat(vert->origin[1]);
2404                                 relativeorigin[2] = BigFloat(vert->origin[2]);
2405                                 relativenormal[0] = BigFloat(vert->normal[0]);
2406                                 relativenormal[1] = BigFloat(vert->normal[1]);
2407                                 relativenormal[2] = BigFloat(vert->normal[2]);
2408                                 // blend the vertex bone weights into the base mesh
2409                                 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2410                                 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2411                                 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2412                                 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2413                                 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2414                                 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2415                                 if (!k)
2416                                 {
2417                                         // store the first (and often only) weight
2418                                         weightinfluence[0] = influence;
2419                                         weightindex[0] = boneindex;
2420                                 }
2421                                 else
2422                                 {
2423                                         // sort the new weight into this vertex's weight table
2424                                         // (which only accepts up to 4 bones per vertex)
2425                                         for (l = 0;l < 4;l++)
2426                                         {
2427                                                 if (weightinfluence[l] < influence)
2428                                                 {
2429                                                         // move weaker influence weights out of the way first
2430                                                         int l2;
2431                                                         for (l2 = 3;l2 > l;l2--)
2432                                                         {
2433                                                                 weightinfluence[l2] = weightinfluence[l2-1];
2434                                                                 weightindex[l2] = weightindex[l2-1];
2435                                                         }
2436                                                         // store the new weight
2437                                                         weightinfluence[l] = influence;
2438                                                         weightindex[l] = boneindex;
2439                                                         break;
2440                                                 }
2441                                         }
2442                                 }
2443                                 data += sizeof(dpmbonevert_t);
2444                         }
2445                         loadmodel->surfmesh.blends[j] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
2446                         loadmodel->surfmesh.data_skeletalindex4ub[j*4  ] = weightindex[0];
2447                         loadmodel->surfmesh.data_skeletalindex4ub[j*4+1] = weightindex[1];
2448                         loadmodel->surfmesh.data_skeletalindex4ub[j*4+2] = weightindex[2];
2449                         loadmodel->surfmesh.data_skeletalindex4ub[j*4+3] = weightindex[3];
2450                         loadmodel->surfmesh.data_skeletalweight4ub[j*4  ] = (unsigned char)(weightinfluence[0]*255.0f);
2451                         loadmodel->surfmesh.data_skeletalweight4ub[j*4+1] = (unsigned char)(weightinfluence[1]*255.0f);
2452                         loadmodel->surfmesh.data_skeletalweight4ub[j*4+2] = (unsigned char)(weightinfluence[2]*255.0f);
2453                         loadmodel->surfmesh.data_skeletalweight4ub[j*4+3] = (unsigned char)(weightinfluence[3]*255.0f);
2454                 }
2455
2456                 // since dpm models do not have named sections, reuse their shader name as the section name
2457                 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2458
2459                 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2460         }
2461         if (loadmodel->surfmesh.num_blends < meshvertices)
2462                 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
2463         Z_Free(bonepose);
2464         Mod_FreeSkinFiles(skinfiles);
2465         Mod_MakeSortedSurfaces(loadmodel);
2466
2467         // compute all the mesh information that was not loaded from the file
2468         if (loadmodel->surfmesh.data_element3s)
2469                 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2470                         loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2471         Mod_BuildBaseBonePoses();
2472         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);
2473         if (loadmodel->surfmesh.data_neighbor3i)
2474                 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2475         loadmodel->surfmesh.isanimated = Mod_Alias_CalculateBoundingBox();
2476         if(mod_alias_force_animated.string[0])
2477                 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
2478
2479         if (!loadmodel->surfmesh.isanimated)
2480         {
2481                 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
2482                 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
2483                 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
2484                 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
2485                 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
2486                 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
2487         }
2488
2489         // because shaders can do somewhat unexpected things, check for unusual features now
2490         for (i = 0;i < loadmodel->num_textures;i++)
2491         {
2492                 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
2493                         mod->DrawSky = R_Q1BSP_DrawSky;
2494                 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
2495                         mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
2496         }
2497 }
2498
2499 // no idea why PSK/PSA files contain weird quaternions but they do...
2500 #define PSKQUATNEGATIONS
2501 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2502 {
2503         int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2504         int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2505         fs_offset_t filesize;
2506         pskpnts_t *pnts;
2507         pskvtxw_t *vtxw;
2508         pskface_t *faces;
2509         pskmatt_t *matts;
2510         pskboneinfo_t *bones;
2511         pskrawweights_t *rawweights;
2512         //pskboneinfo_t *animbones;
2513         pskaniminfo_t *anims;
2514         pskanimkeys_t *animkeys;
2515         void *animfilebuffer, *animbuffer, *animbufferend;
2516         unsigned char *data;
2517         pskchunk_t *pchunk;
2518         skinfile_t *skinfiles;
2519         char animname[MAX_QPATH];
2520         size_t size;
2521         float biggestorigin;
2522
2523         pchunk = (pskchunk_t *)buffer;
2524         if (strcmp(pchunk->id, "ACTRHEAD"))
2525                 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2526
2527         loadmodel->modeldatatypestring = "PSK";
2528
2529         loadmodel->type = mod_alias;
2530         loadmodel->DrawSky = NULL;
2531         loadmodel->DrawAddWaterPlanes = NULL;
2532         loadmodel->Draw = R_Q1BSP_Draw;
2533         loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2534         loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2535         loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2536         loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2537         loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2538         loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2539         loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2540         loadmodel->DrawLight = R_Q1BSP_DrawLight;
2541         loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2542         loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2543         loadmodel->PointSuperContents = NULL;
2544         loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2545         loadmodel->synctype = ST_RAND;
2546
2547         FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2548         strlcat(animname, ".psa", sizeof(animname));
2549         animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2550         animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2551         if (!animbuffer)
2552                 animbufferend = animbuffer;
2553
2554         numpnts = 0;
2555         pnts = NULL;
2556         numvtxw = 0;
2557         vtxw = NULL;
2558         numfaces = 0;
2559         faces = NULL;
2560         nummatts = 0;
2561         matts = NULL;
2562         numbones = 0;
2563         bones = NULL;
2564         numrawweights = 0;
2565         rawweights = NULL;
2566         numanims = 0;
2567         anims = NULL;
2568         numanimkeys = 0;
2569         animkeys = NULL;
2570
2571         while (buffer < bufferend)
2572         {
2573                 pchunk = (pskchunk_t *)buffer;
2574                 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2575                 version = LittleLong(pchunk->version);
2576                 recordsize = LittleLong(pchunk->recordsize);
2577                 numrecords = LittleLong(pchunk->numrecords);
2578                 if (developer_extra.integer)
2579                         Con_DPrintf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2580                 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2581                         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);
2582                 if (!strcmp(pchunk->id, "ACTRHEAD"))
2583                 {
2584                         // nothing to do
2585                 }
2586                 else if (!strcmp(pchunk->id, "PNTS0000"))
2587                 {
2588                         pskpnts_t *p;
2589                         if (recordsize != sizeof(*p))
2590                                 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2591                         // byteswap in place and keep the pointer
2592                         numpnts = numrecords;
2593                         pnts = (pskpnts_t *)buffer;
2594                         for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2595                         {
2596                                 p->origin[0] = LittleFloat(p->origin[0]);
2597                                 p->origin[1] = LittleFloat(p->origin[1]);
2598                                 p->origin[2] = LittleFloat(p->origin[2]);
2599                         }
2600                         buffer = p;
2601                 }
2602                 else if (!strcmp(pchunk->id, "VTXW0000"))
2603                 {
2604                         pskvtxw_t *p;
2605                         if (recordsize != sizeof(*p))
2606                                 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2607                         // byteswap in place and keep the pointer
2608                         numvtxw = numrecords;
2609                         vtxw = (pskvtxw_t *)buffer;
2610                         for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2611                         {
2612                                 p->pntsindex = LittleShort(p->pntsindex);
2613                                 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2614                                 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2615                                 if (p->pntsindex >= numpnts)
2616                                 {
2617                                         Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2618                                         p->pntsindex = 0;
2619                                 }
2620                         }
2621                         buffer = p;
2622                 }
2623                 else if (!strcmp(pchunk->id, "FACE0000"))
2624                 {
2625                         pskface_t *p;
2626                         if (recordsize != sizeof(*p))
2627                                 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2628                         // byteswap in place and keep the pointer
2629                         numfaces = numrecords;
2630                         faces = (pskface_t *)buffer;
2631                         for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2632                         {
2633                                 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2634                                 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2635                                 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2636                                 p->group = LittleLong(p->group);
2637                                 if (p->vtxwindex[0] >= numvtxw)
2638                                 {
2639                                         Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2640                                         p->vtxwindex[0] = 0;
2641                                 }
2642                                 if (p->vtxwindex[1] >= numvtxw)
2643                                 {
2644                                         Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2645                                         p->vtxwindex[1] = 0;
2646                                 }
2647                                 if (p->vtxwindex[2] >= numvtxw)
2648                                 {
2649                                         Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2650                                         p->vtxwindex[2] = 0;
2651                                 }
2652                         }
2653                         buffer = p;
2654                 }
2655                 else if (!strcmp(pchunk->id, "MATT0000"))
2656                 {
2657                         pskmatt_t *p;
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                         nummatts = numrecords;
2662                         matts = (pskmatt_t *)buffer;
2663                         for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2664                         {
2665                                 // nothing to do
2666                         }
2667                         buffer = p;
2668                 }
2669                 else if (!strcmp(pchunk->id, "REFSKELT"))
2670                 {
2671                         pskboneinfo_t *p;
2672                         if (recordsize != sizeof(*p))
2673                                 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2674                         // byteswap in place and keep the pointer
2675                         numbones = numrecords;
2676                         bones = (pskboneinfo_t *)buffer;
2677                         for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2678                         {
2679                                 p->numchildren = LittleLong(p->numchildren);
2680                                 p->parent = LittleLong(p->parent);
2681                                 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2682                                 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2683                                 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2684                                 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2685                                 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2686                                 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2687                                 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2688                                 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2689                                 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2690                                 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2691                                 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2692 #ifdef PSKQUATNEGATIONS
2693                                 if (index)
2694                                 {
2695                                         p->basepose.quat[0] *= -1;
2696                                         p->basepose.quat[1] *= -1;
2697                                         p->basepose.quat[2] *= -1;
2698                                 }
2699                                 else
2700                                 {
2701                                         p->basepose.quat[0] *=  1;
2702                                         p->basepose.quat[1] *= -1;
2703                                         p->basepose.quat[2] *=  1;
2704                                 }
2705 #endif
2706                                 if (p->parent < 0 || p->parent >= numbones)
2707                                 {
2708                                         Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2709                                         p->parent = 0;
2710                                 }
2711                         }
2712                         buffer = p;
2713                 }
2714                 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2715                 {
2716                         pskrawweights_t *p;
2717                         if (recordsize != sizeof(*p))
2718                                 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2719                         // byteswap in place and keep the pointer
2720                         numrawweights = numrecords;
2721                         rawweights = (pskrawweights_t *)buffer;
2722                         for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2723                         {
2724                                 p->weight = LittleFloat(p->weight);
2725                                 p->pntsindex = LittleLong(p->pntsindex);
2726                                 p->boneindex = LittleLong(p->boneindex);
2727                                 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2728                                 {
2729                                         Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2730                                         p->pntsindex = 0;
2731                                 }
2732                                 if (p->boneindex < 0 || p->boneindex >= numbones)
2733                                 {
2734                                         Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2735                                         p->boneindex = 0;
2736                                 }
2737                         }
2738                         buffer = p;
2739                 }
2740         }
2741
2742         while (animbuffer < animbufferend)
2743         {
2744                 pchunk = (pskchunk_t *)animbuffer;
2745                 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2746                 version = LittleLong(pchunk->version);
2747                 recordsize = LittleLong(pchunk->recordsize);
2748                 numrecords = LittleLong(pchunk->numrecords);
2749                 if (developer_extra.integer)
2750                         Con_DPrintf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2751                 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2752                         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);
2753                 if (!strcmp(pchunk->id, "ANIMHEAD"))
2754                 {
2755                         // nothing to do
2756                 }
2757                 else if (!strcmp(pchunk->id, "BONENAMES"))
2758                 {
2759                         pskboneinfo_t *p;
2760                         if (recordsize != sizeof(*p))
2761                                 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2762                         // byteswap in place and keep the pointer
2763                         numanimbones = numrecords;
2764                         //animbones = (pskboneinfo_t *)animbuffer;
2765                         // NOTE: supposedly psa does not need to match the psk model, the
2766                         // bones missing from the psa would simply use their base
2767                         // positions from the psk, but this is hard for me to implement
2768                         // and people can easily make animations that match.
2769                         if (numanimbones != numbones)
2770                                 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2771                         for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2772                         {
2773                                 p->numchildren = LittleLong(p->numchildren);
2774                                 p->parent = LittleLong(p->parent);
2775                                 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2776                                 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2777                                 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2778                                 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2779                                 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2780                                 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2781                                 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2782                                 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2783                                 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2784                                 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2785                                 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2786 #ifdef PSKQUATNEGATIONS
2787                                 if (index)
2788                                 {
2789                                         p->basepose.quat[0] *= -1;
2790                                         p->basepose.quat[1] *= -1;
2791                                         p->basepose.quat[2] *= -1;
2792                                 }
2793                                 else
2794                                 {
2795                                         p->basepose.quat[0] *=  1;
2796                                         p->basepose.quat[1] *= -1;
2797                                         p->basepose.quat[2] *=  1;
2798                                 }
2799 #endif
2800                                 if (p->parent < 0 || p->parent >= numanimbones)
2801                                 {
2802                                         Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2803                                         p->parent = 0;
2804                                 }
2805                                 // check that bones are the same as in the base
2806                                 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2807                                         Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2808                         }
2809                         animbuffer = p;
2810                 }
2811                 else if (!strcmp(pchunk->id, "ANIMINFO"))
2812                 {
2813                         pskaniminfo_t *p;
2814                         if (recordsize != sizeof(*p))
2815                                 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2816                         // byteswap in place and keep the pointer
2817                         numanims = numrecords;
2818                         anims = (pskaniminfo_t *)animbuffer;
2819                         for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2820                         {
2821                                 p->numbones = LittleLong(p->numbones);
2822                                 p->playtime = LittleFloat(p->playtime);
2823                                 p->fps = LittleFloat(p->fps);
2824                                 p->firstframe = LittleLong(p->firstframe);
2825                                 p->numframes = LittleLong(p->numframes);
2826                                 if (p->numbones != numbones)
2827                                         Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2828                         }
2829                         animbuffer = p;
2830                 }
2831                 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2832                 {
2833                         pskanimkeys_t *p;
2834                         if (recordsize != sizeof(*p))
2835                                 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2836                         numanimkeys = numrecords;
2837                         animkeys = (pskanimkeys_t *)animbuffer;
2838                         for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2839                         {
2840                                 p->origin[0] = LittleFloat(p->origin[0]);
2841                                 p->origin[1] = LittleFloat(p->origin[1]);
2842                                 p->origin[2] = LittleFloat(p->origin[2]);
2843                                 p->quat[0] = LittleFloat(p->quat[0]);
2844                                 p->quat[1] = LittleFloat(p->quat[1]);
2845                                 p->quat[2] = LittleFloat(p->quat[2]);
2846                                 p->quat[3] = LittleFloat(p->quat[3]);
2847                                 p->frametime = LittleFloat(p->frametime);
2848 #ifdef PSKQUATNEGATIONS
2849                                 if (index % numbones)
2850                                 {
2851                                         p->quat[0] *= -1;
2852                                         p->quat[1] *= -1;
2853                                         p->quat[2] *= -1;
2854                                 }
2855                                 else
2856                                 {
2857                                         p->quat[0] *=  1;
2858                                         p->quat[1] *= -1;
2859                                         p->quat[2] *=  1;
2860                                 }
2861 #endif
2862                         }
2863                         animbuffer = p;
2864                         // TODO: allocate bonepose stuff
2865                 }
2866                 else
2867                         Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2868         }
2869
2870         if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights)
2871                 Host_Error("%s: missing required chunks", loadmodel->name);
2872
2873         if (numanims)
2874         {
2875                 loadmodel->numframes = 0;
2876                 for (index = 0;index < numanims;index++)
2877                         loadmodel->numframes += anims[index].numframes;
2878                 if (numanimkeys != numbones * loadmodel->numframes)
2879                         Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2880         }
2881         else
2882                 loadmodel->numframes = loadmodel->num_poses = 1;
2883
2884         meshvertices = numvtxw;
2885         meshtriangles = numfaces;
2886
2887         // load external .skin files if present
2888         skinfiles = Mod_LoadSkinFiles();
2889         if (loadmodel->numskins < 1)
2890                 loadmodel->numskins = 1;
2891         loadmodel->num_bones = numbones;
2892         loadmodel->num_poses = loadmodel->numframes;
2893         loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2894         loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2895         loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2896         loadmodel->surfmesh.num_vertices = meshvertices;
2897         loadmodel->surfmesh.num_triangles = meshtriangles;
2898         // do most allocations as one merged chunk
2899         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 char[4]) + loadmodel->surfmesh.num_vertices * sizeof(unsigned char[4]) + loadmodel->surfmesh.num_vertices * sizeof(unsigned short) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]) + 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);
2900         data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2901         loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2902         loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2903         loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2904         loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2905         if (r_enableshadowvolumes.integer)
2906         {
2907                 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2908         }
2909         loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2910         loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2911         loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2912         loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2913         loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2914         loadmodel->surfmesh.data_skeletalindex4ub = (unsigned char *)data;data += loadmodel->surfmesh.num_vertices * sizeof(unsigned char[4]);
2915         loadmodel->surfmesh.data_skeletalweight4ub = (unsigned char *)data;data += loadmodel->surfmesh.num_vertices * sizeof(unsigned char[4]);
2916         loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2917         loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2918         loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2919         loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2920         loadmodel->surfmesh.num_blends = 0;
2921         loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
2922         if (loadmodel->surfmesh.num_vertices <= 65536)
2923         {
2924                 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2925         }
2926         loadmodel->data_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
2927         loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(blendweights_t));
2928
2929         for (i = 0;i < loadmodel->numskins;i++)
2930         {
2931                 loadmodel->skinscenes[i].firstframe = i;
2932                 loadmodel->skinscenes[i].framecount = 1;
2933                 loadmodel->skinscenes[i].loop = true;
2934                 loadmodel->skinscenes[i].framerate = 10;
2935         }
2936
2937         // create surfaces
2938         for (index = 0, i = 0;index < nummatts;index++)
2939         {
2940                 // since psk models do not have named sections, reuse their shader name as the section name
2941                 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2942                 loadmodel->sortedmodelsurfaces[index] = index;
2943                 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2944                 loadmodel->data_surfaces[index].num_firstvertex = 0;
2945                 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2946         }
2947
2948         // copy over the vertex locations and texcoords
2949         for (index = 0;index < numvtxw;index++)
2950         {
2951                 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2952                 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2953                 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2954                 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2955                 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2956         }
2957
2958         // loading the faces is complicated because we need to sort them into surfaces by mattindex
2959         for (index = 0;index < numfaces;index++)
2960                 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2961         for (index = 0, i = 0;index < nummatts;index++)
2962         {
2963                 loadmodel->data_surfaces[index].num_firsttriangle = i;
2964                 i += loadmodel->data_surfaces[index].num_triangles;
2965                 loadmodel->data_surfaces[index].num_triangles = 0;
2966         }
2967         for (index = 0;index < numfaces;index++)
2968         {
2969                 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2970                 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2971                 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2972                 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2973         }
2974
2975         // copy over the bones
2976         for (index = 0;index < numbones;index++)
2977         {
2978                 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2979                 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2980                 if (loadmodel->data_bones[index].parent >= index)
2981                         Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2982         }
2983
2984         // convert the basepose data
2985         if (loadmodel->num_bones)
2986         {
2987                 int boneindex;
2988                 matrix4x4_t *basebonepose;
2989                 float *outinvmatrix = loadmodel->data_baseboneposeinverse;
2990                 matrix4x4_t bonematrix;
2991                 matrix4x4_t tempbonematrix;
2992                 basebonepose = (matrix4x4_t *)Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(matrix4x4_t));
2993                 for (boneindex = 0;boneindex < loadmodel->num_bones;boneindex++)
2994                 {
2995                         Matrix4x4_FromOriginQuat(&bonematrix, bones[boneindex].basepose.origin[0], bones[boneindex].basepose.origin[1], bones[boneindex].basepose.origin[2], bones[boneindex].basepose.quat[0], bones[boneindex].basepose.quat[1], bones[boneindex].basepose.quat[2], bones[boneindex].basepose.quat[3]);
2996                         if (loadmodel->data_bones[boneindex].parent >= 0)
2997                         {
2998                                 tempbonematrix = bonematrix;
2999                                 Matrix4x4_Concat(&bonematrix, basebonepose + loadmodel->data_bones[boneindex].parent, &tempbonematrix);
3000                         }
3001                         basebonepose[boneindex] = bonematrix;
3002                         Matrix4x4_Invert_Simple(&tempbonematrix, basebonepose + boneindex);
3003                         Matrix4x4_ToArray12FloatD3D(&tempbonematrix, outinvmatrix + 12*boneindex);
3004                 }
3005                 Mem_Free(basebonepose);
3006         }
3007
3008         // sort the psk point weights into the vertex weight tables
3009         // (which only accept up to 4 bones per vertex)
3010         for (index = 0;index < numvtxw;index++)
3011         {
3012                 int weightindex[4] = { 0, 0, 0, 0 };
3013                 float weightinfluence[4] = { 0, 0, 0, 0 };
3014                 int l;
3015                 for (j = 0;j < numrawweights;j++)
3016                 {
3017                         if (rawweights[j].pntsindex == vtxw[index].pntsindex)
3018                         {
3019                                 int boneindex = rawweights[j].boneindex;
3020                                 float influence = rawweights[j].weight;
3021                                 for (l = 0;l < 4;l++)
3022                                 {
3023                                         if (weightinfluence[l] < influence)
3024                                         {
3025                                                 // move lower influence weights out of the way first
3026                                                 int l2;
3027                                                 for (l2 = 3;l2 > l;l2--)
3028                                                 {
3029                                                         weightinfluence[l2] = weightinfluence[l2-1];
3030                                                         weightindex[l2] = weightindex[l2-1];
3031                                                 }
3032                                                 // store the new weight
3033                                                 weightinfluence[l] = influence;
3034                                                 weightindex[l] = boneindex;
3035                                                 break;
3036                                         }
3037                                 }
3038                         }
3039                 }
3040                 loadmodel->surfmesh.blends[index] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence);
3041                 loadmodel->surfmesh.data_skeletalindex4ub[index*4  ] = weightindex[0];
3042                 loadmodel->surfmesh.data_skeletalindex4ub[index*4+1] = weightindex[1];
3043                 loadmodel->surfmesh.data_skeletalindex4ub[index*4+2] = weightindex[2];
3044                 loadmodel->surfmesh.data_skeletalindex4ub[index*4+3] = weightindex[3];
3045                 loadmodel->surfmesh.data_skeletalweight4ub[index*4  ] = (unsigned char)(weightinfluence[0]*255.0f);
3046                 loadmodel->surfmesh.data_skeletalweight4ub[index*4+1] = (unsigned char)(weightinfluence[1]*255.0f);
3047                 loadmodel->surfmesh.data_skeletalweight4ub[index*4+2] = (unsigned char)(weightinfluence[2]*255.0f);
3048                 loadmodel->surfmesh.data_skeletalweight4ub[index*4+3] = (unsigned char)(weightinfluence[3]*255.0f);
3049         }
3050         if (loadmodel->surfmesh.num_blends < loadmodel->surfmesh.num_vertices)
3051                 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
3052
3053         // set up the animscenes based on the anims
3054         if (numanims)
3055         {
3056                 for (index = 0, i = 0;index < numanims;index++)
3057                 {
3058                         for (j = 0;j < anims[index].numframes;j++, i++)
3059                         {
3060                                 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
3061                                 loadmodel->animscenes[i].firstframe = i;
3062                                 loadmodel->animscenes[i].framecount = 1;
3063                                 loadmodel->animscenes[i].loop = true;
3064                                 loadmodel->animscenes[i].framerate = anims[index].fps;
3065                         }
3066                 }
3067                 // calculate the scaling value for bone origins so they can be compressed to short
3068                 biggestorigin = 0;
3069                 for (index = 0;index < numanimkeys;index++)
3070                 {
3071                         pskanimkeys_t *k = animkeys + index;
3072                         biggestorigin = max(biggestorigin, fabs(k->origin[0]));
3073                         biggestorigin = max(biggestorigin, fabs(k->origin[1]));
3074                         biggestorigin = max(biggestorigin, fabs(k->origin[2]));
3075                 }
3076                 loadmodel->num_posescale = biggestorigin / 32767.0f;
3077                 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3078         
3079                 // load the poses from the animkeys
3080                 for (index = 0;index < numanimkeys;index++)
3081                 {
3082                         pskanimkeys_t *k = animkeys + index;
3083                         float quat[4];
3084                         Vector4Copy(k->quat, quat);
3085                         if (quat[3] > 0)
3086                                 Vector4Negate(quat, quat);
3087                         Vector4Normalize2(quat, quat);
3088                         // compress poses to the short[7] format for longterm storage
3089                         loadmodel->data_poses7s[index*7+0] = k->origin[0] * loadmodel->num_poseinvscale;
3090                         loadmodel->data_poses7s[index*7+1] = k->origin[1] * loadmodel->num_poseinvscale;
3091                         loadmodel->data_poses7s[index*7+2] = k->origin[2] * loadmodel->num_poseinvscale;
3092                         loadmodel->data_poses7s[index*7+3] = quat[0] * 32767.0f;
3093                         loadmodel->data_poses7s[index*7+4] = quat[1] * 32767.0f;
3094                         loadmodel->data_poses7s[index*7+5] = quat[2] * 32767.0f;
3095                         loadmodel->data_poses7s[index*7+6] = quat[3] * 32767.0f;
3096                 }
3097         }
3098         else
3099         {
3100                 strlcpy(loadmodel->animscenes[0].name, "base", sizeof(loadmodel->animscenes[0].name));
3101                 loadmodel->animscenes[0].firstframe = 0;
3102                 loadmodel->animscenes[0].framecount = 1;
3103                 loadmodel->animscenes[0].loop = true;
3104                 loadmodel->animscenes[0].framerate = 10;
3105
3106                 // calculate the scaling value for bone origins so they can be compressed to short
3107                 biggestorigin = 0;
3108                 for (index = 0;index < numbones;index++)
3109                 {
3110                         pskboneinfo_t *p = bones + index;
3111                         biggestorigin = max(biggestorigin, fabs(p->basepose.origin[0]));
3112                         biggestorigin = max(biggestorigin, fabs(p->basepose.origin[1]));
3113                         biggestorigin = max(biggestorigin, fabs(p->basepose.origin[2]));
3114                 }
3115                 loadmodel->num_posescale = biggestorigin / 32767.0f;
3116                 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3117         
3118                 // load the basepose as a frame
3119                 for (index = 0;index < numbones;index++)
3120                 {
3121                         pskboneinfo_t *p = bones + index;
3122                         float quat[4];
3123                         Vector4Copy(p->basepose.quat, quat);
3124                         if (quat[3] > 0)
3125                                 Vector4Negate(quat, quat);
3126                         Vector4Normalize2(quat, quat);
3127                         // compress poses to the short[7] format for longterm storage
3128                         loadmodel->data_poses7s[index*7+0] = p->basepose.origin[0] * loadmodel->num_poseinvscale;
3129                         loadmodel->data_poses7s[index*7+1] = p->basepose.origin[1] * loadmodel->num_poseinvscale;
3130                         loadmodel->data_poses7s[index*7+2] = p->basepose.origin[2] * loadmodel->num_poseinvscale;
3131                         loadmodel->data_poses7s[index*7+3] = quat[0] * 32767.0f;
3132                         loadmodel->data_poses7s[index*7+4] = quat[1] * 32767.0f;
3133                         loadmodel->data_poses7s[index*7+5] = quat[2] * 32767.0f;
3134                         loadmodel->data_poses7s[index*7+6] = quat[3] * 32767.0f;
3135                 }
3136         }
3137
3138         Mod_FreeSkinFiles(skinfiles);
3139         if (animfilebuffer)
3140                 Mem_Free(animfilebuffer);
3141         Mod_MakeSortedSurfaces(loadmodel);
3142
3143         // compute all the mesh information that was not loaded from the file
3144         // TODO: honor smoothing groups somehow?
3145         if (loadmodel->surfmesh.data_element3s)
3146                 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3147                         loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3148         Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
3149         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);
3150         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);
3151         if (loadmodel->surfmesh.data_neighbor3i)
3152                 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3153         loadmodel->surfmesh.isanimated = Mod_Alias_CalculateBoundingBox();
3154         if(mod_alias_force_animated.string[0])
3155                 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
3156
3157         if (!loadmodel->surfmesh.isanimated)
3158         {
3159                 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3160                 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3161                 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3162                 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3163                 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3164                 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
3165         }
3166
3167         // because shaders can do somewhat unexpected things, check for unusual features now
3168         for (i = 0;i < loadmodel->num_textures;i++)
3169         {
3170                 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
3171                         mod->DrawSky = R_Q1BSP_DrawSky;
3172                 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
3173                         mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
3174         }
3175 }
3176
3177 void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
3178 {
3179         unsigned char *data;
3180         const char *text;
3181         const unsigned char *pbase, *pend;
3182         iqmheader_t header;
3183         skinfile_t *skinfiles;
3184         int i, j, k, meshvertices, meshtriangles;
3185         float biggestorigin;
3186         const unsigned int *inelements;
3187         int *outelements;
3188         const int *inneighbors;
3189         int *outneighbors;
3190         float *outvertex, *outnormal, *outtexcoord, *outsvector, *outtvector, *outcolor;
3191         // this pointers into the file data are read only through Little* functions so they can be unaligned memory
3192         const float *vnormal = NULL;
3193         const float *vposition = NULL;
3194         const float *vtangent = NULL;
3195         const float *vtexcoord = NULL;
3196         const float *vcolor4f = NULL;
3197         const unsigned char *vblendindexes = NULL;
3198         const unsigned char *vblendweights = NULL;
3199         const unsigned char *vcolor4ub = NULL;
3200         const unsigned short *framedata = NULL;
3201         // temporary memory allocations (because the data in the file may be misaligned)
3202         iqmanim_t *anims = NULL;
3203         iqmbounds_t *bounds = NULL;
3204         iqmjoint1_t *joint1 = NULL;
3205         iqmjoint_t *joint = NULL;
3206         iqmmesh_t *meshes = NULL;
3207         iqmpose1_t *pose1 = NULL;
3208         iqmpose_t *pose = NULL;
3209         iqmvertexarray_t *vas = NULL;
3210
3211         pbase = (unsigned char *)buffer;
3212         pend = (unsigned char *)bufferend;
3213
3214         if (pbase + sizeof(iqmheader_t) > pend)
3215                 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model %d", loadmodel->name, (int)(pend - pbase));
3216
3217         // copy struct (otherwise it may be misaligned)
3218         // LordHavoc: okay it's definitely not misaligned here, but for consistency...
3219         memcpy(&header, pbase, sizeof(iqmheader_t));
3220
3221         if (memcmp(header.id, "INTERQUAKEMODEL", 16))
3222                 Host_Error ("Mod_INTERQUAKEMODEL_Load: %s is not an Inter-Quake Model", loadmodel->name);
3223         if (LittleLong(header.version) != 1 && LittleLong(header.version) != 2)
3224                 Host_Error ("Mod_INTERQUAKEMODEL_Load: only version 1 and 2 models are currently supported (name = %s)", loadmodel->name);
3225
3226         loadmodel->modeldatatypestring = "IQM";
3227
3228         loadmodel->type = mod_alias;
3229         loadmodel->synctype = ST_RAND;
3230
3231         // byteswap header
3232         header.version = LittleLong(header.version);
3233         header.filesize = LittleLong(header.filesize);
3234         header.flags = LittleLong(header.flags);
3235         header.num_text = LittleLong(header.num_text);
3236         header.ofs_text = LittleLong(header.ofs_text);
3237         header.num_meshes = LittleLong(header.num_meshes);
3238         header.ofs_meshes = LittleLong(header.ofs_meshes);
3239         header.num_vertexarrays = LittleLong(header.num_vertexarrays);
3240         header.num_vertexes = LittleLong(header.num_vertexes);
3241         header.ofs_vertexarrays = LittleLong(header.ofs_vertexarrays);
3242         header.num_triangles = LittleLong(header.num_triangles);
3243         header.ofs_triangles = LittleLong(header.ofs_triangles);
3244         header.ofs_neighbors = LittleLong(header.ofs_neighbors);
3245         header.num_joints = LittleLong(header.num_joints);
3246         header.ofs_joints = LittleLong(header.ofs_joints);
3247         header.num_poses = LittleLong(header.num_poses);
3248         header.ofs_poses = LittleLong(header.ofs_poses);
3249         header.num_anims = LittleLong(header.num_anims);
3250         header.ofs_anims = LittleLong(header.ofs_anims);
3251         header.num_frames = LittleLong(header.num_frames);
3252         header.num_framechannels = LittleLong(header.num_framechannels);
3253         header.ofs_frames = LittleLong(header.ofs_frames);
3254         header.ofs_bounds = LittleLong(header.ofs_bounds);
3255         header.num_comment = LittleLong(header.num_comment);
3256         header.ofs_comment = LittleLong(header.ofs_comment);
3257         header.num_extensions = LittleLong(header.num_extensions);
3258         header.ofs_extensions = LittleLong(header.ofs_extensions);
3259
3260         if (header.version == 1)
3261         {
3262                 if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint1_t) > pend ||
3263                         pbase + header.ofs_poses + header.num_poses*sizeof(iqmpose1_t) > pend)
3264                 {
3265                         Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3266                         return;
3267                 }
3268         }
3269         else
3270         {
3271                 if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint_t) > pend ||
3272                         pbase + header.ofs_poses + header.num_poses*sizeof(iqmpose_t) > pend)
3273                 {
3274                         Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3275                         return;
3276                 }
3277         }
3278         if (pbase + header.ofs_text + header.num_text > pend ||
3279                 pbase + header.ofs_meshes + header.num_meshes*sizeof(iqmmesh_t) > pend ||
3280                 pbase + header.ofs_vertexarrays + header.num_vertexarrays*sizeof(iqmvertexarray_t) > pend ||
3281                 pbase + header.ofs_triangles + header.num_triangles*sizeof(int[3]) > pend ||
3282                 (header.ofs_neighbors && pbase + header.ofs_neighbors + header.num_triangles*sizeof(int[3]) > pend) ||
3283                 pbase + header.ofs_anims + header.num_anims*sizeof(iqmanim_t) > pend ||
3284                 pbase + header.ofs_frames + header.num_frames*header.num_framechannels*sizeof(unsigned short) > pend ||
3285                 (header.ofs_bounds && pbase + header.ofs_bounds + header.num_frames*sizeof(iqmbounds_t) > pend) ||
3286                 pbase + header.ofs_comment + header.num_comment > pend)
3287         {
3288                 Con_Printf("%s has invalid size or offset information\n", loadmodel->name);
3289                 return;
3290         }
3291
3292         // copy structs to make them aligned in memory (otherwise we crash on Sparc and PowerPC and others)
3293         if (header.num_vertexarrays)
3294                 vas = (iqmvertexarray_t *)(pbase + header.ofs_vertexarrays);
3295         if (header.num_anims)
3296                 anims = (iqmanim_t *)(pbase + header.ofs_anims);
3297         if (header.ofs_bounds)
3298                 bounds = (iqmbounds_t *)(pbase + header.ofs_bounds);
3299         if (header.num_meshes)
3300                 meshes = (iqmmesh_t *)(pbase + header.ofs_meshes);
3301
3302         for (i = 0;i < (int)header.num_vertexarrays;i++)
3303         {
3304                 iqmvertexarray_t va;
3305                 size_t vsize;
3306                 va.type = LittleLong(vas[i].type);
3307                 va.flags = LittleLong(vas[i].flags);
3308                 va.format = LittleLong(vas[i].format);
3309                 va.size = LittleLong(vas[i].size);
3310                 va.offset = LittleLong(vas[i].offset);
3311                 vsize = header.num_vertexes*va.size;
3312                 switch (va.format)
3313                 { 
3314                 case IQM_FLOAT: vsize *= sizeof(float); break;
3315                 case IQM_UBYTE: vsize *= sizeof(unsigned char); break;
3316                 default: continue;
3317                 }
3318                 if (pbase + va.offset + vsize > pend)
3319                         continue;
3320                 // no need to copy the vertex data for alignment because LittleLong/LittleShort will be invoked on reading them, and the destination is aligned
3321                 switch (va.type)
3322                 {
3323                 case IQM_POSITION:
3324                         if (va.format == IQM_FLOAT && va.size == 3)
3325                                 vposition = (const float *)(pbase + va.offset);
3326                         break;
3327                 case IQM_TEXCOORD:
3328                         if (va.format == IQM_FLOAT && va.size == 2)
3329                                 vtexcoord = (const float *)(pbase + va.offset);
3330                         break;
3331                 case IQM_NORMAL:
3332                         if (va.format == IQM_FLOAT && va.size == 3)
3333                                 vnormal = (const float *)(pbase + va.offset);
3334                         break;
3335                 case IQM_TANGENT:
3336                         if (va.format == IQM_FLOAT && va.size == 4)
3337                                 vtangent = (const float *)(pbase + va.offset);
3338                         break;
3339                 case IQM_BLENDINDEXES:
3340                         if (va.format == IQM_UBYTE && va.size == 4)
3341                                 vblendindexes = (const unsigned char *)(pbase + va.offset);
3342                         break;
3343                 case IQM_BLENDWEIGHTS:
3344                         if (va.format == IQM_UBYTE && va.size == 4)
3345                                 vblendweights = (const unsigned char *)(pbase + va.offset);
3346                         break;
3347                 case IQM_COLOR:
3348                         if (va.format == IQM_FLOAT && va.size == 4)
3349                                 vcolor4f = (const float *)(pbase + va.offset);
3350                         if (va.format == IQM_UBYTE && va.size == 4)
3351                                 vcolor4ub = (const unsigned char *)(pbase + va.offset);
3352                         break;
3353                 }
3354         }
3355         if (header.num_vertexes > 0 && (!vposition || !vtexcoord || ((header.num_frames > 0 || header.num_anims > 0) && (!vblendindexes || !vblendweights))))
3356         {
3357                 Con_Printf("%s is missing vertex array data\n", loadmodel->name);
3358                 return;
3359         }
3360
3361         text = header.num_text && header.ofs_text ? (const char *)(pbase + header.ofs_text) : "";
3362
3363         loadmodel->DrawSky = NULL;
3364         loadmodel->DrawAddWaterPlanes = NULL;
3365         loadmodel->Draw = R_Q1BSP_Draw;
3366         loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
3367         loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
3368         loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
3369         loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
3370         loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
3371         loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
3372         loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
3373         loadmodel->DrawLight = R_Q1BSP_DrawLight;
3374         loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
3375         loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
3376         loadmodel->PointSuperContents = NULL;
3377         loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
3378
3379         // load external .skin files if present
3380         skinfiles = Mod_LoadSkinFiles();
3381         if (loadmodel->numskins < 1)
3382                 loadmodel->numskins = 1;
3383
3384         loadmodel->numframes = max(header.num_anims, 1);
3385         loadmodel->num_bones = header.num_joints;
3386         loadmodel->num_poses = max(header.num_frames, 1);
3387         loadmodel->nummodelsurfaces = loadmodel->num_surfaces = header.num_meshes;
3388         loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
3389         loadmodel->num_texturesperskin = loadmodel->num_surfaces;
3390
3391         meshvertices = header.num_vertexes;
3392         meshtriangles = header.num_triangles;
3393
3394         // do most allocations as one merged chunk
3395         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]) + (vcolor4f || vcolor4ub ? sizeof(float[4]) : 0)) + (vblendindexes && vblendweights ? meshvertices * (sizeof(unsigned short) + sizeof(unsigned char[2][4])) : 0) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
3396         loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
3397         loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
3398         loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
3399         loadmodel->surfmesh.num_vertices = meshvertices;
3400         loadmodel->surfmesh.num_triangles = meshtriangles;
3401         loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3402         if (r_enableshadowvolumes.integer)
3403         {
3404                 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
3405         }
3406         loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
3407         loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3408         loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
3409         loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
3410         loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
3411         if (vcolor4f || vcolor4ub)
3412         {
3413                 loadmodel->surfmesh.data_lightmapcolor4f = (float *)data;data += meshvertices * sizeof(float[4]);
3414         }
3415         if (vblendindexes && vblendweights)
3416         {
3417                 loadmodel->surfmesh.data_skeletalindex4ub = (unsigned char *)data;data += meshvertices * sizeof(unsigned char[4]);
3418                 loadmodel->surfmesh.data_skeletalweight4ub = (unsigned char *)data;data += meshvertices * sizeof(unsigned char[4]);
3419         }
3420         loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
3421         loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
3422         loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
3423         loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
3424         if (vblendindexes && vblendweights)
3425         {
3426                 loadmodel->surfmesh.num_blends = 0;
3427                 loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short);
3428         }
3429         if (meshvertices <= 65536)
3430         {
3431                 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
3432         }
3433         loadmodel->data_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
3434         if (vblendindexes && vblendweights)
3435                 loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
3436
3437         for (i = 0;i < loadmodel->numskins;i++)
3438         {
3439                 loadmodel->skinscenes[i].firstframe = i;
3440                 loadmodel->skinscenes[i].framecount = 1;
3441                 loadmodel->skinscenes[i].loop = true;
3442                 loadmodel->skinscenes[i].framerate = 10;
3443         }
3444
3445         // load the bone info
3446         if (header.version == 1)
3447         {
3448                 iqmjoint1_t *injoint1 = (iqmjoint1_t *)(pbase + header.ofs_joints);
3449                 if (loadmodel->num_bones)
3450                         joint1 = (iqmjoint1_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(iqmjoint1_t));
3451                 for (i = 0;i < loadmodel->num_bones;i++)
3452                 {
3453                         matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3454                         joint1[i].name = LittleLong(injoint1[i].name);
3455                         joint1[i].parent = LittleLong(injoint1[i].parent);
3456                         for (j = 0;j < 3;j++)
3457                         {
3458                                 joint1[i].origin[j] = LittleFloat(injoint1[i].origin[j]);
3459                                 joint1[i].rotation[j] = LittleFloat(injoint1[i].rotation[j]);
3460                                 joint1[i].scale[j] = LittleFloat(injoint1[i].scale[j]);
3461                         }
3462                         strlcpy(loadmodel->data_bones[i].name, &text[joint1[i].name], sizeof(loadmodel->data_bones[i].name));
3463                         loadmodel->data_bones[i].parent = joint1[i].parent;
3464                         if (loadmodel->data_bones[i].parent >= i)
3465                                 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3466                         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]);
3467                         Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3468                         if (loadmodel->data_bones[i].parent >= 0)
3469                         {
3470                                 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3471                                 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3472                                 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3473                         }
3474                         else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3475                 }
3476         }
3477         else
3478         {
3479                 iqmjoint_t *injoint = (iqmjoint_t *)(pbase + header.ofs_joints);
3480                 if (header.num_joints)
3481                         joint = (iqmjoint_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(iqmjoint_t));
3482                 for (i = 0;i < loadmodel->num_bones;i++)
3483                 {
3484                         matrix4x4_t relbase, relinvbase, pinvbase, invbase;
3485                         joint[i].name = LittleLong(injoint[i].name);
3486                         joint[i].parent = LittleLong(injoint[i].parent);
3487                         for (j = 0;j < 3;j++)
3488                         {
3489                                 joint[i].origin[j] = LittleFloat(injoint[i].origin[j]);
3490                                 joint[i].rotation[j] = LittleFloat(injoint[i].rotation[j]);
3491                                 joint[i].scale[j] = LittleFloat(injoint[i].scale[j]);
3492                         }
3493                         joint[i].rotation[3] = LittleFloat(injoint[i].rotation[3]);
3494                         strlcpy(loadmodel->data_bones[i].name, &text[joint[i].name], sizeof(loadmodel->data_bones[i].name));
3495                         loadmodel->data_bones[i].parent = joint[i].parent;
3496                         if (loadmodel->data_bones[i].parent >= i)
3497                                 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
3498                         if (joint[i].rotation[3] > 0)
3499                                 Vector4Negate(joint[i].rotation, joint[i].rotation);
3500                         Vector4Normalize2(joint[i].rotation, joint[i].rotation);
3501                         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]);
3502                         Matrix4x4_Invert_Simple(&relinvbase, &relbase);
3503                         if (loadmodel->data_bones[i].parent >= 0)
3504                         {
3505                                 Matrix4x4_FromArray12FloatD3D(&pinvbase, loadmodel->data_baseboneposeinverse + 12*loadmodel->data_bones[i].parent);
3506                                 Matrix4x4_Concat(&invbase, &relinvbase, &pinvbase);
3507                                 Matrix4x4_ToArray12FloatD3D(&invbase, loadmodel->data_baseboneposeinverse + 12*i);
3508                         }       
3509                         else Matrix4x4_ToArray12FloatD3D(&relinvbase, loadmodel->data_baseboneposeinverse + 12*i);
3510                 }
3511         }
3512
3513         // set up the animscenes based on the anims
3514         for (i = 0;i < (int)header.num_anims;i++)
3515         {
3516                 iqmanim_t anim;
3517                 anim.name = LittleLong(anims[i].name);
3518                 anim.first_frame = LittleLong(anims[i].first_frame);
3519                 anim.num_frames = LittleLong(anims[i].num_frames);
3520                 anim.framerate = LittleFloat(anims[i].framerate);
3521                 anim.flags = LittleLong(anims[i].flags);
3522                 strlcpy(loadmodel->animscenes[i].name, &text[anim.name], sizeof(loadmodel->animscenes[i].name));
3523                 loadmodel->animscenes[i].firstframe = anim.first_frame;
3524                 loadmodel->animscenes[i].framecount = anim.num_frames;
3525                 loadmodel->animscenes[i].loop = ((anim.flags & IQM_LOOP) != 0);
3526                 loadmodel->animscenes[i].framerate = anim.framerate;
3527         }
3528         if (header.num_anims <= 0)
3529         {
3530                 strlcpy(loadmodel->animscenes[0].name, "static", sizeof(loadmodel->animscenes[0].name));
3531                 loadmodel->animscenes[0].firstframe = 0;
3532                 loadmodel->animscenes[0].framecount = 1;
3533                 loadmodel->animscenes[0].loop = true;
3534                 loadmodel->animscenes[0].framerate = 10;
3535         }
3536
3537         loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
3538         if(mod_alias_force_animated.string[0])
3539                 loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
3540
3541         biggestorigin = 0;
3542         if (header.version == 1)
3543         {
3544                 iqmpose1_t *inpose1 = (iqmpose1_t *)(pbase + header.ofs_poses);
3545                 if (header.num_poses)
3546                         pose1 = (iqmpose1_t *)Mem_Alloc(loadmodel->mempool, header.num_poses * sizeof(iqmpose1_t));
3547                 for (i = 0;i < (int)header.num_poses;i++)
3548                 {
3549                         float f;
3550                         pose1[i].parent = LittleLong(inpose1[i].parent);
3551                         pose1[i].channelmask = LittleLong(inpose1[i].channelmask);
3552                         for (j = 0;j < 9;j++)
3553                         {
3554                                 pose1[i].channeloffset[j] = LittleFloat(inpose1[i].channeloffset[j]);
3555                                 pose1[i].channelscale[j] = LittleFloat(inpose1[i].channelscale[j]);
3556                         }
3557                         f = fabs(pose1[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3558                         f = fabs(pose1[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3559                         f = fabs(pose1[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3560                         f = fabs(pose1[i].channeloffset[0] + 0xFFFF*pose1[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3561                         f = fabs(pose1[i].channeloffset[1] + 0xFFFF*pose1[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3562                         f = fabs(pose1[i].channeloffset[2] + 0xFFFF*pose1[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3563                 }
3564                 if (header.num_frames <= 0)
3565                 {
3566                         for (i = 0;i < loadmodel->num_bones;i++)
3567                         {
3568                                 float f;
3569                                 f = fabs(joint1[i].origin[0]); biggestorigin = max(biggestorigin, f);
3570                                 f = fabs(joint1[i].origin[1]); biggestorigin = max(biggestorigin, f);
3571                                 f = fabs(joint1[i].origin[2]); biggestorigin = max(biggestorigin, f);
3572                         }
3573                 }
3574         }
3575         else
3576         {
3577                 iqmpose_t *inpose = (iqmpose_t *)(pbase + header.ofs_poses);
3578                 if (header.num_poses)
3579                         pose = (iqmpose_t *)Mem_Alloc(loadmodel->mempool, header.num_poses * sizeof(iqmpose_t));
3580                 for (i = 0;i < (int)header.num_poses;i++)
3581                 {
3582                         float f;
3583                         pose[i].parent = LittleLong(inpose[i].parent);
3584                         pose[i].channelmask = LittleLong(inpose[i].channelmask);
3585                         for (j = 0;j < 10;j++)
3586                         {
3587                                 pose[i].channeloffset[j] = LittleFloat(inpose[i].channeloffset[j]);
3588                                 pose[i].channelscale[j] = LittleFloat(inpose[i].channelscale[j]);
3589                         }
3590                         f = fabs(pose[i].channeloffset[0]); biggestorigin = max(biggestorigin, f);
3591                         f = fabs(pose[i].channeloffset[1]); biggestorigin = max(biggestorigin, f);
3592                         f = fabs(pose[i].channeloffset[2]); biggestorigin = max(biggestorigin, f);
3593                         f = fabs(pose[i].channeloffset[0] + 0xFFFF*pose[i].channelscale[0]); biggestorigin = max(biggestorigin, f);
3594                         f = fabs(pose[i].channeloffset[1] + 0xFFFF*pose[i].channelscale[1]); biggestorigin = max(biggestorigin, f);
3595                         f = fabs(pose[i].channeloffset[2] + 0xFFFF*pose[i].channelscale[2]); biggestorigin = max(biggestorigin, f);
3596                 }
3597                 if (header.num_frames <= 0)
3598                 {
3599                         for (i = 0;i < loadmodel->num_bones;i++)
3600                         {
3601                                 float f;
3602                                 f = fabs(joint[i].origin[0]); biggestorigin = max(biggestorigin, f);
3603                                 f = fabs(joint[i].origin[1]); biggestorigin = max(biggestorigin, f);
3604                                 f = fabs(joint[i].origin[2]); biggestorigin = max(biggestorigin, f);
3605                         }
3606                 }
3607         }
3608         loadmodel->num_posescale = biggestorigin / 32767.0f;
3609         loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
3610
3611         // load the pose data
3612         // this unaligned memory access is safe (LittleShort reads as bytes)
3613         framedata = (const unsigned short *)(pbase + header.ofs_frames);
3614         if (header.version == 1)
3615         {
3616                 for (i = 0, k = 0;i < (int)header.num_frames;i++)
3617                 {
3618                         for (j = 0;j < (int)header.num_poses;j++, k++)
3619                         {
3620                                 float qx, qy, qz, qw;
3621                                 loadmodel->data_poses7s[k*7 + 0] = loadmodel->num_poseinvscale * (pose1[j].channeloffset[0] + (pose1[j].channelmask&1 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[0] : 0));
3622                                 loadmodel->data_poses7s[k*7 + 1] = loadmodel->num_poseinvscale * (pose1[j].channeloffset[1] + (pose1[j].channelmask&2 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[1] : 0));
3623                                 loadmodel->data_poses7s[k*7 + 2] = loadmodel->num_poseinvscale * (pose1[j].channeloffset[2] + (pose1[j].channelmask&4 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[2] : 0));
3624                                 qx = pose1[j].channeloffset[3] + (pose1[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[3] : 0);
3625                                 qy = pose1[j].channeloffset[4] + (pose1[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[4] : 0);
3626                                 qz = pose1[j].channeloffset[5] + (pose1[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[5] : 0);
3627                                 qw = 1.0f - (qx*qx + qy*qy + qz*qz);
3628                                 qw = qw > 0.0f ? -sqrt(qw) : 0.0f;
3629                                 loadmodel->data_poses7s[k*7 + 3] = 32767.0f * qx;
3630                                 loadmodel->data_poses7s[k*7 + 4] = 32767.0f * qy;
3631                                 loadmodel->data_poses7s[k*7 + 5] = 32767.0f * qz;
3632                                 loadmodel->data_poses7s[k*7 + 6] = 32767.0f * qw;
3633                                 // skip scale data for now
3634                                 if(pose1[j].channelmask&64) framedata++;
3635                                 if(pose1[j].channelmask&128) framedata++;
3636                                 if(pose1[j].channelmask&256) framedata++;
3637                         }
3638                 }
3639                 if (header.num_frames <= 0)
3640                 {
3641                         for (i = 0;i < loadmodel->num_bones;i++)
3642                         {
3643                                 float qx, qy, qz, qw;
3644                                 loadmodel->data_poses7s[i*7 + 0] = loadmodel->num_poseinvscale * joint1[i].origin[0];
3645                                 loadmodel->data_poses7s[i*7 + 1] = loadmodel->num_poseinvscale * joint1[i].origin[1];
3646                                 loadmodel->data_poses7s[i*7 + 2] = loadmodel->num_poseinvscale * joint1[i].origin[2];
3647                                 qx = joint1[i].rotation[0];
3648                                 qy = joint1[i].rotation[1];
3649                                 qz = joint1[i].rotation[2];
3650                                 qw = 1.0f - (qx*qx + qy*qy + qz*qz);
3651                                 qw = qw > 0.0f ? -sqrt(qw) : 0.0f;
3652                                 loadmodel->data_poses7s[i*7 + 3] = 32767.0f * qx;
3653                                 loadmodel->data_poses7s[i*7 + 4] = 32767.0f * qy;
3654                                 loadmodel->data_poses7s[i*7 + 5] = 32767.0f * qz;
3655                                 loadmodel->data_poses7s[i*7 + 6] = 32767.0f * qw;
3656                         }
3657                 }
3658         }
3659         else
3660         {
3661                 for (i = 0, k = 0;i < (int)header.num_frames;i++)       
3662                 {
3663                         for (j = 0;j < (int)header.num_poses;j++, k++)
3664                         {
3665                                 float rot[4];
3666                                 loadmodel->data_poses7s[k*7 + 0] = loadmodel->num_poseinvscale * (pose[j].channeloffset[0] + (pose[j].channelmask&1 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[0] : 0));
3667                                 loadmodel->data_poses7s[k*7 + 1] = loadmodel->num_poseinvscale * (pose[j].channeloffset[1] + (pose[j].channelmask&2 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[1] : 0));
3668                                 loadmodel->data_poses7s[k*7 + 2] = loadmodel->num_poseinvscale * (pose[j].channeloffset[2] + (pose[j].channelmask&4 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[2] : 0));
3669                                 rot[0] = pose[j].channeloffset[3] + (pose[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[3] : 0);
3670                                 rot[1] = pose[j].channeloffset[4] + (pose[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[4] : 0);
3671                                 rot[2] = pose[j].channeloffset[5] + (pose[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[5] : 0);
3672                                 rot[3] = pose[j].channeloffset[6] + (pose[j].channelmask&64 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[6] : 0);
3673                                 if (rot[3] > 0)
3674                                         Vector4Negate(rot, rot);
3675                                 Vector4Normalize2(rot, rot);
3676                                 loadmodel->data_poses7s[k*7 + 3] = 32767.0f * rot[0];
3677                                 loadmodel->data_poses7s[k*7 + 4] = 32767.0f * rot[1];
3678                                 loadmodel->data_poses7s[k*7 + 5] = 32767.0f * rot[2];
3679                                 loadmodel->data_poses7s[k*7 + 6] = 32767.0f * rot[3];
3680                                 // skip scale data for now
3681                                 if(pose[j].channelmask&128) framedata++;
3682                                 if(pose[j].channelmask&256) framedata++;
3683                                 if(pose[j].channelmask&512) framedata++;
3684                         }
3685                 }
3686                 if (header.num_frames <= 0)
3687                 {
3688                         for (i = 0;i < loadmodel->num_bones;i++)
3689                         {
3690                                 loadmodel->data_poses7s[i*7 + 0] = loadmodel->num_poseinvscale * joint[i].origin[0];
3691                                 loadmodel->data_poses7s[i*7 + 1] = loadmodel->num_poseinvscale * joint[i].origin[1];
3692                                 loadmodel->data_poses7s[i*7 + 2] = loadmodel->num_poseinvscale * joint[i].origin[2];
3693                                 loadmodel->data_poses7s[i*7 + 3] = 32767.0f * joint[i].rotation[0];
3694                                 loadmodel->data_poses7s[i*7 + 4] = 32767.0f * joint[i].rotation[1];
3695                                 loadmodel->data_poses7s[i*7 + 5] = 32767.0f * joint[i].rotation[2];
3696                                 loadmodel->data_poses7s[i*7 + 6] = 32767.0f * joint[i].rotation[3];
3697                         }
3698                 }
3699         }
3700
3701         // load bounding box data
3702         if (header.ofs_bounds)
3703         {
3704                 float xyradius = 0, radius = 0;
3705                 VectorClear(loadmodel->normalmins);
3706                 VectorClear(loadmodel->normalmaxs);
3707                 for (i = 0; i < (int)header.num_frames;i++)
3708                 {
3709                         iqmbounds_t bound;
3710                         bound.mins[0] = LittleFloat(bounds[i].mins[0]);
3711                         bound.mins[1] = LittleFloat(bounds[i].mins[1]);
3712                         bound.mins[2] = LittleFloat(bounds[i].mins[2]);
3713                         bound.maxs[0] = LittleFloat(bounds[i].maxs[0]);                 
3714                         bound.maxs[1] = LittleFloat(bounds[i].maxs[1]); 
3715                         bound.maxs[2] = LittleFloat(bounds[i].maxs[2]); 
3716                         bound.xyradius = LittleFloat(bounds[i].xyradius);
3717                         bound.radius = LittleFloat(bounds[i].radius);
3718                         if (!i)
3719                         {
3720                                 VectorCopy(bound.mins, loadmodel->normalmins);
3721                                 VectorCopy(bound.maxs, loadmodel->normalmaxs);
3722                         }
3723                         else
3724                         {
3725                                 if (loadmodel->normalmins[0] > bound.mins[0]) loadmodel->normalmins[0] = bound.mins[0];
3726                                 if (loadmodel->normalmins[1] > bound.mins[1]) loadmodel->normalmins[1] = bound.mins[1];
3727                                 if (loadmodel->normalmins[2] > bound.mins[2]) loadmodel->normalmins[2] = bound.mins[2];
3728                                 if (loadmodel->normalmaxs[0] < bound.maxs[0]) loadmodel->normalmaxs[0] = bound.maxs[0];
3729                                 if (loadmodel->normalmaxs[1] < bound.maxs[1]) loadmodel->normalmaxs[1] = bound.maxs[1];
3730                                 if (loadmodel->normalmaxs[2] < bound.maxs[2]) loadmodel->normalmaxs[2] = bound.maxs[2];
3731                         }
3732                         if (bound.xyradius > xyradius)
3733                                 xyradius = bound.xyradius;
3734                         if (bound.radius > radius)
3735                                 radius = bound.radius;
3736                 }
3737                 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -xyradius;
3738                 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = xyradius;
3739                 loadmodel->yawmins[2] = loadmodel->normalmins[2];
3740                 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
3741                 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
3742                 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
3743                 loadmodel->radius = radius;
3744                 loadmodel->radius2 = radius * radius;
3745         }
3746
3747         // load triangle data
3748         // this unaligned memory access is safe (LittleLong reads as bytes)
3749         inelements = (const unsigned int *)(pbase + header.ofs_triangles);
3750         outelements = loadmodel->surfmesh.data_element3i;
3751         for (i = 0;i < (int)header.num_triangles;i++)
3752         {
3753                 outelements[0] = LittleLong(inelements[0]);
3754                 outelements[1] = LittleLong(inelements[1]);
3755                 outelements[2] = LittleLong(inelements[2]);
3756                 outelements += 3;
3757                 inelements += 3;
3758         }
3759         Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, header.num_vertexes, __FILE__, __LINE__);
3760
3761         if (header.ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
3762         {
3763                 // this unaligned memory access is safe (LittleLong reads as bytes)
3764                 inneighbors = (const int *)(pbase + header.ofs_neighbors);
3765                 outneighbors = loadmodel->surfmesh.data_neighbor3i;
3766                 for (i = 0;i < (int)header.num_triangles;i++)
3767                 {
3768                         outneighbors[0] = LittleLong(inneighbors[0]);
3769                         outneighbors[1] = LittleLong(inneighbors[1]);
3770                         outneighbors[2] = LittleLong(inneighbors[2]);
3771                         outneighbors += 3;
3772                         inneighbors += 3;
3773                 }
3774         }
3775
3776         // load vertex data
3777         // this unaligned memory access is safe (LittleFloat reads as bytes)
3778         outvertex = loadmodel->surfmesh.data_vertex3f;
3779         for (i = 0;i < (int)header.num_vertexes;i++)
3780         {
3781                 outvertex[0] = LittleFloat(vposition[0]);
3782                 outvertex[1] = LittleFloat(vposition[1]);
3783                 outvertex[2] = LittleFloat(vposition[2]);
3784                 vposition += 3;
3785                 outvertex += 3;
3786         }
3787
3788         outtexcoord = loadmodel->surfmesh.data_texcoordtexture2f;
3789         // this unaligned memory access is safe (LittleFloat reads as bytes)
3790         for (i = 0;i < (int)header.num_vertexes;i++)
3791         {
3792                 outtexcoord[0] = LittleFloat(vtexcoord[0]);
3793                 outtexcoord[1] = LittleFloat(vtexcoord[1]);
3794                 vtexcoord += 2;
3795                 outtexcoord += 2;
3796         }
3797
3798         // this unaligned memory access is safe (LittleFloat reads as bytes)
3799         if(vnormal)
3800         {
3801                 outnormal = loadmodel->surfmesh.data_normal3f;
3802                 for (i = 0;i < (int)header.num_vertexes;i++)
3803                 {
3804                         outnormal[0] = LittleFloat(vnormal[0]);
3805                         outnormal[1] = LittleFloat(vnormal[1]);
3806                         outnormal[2] = LittleFloat(vnormal[2]);
3807                         vnormal += 3;
3808                         outnormal += 3;
3809                 }
3810         }
3811
3812         // this unaligned memory access is safe (LittleFloat reads as bytes)
3813         if(vnormal && vtangent)
3814         {
3815                 outnormal = loadmodel->surfmesh.data_normal3f;
3816                 outsvector = loadmodel->surfmesh.data_svector3f;
3817                 outtvector = loadmodel->surfmesh.data_tvector3f;
3818                 for (i = 0;i < (int)header.num_vertexes;i++)
3819                 {
3820                         outsvector[0] = LittleFloat(vtangent[0]);
3821                         outsvector[1] = LittleFloat(vtangent[1]);
3822                         outsvector[2] = LittleFloat(vtangent[2]);
3823                         if(LittleFloat(vtangent[3]) < 0)
3824                                 CrossProduct(outsvector, outnormal, outtvector);
3825                         else
3826                                 CrossProduct(outnormal, outsvector, outtvector);
3827                         vtangent += 4;
3828                         outnormal += 3;
3829                         outsvector += 3;
3830                         outtvector += 3;
3831                 }
3832         }
3833
3834         // this unaligned memory access is safe (all bytes)
3835         if (vblendindexes && vblendweights)
3836         {
3837                 for (i = 0; i < (int)header.num_vertexes;i++)
3838                 {
3839                         blendweights_t weights;
3840                         memcpy(weights.index, vblendindexes + i*4, 4);
3841                         memcpy(weights.influence, vblendweights + i*4, 4);
3842                         loadmodel->surfmesh.blends[i] = Mod_Skeletal_AddBlend(loadmodel, &weights);
3843                         loadmodel->surfmesh.data_skeletalindex4ub[i*4  ] = weights.index[0];
3844                         loadmodel->surfmesh.data_skeletalindex4ub[i*4+1] = weights.index[1];
3845                         loadmodel->surfmesh.data_skeletalindex4ub[i*4+2] = weights.index[2];
3846                         loadmodel->surfmesh.data_skeletalindex4ub[i*4+3] = weights.index[3];
3847                         loadmodel->surfmesh.data_skeletalweight4ub[i*4  ] = weights.influence[0];
3848                         loadmodel->surfmesh.data_skeletalweight4ub[i*4+1] = weights.influence[1];
3849                         loadmodel->surfmesh.data_skeletalweight4ub[i*4+2] = weights.influence[2];
3850                         loadmodel->surfmesh.data_skeletalweight4ub[i*4+3] = weights.influence[3];
3851                 }
3852         }
3853
3854         if (vcolor4f)
3855         {
3856                 outcolor = loadmodel->surfmesh.data_lightmapcolor4f;
3857                 // this unaligned memory access is safe (LittleFloat reads as bytes)
3858                 for (i = 0;i < (int)header.num_vertexes;i++)
3859                 {
3860                         outcolor[0] = LittleFloat(vcolor4f[0]);
3861                         outcolor[1] = LittleFloat(vcolor4f[1]);
3862                         outcolor[2] = LittleFloat(vcolor4f[2]);
3863                         outcolor[3] = LittleFloat(vcolor4f[3]);
3864                         vcolor4f += 4;
3865                         outcolor += 4;
3866                 }
3867         }
3868         else if (vcolor4ub)
3869         {
3870                 outcolor = loadmodel->surfmesh.data_lightmapcolor4f;
3871                 // this unaligned memory access is safe (all bytes)
3872                 for (i = 0;i < (int)header.num_vertexes;i++)
3873                 {
3874                         outcolor[0] = vcolor4ub[0] * (1.0f / 255.0f);
3875                         outcolor[1] = vcolor4ub[1] * (1.0f / 255.0f);
3876                         outcolor[2] = vcolor4ub[2] * (1.0f / 255.0f);
3877                         outcolor[3] = vcolor4ub[3] * (1.0f / 255.0f);
3878                         vcolor4ub += 4;
3879                         outcolor += 4;
3880                 }
3881         }
3882
3883         // load meshes
3884         for (i = 0;i < (int)header.num_meshes;i++)
3885         {
3886                 iqmmesh_t mesh;
3887                 msurface_t *surface;
3888
3889                 mesh.name = LittleLong(meshes[i].name);
3890                 mesh.material = LittleLong(meshes[i].material);
3891                 mesh.first_vertex = LittleLong(meshes[i].first_vertex);
3892                 mesh.num_vertexes = LittleLong(meshes[i].num_vertexes);
3893                 mesh.first_triangle = LittleLong(meshes[i].first_triangle);
3894                 mesh.num_triangles = LittleLong(meshes[i].num_triangles);
3895
3896                 loadmodel->sortedmodelsurfaces[i] = i;
3897                 surface = loadmodel->data_surfaces + i;
3898                 surface->texture = loadmodel->data_textures + i;
3899                 surface->num_firsttriangle = mesh.first_triangle;
3900                 surface->num_triangles = mesh.num_triangles;
3901                 surface->num_firstvertex = mesh.first_vertex;
3902                 surface->num_vertices = mesh.num_vertexes;
3903
3904                 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, &text[mesh.name], &text[mesh.material]);
3905         }
3906
3907         Mod_FreeSkinFiles(skinfiles);
3908         Mod_MakeSortedSurfaces(loadmodel);
3909
3910         // compute all the mesh information that was not loaded from the file
3911         if (loadmodel->surfmesh.data_element3s)
3912                 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
3913                         loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
3914         if (!vnormal)
3915                 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);
3916         if (!vnormal || !vtangent)
3917                 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);
3918         if (!header.ofs_neighbors && loadmodel->surfmesh.data_neighbor3i)
3919                 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
3920         if (!header.ofs_bounds)
3921                 Mod_Alias_CalculateBoundingBox();
3922
3923         if (!loadmodel->surfmesh.isanimated && loadmodel->surfmesh.num_triangles >= 1)
3924         {
3925                 Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
3926                 loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
3927                 loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
3928                 loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
3929                 loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh;
3930                 loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh;
3931         }
3932
3933         if (joint        ) Mem_Free(joint        );joint         = NULL;
3934         if (joint1       ) Mem_Free(joint1       );joint1        = NULL;
3935         if (pose         ) Mem_Free(pose         );pose          = NULL;
3936         if (pose1        ) Mem_Free(pose1        );pose1         = NULL;
3937
3938         // because shaders can do somewhat unexpected things, check for unusual features now
3939         for (i = 0;i < loadmodel->num_textures;i++)
3940         {
3941                 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_SKY))
3942                         mod->DrawSky = R_Q1BSP_DrawSky;
3943                 if (loadmodel->data_textures[i].basematerialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA))
3944                         mod->DrawAddWaterPlanes = R_Q1BSP_DrawAddWaterPlanes;
3945         }
3946 }