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