2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 cvar_t r_skeletal_debugbone = {0, "r_skeletal_debugbone", "-1", "development cvar for testing skeletal model code"};
26 cvar_t r_skeletal_debugbonecomponent = {0, "r_skeletal_debugbonecomponent", "3", "development cvar for testing skeletal model code"};
27 cvar_t r_skeletal_debugbonevalue = {0, "r_skeletal_debugbonevalue", "100", "development cvar for testing skeletal model code"};
28 cvar_t r_skeletal_debugtranslatex = {0, "r_skeletal_debugtranslatex", "1", "development cvar for testing skeletal model code"};
29 cvar_t r_skeletal_debugtranslatey = {0, "r_skeletal_debugtranslatey", "1", "development cvar for testing skeletal model code"};
30 cvar_t r_skeletal_debugtranslatez = {0, "r_skeletal_debugtranslatez", "1", "development cvar for testing skeletal model code"};
32 float mod_md3_sin[320];
34 void Mod_AliasInit (void)
37 Cvar_RegisterVariable(&r_skeletal_debugbone);
38 Cvar_RegisterVariable(&r_skeletal_debugbonecomponent);
39 Cvar_RegisterVariable(&r_skeletal_debugbonevalue);
40 Cvar_RegisterVariable(&r_skeletal_debugtranslatex);
41 Cvar_RegisterVariable(&r_skeletal_debugtranslatey);
42 Cvar_RegisterVariable(&r_skeletal_debugtranslatez);
43 for (i = 0;i < 320;i++)
44 mod_md3_sin[i] = sin(i * M_PI * 2.0f / 256.0);
47 void Mod_Skeletal_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
50 // vertex weighted skeletal
53 float boneposerelative[MAX_BONES][12];
54 float *matrix, m[12], bonepose[MAX_BONES][12];
57 size = model->num_surfaces * sizeof(msurface_t) + model->num_surfaces * sizeof(int) + model->num_surfaces * model->numskins * sizeof(texture_t) + model->surfmesh.num_triangles * sizeof(int[3]) + model->surfmesh.num_triangles * sizeof(int[3]) + model->surfmesh.num_vertices * sizeof(float[3]) + model->surfmesh.num_vertices * sizeof(float[3]) + model->surfmesh.num_vertices * sizeof(float[3]) + model->surfmesh.num_vertices * sizeof(float[3]) + model->surfmesh.num_vertices * sizeof(float[2]) + model->surfmesh.num_vertices * sizeof(int[4]) + model->surfmesh.num_vertices * sizeof(float[4]) + model->num_poses * sizeof(float[12]) + model->num_bones * sizeof(float[12]) + model->numskins * sizeof(animscene_t) + model->num_bones * sizeof(aliasbone_t) + model->numframes * sizeof(animscene_t) + ((model->surfmesh.num_vertices <= 65536) ? (model->surfmesh.num_triangles * sizeof(unsigned short[3])) : 0);
58 if (size != ((memheader_t *)model->data_surfaces)[-1].size)
59 Sys_Error("%s:%i: %i != %i", __FILE__, __LINE__, (int)size, (int)((memheader_t *)model->data_surfaces)[-1].size);
61 // interpolate matrices and concatenate them to their parents
62 for (i = 0;i < model->num_bones;i++)
64 for (k = 0;k < 12;k++)
66 for (blends = 0;blends < 4 && frameblend[blends].lerp > 0;blends++)
68 matrix = model->data_poses + (frameblend[blends].frame * model->num_bones + i) * 12;
69 if ((unsigned char *)(matrix + 12) >(unsigned char *)model->data_surfaces + ((memheader_t *)model->data_surfaces)[-1].size)
70 Sys_Error("%s:%i: matrix %p >= data %p + size %i\n", __FILE__, __LINE__, matrix, model->data_surfaces, (int)((memheader_t *)model->data_surfaces)[-1].size);
71 for (k = 0;k < 12;k++)
72 m[k] += matrix[k] * frameblend[blends].lerp;
74 if (i == r_skeletal_debugbone.integer)
75 m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
76 m[3] *= r_skeletal_debugtranslatex.value;
77 m[7] *= r_skeletal_debugtranslatey.value;
78 m[11] *= r_skeletal_debugtranslatez.value;
79 if (model->data_bones[i].parent >= 0)
80 R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
82 for (k = 0;k < 12;k++)
83 bonepose[i][k] = m[k];
84 // create a relative deformation matrix to describe displacement
85 // from the base mesh, which is used by the actual weighting
86 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]);
88 // blend the vertex bone weights
89 // special case for the extremely common wf[0] == 1 because it saves 3 multiplies per array when compared to the other case (w[0] is always 1 if only one bone controls this vertex, artists only use multiple bones for certain special cases)
90 // special case for the first bone because it avoids the need to memset the arrays before filling
92 const float *v = model->surfmesh.data_vertex3f;
93 const int *wi = model->surfmesh.data_vertexweightindex4i;
94 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
95 memset(vertex3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
96 for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, wi += 4, wf += 4, vertex3f += 3)
100 const float *m = boneposerelative[wi[0]];
101 vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
102 vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
103 vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
107 const float *m = boneposerelative[wi[0]];
109 vertex3f[0] = f * (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
110 vertex3f[1] = f * (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
111 vertex3f[2] = f * (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
112 for (k = 1;k < 4 && wf[k];k++)
114 const float *m = boneposerelative[wi[k]];
116 vertex3f[0] += f * (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
117 vertex3f[1] += f * (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
118 vertex3f[2] += f * (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
125 const float *n = model->surfmesh.data_normal3f;
126 const int *wi = model->surfmesh.data_vertexweightindex4i;
127 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
128 memset(normal3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
129 for (i = 0;i < model->surfmesh.num_vertices;i++, n += 3, wi += 4, wf += 4, normal3f += 3)
133 const float *m = boneposerelative[wi[0]];
134 normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
135 normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
136 normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
140 const float *m = boneposerelative[wi[0]];
142 normal3f[0] = f * (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
143 normal3f[1] = f * (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
144 normal3f[2] = f * (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
145 for (k = 1;k < 4 && wf[k];k++)
147 const float *m = boneposerelative[wi[k]];
149 normal3f[0] += f * (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
150 normal3f[1] += f * (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
151 normal3f[2] += f * (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
158 const float *sv = model->surfmesh.data_svector3f;
159 const int *wi = model->surfmesh.data_vertexweightindex4i;
160 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
161 memset(svector3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
162 for (i = 0;i < model->surfmesh.num_vertices;i++, sv += 3, wi += 4, wf += 4, svector3f += 3)
166 const float *m = boneposerelative[wi[0]];
167 svector3f[0] = (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
168 svector3f[1] = (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
169 svector3f[2] = (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
173 const float *m = boneposerelative[wi[0]];
175 svector3f[0] = f * (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
176 svector3f[1] = f * (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
177 svector3f[2] = f * (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
178 for (k = 1;k < 4 && wf[k];k++)
180 const float *m = boneposerelative[wi[k]];
182 svector3f[0] += f * (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
183 svector3f[1] += f * (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
184 svector3f[2] += f * (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
191 const float *tv = model->surfmesh.data_tvector3f;
192 const int *wi = model->surfmesh.data_vertexweightindex4i;
193 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
194 memset(tvector3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
195 for (i = 0;i < model->surfmesh.num_vertices;i++, tv += 3, wi += 4, wf += 4, tvector3f += 3)
199 const float *m = boneposerelative[wi[0]];
200 tvector3f[0] = (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
201 tvector3f[1] = (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
202 tvector3f[2] = (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
206 const float *m = boneposerelative[wi[0]];
208 tvector3f[0] = f * (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
209 tvector3f[1] = f * (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
210 tvector3f[2] = f * (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
211 for (k = 1;k < 4 && wf[k];k++)
213 const float *m = boneposerelative[wi[k]];
215 tvector3f[0] += f * (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
216 tvector3f[1] += f * (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
217 tvector3f[2] += f * (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
224 void Mod_MD3_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
227 int i, numblends, blendnum;
228 int numverts = model->surfmesh.num_vertices;
230 for (blendnum = 0;blendnum < 4;blendnum++)
232 //VectorMA(translate, model->surfmesh.num_morphmdlframetranslate, frameblend[blendnum].lerp, translate);
233 if (frameblend[blendnum].lerp > 0)
234 numblends = blendnum + 1;
236 // special case for the first blend because it avoids some adds and the need to memset the arrays first
237 for (blendnum = 0;blendnum < numblends;blendnum++)
239 const md3vertex_t *verts = model->surfmesh.data_morphmd3vertex + numverts * frameblend[blendnum].frame;
240 float scale = frameblend[blendnum].lerp * (1.0f / 64.0f);
243 for (i = 0;i < numverts;i++)
245 vertex3f[i * 3 + 0] = verts[i].origin[0] * scale;
246 vertex3f[i * 3 + 1] = verts[i].origin[1] * scale;
247 vertex3f[i * 3 + 2] = verts[i].origin[2] * scale;
252 for (i = 0;i < numverts;i++)
254 vertex3f[i * 3 + 0] += verts[i].origin[0] * scale;
255 vertex3f[i * 3 + 1] += verts[i].origin[1] * scale;
256 vertex3f[i * 3 + 2] += verts[i].origin[2] * scale;
259 // the yaw and pitch stored in md3 models are 8bit quantized angles
260 // (0-255), and as such a lookup table is very well suited to
261 // decoding them, and since cosine is equivilant to sine with an
262 // extra 45 degree rotation, this uses one lookup table for both
263 // sine and cosine with a +64 bias to get cosine.
266 float lerp = frameblend[blendnum].lerp;
269 for (i = 0;i < numverts;i++)
271 normal3f[i * 3 + 0] = mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
272 normal3f[i * 3 + 1] = mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
273 normal3f[i * 3 + 2] = mod_md3_sin[verts[i].pitch + 64] * lerp;
278 for (i = 0;i < numverts;i++)
280 normal3f[i * 3 + 0] += mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
281 normal3f[i * 3 + 1] += mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
282 normal3f[i * 3 + 2] += mod_md3_sin[verts[i].pitch + 64] * lerp;
288 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].frame;
289 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
292 for (i = 0;i < numverts;i++, texvecvert++)
294 VectorScale(texvecvert->svec, f, svector3f + i*3);
295 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
300 for (i = 0;i < numverts;i++, texvecvert++)
302 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
303 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
310 void Mod_MDL_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
313 int i, numblends, blendnum;
314 int numverts = model->surfmesh.num_vertices;
316 VectorClear(translate);
318 // blend the frame translates to avoid redundantly doing so on each vertex
319 // (a bit of a brain twister but it works)
320 for (blendnum = 0;blendnum < 4;blendnum++)
322 if (model->surfmesh.data_morphmd2framesize6f)
323 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].frame * 6 + 3, translate);
325 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.num_morphmdlframetranslate, translate);
326 if (frameblend[blendnum].lerp > 0)
327 numblends = blendnum + 1;
329 // special case for the first blend because it avoids some adds and the need to memset the arrays first
330 for (blendnum = 0;blendnum < numblends;blendnum++)
332 const trivertx_t *verts = model->surfmesh.data_morphmdlvertex + numverts * frameblend[blendnum].frame;
334 if (model->surfmesh.data_morphmd2framesize6f)
335 VectorScale(model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].frame * 6, frameblend[blendnum].lerp, scale);
337 VectorScale(model->surfmesh.num_morphmdlframescale, frameblend[blendnum].lerp, scale);
340 for (i = 0;i < numverts;i++)
342 vertex3f[i * 3 + 0] = translate[0] + verts[i].v[0] * scale[0];
343 vertex3f[i * 3 + 1] = translate[1] + verts[i].v[1] * scale[1];
344 vertex3f[i * 3 + 2] = translate[2] + verts[i].v[2] * scale[2];
349 for (i = 0;i < numverts;i++)
351 vertex3f[i * 3 + 0] += verts[i].v[0] * scale[0];
352 vertex3f[i * 3 + 1] += verts[i].v[1] * scale[1];
353 vertex3f[i * 3 + 2] += verts[i].v[2] * scale[2];
356 // the vertex normals in mdl models are an index into a table of
357 // 162 unique values, this very crude quantization reduces the
358 // vertex normal to only one byte, which saves a lot of space but
359 // also makes lighting pretty coarse
362 float lerp = frameblend[blendnum].lerp;
365 for (i = 0;i < numverts;i++)
367 const float *vn = m_bytenormals[verts[i].lightnormalindex];
368 VectorScale(vn, lerp, normal3f + i*3);
373 for (i = 0;i < numverts;i++)
375 const float *vn = m_bytenormals[verts[i].lightnormalindex];
376 VectorMA(normal3f + i*3, lerp, vn, normal3f + i*3);
382 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].frame;
383 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
386 for (i = 0;i < numverts;i++, texvecvert++)
388 VectorScale(texvecvert->svec, f, svector3f + i*3);
389 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
394 for (i = 0;i < numverts;i++, texvecvert++)
396 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
397 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
404 int Mod_Alias_GetTagMatrix(const dp_model_t *model, int poseframe, int tagindex, matrix4x4_t *outmatrix)
406 const float *boneframe;
407 float tempbonematrix[12], bonematrix[12];
408 *outmatrix = identitymatrix;
409 if (model->num_bones)
411 if (tagindex < 0 || tagindex >= model->num_bones)
413 if (poseframe >= model->num_poses)
415 boneframe = model->data_poses + poseframe * model->num_bones * 12;
416 memcpy(bonematrix, boneframe + tagindex * 12, sizeof(float[12]));
417 while (model->data_bones[tagindex].parent >= 0)
419 memcpy(tempbonematrix, bonematrix, sizeof(float[12]));
420 R_ConcatTransforms(boneframe + model->data_bones[tagindex].parent * 12, tempbonematrix, bonematrix);
421 tagindex = model->data_bones[tagindex].parent;
423 Matrix4x4_FromArray12FloatD3D(outmatrix, bonematrix);
425 else if (model->num_tags)
427 if (tagindex < 0 || tagindex >= model->num_tags)
429 if (poseframe >= model->num_tagframes)
431 Matrix4x4_FromArray12FloatGL(outmatrix, model->data_tags[poseframe * model->num_tags + tagindex].matrixgl);
436 int Mod_Alias_GetTagIndexForName(const dp_model_t *model, unsigned int skin, const char *tagname)
439 if(skin >= (unsigned int)model->numskins)
441 if (model->num_bones)
442 for (i = 0;i < model->num_bones;i++)
443 if (!strcasecmp(tagname, model->data_bones[i].name))
446 for (i = 0;i < model->num_tags;i++)
447 if (!strcasecmp(tagname, model->data_tags[i].name))
452 static void Mod_BuildBaseBonePoses(void)
456 float *basebonepose = Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(float[12]));
457 float *in12f = loadmodel->data_poses;
458 float *out12f = basebonepose;
459 float *outinv12f = loadmodel->data_baseboneposeinverse;
460 for (i = 0;i < loadmodel->num_bones;i++, in12f += 12, out12f += 12, outinv12f += 12)
462 if (loadmodel->data_bones[i].parent >= 0)
463 R_ConcatTransforms(basebonepose + 12 * loadmodel->data_bones[i].parent, in12f, out12f);
465 for (k = 0;k < 12;k++)
466 out12f[k] = in12f[k];
470 // we only support uniform scaling, so assume the first row is enough
471 // (note the lack of sqrt here, because we're trying to undo the scaling,
472 // this means multiplying by the inverse scale twice - squaring it, which
473 // makes the sqrt a waste of time)
474 scale = 1.0 / (out12f[ 0] * out12f[ 0] + out12f[ 1] * out12f[ 1] + out12f[ 2] * out12f[ 2]);
476 // invert the rotation by transposing and multiplying by the squared
477 // recipricol of the input matrix scale as described above
478 outinv12f[ 0] = (float)(out12f[ 0] * scale);
479 outinv12f[ 1] = (float)(out12f[ 4] * scale);
480 outinv12f[ 2] = (float)(out12f[ 8] * scale);
481 outinv12f[ 4] = (float)(out12f[ 1] * scale);
482 outinv12f[ 5] = (float)(out12f[ 5] * scale);
483 outinv12f[ 6] = (float)(out12f[ 9] * scale);
484 outinv12f[ 8] = (float)(out12f[ 2] * scale);
485 outinv12f[ 9] = (float)(out12f[ 6] * scale);
486 outinv12f[10] = (float)(out12f[10] * scale);
488 // invert the translate
489 outinv12f[ 3] = -(out12f[ 3] * outinv12f[ 0] + out12f[ 7] * outinv12f[ 1] + out12f[11] * outinv12f[ 2]);
490 outinv12f[ 7] = -(out12f[ 3] * outinv12f[ 4] + out12f[ 7] * outinv12f[ 5] + out12f[11] * outinv12f[ 6]);
491 outinv12f[11] = -(out12f[ 3] * outinv12f[ 8] + out12f[ 7] * outinv12f[ 9] + out12f[11] * outinv12f[10]);
493 Mem_Free(basebonepose);
496 static void Mod_Alias_CalculateBoundingBox(void)
499 qboolean firstvertex = true;
500 float dist, yawradius, radius;
503 frameblend_t frameblend[4];
504 memset(frameblend, 0, sizeof(frameblend));
505 frameblend[0].lerp = 1;
506 vertex3f = Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
507 VectorClear(loadmodel->normalmins);
508 VectorClear(loadmodel->normalmaxs);
511 for (frameblend[0].frame = 0;frameblend[0].frame < loadmodel->num_poses;frameblend[0].frame++)
513 loadmodel->AnimateVertices(loadmodel, frameblend, vertex3f, NULL, NULL, NULL);
514 for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
519 VectorCopy(v, loadmodel->normalmins);
520 VectorCopy(v, loadmodel->normalmaxs);
524 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
525 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
526 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
527 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
528 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
529 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
531 dist = v[0] * v[0] + v[1] * v[1];
532 if (yawradius < dist)
540 radius = sqrt(radius);
541 yawradius = sqrt(yawradius);
542 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
543 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
544 loadmodel->yawmins[2] = loadmodel->normalmins[2];
545 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
546 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
547 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
548 loadmodel->radius = radius;
549 loadmodel->radius2 = radius * radius;
552 static void Mod_Alias_MorphMesh_CompileFrames(void)
555 frameblend_t frameblend[4] = {{0, 1}, {0, 0}, {0, 0}, {0, 0}};
556 unsigned char *datapointer;
557 datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
558 loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
559 loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
560 loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
561 loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
562 loadmodel->surfmesh.data_morphtexvecvertex = (texvecvertex_t *)datapointer;datapointer += loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices * sizeof(texvecvertex_t);
563 // 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)
564 for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
566 frameblend[0].frame = i;
567 loadmodel->AnimateVertices(loadmodel, frameblend, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
568 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);
569 // encode the svector and tvector in 3 byte format for permanent storage
570 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
572 VectorScale(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
573 VectorScale(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
578 static void Mod_MDLMD2MD3_TraceBox(dp_model_t *model, int frame, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask)
581 float segmentmins[3], segmentmaxs[3];
582 frameblend_t frameblend[4];
584 static int maxvertices = 0;
585 static float *vertex3f = NULL;
586 memset(trace, 0, sizeof(*trace));
588 trace->realfraction = 1;
589 trace->hitsupercontentsmask = hitsupercontentsmask;
590 memset(frameblend, 0, sizeof(frameblend));
591 frameblend[0].frame = frame;
592 frameblend[0].lerp = 1;
593 if (maxvertices < model->surfmesh.num_vertices)
597 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
598 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
600 if (VectorLength2(boxmins) + VectorLength2(boxmaxs) == 0)
603 segmentmins[0] = min(start[0], end[0]) - 1;
604 segmentmins[1] = min(start[1], end[1]) - 1;
605 segmentmins[2] = min(start[2], end[2]) - 1;
606 segmentmaxs[0] = max(start[0], end[0]) + 1;
607 segmentmaxs[1] = max(start[1], end[1]) + 1;
608 segmentmaxs[2] = max(start[2], end[2]) + 1;
609 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
611 model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL);
612 Collision_TraceLineTriangleMeshFloat(trace, start, end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, SUPERCONTENTS_SOLID, 0, surface->texture, segmentmins, segmentmaxs);
617 // box trace, performed as brush trace
618 colbrushf_t *thisbrush_start, *thisbrush_end;
619 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
620 segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
621 segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
622 segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
623 segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
624 segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
625 segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
626 VectorAdd(start, boxmins, boxstartmins);
627 VectorAdd(start, boxmaxs, boxstartmaxs);
628 VectorAdd(end, boxmins, boxendmins);
629 VectorAdd(end, boxmaxs, boxendmaxs);
630 thisbrush_start = Collision_BrushForBox(&identitymatrix, boxstartmins, boxstartmaxs, 0, 0, NULL);
631 thisbrush_end = Collision_BrushForBox(&identitymatrix, boxendmins, boxendmaxs, 0, 0, NULL);
632 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
634 if (maxvertices < model->surfmesh.num_vertices)
638 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
639 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
641 model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL);
642 Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, SUPERCONTENTS_SOLID, 0, surface->texture, segmentmins, segmentmaxs);
647 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
650 for (i = 0;i < inverts;i++)
652 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
654 j = vertremap[i]; // not onseam
657 j = vertremap[i+inverts]; // onseam
663 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
665 int i, f, pose, groupframes;
667 daliasframetype_t *pframetype;
668 daliasframe_t *pinframe;
669 daliasgroup_t *group;
670 daliasinterval_t *intervals;
673 scene = loadmodel->animscenes;
674 for (f = 0;f < loadmodel->numframes;f++)
676 pframetype = (daliasframetype_t *)datapointer;
677 datapointer += sizeof(daliasframetype_t);
678 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
680 // a single frame is still treated as a group
687 group = (daliasgroup_t *)datapointer;
688 datapointer += sizeof(daliasgroup_t);
689 groupframes = LittleLong (group->numframes);
691 // intervals (time per frame)
692 intervals = (daliasinterval_t *)datapointer;
693 datapointer += sizeof(daliasinterval_t) * groupframes;
695 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
696 if (interval < 0.01f)
698 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
703 // get scene name from first frame
704 pinframe = (daliasframe_t *)datapointer;
706 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
707 scene->firstframe = pose;
708 scene->framecount = groupframes;
709 scene->framerate = 1.0f / interval;
714 for (i = 0;i < groupframes;i++)
716 pinframe = (daliasframe_t *)datapointer;
717 datapointer += sizeof(daliasframe_t);
718 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
719 datapointer += sizeof(trivertx_t) * inverts;
725 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
727 if (cls.state == ca_dedicated)
731 skinframe = R_SkinFrame_LoadMissing();
732 memset(texture, 0, sizeof(*texture));
733 texture->currentframe = texture;
734 //texture->animated = false;
735 texture->numskinframes = 1;
736 texture->skinframerate = 1;
737 texture->skinframes[0] = skinframe;
738 texture->currentskinframe = skinframe;
739 //texture->backgroundnumskinframes = 0;
740 //texture->customblendfunc[0] = 0;
741 //texture->customblendfunc[1] = 0;
742 //texture->surfaceflags = 0;
743 //texture->supercontents = 0;
744 //texture->surfaceparms = 0;
745 //texture->textureflags = 0;
747 texture->basematerialflags = MATERIALFLAG_WALL;
748 if (texture->currentskinframe->fog)
749 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
750 texture->currentmaterialflags = texture->basematerialflags;
753 static void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, char *meshname, char *shadername)
756 skinfileitem_t *skinfileitem;
759 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
760 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
762 memset(skin, 0, sizeof(*skin));
764 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
766 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
767 if (!strcmp(skinfileitem->name, meshname))
769 Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
775 // don't render unmentioned meshes
776 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
777 skin->basematerialflags = skin->currentmaterialflags = 0;
782 Mod_LoadTextureFromQ3Shader(skin, shadername, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
785 #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);
786 #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);
787 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
789 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
790 float scales, scalet, interval;
794 stvert_t *pinstverts;
795 dtriangle_t *pintriangles;
796 daliasskintype_t *pinskintype;
797 daliasskingroup_t *pinskingroup;
798 daliasskininterval_t *pinskinintervals;
799 daliasframetype_t *pinframetype;
800 daliasgroup_t *pinframegroup;
801 unsigned char *datapointer, *startframes, *startskins;
802 char name[MAX_QPATH];
803 skinframe_t *tempskinframe;
804 animscene_t *tempskinscenes;
805 texture_t *tempaliasskins;
807 int *vertonseam, *vertremap;
808 skinfile_t *skinfiles;
810 datapointer = (unsigned char *)buffer;
811 pinmodel = (mdl_t *)datapointer;
812 datapointer += sizeof(mdl_t);
814 version = LittleLong (pinmodel->version);
815 if (version != ALIAS_VERSION)
816 Host_Error ("%s has wrong version number (%i should be %i)",
817 loadmodel->name, version, ALIAS_VERSION);
819 loadmodel->modeldatatypestring = "MDL";
821 loadmodel->type = mod_alias;
822 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
823 loadmodel->DrawSky = NULL;
824 loadmodel->DrawAddWaterPlanes = NULL;
825 loadmodel->Draw = R_Q1BSP_Draw;
826 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
827 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
828 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
829 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
830 loadmodel->DrawLight = R_Q1BSP_DrawLight;
831 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
832 loadmodel->PointSuperContents = NULL;
834 loadmodel->num_surfaces = 1;
835 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
836 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
837 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
838 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
839 loadmodel->surfacelist[0] = 0;
841 loadmodel->numskins = LittleLong(pinmodel->numskins);
842 BOUNDI(loadmodel->numskins,0,65536);
843 skinwidth = LittleLong (pinmodel->skinwidth);
844 BOUNDI(skinwidth,0,65536);
845 skinheight = LittleLong (pinmodel->skinheight);
846 BOUNDI(skinheight,0,65536);
847 numverts = LittleLong(pinmodel->numverts);
848 BOUNDI(numverts,0,65536);
849 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
850 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
851 loadmodel->numframes = LittleLong(pinmodel->numframes);
852 BOUNDI(loadmodel->numframes,0,65536);
853 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
854 BOUNDI(loadmodel->synctype,0,2);
855 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
856 i = LittleLong (pinmodel->flags);
857 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
859 for (i = 0;i < 3;i++)
861 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
862 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
865 startskins = datapointer;
867 for (i = 0;i < loadmodel->numskins;i++)
869 pinskintype = (daliasskintype_t *)datapointer;
870 datapointer += sizeof(daliasskintype_t);
871 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
875 pinskingroup = (daliasskingroup_t *)datapointer;
876 datapointer += sizeof(daliasskingroup_t);
877 groupskins = LittleLong(pinskingroup->numskins);
878 datapointer += sizeof(daliasskininterval_t) * groupskins;
881 for (j = 0;j < groupskins;j++)
883 datapointer += skinwidth * skinheight;
888 pinstverts = (stvert_t *)datapointer;
889 datapointer += sizeof(stvert_t) * numverts;
891 pintriangles = (dtriangle_t *)datapointer;
892 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
894 startframes = datapointer;
895 loadmodel->surfmesh.num_morphframes = 0;
896 for (i = 0;i < loadmodel->numframes;i++)
898 pinframetype = (daliasframetype_t *)datapointer;
899 datapointer += sizeof(daliasframetype_t);
900 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
904 pinframegroup = (daliasgroup_t *)datapointer;
905 datapointer += sizeof(daliasgroup_t);
906 groupframes = LittleLong(pinframegroup->numframes);
907 datapointer += sizeof(daliasinterval_t) * groupframes;
910 for (j = 0;j < groupframes;j++)
912 datapointer += sizeof(daliasframe_t);
913 datapointer += sizeof(trivertx_t) * numverts;
914 loadmodel->surfmesh.num_morphframes++;
917 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
919 // store texture coordinates into temporary array, they will be stored
920 // after usage is determined (triangle data)
921 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
922 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
923 vertonseam = vertremap + numverts * 2;
925 scales = 1.0 / skinwidth;
926 scalet = 1.0 / skinheight;
927 for (i = 0;i < numverts;i++)
929 vertonseam[i] = LittleLong(pinstverts[i].onseam);
930 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
931 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
932 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
933 vertst[(i+numverts)*2+1] = vertst[i*2+1];
936 // load triangle data
937 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
939 // read the triangle elements
940 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
941 for (j = 0;j < 3;j++)
942 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
943 // validate (note numverts is used because this is the original data)
944 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
945 // now butcher the elements according to vertonseam and tri->facesfront
946 // and then compact the vertex set to remove duplicates
947 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
948 if (!LittleLong(pintriangles[i].facesfront)) // backface
949 for (j = 0;j < 3;j++)
950 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
951 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
953 // (this uses vertremap to count usage to save some memory)
954 for (i = 0;i < numverts*2;i++)
956 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
957 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
958 // build remapping table and compact array
959 loadmodel->surfmesh.num_vertices = 0;
960 for (i = 0;i < numverts*2;i++)
964 vertremap[i] = loadmodel->surfmesh.num_vertices;
965 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
966 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
967 loadmodel->surfmesh.num_vertices++;
970 vertremap[i] = -1; // not used at all
972 // remap the elements to the new vertex set
973 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
974 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
975 // store the texture coordinates
976 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
977 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
979 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
980 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
983 // generate ushort elements array if possible
984 if (loadmodel->surfmesh.num_vertices <= 65536)
986 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
987 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
988 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
992 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
993 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
994 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
995 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
996 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
997 Mod_Alias_CalculateBoundingBox();
998 Mod_Alias_MorphMesh_CompileFrames();
1001 Mem_Free(vertremap);
1004 skinfiles = Mod_LoadSkinFiles();
1005 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1006 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1007 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1008 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1011 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1012 Mod_FreeSkinFiles(skinfiles);
1013 for (i = 0;i < loadmodel->numskins;i++)
1015 loadmodel->skinscenes[i].firstframe = i;
1016 loadmodel->skinscenes[i].framecount = 1;
1017 loadmodel->skinscenes[i].loop = true;
1018 loadmodel->skinscenes[i].framerate = 10;
1024 datapointer = startskins;
1025 for (i = 0;i < loadmodel->numskins;i++)
1027 pinskintype = (daliasskintype_t *)datapointer;
1028 datapointer += sizeof(daliasskintype_t);
1030 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1037 pinskingroup = (daliasskingroup_t *)datapointer;
1038 datapointer += sizeof(daliasskingroup_t);
1040 groupskins = LittleLong (pinskingroup->numskins);
1042 pinskinintervals = (daliasskininterval_t *)datapointer;
1043 datapointer += sizeof(daliasskininterval_t) * groupskins;
1045 interval = LittleFloat(pinskinintervals[0].interval);
1046 if (interval < 0.01f)
1048 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1053 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1054 loadmodel->skinscenes[i].firstframe = totalskins;
1055 loadmodel->skinscenes[i].framecount = groupskins;
1056 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1057 loadmodel->skinscenes[i].loop = true;
1059 for (j = 0;j < groupskins;j++)
1062 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1064 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1065 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))
1066 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));
1067 datapointer += skinwidth * skinheight;
1071 // check for skins that don't exist in the model, but do exist as external images
1072 // (this was added because yummyluv kept pestering me about support for it)
1073 // TODO: support shaders here?
1074 while ((tempskinframe = R_SkinFrame_LoadExternal(va("%s_%i", loadmodel->name, loadmodel->numskins), (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS, false)))
1076 // expand the arrays to make room
1077 tempskinscenes = loadmodel->skinscenes;
1078 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1079 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1080 Mem_Free(tempskinscenes);
1082 tempaliasskins = loadmodel->data_textures;
1083 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1084 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1085 Mem_Free(tempaliasskins);
1087 // store the info about the new skin
1088 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1089 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1090 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1091 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1092 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1093 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1095 //increase skin counts
1096 loadmodel->numskins++;
1099 // fix up the pointers since they are pointing at the old textures array
1100 // FIXME: this is a hack!
1101 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1102 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1106 surface = loadmodel->data_surfaces;
1107 surface->texture = loadmodel->data_textures;
1108 surface->num_firsttriangle = 0;
1109 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1110 surface->num_firstvertex = 0;
1111 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1113 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1116 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1118 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1119 float iskinwidth, iskinheight;
1120 unsigned char *data;
1121 msurface_t *surface;
1123 unsigned char *base, *datapointer;
1124 md2frame_t *pinframe;
1126 md2triangle_t *intri;
1127 unsigned short *inst;
1128 struct md2verthash_s
1130 struct md2verthash_s *next;
1134 *hash, **md2verthash, *md2verthashdata;
1135 skinfile_t *skinfiles;
1137 pinmodel = (md2_t *)buffer;
1138 base = (unsigned char *)buffer;
1140 version = LittleLong (pinmodel->version);
1141 if (version != MD2ALIAS_VERSION)
1142 Host_Error ("%s has wrong version number (%i should be %i)",
1143 loadmodel->name, version, MD2ALIAS_VERSION);
1145 loadmodel->modeldatatypestring = "MD2";
1147 loadmodel->type = mod_alias;
1148 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1149 loadmodel->DrawSky = NULL;
1150 loadmodel->DrawAddWaterPlanes = NULL;
1151 loadmodel->Draw = R_Q1BSP_Draw;
1152 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1153 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1154 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1155 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1156 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1157 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1158 loadmodel->PointSuperContents = NULL;
1160 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1161 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1162 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1163 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1164 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1165 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1166 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1167 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1169 end = LittleLong(pinmodel->ofs_end);
1170 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1171 Host_Error ("%s is not a valid model", loadmodel->name);
1172 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1173 Host_Error ("%s is not a valid model", loadmodel->name);
1174 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1175 Host_Error ("%s is not a valid model", loadmodel->name);
1176 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1177 Host_Error ("%s is not a valid model", loadmodel->name);
1178 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1179 Host_Error ("%s is not a valid model", loadmodel->name);
1181 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1182 numxyz = LittleLong(pinmodel->num_xyz);
1183 numst = LittleLong(pinmodel->num_st);
1184 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1185 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1186 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1187 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1188 skinwidth = LittleLong(pinmodel->skinwidth);
1189 skinheight = LittleLong(pinmodel->skinheight);
1190 iskinwidth = 1.0f / skinwidth;
1191 iskinheight = 1.0f / skinheight;
1193 loadmodel->num_surfaces = 1;
1194 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1195 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]) + loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1196 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1197 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1198 loadmodel->surfacelist[0] = 0;
1199 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1200 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1201 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1202 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1204 loadmodel->synctype = ST_RAND;
1207 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1208 skinfiles = Mod_LoadSkinFiles();
1211 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1212 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1213 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1214 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1215 Mod_FreeSkinFiles(skinfiles);
1217 else if (loadmodel->numskins)
1219 // skins found (most likely not a player model)
1220 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1221 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1222 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1223 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1224 Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
1228 // no skins (most likely a player model)
1229 loadmodel->numskins = 1;
1230 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1231 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1232 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1233 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1236 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1237 for (i = 0;i < loadmodel->numskins;i++)
1239 loadmodel->skinscenes[i].firstframe = i;
1240 loadmodel->skinscenes[i].framecount = 1;
1241 loadmodel->skinscenes[i].loop = true;
1242 loadmodel->skinscenes[i].framerate = 10;
1245 // load the triangles and stvert data
1246 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1247 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1248 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1249 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1250 // swap the triangle list
1251 loadmodel->surfmesh.num_vertices = 0;
1252 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1254 for (j = 0;j < 3;j++)
1256 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1257 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1260 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1265 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1268 hashindex = (xyz * 256 + st) & 65535;
1269 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1270 if (hash->xyz == xyz && hash->st == st)
1274 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1277 hash->next = md2verthash[hashindex];
1278 md2verthash[hashindex] = hash;
1280 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1284 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1285 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));
1286 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1287 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1288 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1291 hash = md2verthashdata + i;
1292 vertremap[i] = hash->xyz;
1293 sts = LittleShort(inst[hash->st*2+0]);
1294 stt = LittleShort(inst[hash->st*2+1]);
1295 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1297 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1301 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1302 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1305 Mem_Free(md2verthash);
1306 Mem_Free(md2verthashdata);
1308 // generate ushort elements array if possible
1309 if (loadmodel->surfmesh.num_vertices <= 65536)
1311 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1312 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1313 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1317 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1318 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1323 pinframe = (md2frame_t *)datapointer;
1324 datapointer += sizeof(md2frame_t);
1325 // store the frame scale/translate into the appropriate array
1326 for (j = 0;j < 3;j++)
1328 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1329 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1331 // convert the vertices
1332 v = (trivertx_t *)datapointer;
1333 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1334 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1335 out[k] = v[vertremap[k]];
1336 datapointer += numxyz * sizeof(trivertx_t);
1338 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1339 loadmodel->animscenes[i].firstframe = i;
1340 loadmodel->animscenes[i].framecount = 1;
1341 loadmodel->animscenes[i].framerate = 10;
1342 loadmodel->animscenes[i].loop = true;
1345 Mem_Free(vertremap);
1347 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1348 Mod_Alias_CalculateBoundingBox();
1349 Mod_Alias_MorphMesh_CompileFrames();
1351 surface = loadmodel->data_surfaces;
1352 surface->texture = loadmodel->data_textures;
1353 surface->num_firsttriangle = 0;
1354 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1355 surface->num_firstvertex = 0;
1356 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1358 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1361 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1363 int i, j, k, version, meshvertices, meshtriangles;
1364 unsigned char *data;
1365 msurface_t *surface;
1366 md3modelheader_t *pinmodel;
1367 md3frameinfo_t *pinframe;
1370 skinfile_t *skinfiles;
1372 pinmodel = (md3modelheader_t *)buffer;
1374 if (memcmp(pinmodel->identifier, "IDP3", 4))
1375 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1376 version = LittleLong (pinmodel->version);
1377 if (version != MD3VERSION)
1378 Host_Error ("%s has wrong version number (%i should be %i)",
1379 loadmodel->name, version, MD3VERSION);
1381 skinfiles = Mod_LoadSkinFiles();
1382 if (loadmodel->numskins < 1)
1383 loadmodel->numskins = 1;
1385 loadmodel->modeldatatypestring = "MD3";
1387 loadmodel->type = mod_alias;
1388 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1389 loadmodel->DrawSky = NULL;
1390 loadmodel->DrawAddWaterPlanes = NULL;
1391 loadmodel->Draw = R_Q1BSP_Draw;
1392 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1393 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1394 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1395 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1396 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1397 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1398 loadmodel->PointSuperContents = NULL;
1399 loadmodel->synctype = ST_RAND;
1400 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1401 i = LittleLong (pinmodel->flags);
1402 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1404 // set up some global info about the model
1405 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1406 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1408 // make skinscenes for the skins (no groups)
1409 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1410 for (i = 0;i < loadmodel->numskins;i++)
1412 loadmodel->skinscenes[i].firstframe = i;
1413 loadmodel->skinscenes[i].framecount = 1;
1414 loadmodel->skinscenes[i].loop = true;
1415 loadmodel->skinscenes[i].framerate = 10;
1419 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1420 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1422 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1423 loadmodel->animscenes[i].firstframe = i;
1424 loadmodel->animscenes[i].framecount = 1;
1425 loadmodel->animscenes[i].framerate = 10;
1426 loadmodel->animscenes[i].loop = true;
1430 loadmodel->num_tagframes = loadmodel->numframes;
1431 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1432 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1433 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1435 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1436 for (j = 0;j < 9;j++)
1437 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1438 for (j = 0;j < 3;j++)
1439 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1440 //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);
1446 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)))
1448 if (memcmp(pinmesh->identifier, "IDP3", 4))
1449 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1450 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1451 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1452 meshvertices += LittleLong(pinmesh->num_vertices);
1453 meshtriangles += LittleLong(pinmesh->num_triangles);
1456 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1457 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1458 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1459 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]) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshvertices * sizeof(float[2]) + meshvertices * loadmodel->numframes * sizeof(md3vertex_t));
1460 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1461 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1462 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1463 loadmodel->surfmesh.num_vertices = meshvertices;
1464 loadmodel->surfmesh.num_triangles = meshtriangles;
1465 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1466 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1467 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1468 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1469 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1470 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1471 if (meshvertices <= 65536)
1473 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1474 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1475 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1480 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)))
1482 if (memcmp(pinmesh->identifier, "IDP3", 4))
1483 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1484 loadmodel->surfacelist[i] = i;
1485 surface = loadmodel->data_surfaces + i;
1486 surface->texture = loadmodel->data_textures + i;
1487 surface->num_firsttriangle = meshtriangles;
1488 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1489 surface->num_firstvertex = meshvertices;
1490 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1491 meshvertices += surface->num_vertices;
1492 meshtriangles += surface->num_triangles;
1494 for (j = 0;j < surface->num_triangles * 3;j++)
1495 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1496 for (j = 0;j < surface->num_vertices;j++)
1498 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1499 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1501 for (j = 0;j < loadmodel->numframes;j++)
1503 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1504 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1505 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1507 out->origin[0] = LittleShort(in->origin[0]);
1508 out->origin[1] = LittleShort(in->origin[1]);
1509 out->origin[2] = LittleShort(in->origin[2]);
1510 out->pitch = in->pitch;
1515 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1517 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1519 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1520 Mod_Alias_MorphMesh_CompileFrames();
1521 Mod_Alias_CalculateBoundingBox();
1522 Mod_FreeSkinFiles(skinfiles);
1524 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1525 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1528 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1530 zymtype1header_t *pinmodel, *pheader;
1531 unsigned char *pbase;
1532 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1533 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose;
1534 zymvertex_t *verts, *vertdata;
1538 skinfile_t *skinfiles;
1539 unsigned char *data;
1540 msurface_t *surface;
1542 pinmodel = (zymtype1header_t *)buffer;
1543 pbase = (unsigned char *)buffer;
1544 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1545 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1546 if (BigLong(pinmodel->type) != 1)
1547 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1549 loadmodel->modeldatatypestring = "ZYM";
1551 loadmodel->type = mod_alias;
1552 loadmodel->synctype = ST_RAND;
1556 pheader->type = BigLong(pinmodel->type);
1557 pheader->filesize = BigLong(pinmodel->filesize);
1558 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1559 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1560 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1561 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1562 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1563 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1564 pheader->radius = BigFloat(pinmodel->radius);
1565 pheader->numverts = BigLong(pinmodel->numverts);
1566 pheader->numtris = BigLong(pinmodel->numtris);
1567 pheader->numshaders = BigLong(pinmodel->numshaders);
1568 pheader->numbones = BigLong(pinmodel->numbones);
1569 pheader->numscenes = BigLong(pinmodel->numscenes);
1570 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1571 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1572 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1573 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1574 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1575 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1576 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1577 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1578 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1579 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1580 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1581 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1582 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1583 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1584 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1585 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1586 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1587 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1589 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1591 Con_Printf("%s has no geometry\n", loadmodel->name);
1594 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1596 Con_Printf("%s has no animations\n", loadmodel->name);
1600 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1601 loadmodel->DrawSky = NULL;
1602 loadmodel->DrawAddWaterPlanes = NULL;
1603 loadmodel->Draw = R_Q1BSP_Draw;
1604 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1605 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1606 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1607 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1608 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1609 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1610 loadmodel->PointSuperContents = NULL;
1612 loadmodel->numframes = pheader->numscenes;
1613 loadmodel->num_surfaces = pheader->numshaders;
1615 skinfiles = Mod_LoadSkinFiles();
1616 if (loadmodel->numskins < 1)
1617 loadmodel->numskins = 1;
1619 // make skinscenes for the skins (no groups)
1620 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1621 for (i = 0;i < loadmodel->numskins;i++)
1623 loadmodel->skinscenes[i].firstframe = i;
1624 loadmodel->skinscenes[i].framecount = 1;
1625 loadmodel->skinscenes[i].loop = true;
1626 loadmodel->skinscenes[i].framerate = 10;
1630 modelradius = pheader->radius;
1631 for (i = 0;i < 3;i++)
1633 loadmodel->normalmins[i] = pheader->mins[i];
1634 loadmodel->normalmaxs[i] = pheader->maxs[i];
1635 loadmodel->rotatedmins[i] = -modelradius;
1636 loadmodel->rotatedmaxs[i] = modelradius;
1638 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1639 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1640 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1641 if (loadmodel->yawmaxs[0] > modelradius)
1642 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1643 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1644 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1645 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1646 loadmodel->radius = modelradius;
1647 loadmodel->radius2 = modelradius * modelradius;
1649 // go through the lumps, swapping things
1651 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1652 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1653 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1654 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1655 for (i = 0;i < pheader->numscenes;i++)
1657 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1658 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1659 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1660 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1661 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1662 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1663 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1664 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1665 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1666 if (loadmodel->animscenes[i].framerate < 0)
1667 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1671 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1672 loadmodel->num_bones = pheader->numbones;
1673 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, pheader->numbones * sizeof(aliasbone_t));
1674 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1675 for (i = 0;i < pheader->numbones;i++)
1677 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1678 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1679 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1680 if (loadmodel->data_bones[i].parent >= i)
1681 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1684 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1685 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1686 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1687 for (i = 0;i < pheader->numverts;i++)
1689 vertbonecounts[i] = BigLong(bonecount[i]);
1690 if (vertbonecounts[i] != 1)
1691 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1694 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]);
1696 meshvertices = pheader->numverts;
1697 meshtriangles = pheader->numtris;
1699 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1700 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1701 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1702 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]) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshvertices * sizeof(float[14]) + meshvertices * sizeof(int[4]) + meshvertices * sizeof(float[4]) + loadmodel->num_poses * sizeof(float[12]) + loadmodel->num_bones * sizeof(float[12]));
1703 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1704 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1705 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1706 loadmodel->surfmesh.num_vertices = meshvertices;
1707 loadmodel->surfmesh.num_triangles = meshtriangles;
1708 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1709 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1710 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1711 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1712 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1713 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1714 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1715 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1716 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1717 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
1718 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1719 if (loadmodel->surfmesh.num_vertices <= 65536)
1721 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1722 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1723 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1726 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1727 poses = (float *) (pheader->lump_poses.start + pbase);
1728 for (i = 0;i < pheader->lump_poses.length / 4;i++)
1729 loadmodel->data_poses[i] = BigFloat(poses[i]);
1731 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1732 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1733 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1734 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1735 // (converting from weight-blending skeletal animation to
1736 // deformation-based skeletal animation)
1737 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1738 for (i = 0;i < loadmodel->num_bones;i++)
1740 const float *m = loadmodel->data_poses + i * 12;
1741 if (loadmodel->data_bones[i].parent >= 0)
1742 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1744 for (k = 0;k < 12;k++)
1745 bonepose[12*i+k] = m[k];
1747 for (j = 0;j < pheader->numverts;j++)
1749 // this format really should have had a per vertexweight weight value...
1750 // but since it does not, the weighting is completely ignored and
1751 // only one weight is allowed per vertex
1752 int boneindex = BigLong(vertdata[j].bonenum);
1753 const float *m = bonepose + 12 * boneindex;
1754 float relativeorigin[3];
1755 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1756 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1757 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1758 // transform the vertex bone weight into the base mesh
1759 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1760 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1761 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1762 // store the weight as the primary weight on this vertex
1763 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
1764 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = 1;
1767 // normals and tangents are calculated after elements are loaded
1769 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1770 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1771 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1772 for (i = 0;i < pheader->numverts;i++)
1774 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1775 // flip T coordinate for OpenGL
1776 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1779 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1780 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1781 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1783 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1784 //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)
1785 // byteswap, validate, and swap winding order of tris
1786 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1787 if (pheader->lump_render.length != count)
1788 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1789 renderlist = (int *) (pheader->lump_render.start + pbase);
1790 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1792 for (i = 0;i < loadmodel->num_surfaces;i++)
1794 int firstvertex, lastvertex;
1795 if (renderlist >= renderlistend)
1796 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1797 count = BigLong(*renderlist);renderlist++;
1798 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1799 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1801 loadmodel->surfacelist[i] = i;
1802 surface = loadmodel->data_surfaces + i;
1803 surface->texture = loadmodel->data_textures + i;
1804 surface->num_firsttriangle = meshtriangles;
1805 surface->num_triangles = count;
1806 meshtriangles += surface->num_triangles;
1808 // load the elements
1809 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
1810 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
1812 outelements[j*3+2] = BigLong(renderlist[0]);
1813 outelements[j*3+1] = BigLong(renderlist[1]);
1814 outelements[j*3+0] = BigLong(renderlist[2]);
1816 // validate the elements and find the used vertex range
1817 firstvertex = meshvertices;
1819 for (j = 0;j < surface->num_triangles * 3;j++)
1821 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
1822 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
1823 firstvertex = min(firstvertex, outelements[j]);
1824 lastvertex = max(lastvertex, outelements[j]);
1826 surface->num_firstvertex = firstvertex;
1827 surface->num_vertices = lastvertex + 1 - firstvertex;
1829 // since zym models do not have named sections, reuse their shader
1830 // name as the section name
1831 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
1832 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
1834 Mod_FreeSkinFiles(skinfiles);
1835 Mem_Free(vertbonecounts);
1838 // compute all the mesh information that was not loaded from the file
1839 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
1840 Mod_BuildBaseBonePoses();
1841 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
1842 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, true);
1843 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1845 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1848 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1850 dpmheader_t *pheader;
1854 unsigned char *pbase;
1855 int i, j, k, meshvertices, meshtriangles;
1856 skinfile_t *skinfiles;
1857 unsigned char *data;
1860 pheader = (dpmheader_t *)buffer;
1861 pbase = (unsigned char *)buffer;
1862 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
1863 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
1864 if (BigLong(pheader->type) != 2)
1865 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1867 loadmodel->modeldatatypestring = "DPM";
1869 loadmodel->type = mod_alias;
1870 loadmodel->synctype = ST_RAND;
1873 pheader->type = BigLong(pheader->type);
1874 pheader->filesize = BigLong(pheader->filesize);
1875 pheader->mins[0] = BigFloat(pheader->mins[0]);
1876 pheader->mins[1] = BigFloat(pheader->mins[1]);
1877 pheader->mins[2] = BigFloat(pheader->mins[2]);
1878 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
1879 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
1880 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
1881 pheader->yawradius = BigFloat(pheader->yawradius);
1882 pheader->allradius = BigFloat(pheader->allradius);
1883 pheader->num_bones = BigLong(pheader->num_bones);
1884 pheader->num_meshs = BigLong(pheader->num_meshs);
1885 pheader->num_frames = BigLong(pheader->num_frames);
1886 pheader->ofs_bones = BigLong(pheader->ofs_bones);
1887 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
1888 pheader->ofs_frames = BigLong(pheader->ofs_frames);
1890 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
1892 Con_Printf("%s has no geometry\n", loadmodel->name);
1895 if (pheader->num_frames < 1)
1897 Con_Printf("%s has no frames\n", loadmodel->name);
1901 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1902 loadmodel->DrawSky = NULL;
1903 loadmodel->DrawAddWaterPlanes = NULL;
1904 loadmodel->Draw = R_Q1BSP_Draw;
1905 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1906 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1907 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1908 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1909 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1910 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1911 loadmodel->PointSuperContents = NULL;
1914 for (i = 0;i < 3;i++)
1916 loadmodel->normalmins[i] = pheader->mins[i];
1917 loadmodel->normalmaxs[i] = pheader->maxs[i];
1918 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
1919 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
1920 loadmodel->rotatedmins[i] = -pheader->allradius;
1921 loadmodel->rotatedmaxs[i] = pheader->allradius;
1923 loadmodel->radius = pheader->allradius;
1924 loadmodel->radius2 = pheader->allradius * pheader->allradius;
1926 // load external .skin files if present
1927 skinfiles = Mod_LoadSkinFiles();
1928 if (loadmodel->numskins < 1)
1929 loadmodel->numskins = 1;
1934 // gather combined statistics from the meshes
1935 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
1936 for (i = 0;i < (int)pheader->num_meshs;i++)
1938 int numverts = BigLong(dpmmesh->num_verts);
1939 meshvertices += numverts;;
1940 meshtriangles += BigLong(dpmmesh->num_tris);
1944 loadmodel->numframes = pheader->num_frames;
1945 loadmodel->num_bones = pheader->num_bones;
1946 loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
1947 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
1948 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1949 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1950 // do most allocations as one merged chunk
1951 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) + meshtriangles * sizeof(int[3]) + meshvertices * (sizeof(float[14]) + sizeof(int[4]) + sizeof(float[4])) + loadmodel->num_poses * sizeof(float[12]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
1952 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1953 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1954 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1955 loadmodel->surfmesh.num_vertices = meshvertices;
1956 loadmodel->surfmesh.num_triangles = meshtriangles;
1957 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1958 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1959 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1960 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1961 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1962 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1963 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1964 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1965 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1966 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
1967 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1968 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
1969 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
1970 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1971 if (meshvertices <= 65536)
1973 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1974 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1975 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1978 for (i = 0;i < loadmodel->numskins;i++)
1980 loadmodel->skinscenes[i].firstframe = i;
1981 loadmodel->skinscenes[i].framecount = 1;
1982 loadmodel->skinscenes[i].loop = true;
1983 loadmodel->skinscenes[i].framerate = 10;
1986 // load the bone info
1987 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
1988 for (i = 0;i < loadmodel->num_bones;i++)
1990 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1991 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1992 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1993 if (loadmodel->data_bones[i].parent >= i)
1994 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1998 frame = (dpmframe_t *) (pbase + pheader->ofs_frames);
1999 for (i = 0;i < loadmodel->numframes;i++)
2002 memcpy(loadmodel->animscenes[i].name, frame->name, sizeof(frame->name));
2003 loadmodel->animscenes[i].firstframe = i;
2004 loadmodel->animscenes[i].framecount = 1;
2005 loadmodel->animscenes[i].loop = true;
2006 loadmodel->animscenes[i].framerate = 10;
2007 // load the bone poses for this frame
2008 poses = (float *) (pbase + BigLong(frame->ofs_bonepositions));
2009 for (j = 0;j < loadmodel->num_bones*12;j++)
2010 loadmodel->data_poses[i * loadmodel->num_bones*12 + j] = BigFloat(poses[j]);
2011 // stuff not processed here: mins, maxs, yawradius, allradius
2015 // load the meshes now
2016 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2019 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2020 // (converting from weight-blending skeletal animation to
2021 // deformation-based skeletal animation)
2022 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2023 for (i = 0;i < loadmodel->num_bones;i++)
2025 const float *m = loadmodel->data_poses + i * 12;
2026 if (loadmodel->data_bones[i].parent >= 0)
2027 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2029 for (k = 0;k < 12;k++)
2030 bonepose[12*i+k] = m[k];
2032 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2034 const int *inelements;
2036 const float *intexcoord;
2037 msurface_t *surface;
2039 loadmodel->surfacelist[i] = i;
2040 surface = loadmodel->data_surfaces + i;
2041 surface->texture = loadmodel->data_textures + i;
2042 surface->num_firsttriangle = meshtriangles;
2043 surface->num_triangles = BigLong(dpmmesh->num_tris);
2044 surface->num_firstvertex = meshvertices;
2045 surface->num_vertices = BigLong(dpmmesh->num_verts);
2046 meshvertices += surface->num_vertices;
2047 meshtriangles += surface->num_triangles;
2049 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2050 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2051 for (j = 0;j < surface->num_triangles;j++)
2053 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2054 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2055 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2056 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2061 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2062 for (j = 0;j < surface->num_vertices*2;j++)
2063 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2065 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2066 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2070 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2071 data += sizeof(dpmvertex_t);
2072 for (k = 0;k < numweights;k++)
2074 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2075 int boneindex = BigLong(vert->bonenum);
2076 const float *m = bonepose + 12 * boneindex;
2077 float influence = BigFloat(vert->influence);
2078 float relativeorigin[3], relativenormal[3];
2079 relativeorigin[0] = BigFloat(vert->origin[0]);
2080 relativeorigin[1] = BigFloat(vert->origin[1]);
2081 relativeorigin[2] = BigFloat(vert->origin[2]);
2082 relativenormal[0] = BigFloat(vert->normal[0]);
2083 relativenormal[1] = BigFloat(vert->normal[1]);
2084 relativenormal[2] = BigFloat(vert->normal[2]);
2085 // blend the vertex bone weights into the base mesh
2086 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2087 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2088 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2089 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2090 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2091 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2094 // store the first (and often only) weight
2095 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = influence;
2096 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
2100 // sort the new weight into this vertex's weight table
2101 // (which only accepts up to 4 bones per vertex)
2102 for (l = 0;l < 4;l++)
2104 if (loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] < influence)
2106 // move weaker influence weights out of the way first
2108 for (l2 = 3;l2 > l;l2--)
2110 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2-1];
2111 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2-1];
2113 // store the new weight
2114 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] = influence;
2115 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l] = boneindex;
2120 data += sizeof(dpmbonevert_t);
2123 for (l = 0;l < 4;l++)
2124 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l];
2125 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2127 float f = 1.0f / sum;
2128 for (l = 0;l < 4;l++)
2129 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] *= f;
2133 // since dpm models do not have named sections, reuse their shader name as the section name
2134 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2136 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2139 Mod_FreeSkinFiles(skinfiles);
2141 // compute all the mesh information that was not loaded from the file
2142 Mod_BuildBaseBonePoses();
2143 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, true);
2144 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2146 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2149 // no idea why PSK/PSA files contain weird quaternions but they do...
2150 #define PSKQUATNEGATIONS
2151 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2153 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2154 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2155 fs_offset_t filesize;
2160 pskboneinfo_t *bones;
2161 pskrawweights_t *rawweights;
2162 pskboneinfo_t *animbones;
2163 pskaniminfo_t *anims;
2164 pskanimkeys_t *animkeys;
2165 void *animfilebuffer, *animbuffer, *animbufferend;
2166 unsigned char *data;
2168 skinfile_t *skinfiles;
2169 char animname[MAX_QPATH];
2172 pchunk = (pskchunk_t *)buffer;
2173 if (strcmp(pchunk->id, "ACTRHEAD"))
2174 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2176 loadmodel->modeldatatypestring = "PSK";
2178 loadmodel->type = mod_alias;
2179 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2180 loadmodel->DrawSky = NULL;
2181 loadmodel->DrawAddWaterPlanes = NULL;
2182 loadmodel->Draw = R_Q1BSP_Draw;
2183 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2184 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2185 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2186 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2187 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2188 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2189 loadmodel->PointSuperContents = NULL;
2190 loadmodel->synctype = ST_RAND;
2192 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2193 strlcat(animname, ".psa", sizeof(animname));
2194 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2195 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2196 if (animbuffer == NULL)
2197 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2216 while (buffer < bufferend)
2218 pchunk = (pskchunk_t *)buffer;
2219 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2220 version = LittleLong(pchunk->version);
2221 recordsize = LittleLong(pchunk->recordsize);
2222 numrecords = LittleLong(pchunk->numrecords);
2223 if (developer.integer >= 100)
2224 Con_Printf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2225 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2226 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);
2227 if (!strcmp(pchunk->id, "ACTRHEAD"))
2231 else if (!strcmp(pchunk->id, "PNTS0000"))
2234 if (recordsize != sizeof(*p))
2235 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2236 // byteswap in place and keep the pointer
2237 numpnts = numrecords;
2238 pnts = (pskpnts_t *)buffer;
2239 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2241 p->origin[0] = LittleFloat(p->origin[0]);
2242 p->origin[1] = LittleFloat(p->origin[1]);
2243 p->origin[2] = LittleFloat(p->origin[2]);
2247 else if (!strcmp(pchunk->id, "VTXW0000"))
2250 if (recordsize != sizeof(*p))
2251 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2252 // byteswap in place and keep the pointer
2253 numvtxw = numrecords;
2254 vtxw = (pskvtxw_t *)buffer;
2255 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2257 p->pntsindex = LittleShort(p->pntsindex);
2258 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2259 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2260 if (p->pntsindex >= numpnts)
2262 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2268 else if (!strcmp(pchunk->id, "FACE0000"))
2271 if (recordsize != sizeof(*p))
2272 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2273 // byteswap in place and keep the pointer
2274 numfaces = numrecords;
2275 faces = (pskface_t *)buffer;
2276 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2278 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2279 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2280 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2281 p->group = LittleLong(p->group);
2282 if (p->vtxwindex[0] >= numvtxw)
2284 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2285 p->vtxwindex[0] = 0;
2287 if (p->vtxwindex[1] >= numvtxw)
2289 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2290 p->vtxwindex[1] = 0;
2292 if (p->vtxwindex[2] >= numvtxw)
2294 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2295 p->vtxwindex[2] = 0;
2300 else if (!strcmp(pchunk->id, "MATT0000"))
2303 if (recordsize != sizeof(*p))
2304 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2305 // byteswap in place and keep the pointer
2306 nummatts = numrecords;
2307 matts = (pskmatt_t *)buffer;
2308 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2314 else if (!strcmp(pchunk->id, "REFSKELT"))
2317 if (recordsize != sizeof(*p))
2318 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2319 // byteswap in place and keep the pointer
2320 numbones = numrecords;
2321 bones = (pskboneinfo_t *)buffer;
2322 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2324 p->numchildren = LittleLong(p->numchildren);
2325 p->parent = LittleLong(p->parent);
2326 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2327 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2328 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2329 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2330 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2331 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2332 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2333 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2334 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2335 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2336 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2337 #ifdef PSKQUATNEGATIONS
2340 p->basepose.quat[0] *= -1;
2341 p->basepose.quat[1] *= -1;
2342 p->basepose.quat[2] *= -1;
2346 p->basepose.quat[0] *= 1;
2347 p->basepose.quat[1] *= -1;
2348 p->basepose.quat[2] *= 1;
2351 if (p->parent < 0 || p->parent >= numbones)
2353 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2359 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2362 if (recordsize != sizeof(*p))
2363 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2364 // byteswap in place and keep the pointer
2365 numrawweights = numrecords;
2366 rawweights = (pskrawweights_t *)buffer;
2367 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2369 p->weight = LittleFloat(p->weight);
2370 p->pntsindex = LittleLong(p->pntsindex);
2371 p->boneindex = LittleLong(p->boneindex);
2372 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2374 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2377 if (p->boneindex < 0 || p->boneindex >= numbones)
2379 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2387 while (animbuffer < animbufferend)
2389 pchunk = (pskchunk_t *)animbuffer;
2390 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2391 version = LittleLong(pchunk->version);
2392 recordsize = LittleLong(pchunk->recordsize);
2393 numrecords = LittleLong(pchunk->numrecords);
2394 if (developer.integer >= 100)
2395 Con_Printf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2396 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2397 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);
2398 if (!strcmp(pchunk->id, "ANIMHEAD"))
2402 else if (!strcmp(pchunk->id, "BONENAMES"))
2405 if (recordsize != sizeof(*p))
2406 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2407 // byteswap in place and keep the pointer
2408 numanimbones = numrecords;
2409 animbones = (pskboneinfo_t *)animbuffer;
2410 // NOTE: supposedly psa does not need to match the psk model, the
2411 // bones missing from the psa would simply use their base
2412 // positions from the psk, but this is hard for me to implement
2413 // and people can easily make animations that match.
2414 if (numanimbones != numbones)
2415 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2416 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2418 p->numchildren = LittleLong(p->numchildren);
2419 p->parent = LittleLong(p->parent);
2420 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2421 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2422 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2423 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2424 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2425 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2426 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2427 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2428 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2429 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2430 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2431 #ifdef PSKQUATNEGATIONS
2434 p->basepose.quat[0] *= -1;
2435 p->basepose.quat[1] *= -1;
2436 p->basepose.quat[2] *= -1;
2440 p->basepose.quat[0] *= 1;
2441 p->basepose.quat[1] *= -1;
2442 p->basepose.quat[2] *= 1;
2445 if (p->parent < 0 || p->parent >= numanimbones)
2447 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2450 // check that bones are the same as in the base
2451 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2452 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2456 else if (!strcmp(pchunk->id, "ANIMINFO"))
2459 if (recordsize != sizeof(*p))
2460 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2461 // byteswap in place and keep the pointer
2462 numanims = numrecords;
2463 anims = (pskaniminfo_t *)animbuffer;
2464 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2466 p->numbones = LittleLong(p->numbones);
2467 p->playtime = LittleFloat(p->playtime);
2468 p->fps = LittleFloat(p->fps);
2469 p->firstframe = LittleLong(p->firstframe);
2470 p->numframes = LittleLong(p->numframes);
2471 if (p->numbones != numbones)
2472 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2476 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2479 if (recordsize != sizeof(*p))
2480 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2481 numanimkeys = numrecords;
2482 animkeys = (pskanimkeys_t *)animbuffer;
2483 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2485 p->origin[0] = LittleFloat(p->origin[0]);
2486 p->origin[1] = LittleFloat(p->origin[1]);
2487 p->origin[2] = LittleFloat(p->origin[2]);
2488 p->quat[0] = LittleFloat(p->quat[0]);
2489 p->quat[1] = LittleFloat(p->quat[1]);
2490 p->quat[2] = LittleFloat(p->quat[2]);
2491 p->quat[3] = LittleFloat(p->quat[3]);
2492 p->frametime = LittleFloat(p->frametime);
2493 #ifdef PSKQUATNEGATIONS
2494 if (index % numbones)
2509 // TODO: allocate bonepose stuff
2512 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2515 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2516 Host_Error("%s: missing required chunks", loadmodel->name);
2518 loadmodel->numframes = 0;
2519 for (index = 0;index < numanims;index++)
2520 loadmodel->numframes += anims[index].numframes;
2522 if (numanimkeys != numbones * loadmodel->numframes)
2523 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2525 meshvertices = numvtxw;
2526 meshtriangles = numfaces;
2528 // load external .skin files if present
2529 skinfiles = Mod_LoadSkinFiles();
2530 if (loadmodel->numskins < 1)
2531 loadmodel->numskins = 1;
2532 loadmodel->num_bones = numbones;
2533 loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
2534 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2535 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2536 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2537 loadmodel->surfmesh.num_vertices = meshvertices;
2538 loadmodel->surfmesh.num_triangles = meshtriangles;
2539 // do most allocations as one merged chunk
2540 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]) + loadmodel->surfmesh.num_triangles * sizeof(int[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[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[2]) + loadmodel->surfmesh.num_vertices * sizeof(int[4]) + loadmodel->surfmesh.num_vertices * sizeof(float[4]) + loadmodel->num_poses * sizeof(float[12]) + 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);
2541 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2542 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2543 loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2544 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2545 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2546 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2547 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2548 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2549 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2550 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2551 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2552 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += loadmodel->surfmesh.num_vertices * sizeof(int[4]);
2553 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[4]);
2554 loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
2555 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2556 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2557 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2558 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2559 if (loadmodel->surfmesh.num_vertices <= 65536)
2561 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2562 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2563 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2565 if (data != (unsigned char *)loadmodel->data_surfaces + size)
2566 Sys_Error("%s: combined alloc has wrong size! (%i bytes should be %i)\n", loadmodel->name, (int)size, (int)(data - (unsigned char *)loadmodel->data_surfaces));
2568 for (i = 0;i < loadmodel->numskins;i++)
2570 loadmodel->skinscenes[i].firstframe = i;
2571 loadmodel->skinscenes[i].framecount = 1;
2572 loadmodel->skinscenes[i].loop = true;
2573 loadmodel->skinscenes[i].framerate = 10;
2577 for (index = 0, i = 0;index < nummatts;index++)
2579 // since psk models do not have named sections, reuse their shader name as the section name
2580 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2581 loadmodel->surfacelist[index] = index;
2582 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2583 loadmodel->data_surfaces[index].num_firstvertex = 0;
2584 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2587 // copy over the vertex locations and texcoords
2588 for (index = 0;index < numvtxw;index++)
2590 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2591 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2592 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2593 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2594 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2597 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2598 for (index = 0;index < numfaces;index++)
2599 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2600 for (index = 0, i = 0;index < nummatts;index++)
2602 loadmodel->data_surfaces[index].num_firsttriangle = i;
2603 i += loadmodel->data_surfaces[index].num_triangles;
2604 loadmodel->data_surfaces[index].num_triangles = 0;
2606 for (index = 0;index < numfaces;index++)
2608 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2609 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2610 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2611 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2614 // copy over the bones
2615 for (index = 0;index < numbones;index++)
2617 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2618 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2619 if (loadmodel->data_bones[index].parent >= index)
2620 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2623 // sort the psk point weights into the vertex weight tables
2624 // (which only accept up to 4 bones per vertex)
2625 for (index = 0;index < numvtxw;index++)
2629 for (j = 0;j < numrawweights;j++)
2631 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2633 int boneindex = rawweights[j].boneindex;
2634 float influence = rawweights[j].weight;
2635 for (l = 0;l < 4;l++)
2637 if (loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] < influence)
2639 // move lower influence weights out of the way first
2641 for (l2 = 3;l2 > l;l2--)
2643 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2-1];
2644 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2-1];
2646 // store the new weight
2647 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] = influence;
2648 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l] = boneindex;
2655 for (l = 0;l < 4;l++)
2656 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l];
2657 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2659 float f = 1.0f / sum;
2660 for (l = 0;l < 4;l++)
2661 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] *= f;
2665 // set up the animscenes based on the anims
2666 for (index = 0, i = 0;index < numanims;index++)
2668 for (j = 0;j < anims[index].numframes;j++, i++)
2670 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2671 loadmodel->animscenes[i].firstframe = i;
2672 loadmodel->animscenes[i].framecount = 1;
2673 loadmodel->animscenes[i].loop = true;
2674 loadmodel->animscenes[i].framerate = 10;
2678 // load the poses from the animkeys
2679 for (index = 0;index < numanimkeys;index++)
2681 pskanimkeys_t *k = animkeys + index;
2683 Matrix4x4_FromOriginQuat(&matrix, k->origin[0], k->origin[1], k->origin[2], k->quat[0], k->quat[1], k->quat[2], k->quat[3]);
2684 Matrix4x4_ToArray12FloatD3D(&matrix, loadmodel->data_poses + index*12);
2686 Mod_FreeSkinFiles(skinfiles);
2687 Mem_Free(animfilebuffer);
2689 // compute all the mesh information that was not loaded from the file
2690 // TODO: honor smoothing groups somehow?
2691 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2692 Mod_BuildBaseBonePoses();
2693 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2694 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, true);
2695 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2696 Mod_Alias_CalculateBoundingBox();
2698 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]) + loadmodel->surfmesh.num_triangles * sizeof(int[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[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[2]) + loadmodel->surfmesh.num_vertices * sizeof(int[4]) + loadmodel->surfmesh.num_vertices * sizeof(float[4]) + loadmodel->num_poses * sizeof(float[12]) + 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);
2699 if (size != ((memheader_t *)loadmodel->data_surfaces)[-1].size)
2700 Sys_Error("%s:%i: %i != %i", __FILE__, __LINE__, (int)size, (int)((memheader_t *)loadmodel->data_surfaces)[-1].size);
2702 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;