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"};
31 cvar_t mod_alias_supporttagscale = {0, "mod_alias_supporttagscale", "1", "support scaling factors in bone/tag attachment matrices as supported by MD3"};
33 float mod_md3_sin[320];
35 void Mod_AliasInit (void)
38 Cvar_RegisterVariable(&r_skeletal_debugbone);
39 Cvar_RegisterVariable(&r_skeletal_debugbonecomponent);
40 Cvar_RegisterVariable(&r_skeletal_debugbonevalue);
41 Cvar_RegisterVariable(&r_skeletal_debugtranslatex);
42 Cvar_RegisterVariable(&r_skeletal_debugtranslatey);
43 Cvar_RegisterVariable(&r_skeletal_debugtranslatez);
44 Cvar_RegisterVariable(&mod_alias_supporttagscale);
45 for (i = 0;i < 320;i++)
46 mod_md3_sin[i] = sin(i * M_PI * 2.0f / 256.0);
49 void Mod_Skeletal_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
52 // vertex weighted skeletal
55 float boneposerelative[MAX_BONES][12];
56 float matrix[12], m[12], bonepose[MAX_BONES][12];
58 if (skeleton && !skeleton->relativetransforms)
61 // interpolate matrices
64 for (i = 0;i < model->num_bones;i++)
66 Matrix4x4_ToArray12FloatD3D(&skeleton->relativetransforms[i], m);
67 if (model->data_bones[i].parent >= 0)
68 R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
70 for (k = 0;k < 12;k++)
71 bonepose[i][k] = m[k];
73 // create a relative deformation matrix to describe displacement
74 // from the base mesh, which is used by the actual weighting
75 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]);
80 float originscale = model->num_posescale;
83 for (i = 0;i < model->num_bones;i++)
85 for (k = 0;k < 12;k++)
87 for (blends = 0;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++)
89 pose6s = model->data_poses6s + 6 * (frameblend[blends].subframe * model->num_bones + i);
90 x = pose6s[3] * (1.0f / 32767.0f);
91 y = pose6s[4] * (1.0f / 32767.0f);
92 z = pose6s[5] * (1.0f / 32767.0f);
93 w = 1.0f - (x*x+y*y+z*z);
94 w = w > 0.0f ? -sqrt(w) : 0.0f;
95 matrix[ 0]=1-2*(y*y+z*z);
96 matrix[ 1]= 2*(x*y-z*w);
97 matrix[ 2]= 2*(x*z+y*w);
98 matrix[ 3]=pose6s[0] * originscale;
99 matrix[ 4]= 2*(x*y+z*w);
100 matrix[ 5]=1-2*(x*x+z*z);
101 matrix[ 6]= 2*(y*z-x*w);
102 matrix[ 7]=pose6s[1] * originscale;
103 matrix[ 8]= 2*(x*z-y*w);
104 matrix[ 9]= 2*(y*z+x*w);
105 matrix[10]=1-2*(x*x+y*y);
106 matrix[11]=pose6s[2] * originscale;
107 for (k = 0;k < 12;k++)
108 m[k] += matrix[k] * frameblend[blends].lerp;
111 VectorNormalize(m + 4);
112 VectorNormalize(m + 8);
113 if (i == r_skeletal_debugbone.integer)
114 m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
115 m[3] *= r_skeletal_debugtranslatex.value;
116 m[7] *= r_skeletal_debugtranslatey.value;
117 m[11] *= r_skeletal_debugtranslatez.value;
118 if (model->data_bones[i].parent >= 0)
119 R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
121 for (k = 0;k < 12;k++)
122 bonepose[i][k] = m[k];
123 // create a relative deformation matrix to describe displacement
124 // from the base mesh, which is used by the actual weighting
125 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]);
129 // blend the vertex bone weights
130 // 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)
131 // special case for the first bone because it avoids the need to memset the arrays before filling
134 const float *v = model->surfmesh.data_vertex3f;
135 const int *wi = model->surfmesh.data_vertexweightindex4i;
136 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
137 memset(vertex3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
138 for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, wi += 4, wf += 4, vertex3f += 3)
142 const float *m = boneposerelative[wi[0]];
143 vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
144 vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
145 vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
149 const float *m = boneposerelative[wi[0]];
151 vertex3f[0] = f * (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
152 vertex3f[1] = f * (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
153 vertex3f[2] = f * (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
154 for (k = 1;k < 4 && wf[k];k++)
156 const float *m = boneposerelative[wi[k]];
158 vertex3f[0] += f * (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]);
159 vertex3f[1] += f * (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]);
160 vertex3f[2] += f * (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]);
167 const float *n = model->surfmesh.data_normal3f;
168 const int *wi = model->surfmesh.data_vertexweightindex4i;
169 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
170 memset(normal3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
171 for (i = 0;i < model->surfmesh.num_vertices;i++, n += 3, wi += 4, wf += 4, normal3f += 3)
175 const float *m = boneposerelative[wi[0]];
176 normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
177 normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
178 normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
182 const float *m = boneposerelative[wi[0]];
184 normal3f[0] = f * (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
185 normal3f[1] = f * (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
186 normal3f[2] = f * (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
187 for (k = 1;k < 4 && wf[k];k++)
189 const float *m = boneposerelative[wi[k]];
191 normal3f[0] += f * (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]);
192 normal3f[1] += f * (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]);
193 normal3f[2] += f * (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]);
200 const float *sv = model->surfmesh.data_svector3f;
201 const int *wi = model->surfmesh.data_vertexweightindex4i;
202 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
203 memset(svector3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
204 for (i = 0;i < model->surfmesh.num_vertices;i++, sv += 3, wi += 4, wf += 4, svector3f += 3)
208 const float *m = boneposerelative[wi[0]];
209 svector3f[0] = (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
210 svector3f[1] = (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
211 svector3f[2] = (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
215 const float *m = boneposerelative[wi[0]];
217 svector3f[0] = f * (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
218 svector3f[1] = f * (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
219 svector3f[2] = f * (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
220 for (k = 1;k < 4 && wf[k];k++)
222 const float *m = boneposerelative[wi[k]];
224 svector3f[0] += f * (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]);
225 svector3f[1] += f * (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]);
226 svector3f[2] += f * (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]);
233 const float *tv = model->surfmesh.data_tvector3f;
234 const int *wi = model->surfmesh.data_vertexweightindex4i;
235 const float *wf = model->surfmesh.data_vertexweightinfluence4f;
236 memset(tvector3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
237 for (i = 0;i < model->surfmesh.num_vertices;i++, tv += 3, wi += 4, wf += 4, tvector3f += 3)
241 const float *m = boneposerelative[wi[0]];
242 tvector3f[0] = (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
243 tvector3f[1] = (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
244 tvector3f[2] = (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
248 const float *m = boneposerelative[wi[0]];
250 tvector3f[0] = f * (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
251 tvector3f[1] = f * (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
252 tvector3f[2] = f * (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
253 for (k = 1;k < 4 && wf[k];k++)
255 const float *m = boneposerelative[wi[k]];
257 tvector3f[0] += f * (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]);
258 tvector3f[1] += f * (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]);
259 tvector3f[2] += f * (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]);
266 void Mod_MD3_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
269 int i, numblends, blendnum;
270 int numverts = model->surfmesh.num_vertices;
272 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
274 //VectorMA(translate, model->surfmesh.num_morphmdlframetranslate, frameblend[blendnum].lerp, translate);
275 if (frameblend[blendnum].lerp > 0)
276 numblends = blendnum + 1;
278 // special case for the first blend because it avoids some adds and the need to memset the arrays first
279 for (blendnum = 0;blendnum < numblends;blendnum++)
281 const md3vertex_t *verts = model->surfmesh.data_morphmd3vertex + numverts * frameblend[blendnum].subframe;
284 float scale = frameblend[blendnum].lerp * (1.0f / 64.0f);
287 for (i = 0;i < numverts;i++)
289 vertex3f[i * 3 + 0] = verts[i].origin[0] * scale;
290 vertex3f[i * 3 + 1] = verts[i].origin[1] * scale;
291 vertex3f[i * 3 + 2] = verts[i].origin[2] * scale;
296 for (i = 0;i < numverts;i++)
298 vertex3f[i * 3 + 0] += verts[i].origin[0] * scale;
299 vertex3f[i * 3 + 1] += verts[i].origin[1] * scale;
300 vertex3f[i * 3 + 2] += verts[i].origin[2] * scale;
304 // the yaw and pitch stored in md3 models are 8bit quantized angles
305 // (0-255), and as such a lookup table is very well suited to
306 // decoding them, and since cosine is equivilant to sine with an
307 // extra 45 degree rotation, this uses one lookup table for both
308 // sine and cosine with a +64 bias to get cosine.
311 float lerp = frameblend[blendnum].lerp;
314 for (i = 0;i < numverts;i++)
316 normal3f[i * 3 + 0] = mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
317 normal3f[i * 3 + 1] = mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
318 normal3f[i * 3 + 2] = mod_md3_sin[verts[i].pitch + 64] * lerp;
323 for (i = 0;i < numverts;i++)
325 normal3f[i * 3 + 0] += mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp;
326 normal3f[i * 3 + 1] += mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp;
327 normal3f[i * 3 + 2] += mod_md3_sin[verts[i].pitch + 64] * lerp;
333 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
334 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
337 for (i = 0;i < numverts;i++, texvecvert++)
339 VectorScale(texvecvert->svec, f, svector3f + i*3);
340 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
345 for (i = 0;i < numverts;i++, texvecvert++)
347 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
348 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
355 void Mod_MDL_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
358 int i, numblends, blendnum;
359 int numverts = model->surfmesh.num_vertices;
361 VectorClear(translate);
363 // blend the frame translates to avoid redundantly doing so on each vertex
364 // (a bit of a brain twister but it works)
365 for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
367 if (model->surfmesh.data_morphmd2framesize6f)
368 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6 + 3, translate);
370 VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.num_morphmdlframetranslate, translate);
371 if (frameblend[blendnum].lerp > 0)
372 numblends = blendnum + 1;
374 // special case for the first blend because it avoids some adds and the need to memset the arrays first
375 for (blendnum = 0;blendnum < numblends;blendnum++)
377 const trivertx_t *verts = model->surfmesh.data_morphmdlvertex + numverts * frameblend[blendnum].subframe;
381 if (model->surfmesh.data_morphmd2framesize6f)
382 VectorScale(model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6, frameblend[blendnum].lerp, scale);
384 VectorScale(model->surfmesh.num_morphmdlframescale, frameblend[blendnum].lerp, scale);
387 for (i = 0;i < numverts;i++)
389 vertex3f[i * 3 + 0] = translate[0] + verts[i].v[0] * scale[0];
390 vertex3f[i * 3 + 1] = translate[1] + verts[i].v[1] * scale[1];
391 vertex3f[i * 3 + 2] = translate[2] + verts[i].v[2] * scale[2];
396 for (i = 0;i < numverts;i++)
398 vertex3f[i * 3 + 0] += verts[i].v[0] * scale[0];
399 vertex3f[i * 3 + 1] += verts[i].v[1] * scale[1];
400 vertex3f[i * 3 + 2] += verts[i].v[2] * scale[2];
404 // the vertex normals in mdl models are an index into a table of
405 // 162 unique values, this very crude quantization reduces the
406 // vertex normal to only one byte, which saves a lot of space but
407 // also makes lighting pretty coarse
410 float lerp = frameblend[blendnum].lerp;
413 for (i = 0;i < numverts;i++)
415 const float *vn = m_bytenormals[verts[i].lightnormalindex];
416 VectorScale(vn, lerp, normal3f + i*3);
421 for (i = 0;i < numverts;i++)
423 const float *vn = m_bytenormals[verts[i].lightnormalindex];
424 VectorMA(normal3f + i*3, lerp, vn, normal3f + i*3);
430 const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
431 float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
434 for (i = 0;i < numverts;i++, texvecvert++)
436 VectorScale(texvecvert->svec, f, svector3f + i*3);
437 VectorScale(texvecvert->tvec, f, tvector3f + i*3);
442 for (i = 0;i < numverts;i++, texvecvert++)
444 VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3);
445 VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3);
452 int Mod_Alias_GetTagMatrix(const dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, int tagindex, matrix4x4_t *outmatrix)
455 matrix4x4_t parentbonematrix;
456 matrix4x4_t tempbonematrix;
457 matrix4x4_t bonematrix;
458 matrix4x4_t blendmatrix;
465 *outmatrix = identitymatrix;
466 if (skeleton && skeleton->relativetransforms)
468 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
470 *outmatrix = skeleton->relativetransforms[tagindex];
471 while ((tagindex = model->data_bones[tagindex].parent) >= 0)
474 Matrix4x4_Concat(outmatrix, &skeleton->relativetransforms[tagindex], &temp);
477 else if (model->num_bones)
479 if (tagindex < 0 || tagindex >= model->num_bones)
481 Matrix4x4_Clear(&blendmatrix);
482 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
484 lerp = frameblend[blendindex].lerp;
485 Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
486 parenttagindex = tagindex;
487 while ((parenttagindex = model->data_bones[parenttagindex].parent) >= 0)
489 Matrix4x4_FromBonePose6s(&parentbonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + parenttagindex));
490 tempbonematrix = bonematrix;
491 Matrix4x4_Concat(&bonematrix, &parentbonematrix, &tempbonematrix);
493 Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
495 *outmatrix = blendmatrix;
497 else if (model->num_tags)
499 if (tagindex < 0 || tagindex >= model->num_tags)
501 for (k = 0;k < 12;k++)
503 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
505 lerp = frameblend[blendindex].lerp;
506 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
507 for (k = 0;k < 12;k++)
508 blendtag[k] += input[k] * lerp;
510 Matrix4x4_FromArray12FloatGL(outmatrix, blendtag);
513 if(!mod_alias_supporttagscale.integer)
514 Matrix4x4_Normalize3(outmatrix, outmatrix);
519 int Mod_Alias_GetExtendedTagInfoForIndex(const dp_model_t *model, unsigned int skin, const frameblend_t *frameblend, const skeleton_t *skeleton, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
524 matrix4x4_t bonematrix;
525 matrix4x4_t blendmatrix;
529 if (skeleton && skeleton->relativetransforms)
531 if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
533 *parentindex = skeleton->model->data_bones[tagindex].parent;
534 *tagname = skeleton->model->data_bones[tagindex].name;
535 *tag_localmatrix = skeleton->relativetransforms[tagindex];
538 else if (model->num_bones)
540 if (tagindex < 0 || tagindex >= model->num_bones)
542 *parentindex = model->data_bones[tagindex].parent;
543 *tagname = model->data_bones[tagindex].name;
544 Matrix4x4_Clear(&blendmatrix);
545 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
547 lerp = frameblend[blendindex].lerp;
548 Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
549 Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
551 *tag_localmatrix = blendmatrix;
554 else if (model->num_tags)
556 if (tagindex < 0 || tagindex >= model->num_tags)
559 *tagname = model->data_tags[tagindex].name;
560 for (k = 0;k < 12;k++)
562 for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
564 lerp = frameblend[blendindex].lerp;
565 input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
566 for (k = 0;k < 12;k++)
567 blendtag[k] += input[k] * lerp;
569 Matrix4x4_FromArray12FloatGL(tag_localmatrix, blendtag);
576 int Mod_Alias_GetTagIndexForName(const dp_model_t *model, unsigned int skin, const char *tagname)
579 if(skin >= (unsigned int)model->numskins)
581 if (model->num_bones)
582 for (i = 0;i < model->num_bones;i++)
583 if (!strcasecmp(tagname, model->data_bones[i].name))
586 for (i = 0;i < model->num_tags;i++)
587 if (!strcasecmp(tagname, model->data_tags[i].name))
592 static void Mod_BuildBaseBonePoses(void)
595 matrix4x4_t *basebonepose;
596 float *outinvmatrix = loadmodel->data_baseboneposeinverse;
597 matrix4x4_t bonematrix;
598 matrix4x4_t tempbonematrix;
599 if (!loadmodel->num_bones)
601 basebonepose = (matrix4x4_t *)Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(matrix4x4_t));
602 for (boneindex = 0;boneindex < loadmodel->num_bones;boneindex++)
604 Matrix4x4_FromBonePose6s(&bonematrix, loadmodel->num_posescale, loadmodel->data_poses6s + 6 * boneindex);
605 if (loadmodel->data_bones[boneindex].parent >= 0)
607 tempbonematrix = bonematrix;
608 Matrix4x4_Concat(&bonematrix, basebonepose + loadmodel->data_bones[boneindex].parent, &tempbonematrix);
610 basebonepose[boneindex] = bonematrix;
611 Matrix4x4_Invert_Simple(&tempbonematrix, basebonepose + boneindex);
612 Matrix4x4_ToArray12FloatD3D(&tempbonematrix, outinvmatrix + 12*boneindex);
614 Mem_Free(basebonepose);
617 static void Mod_Alias_CalculateBoundingBox(void)
620 qboolean firstvertex = true;
621 float dist, yawradius, radius;
624 frameblend_t frameblend[MAX_FRAMEBLENDS];
625 memset(frameblend, 0, sizeof(frameblend));
626 frameblend[0].lerp = 1;
627 vertex3f = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
628 VectorClear(loadmodel->normalmins);
629 VectorClear(loadmodel->normalmaxs);
632 for (frameblend[0].subframe = 0;frameblend[0].subframe < loadmodel->num_poses;frameblend[0].subframe++)
634 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, vertex3f, NULL, NULL, NULL);
635 for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
640 VectorCopy(v, loadmodel->normalmins);
641 VectorCopy(v, loadmodel->normalmaxs);
645 if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0];
646 if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1];
647 if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2];
648 if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0];
649 if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1];
650 if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2];
652 dist = v[0] * v[0] + v[1] * v[1];
653 if (yawradius < dist)
662 radius = sqrt(radius);
663 yawradius = sqrt(yawradius);
664 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
665 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
666 loadmodel->yawmins[2] = loadmodel->normalmins[2];
667 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
668 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
669 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
670 loadmodel->radius = radius;
671 loadmodel->radius2 = radius * radius;
674 static void Mod_Alias_MorphMesh_CompileFrames(void)
677 frameblend_t frameblend[MAX_FRAMEBLENDS];
678 unsigned char *datapointer;
679 memset(frameblend, 0, sizeof(frameblend));
680 frameblend[0].lerp = 1;
681 datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
682 loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
683 loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
684 loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
685 loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
686 loadmodel->surfmesh.data_morphtexvecvertex = (texvecvertex_t *)datapointer;datapointer += loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices * sizeof(texvecvertex_t);
687 // 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)
688 for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
690 frameblend[0].subframe = i;
691 loadmodel->AnimateVertices(loadmodel, frameblend, NULL, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
692 Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, r_smoothnormals_areaweighting.integer != 0);
693 // encode the svector and tvector in 3 byte format for permanent storage
694 for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
696 VectorScaleCast(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
697 VectorScaleCast(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
702 static void Mod_MDLMD2MD3_TraceLine(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask)
705 float segmentmins[3], segmentmaxs[3];
707 static int maxvertices = 0;
708 static float *vertex3f = NULL;
709 memset(trace, 0, sizeof(*trace));
711 trace->realfraction = 1;
712 trace->hitsupercontentsmask = hitsupercontentsmask;
713 if (maxvertices < model->surfmesh.num_vertices)
717 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
718 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
720 segmentmins[0] = min(start[0], end[0]) - 1;
721 segmentmins[1] = min(start[1], end[1]) - 1;
722 segmentmins[2] = min(start[2], end[2]) - 1;
723 segmentmaxs[0] = max(start[0], end[0]) + 1;
724 segmentmaxs[1] = max(start[1], end[1]) + 1;
725 segmentmaxs[2] = max(start[2], end[2]) + 1;
726 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
727 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
728 Collision_TraceLineTriangleMeshFloat(trace, start, end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs);
731 static int maxvertices = 0;
732 static float *vertex3f = NULL;
734 static void Mod_MDLMD2MD3_TraceBox(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask)
737 vec3_t shiftstart, shiftend;
738 float segmentmins[3], segmentmaxs[3];
740 colboxbrushf_t thisbrush_start, thisbrush_end;
741 vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
743 if (VectorCompare(boxmins, boxmaxs))
745 VectorAdd(start, boxmins, shiftstart);
746 VectorAdd(end, boxmins, shiftend);
747 Mod_MDLMD2MD3_TraceLine(model, frameblend, skeleton, trace, start, end, hitsupercontentsmask);
748 VectorSubtract(trace->endpos, boxmins, trace->endpos);
752 // box trace, performed as brush trace
753 memset(trace, 0, sizeof(*trace));
755 trace->realfraction = 1;
756 trace->hitsupercontentsmask = hitsupercontentsmask;
757 if (maxvertices < model->surfmesh.num_vertices)
761 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
762 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
764 segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
765 segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
766 segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
767 segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1;
768 segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1;
769 segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1;
770 VectorAdd(start, boxmins, boxstartmins);
771 VectorAdd(start, boxmaxs, boxstartmaxs);
772 VectorAdd(end, boxmins, boxendmins);
773 VectorAdd(end, boxmaxs, boxendmaxs);
774 Collision_BrushForBox(&thisbrush_start, boxstartmins, boxstartmaxs, 0, 0, NULL);
775 Collision_BrushForBox(&thisbrush_end, boxendmins, boxendmaxs, 0, 0, NULL);
776 if (maxvertices < model->surfmesh.num_vertices)
780 maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
781 vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
783 model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
784 for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
785 Collision_TraceBrushTriangleMeshFloat(trace, &thisbrush_start.brush, &thisbrush_end.brush, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs);
788 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
791 for (i = 0;i < inverts;i++)
793 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
795 j = vertremap[i]; // not onseam
798 j = vertremap[i+inverts]; // onseam
804 static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *vertremap)
806 int i, f, pose, groupframes;
808 daliasframetype_t *pframetype;
809 daliasframe_t *pinframe;
810 daliasgroup_t *group;
811 daliasinterval_t *intervals;
814 scene = loadmodel->animscenes;
815 for (f = 0;f < loadmodel->numframes;f++)
817 pframetype = (daliasframetype_t *)datapointer;
818 datapointer += sizeof(daliasframetype_t);
819 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
821 // a single frame is still treated as a group
828 group = (daliasgroup_t *)datapointer;
829 datapointer += sizeof(daliasgroup_t);
830 groupframes = LittleLong (group->numframes);
832 // intervals (time per frame)
833 intervals = (daliasinterval_t *)datapointer;
834 datapointer += sizeof(daliasinterval_t) * groupframes;
836 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
837 if (interval < 0.01f)
839 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
844 // get scene name from first frame
845 pinframe = (daliasframe_t *)datapointer;
847 strlcpy(scene->name, pinframe->name, sizeof(scene->name));
848 scene->firstframe = pose;
849 scene->framecount = groupframes;
850 scene->framerate = 1.0f / interval;
855 for (i = 0;i < groupframes;i++)
857 pinframe = (daliasframe_t *)datapointer;
858 datapointer += sizeof(daliasframe_t);
859 Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap);
860 datapointer += sizeof(trivertx_t) * inverts;
866 static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe)
868 if (cls.state == ca_dedicated)
872 skinframe = R_SkinFrame_LoadMissing();
873 memset(texture, 0, sizeof(*texture));
874 texture->currentframe = texture;
875 //texture->animated = false;
876 texture->numskinframes = 1;
877 texture->skinframerate = 1;
878 texture->skinframes[0] = skinframe;
879 texture->currentskinframe = skinframe;
880 //texture->backgroundnumskinframes = 0;
881 //texture->customblendfunc[0] = 0;
882 //texture->customblendfunc[1] = 0;
883 //texture->surfaceflags = 0;
884 //texture->supercontents = 0;
885 //texture->surfaceparms = 0;
886 //texture->textureflags = 0;
888 texture->basematerialflags = MATERIALFLAG_WALL;
889 if (texture->currentskinframe->hasalpha)
890 texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
891 texture->currentmaterialflags = texture->basematerialflags;
892 texture->specularscalemod = 1;
893 texture->specularpowermod = 1;
896 void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
899 skinfileitem_t *skinfileitem;
902 // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces]
903 for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces)
905 memset(skin, 0, sizeof(*skin));
907 for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next)
909 // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
910 if (!strcmp(skinfileitem->name, meshname))
912 Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
918 // don't render unmentioned meshes
919 Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
920 skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
925 Mod_LoadTextureFromQ3Shader(skin, shadername, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
928 #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);
929 #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);
930 void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
932 int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
933 float scales, scalet, interval;
937 stvert_t *pinstverts;
938 dtriangle_t *pintriangles;
939 daliasskintype_t *pinskintype;
940 daliasskingroup_t *pinskingroup;
941 daliasskininterval_t *pinskinintervals;
942 daliasframetype_t *pinframetype;
943 daliasgroup_t *pinframegroup;
944 unsigned char *datapointer, *startframes, *startskins;
945 char name[MAX_QPATH];
946 skinframe_t *tempskinframe;
947 animscene_t *tempskinscenes;
948 texture_t *tempaliasskins;
950 int *vertonseam, *vertremap;
951 skinfile_t *skinfiles;
953 datapointer = (unsigned char *)buffer;
954 pinmodel = (mdl_t *)datapointer;
955 datapointer += sizeof(mdl_t);
957 version = LittleLong (pinmodel->version);
958 if (version != ALIAS_VERSION)
959 Host_Error ("%s has wrong version number (%i should be %i)",
960 loadmodel->name, version, ALIAS_VERSION);
962 loadmodel->modeldatatypestring = "MDL";
964 loadmodel->type = mod_alias;
965 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
966 loadmodel->DrawSky = NULL;
967 loadmodel->DrawAddWaterPlanes = NULL;
968 loadmodel->Draw = R_Q1BSP_Draw;
969 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
970 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
971 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
972 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
973 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
974 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
975 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
976 loadmodel->DrawLight = R_Q1BSP_DrawLight;
977 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
978 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
979 loadmodel->PointSuperContents = NULL;
981 loadmodel->num_surfaces = 1;
982 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
983 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
984 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
985 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
986 loadmodel->sortedmodelsurfaces[0] = 0;
988 loadmodel->numskins = LittleLong(pinmodel->numskins);
989 BOUNDI(loadmodel->numskins,0,65536);
990 skinwidth = LittleLong (pinmodel->skinwidth);
991 BOUNDI(skinwidth,0,65536);
992 skinheight = LittleLong (pinmodel->skinheight);
993 BOUNDI(skinheight,0,65536);
994 numverts = LittleLong(pinmodel->numverts);
995 BOUNDI(numverts,0,65536);
996 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->numtris);
997 BOUNDI(loadmodel->surfmesh.num_triangles,0,65536);
998 loadmodel->numframes = LittleLong(pinmodel->numframes);
999 BOUNDI(loadmodel->numframes,0,65536);
1000 loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype);
1001 BOUNDI(loadmodel->synctype,0,2);
1002 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1003 i = LittleLong (pinmodel->flags);
1004 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1006 for (i = 0;i < 3;i++)
1008 loadmodel->surfmesh.num_morphmdlframescale[i] = LittleFloat (pinmodel->scale[i]);
1009 loadmodel->surfmesh.num_morphmdlframetranslate[i] = LittleFloat (pinmodel->scale_origin[i]);
1012 startskins = datapointer;
1014 for (i = 0;i < loadmodel->numskins;i++)
1016 pinskintype = (daliasskintype_t *)datapointer;
1017 datapointer += sizeof(daliasskintype_t);
1018 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
1022 pinskingroup = (daliasskingroup_t *)datapointer;
1023 datapointer += sizeof(daliasskingroup_t);
1024 groupskins = LittleLong(pinskingroup->numskins);
1025 datapointer += sizeof(daliasskininterval_t) * groupskins;
1028 for (j = 0;j < groupskins;j++)
1030 datapointer += skinwidth * skinheight;
1035 pinstverts = (stvert_t *)datapointer;
1036 datapointer += sizeof(stvert_t) * numverts;
1038 pintriangles = (dtriangle_t *)datapointer;
1039 datapointer += sizeof(dtriangle_t) * loadmodel->surfmesh.num_triangles;
1041 startframes = datapointer;
1042 loadmodel->surfmesh.num_morphframes = 0;
1043 for (i = 0;i < loadmodel->numframes;i++)
1045 pinframetype = (daliasframetype_t *)datapointer;
1046 datapointer += sizeof(daliasframetype_t);
1047 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
1051 pinframegroup = (daliasgroup_t *)datapointer;
1052 datapointer += sizeof(daliasgroup_t);
1053 groupframes = LittleLong(pinframegroup->numframes);
1054 datapointer += sizeof(daliasinterval_t) * groupframes;
1057 for (j = 0;j < groupframes;j++)
1059 datapointer += sizeof(daliasframe_t);
1060 datapointer += sizeof(trivertx_t) * numverts;
1061 loadmodel->surfmesh.num_morphframes++;
1064 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1066 // store texture coordinates into temporary array, they will be stored
1067 // after usage is determined (triangle data)
1068 vertst = (float *)Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
1069 vertremap = (int *)Mem_Alloc(tempmempool, numverts * 3 * sizeof(int));
1070 vertonseam = vertremap + numverts * 2;
1072 scales = 1.0 / skinwidth;
1073 scalet = 1.0 / skinheight;
1074 for (i = 0;i < numverts;i++)
1076 vertonseam[i] = LittleLong(pinstverts[i].onseam);
1077 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
1078 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
1079 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
1080 vertst[(i+numverts)*2+1] = vertst[i*2+1];
1083 // load triangle data
1084 loadmodel->surfmesh.data_element3i = (int *)Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * loadmodel->surfmesh.num_triangles);
1086 // read the triangle elements
1087 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1088 for (j = 0;j < 3;j++)
1089 loadmodel->surfmesh.data_element3i[i*3+j] = LittleLong(pintriangles[i].vertindex[j]);
1090 // validate (note numverts is used because this is the original data)
1091 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, numverts, __FILE__, __LINE__);
1092 // now butcher the elements according to vertonseam and tri->facesfront
1093 // and then compact the vertex set to remove duplicates
1094 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1095 if (!LittleLong(pintriangles[i].facesfront)) // backface
1096 for (j = 0;j < 3;j++)
1097 if (vertonseam[loadmodel->surfmesh.data_element3i[i*3+j]])
1098 loadmodel->surfmesh.data_element3i[i*3+j] += numverts;
1100 // (this uses vertremap to count usage to save some memory)
1101 for (i = 0;i < numverts*2;i++)
1103 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1104 vertremap[loadmodel->surfmesh.data_element3i[i]]++;
1105 // build remapping table and compact array
1106 loadmodel->surfmesh.num_vertices = 0;
1107 for (i = 0;i < numverts*2;i++)
1111 vertremap[i] = loadmodel->surfmesh.num_vertices;
1112 vertst[loadmodel->surfmesh.num_vertices*2+0] = vertst[i*2+0];
1113 vertst[loadmodel->surfmesh.num_vertices*2+1] = vertst[i*2+1];
1114 loadmodel->surfmesh.num_vertices++;
1117 vertremap[i] = -1; // not used at all
1119 // remap the elements to the new vertex set
1120 for (i = 0;i < loadmodel->surfmesh.num_triangles * 3;i++)
1121 loadmodel->surfmesh.data_element3i[i] = vertremap[loadmodel->surfmesh.data_element3i[i]];
1122 // store the texture coordinates
1123 loadmodel->surfmesh.data_texcoordtexture2f = (float *)Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * loadmodel->surfmesh.num_vertices);
1124 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1126 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = vertst[i*2+0];
1127 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
1130 // generate ushort elements array if possible
1131 if (loadmodel->surfmesh.num_vertices <= 65536)
1132 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1133 if (loadmodel->surfmesh.data_element3s)
1134 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1135 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1138 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1139 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
1140 loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
1141 Mod_MDL_LoadFrames (startframes, numverts, vertremap);
1142 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1143 Mod_Alias_CalculateBoundingBox();
1144 Mod_Alias_MorphMesh_CompileFrames();
1147 Mem_Free(vertremap);
1150 skinfiles = Mod_LoadSkinFiles();
1153 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1154 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1155 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1156 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1157 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1158 Mod_FreeSkinFiles(skinfiles);
1159 for (i = 0;i < loadmodel->numskins;i++)
1161 loadmodel->skinscenes[i].firstframe = i;
1162 loadmodel->skinscenes[i].framecount = 1;
1163 loadmodel->skinscenes[i].loop = true;
1164 loadmodel->skinscenes[i].framerate = 10;
1169 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
1170 loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
1171 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1172 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1174 datapointer = startskins;
1175 for (i = 0;i < loadmodel->numskins;i++)
1177 pinskintype = (daliasskintype_t *)datapointer;
1178 datapointer += sizeof(daliasskintype_t);
1180 if (pinskintype->type == ALIAS_SKIN_SINGLE)
1187 pinskingroup = (daliasskingroup_t *)datapointer;
1188 datapointer += sizeof(daliasskingroup_t);
1190 groupskins = LittleLong (pinskingroup->numskins);
1192 pinskinintervals = (daliasskininterval_t *)datapointer;
1193 datapointer += sizeof(daliasskininterval_t) * groupskins;
1195 interval = LittleFloat(pinskinintervals[0].interval);
1196 if (interval < 0.01f)
1198 Con_Printf("%s has an invalid interval %f, changing to 0.1\n", loadmodel->name, interval);
1203 dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
1204 loadmodel->skinscenes[i].firstframe = totalskins;
1205 loadmodel->skinscenes[i].framecount = groupskins;
1206 loadmodel->skinscenes[i].framerate = 1.0f / interval;
1207 loadmodel->skinscenes[i].loop = true;
1209 for (j = 0;j < groupskins;j++)
1212 dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
1214 dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
1215 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))
1216 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));
1217 datapointer += skinwidth * skinheight;
1221 // check for skins that don't exist in the model, but do exist as external images
1222 // (this was added because yummyluv kept pestering me about support for it)
1223 // TODO: support shaders here?
1224 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)))
1226 // expand the arrays to make room
1227 tempskinscenes = loadmodel->skinscenes;
1228 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
1229 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
1230 Mem_Free(tempskinscenes);
1232 tempaliasskins = loadmodel->data_textures;
1233 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * (totalskins + 1) * sizeof(texture_t));
1234 memcpy(loadmodel->data_textures, tempaliasskins, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
1235 Mem_Free(tempaliasskins);
1237 // store the info about the new skin
1238 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe);
1239 strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name));
1240 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
1241 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
1242 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
1243 loadmodel->skinscenes[loadmodel->numskins].loop = true;
1245 //increase skin counts
1246 loadmodel->numskins++;
1249 // fix up the pointers since they are pointing at the old textures array
1250 // FIXME: this is a hack!
1251 for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++)
1252 loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j];
1256 surface = loadmodel->data_surfaces;
1257 surface->texture = loadmodel->data_textures;
1258 surface->num_firsttriangle = 0;
1259 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1260 surface->num_firstvertex = 0;
1261 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1263 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1266 void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
1268 int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
1269 float iskinwidth, iskinheight;
1270 unsigned char *data;
1271 msurface_t *surface;
1273 unsigned char *base, *datapointer;
1274 md2frame_t *pinframe;
1276 md2triangle_t *intri;
1277 unsigned short *inst;
1278 struct md2verthash_s
1280 struct md2verthash_s *next;
1284 *hash, **md2verthash, *md2verthashdata;
1285 skinfile_t *skinfiles;
1287 pinmodel = (md2_t *)buffer;
1288 base = (unsigned char *)buffer;
1290 version = LittleLong (pinmodel->version);
1291 if (version != MD2ALIAS_VERSION)
1292 Host_Error ("%s has wrong version number (%i should be %i)",
1293 loadmodel->name, version, MD2ALIAS_VERSION);
1295 loadmodel->modeldatatypestring = "MD2";
1297 loadmodel->type = mod_alias;
1298 loadmodel->AnimateVertices = Mod_MDL_AnimateVertices;
1299 loadmodel->DrawSky = NULL;
1300 loadmodel->DrawAddWaterPlanes = NULL;
1301 loadmodel->Draw = R_Q1BSP_Draw;
1302 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1303 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1304 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1305 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1306 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1307 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1308 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1309 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1310 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1311 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1312 loadmodel->PointSuperContents = NULL;
1314 if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536)
1315 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
1316 if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
1317 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
1318 if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
1319 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
1320 if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
1321 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
1323 end = LittleLong(pinmodel->ofs_end);
1324 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
1325 Host_Error ("%s is not a valid model", loadmodel->name);
1326 if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
1327 Host_Error ("%s is not a valid model", loadmodel->name);
1328 if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
1329 Host_Error ("%s is not a valid model", loadmodel->name);
1330 if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
1331 Host_Error ("%s is not a valid model", loadmodel->name);
1332 if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
1333 Host_Error ("%s is not a valid model", loadmodel->name);
1335 loadmodel->numskins = LittleLong(pinmodel->num_skins);
1336 numxyz = LittleLong(pinmodel->num_xyz);
1337 numst = LittleLong(pinmodel->num_st);
1338 loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
1339 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1340 loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
1341 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1342 skinwidth = LittleLong(pinmodel->skinwidth);
1343 skinheight = LittleLong(pinmodel->skinheight);
1344 iskinwidth = 1.0f / skinwidth;
1345 iskinheight = 1.0f / skinheight;
1347 loadmodel->num_surfaces = 1;
1348 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1349 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]));
1350 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1351 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1352 loadmodel->sortedmodelsurfaces[0] = 0;
1353 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
1354 loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
1355 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1356 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
1358 loadmodel->synctype = ST_RAND;
1361 inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
1362 skinfiles = Mod_LoadSkinFiles();
1365 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1366 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1367 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1368 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
1369 Mod_FreeSkinFiles(skinfiles);
1371 else if (loadmodel->numskins)
1373 // skins found (most likely not a player model)
1374 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1375 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1376 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1377 for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
1378 Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
1382 // no skins (most likely a player model)
1383 loadmodel->numskins = 1;
1384 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1385 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1386 loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
1387 Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
1390 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1391 for (i = 0;i < loadmodel->numskins;i++)
1393 loadmodel->skinscenes[i].firstframe = i;
1394 loadmodel->skinscenes[i].framecount = 1;
1395 loadmodel->skinscenes[i].loop = true;
1396 loadmodel->skinscenes[i].framerate = 10;
1399 // load the triangles and stvert data
1400 inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
1401 intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
1402 md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
1403 md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
1404 // swap the triangle list
1405 loadmodel->surfmesh.num_vertices = 0;
1406 for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
1408 for (j = 0;j < 3;j++)
1410 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
1411 st = (unsigned short) LittleShort (intri[i].index_st[j]);
1414 Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
1419 Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
1422 hashindex = (xyz * 256 + st) & 65535;
1423 for (hash = md2verthash[hashindex];hash;hash = hash->next)
1424 if (hash->xyz == xyz && hash->st == st)
1428 hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
1431 hash->next = md2verthash[hashindex];
1432 md2verthash[hashindex] = hash;
1434 loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
1438 vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
1439 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));
1440 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
1441 loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
1442 for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
1445 hash = md2verthashdata + i;
1446 vertremap[i] = hash->xyz;
1447 sts = LittleShort(inst[hash->st*2+0]);
1448 stt = LittleShort(inst[hash->st*2+1]);
1449 if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
1451 Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
1455 loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
1456 loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
1459 Mem_Free(md2verthash);
1460 Mem_Free(md2verthashdata);
1462 // generate ushort elements array if possible
1463 if (loadmodel->surfmesh.num_vertices <= 65536)
1464 loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
1465 if (loadmodel->surfmesh.data_element3s)
1466 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1467 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1470 datapointer = (base + LittleLong(pinmodel->ofs_frames));
1471 for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
1476 pinframe = (md2frame_t *)datapointer;
1477 datapointer += sizeof(md2frame_t);
1478 // store the frame scale/translate into the appropriate array
1479 for (j = 0;j < 3;j++)
1481 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
1482 loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
1484 // convert the vertices
1485 v = (trivertx_t *)datapointer;
1486 out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
1487 for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
1488 out[k] = v[vertremap[k]];
1489 datapointer += numxyz * sizeof(trivertx_t);
1491 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1492 loadmodel->animscenes[i].firstframe = i;
1493 loadmodel->animscenes[i].framecount = 1;
1494 loadmodel->animscenes[i].framerate = 10;
1495 loadmodel->animscenes[i].loop = true;
1498 Mem_Free(vertremap);
1500 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1501 Mod_Alias_CalculateBoundingBox();
1502 Mod_Alias_MorphMesh_CompileFrames();
1504 surface = loadmodel->data_surfaces;
1505 surface->texture = loadmodel->data_textures;
1506 surface->num_firsttriangle = 0;
1507 surface->num_triangles = loadmodel->surfmesh.num_triangles;
1508 surface->num_firstvertex = 0;
1509 surface->num_vertices = loadmodel->surfmesh.num_vertices;
1511 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
1514 void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
1516 int i, j, k, version, meshvertices, meshtriangles;
1517 unsigned char *data;
1518 msurface_t *surface;
1519 md3modelheader_t *pinmodel;
1520 md3frameinfo_t *pinframe;
1523 skinfile_t *skinfiles;
1525 pinmodel = (md3modelheader_t *)buffer;
1527 if (memcmp(pinmodel->identifier, "IDP3", 4))
1528 Host_Error ("%s is not a MD3 (IDP3) file", loadmodel->name);
1529 version = LittleLong (pinmodel->version);
1530 if (version != MD3VERSION)
1531 Host_Error ("%s has wrong version number (%i should be %i)",
1532 loadmodel->name, version, MD3VERSION);
1534 skinfiles = Mod_LoadSkinFiles();
1535 if (loadmodel->numskins < 1)
1536 loadmodel->numskins = 1;
1538 loadmodel->modeldatatypestring = "MD3";
1540 loadmodel->type = mod_alias;
1541 loadmodel->AnimateVertices = Mod_MD3_AnimateVertices;
1542 loadmodel->DrawSky = NULL;
1543 loadmodel->DrawAddWaterPlanes = NULL;
1544 loadmodel->Draw = R_Q1BSP_Draw;
1545 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1546 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1547 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1548 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1549 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1550 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1551 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1552 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1553 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1554 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1555 loadmodel->PointSuperContents = NULL;
1556 loadmodel->synctype = ST_RAND;
1557 // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc)
1558 i = LittleLong (pinmodel->flags);
1559 loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00);
1561 // set up some global info about the model
1562 loadmodel->numframes = LittleLong(pinmodel->num_frames);
1563 loadmodel->num_surfaces = LittleLong(pinmodel->num_meshes);
1565 // make skinscenes for the skins (no groups)
1566 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1567 for (i = 0;i < loadmodel->numskins;i++)
1569 loadmodel->skinscenes[i].firstframe = i;
1570 loadmodel->skinscenes[i].framecount = 1;
1571 loadmodel->skinscenes[i].loop = true;
1572 loadmodel->skinscenes[i].framerate = 10;
1576 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
1577 for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
1579 strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
1580 loadmodel->animscenes[i].firstframe = i;
1581 loadmodel->animscenes[i].framecount = 1;
1582 loadmodel->animscenes[i].framerate = 10;
1583 loadmodel->animscenes[i].loop = true;
1587 loadmodel->num_tagframes = loadmodel->numframes;
1588 loadmodel->num_tags = LittleLong(pinmodel->num_tags);
1589 loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t));
1590 for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++)
1592 strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name));
1593 for (j = 0;j < 9;j++)
1594 loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]);
1595 for (j = 0;j < 3;j++)
1596 loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]);
1597 //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);
1603 for (i = 0, pinmesh = (md3mesh_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_meshes));i < loadmodel->num_surfaces;i++, pinmesh = (md3mesh_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_end)))
1605 if (memcmp(pinmesh->identifier, "IDP3", 4))
1606 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1607 if (LittleLong(pinmesh->num_frames) != loadmodel->numframes)
1608 Host_Error("Mod_IDP3_Load: mesh numframes differs from header");
1609 meshvertices += LittleLong(pinmesh->num_vertices);
1610 meshtriangles += LittleLong(pinmesh->num_triangles);
1613 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1614 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1615 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1616 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));
1617 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1618 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1619 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1620 loadmodel->surfmesh.num_vertices = meshvertices;
1621 loadmodel->surfmesh.num_triangles = meshtriangles;
1622 loadmodel->surfmesh.num_morphframes = loadmodel->numframes; // TODO: remove?
1623 loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
1624 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1625 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1626 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1627 loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
1628 if (meshvertices <= 65536)
1629 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
1633 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)))
1635 if (memcmp(pinmesh->identifier, "IDP3", 4))
1636 Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
1637 loadmodel->sortedmodelsurfaces[i] = i;
1638 surface = loadmodel->data_surfaces + i;
1639 surface->texture = loadmodel->data_textures + i;
1640 surface->num_firsttriangle = meshtriangles;
1641 surface->num_triangles = LittleLong(pinmesh->num_triangles);
1642 surface->num_firstvertex = meshvertices;
1643 surface->num_vertices = LittleLong(pinmesh->num_vertices);
1644 meshvertices += surface->num_vertices;
1645 meshtriangles += surface->num_triangles;
1647 for (j = 0;j < surface->num_triangles * 3;j++)
1648 loadmodel->surfmesh.data_element3i[j + surface->num_firsttriangle * 3] = surface->num_firstvertex + LittleLong(((int *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_elements)))[j]);
1649 for (j = 0;j < surface->num_vertices;j++)
1651 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 0] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 0]);
1652 loadmodel->surfmesh.data_texcoordtexture2f[(j + surface->num_firstvertex) * 2 + 1] = LittleFloat(((float *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_texcoords)))[j * 2 + 1]);
1654 for (j = 0;j < loadmodel->numframes;j++)
1656 const md3vertex_t *in = (md3vertex_t *)((unsigned char *)pinmesh + LittleLong(pinmesh->lump_framevertices)) + j * surface->num_vertices;
1657 md3vertex_t *out = loadmodel->surfmesh.data_morphmd3vertex + surface->num_firstvertex + j * loadmodel->surfmesh.num_vertices;
1658 for (k = 0;k < surface->num_vertices;k++, in++, out++)
1660 out->origin[0] = LittleShort(in->origin[0]);
1661 out->origin[1] = LittleShort(in->origin[1]);
1662 out->origin[2] = LittleShort(in->origin[2]);
1663 out->pitch = in->pitch;
1668 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : "");
1670 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
1672 if (loadmodel->surfmesh.data_element3s)
1673 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
1674 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
1675 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
1676 Mod_Alias_MorphMesh_CompileFrames();
1677 Mod_Alias_CalculateBoundingBox();
1678 Mod_FreeSkinFiles(skinfiles);
1679 Mod_MakeSortedSurfaces(loadmodel);
1681 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
1682 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
1685 void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
1687 zymtype1header_t *pinmodel, *pheader;
1688 unsigned char *pbase;
1689 int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
1690 float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose, f, biggestorigin;
1691 zymvertex_t *verts, *vertdata;
1695 skinfile_t *skinfiles;
1696 unsigned char *data;
1697 msurface_t *surface;
1699 pinmodel = (zymtype1header_t *)buffer;
1700 pbase = (unsigned char *)buffer;
1701 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
1702 Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name);
1703 if (BigLong(pinmodel->type) != 1)
1704 Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name);
1706 loadmodel->modeldatatypestring = "ZYM";
1708 loadmodel->type = mod_alias;
1709 loadmodel->synctype = ST_RAND;
1713 pheader->type = BigLong(pinmodel->type);
1714 pheader->filesize = BigLong(pinmodel->filesize);
1715 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
1716 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
1717 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
1718 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
1719 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
1720 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
1721 pheader->radius = BigFloat(pinmodel->radius);
1722 pheader->numverts = BigLong(pinmodel->numverts);
1723 pheader->numtris = BigLong(pinmodel->numtris);
1724 pheader->numshaders = BigLong(pinmodel->numshaders);
1725 pheader->numbones = BigLong(pinmodel->numbones);
1726 pheader->numscenes = BigLong(pinmodel->numscenes);
1727 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
1728 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
1729 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
1730 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
1731 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
1732 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
1733 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
1734 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
1735 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
1736 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
1737 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
1738 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
1739 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
1740 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
1741 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
1742 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
1743 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
1744 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
1746 if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1)
1748 Con_Printf("%s has no geometry\n", loadmodel->name);
1751 if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4]))
1753 Con_Printf("%s has no animations\n", loadmodel->name);
1757 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
1758 loadmodel->DrawSky = NULL;
1759 loadmodel->DrawAddWaterPlanes = NULL;
1760 loadmodel->Draw = R_Q1BSP_Draw;
1761 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
1762 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
1763 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
1764 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
1765 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
1766 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
1767 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
1768 loadmodel->DrawLight = R_Q1BSP_DrawLight;
1769 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
1770 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
1771 loadmodel->PointSuperContents = NULL;
1773 loadmodel->numframes = pheader->numscenes;
1774 loadmodel->num_surfaces = pheader->numshaders;
1776 skinfiles = Mod_LoadSkinFiles();
1777 if (loadmodel->numskins < 1)
1778 loadmodel->numskins = 1;
1780 // make skinscenes for the skins (no groups)
1781 loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
1782 for (i = 0;i < loadmodel->numskins;i++)
1784 loadmodel->skinscenes[i].firstframe = i;
1785 loadmodel->skinscenes[i].framecount = 1;
1786 loadmodel->skinscenes[i].loop = true;
1787 loadmodel->skinscenes[i].framerate = 10;
1791 modelradius = pheader->radius;
1792 for (i = 0;i < 3;i++)
1794 loadmodel->normalmins[i] = pheader->mins[i];
1795 loadmodel->normalmaxs[i] = pheader->maxs[i];
1796 loadmodel->rotatedmins[i] = -modelradius;
1797 loadmodel->rotatedmaxs[i] = modelradius;
1799 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
1800 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
1801 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
1802 if (loadmodel->yawmaxs[0] > modelradius)
1803 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
1804 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
1805 loadmodel->yawmins[2] = loadmodel->normalmins[2];
1806 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
1807 loadmodel->radius = modelradius;
1808 loadmodel->radius2 = modelradius * modelradius;
1810 // go through the lumps, swapping things
1812 //zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
1813 loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
1814 scene = (zymscene_t *) (pheader->lump_scenes.start + pbase);
1815 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
1816 for (i = 0;i < pheader->numscenes;i++)
1818 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
1819 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
1820 loadmodel->animscenes[i].framecount = BigLong(scene->length);
1821 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
1822 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1823 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1824 Host_Error("%s scene->firstframe (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, numposes);
1825 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1826 Host_Error("%s scene->firstframe (%i) + framecount (%i) >= numposes (%i)", loadmodel->name, loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1827 if (loadmodel->animscenes[i].framerate < 0)
1828 Host_Error("%s scene->framerate (%f) < 0", loadmodel->name, loadmodel->animscenes[i].framerate);
1832 //zymlump_t lump_bones; // zymbone_t bone[numbones];
1833 loadmodel->num_bones = pheader->numbones;
1834 loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
1835 bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
1836 for (i = 0;i < pheader->numbones;i++)
1838 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
1839 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
1840 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
1841 if (loadmodel->data_bones[i].parent >= i)
1842 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
1845 //zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1846 vertbonecounts = (int *)Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1847 bonecount = (int *) (pheader->lump_vertbonecounts.start + pbase);
1848 for (i = 0;i < pheader->numverts;i++)
1850 vertbonecounts[i] = BigLong(bonecount[i]);
1851 if (vertbonecounts[i] != 1)
1852 Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
1855 loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
1857 meshvertices = pheader->numverts;
1858 meshtriangles = pheader->numtris;
1860 loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
1861 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
1862 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
1863 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + 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 * loadmodel->num_bones * sizeof(short[6]) + loadmodel->num_bones * sizeof(float[12]));
1864 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
1865 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
1866 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
1867 loadmodel->surfmesh.num_vertices = meshvertices;
1868 loadmodel->surfmesh.num_triangles = meshtriangles;
1869 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1870 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
1871 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
1872 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1873 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
1874 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
1875 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
1876 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
1877 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
1878 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
1879 if (loadmodel->surfmesh.num_vertices <= 65536)
1880 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
1881 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
1883 //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1884 poses = (float *) (pheader->lump_poses.start + pbase);
1886 for (i = 0;i < loadmodel->num_bones * numposes * 12;i++)
1888 f = fabs(BigFloat(poses[i]));
1889 biggestorigin = max(biggestorigin, f);
1891 loadmodel->num_posescale = biggestorigin / 32767.0f;
1892 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
1893 for (i = 0;i < loadmodel->num_bones * numposes;i++)
1896 matrix4x4_t posematrix;
1897 for (j = 0;j < 12;j++)
1898 pose[j] = BigFloat(poses[i*12+j]);
1899 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
1900 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*i);
1903 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1904 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1905 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1906 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1907 // (converting from weight-blending skeletal animation to
1908 // deformation-based skeletal animation)
1909 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1910 for (i = 0;i < loadmodel->num_bones;i++)
1913 for (k = 0;k < 12;k++)
1914 m[k] = BigFloat(poses[i*12+k]);
1915 if (loadmodel->data_bones[i].parent >= 0)
1916 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1918 for (k = 0;k < 12;k++)
1919 bonepose[12*i+k] = m[k];
1921 for (j = 0;j < pheader->numverts;j++)
1923 // this format really should have had a per vertexweight weight value...
1924 // but since it does not, the weighting is completely ignored and
1925 // only one weight is allowed per vertex
1926 int boneindex = BigLong(vertdata[j].bonenum);
1927 const float *m = bonepose + 12 * boneindex;
1928 float relativeorigin[3];
1929 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1930 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1931 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1932 // transform the vertex bone weight into the base mesh
1933 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1934 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1935 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1936 // store the weight as the primary weight on this vertex
1937 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
1938 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = 1;
1941 // normals and tangents are calculated after elements are loaded
1943 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1944 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1945 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1946 for (i = 0;i < pheader->numverts;i++)
1948 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1949 // flip T coordinate for OpenGL
1950 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1953 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1954 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1955 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1957 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1958 //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)
1959 // byteswap, validate, and swap winding order of tris
1960 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1961 if (pheader->lump_render.length != count)
1962 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1963 renderlist = (int *) (pheader->lump_render.start + pbase);
1964 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1966 for (i = 0;i < loadmodel->num_surfaces;i++)
1968 int firstvertex, lastvertex;
1969 if (renderlist >= renderlistend)
1970 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1971 count = BigLong(*renderlist);renderlist++;
1972 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1973 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1975 loadmodel->sortedmodelsurfaces[i] = i;
1976 surface = loadmodel->data_surfaces + i;
1977 surface->texture = loadmodel->data_textures + i;
1978 surface->num_firsttriangle = meshtriangles;
1979 surface->num_triangles = count;
1980 meshtriangles += surface->num_triangles;
1982 // load the elements
1983 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
1984 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
1986 outelements[j*3+2] = BigLong(renderlist[0]);
1987 outelements[j*3+1] = BigLong(renderlist[1]);
1988 outelements[j*3+0] = BigLong(renderlist[2]);
1990 // validate the elements and find the used vertex range
1991 firstvertex = meshvertices;
1993 for (j = 0;j < surface->num_triangles * 3;j++)
1995 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
1996 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
1997 firstvertex = min(firstvertex, outelements[j]);
1998 lastvertex = max(lastvertex, outelements[j]);
2000 surface->num_firstvertex = firstvertex;
2001 surface->num_vertices = lastvertex + 1 - firstvertex;
2003 // since zym models do not have named sections, reuse their shader
2004 // name as the section name
2005 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
2006 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
2008 Mod_FreeSkinFiles(skinfiles);
2009 Mem_Free(vertbonecounts);
2011 Mod_MakeSortedSurfaces(loadmodel);
2013 // compute all the mesh information that was not loaded from the file
2014 if (loadmodel->surfmesh.data_element3s)
2015 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2016 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2017 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2018 Mod_BuildBaseBonePoses();
2019 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2020 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);
2021 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2023 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2026 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2028 dpmheader_t *pheader;
2032 unsigned char *pbase;
2033 int i, j, k, meshvertices, meshtriangles;
2034 skinfile_t *skinfiles;
2035 unsigned char *data;
2037 float biggestorigin;
2041 pheader = (dpmheader_t *)buffer;
2042 pbase = (unsigned char *)buffer;
2043 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2044 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2045 if (BigLong(pheader->type) != 2)
2046 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2048 loadmodel->modeldatatypestring = "DPM";
2050 loadmodel->type = mod_alias;
2051 loadmodel->synctype = ST_RAND;
2054 pheader->type = BigLong(pheader->type);
2055 pheader->filesize = BigLong(pheader->filesize);
2056 pheader->mins[0] = BigFloat(pheader->mins[0]);
2057 pheader->mins[1] = BigFloat(pheader->mins[1]);
2058 pheader->mins[2] = BigFloat(pheader->mins[2]);
2059 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2060 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2061 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2062 pheader->yawradius = BigFloat(pheader->yawradius);
2063 pheader->allradius = BigFloat(pheader->allradius);
2064 pheader->num_bones = BigLong(pheader->num_bones);
2065 pheader->num_meshs = BigLong(pheader->num_meshs);
2066 pheader->num_frames = BigLong(pheader->num_frames);
2067 pheader->ofs_bones = BigLong(pheader->ofs_bones);
2068 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2069 pheader->ofs_frames = BigLong(pheader->ofs_frames);
2071 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2073 Con_Printf("%s has no geometry\n", loadmodel->name);
2076 if (pheader->num_frames < 1)
2078 Con_Printf("%s has no frames\n", loadmodel->name);
2082 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2083 loadmodel->DrawSky = NULL;
2084 loadmodel->DrawAddWaterPlanes = NULL;
2085 loadmodel->Draw = R_Q1BSP_Draw;
2086 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2087 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2088 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2089 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2090 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2091 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2092 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2093 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2094 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2095 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2096 loadmodel->PointSuperContents = NULL;
2099 for (i = 0;i < 3;i++)
2101 loadmodel->normalmins[i] = pheader->mins[i];
2102 loadmodel->normalmaxs[i] = pheader->maxs[i];
2103 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2104 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2105 loadmodel->rotatedmins[i] = -pheader->allradius;
2106 loadmodel->rotatedmaxs[i] = pheader->allradius;
2108 loadmodel->radius = pheader->allradius;
2109 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2111 // load external .skin files if present
2112 skinfiles = Mod_LoadSkinFiles();
2113 if (loadmodel->numskins < 1)
2114 loadmodel->numskins = 1;
2119 // gather combined statistics from the meshes
2120 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2121 for (i = 0;i < (int)pheader->num_meshs;i++)
2123 int numverts = BigLong(dpmmesh->num_verts);
2124 meshvertices += numverts;
2125 meshtriangles += BigLong(dpmmesh->num_tris);
2129 loadmodel->numframes = pheader->num_frames;
2130 loadmodel->num_bones = pheader->num_bones;
2131 loadmodel->num_poses = loadmodel->numframes;
2132 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2133 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2134 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2135 // do most allocations as one merged chunk
2136 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 * loadmodel->num_bones * sizeof(short[6]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
2137 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2138 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2139 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2140 loadmodel->surfmesh.num_vertices = meshvertices;
2141 loadmodel->surfmesh.num_triangles = meshtriangles;
2142 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2143 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2144 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2145 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2146 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2147 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2148 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2149 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
2150 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
2151 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2152 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2153 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2154 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2155 if (meshvertices <= 65536)
2156 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2157 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2159 for (i = 0;i < loadmodel->numskins;i++)
2161 loadmodel->skinscenes[i].firstframe = i;
2162 loadmodel->skinscenes[i].framecount = 1;
2163 loadmodel->skinscenes[i].loop = true;
2164 loadmodel->skinscenes[i].framerate = 10;
2167 // load the bone info
2168 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2169 for (i = 0;i < loadmodel->num_bones;i++)
2171 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2172 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2173 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2174 if (loadmodel->data_bones[i].parent >= i)
2175 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2179 frames = (dpmframe_t *) (pbase + pheader->ofs_frames);
2181 for (i = 0;i < loadmodel->numframes;i++)
2184 memcpy(loadmodel->animscenes[i].name, frames[i].name, sizeof(frames[i].name));
2185 loadmodel->animscenes[i].firstframe = i;
2186 loadmodel->animscenes[i].framecount = 1;
2187 loadmodel->animscenes[i].loop = true;
2188 loadmodel->animscenes[i].framerate = 10;
2189 // load the bone poses for this frame
2190 poses = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2191 for (j = 0;j < loadmodel->num_bones*12;j++)
2193 f = fabs(BigFloat(poses[j]));
2194 biggestorigin = max(biggestorigin, f);
2196 // stuff not processed here: mins, maxs, yawradius, allradius
2198 loadmodel->num_posescale = biggestorigin / 32767.0f;
2199 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2200 for (i = 0;i < loadmodel->numframes;i++)
2202 poses = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2203 for (j = 0;j < loadmodel->num_bones;j++)
2206 matrix4x4_t posematrix;
2207 for (k = 0;k < 12;k++)
2208 pose[k] = BigFloat(poses[j*12+k]);
2209 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2210 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
2214 // load the meshes now
2215 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2218 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2219 // (converting from weight-blending skeletal animation to
2220 // deformation-based skeletal animation)
2221 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2222 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2223 for (i = 0;i < loadmodel->num_bones;i++)
2226 for (k = 0;k < 12;k++)
2227 m[k] = BigFloat(poses[i*12+k]);
2228 if (loadmodel->data_bones[i].parent >= 0)
2229 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2231 for (k = 0;k < 12;k++)
2232 bonepose[12*i+k] = m[k];
2234 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2236 const int *inelements;
2238 const float *intexcoord;
2239 msurface_t *surface;
2241 loadmodel->sortedmodelsurfaces[i] = i;
2242 surface = loadmodel->data_surfaces + i;
2243 surface->texture = loadmodel->data_textures + i;
2244 surface->num_firsttriangle = meshtriangles;
2245 surface->num_triangles = BigLong(dpmmesh->num_tris);
2246 surface->num_firstvertex = meshvertices;
2247 surface->num_vertices = BigLong(dpmmesh->num_verts);
2248 meshvertices += surface->num_vertices;
2249 meshtriangles += surface->num_triangles;
2251 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2252 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2253 for (j = 0;j < surface->num_triangles;j++)
2255 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2256 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2257 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2258 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2263 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2264 for (j = 0;j < surface->num_vertices*2;j++)
2265 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2267 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2268 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2272 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2273 data += sizeof(dpmvertex_t);
2274 for (k = 0;k < numweights;k++)
2276 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2277 int boneindex = BigLong(vert->bonenum);
2278 const float *m = bonepose + 12 * boneindex;
2279 float influence = BigFloat(vert->influence);
2280 float relativeorigin[3], relativenormal[3];
2281 relativeorigin[0] = BigFloat(vert->origin[0]);
2282 relativeorigin[1] = BigFloat(vert->origin[1]);
2283 relativeorigin[2] = BigFloat(vert->origin[2]);
2284 relativenormal[0] = BigFloat(vert->normal[0]);
2285 relativenormal[1] = BigFloat(vert->normal[1]);
2286 relativenormal[2] = BigFloat(vert->normal[2]);
2287 // blend the vertex bone weights into the base mesh
2288 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2289 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2290 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2291 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2292 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2293 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2296 // store the first (and often only) weight
2297 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = influence;
2298 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
2302 // sort the new weight into this vertex's weight table
2303 // (which only accepts up to 4 bones per vertex)
2304 for (l = 0;l < 4;l++)
2306 if (loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] < influence)
2308 // move weaker influence weights out of the way first
2310 for (l2 = 3;l2 > l;l2--)
2312 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2-1];
2313 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2-1];
2315 // store the new weight
2316 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] = influence;
2317 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l] = boneindex;
2322 data += sizeof(dpmbonevert_t);
2325 for (l = 0;l < 4;l++)
2326 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l];
2327 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2329 float f = 1.0f / sum;
2330 for (l = 0;l < 4;l++)
2331 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] *= f;
2335 // since dpm models do not have named sections, reuse their shader name as the section name
2336 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2338 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2341 Mod_FreeSkinFiles(skinfiles);
2342 Mod_MakeSortedSurfaces(loadmodel);
2344 // compute all the mesh information that was not loaded from the file
2345 if (loadmodel->surfmesh.data_element3s)
2346 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2347 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2348 Mod_BuildBaseBonePoses();
2349 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);
2350 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2352 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2355 // no idea why PSK/PSA files contain weird quaternions but they do...
2356 #define PSKQUATNEGATIONS
2357 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2359 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2360 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2361 fs_offset_t filesize;
2366 pskboneinfo_t *bones;
2367 pskrawweights_t *rawweights;
2368 pskboneinfo_t *animbones;
2369 pskaniminfo_t *anims;
2370 pskanimkeys_t *animkeys;
2371 void *animfilebuffer, *animbuffer, *animbufferend;
2372 unsigned char *data;
2374 skinfile_t *skinfiles;
2375 char animname[MAX_QPATH];
2377 float biggestorigin;
2379 pchunk = (pskchunk_t *)buffer;
2380 if (strcmp(pchunk->id, "ACTRHEAD"))
2381 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2383 loadmodel->modeldatatypestring = "PSK";
2385 loadmodel->type = mod_alias;
2386 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2387 loadmodel->DrawSky = NULL;
2388 loadmodel->DrawAddWaterPlanes = NULL;
2389 loadmodel->Draw = R_Q1BSP_Draw;
2390 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2391 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2392 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2393 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2394 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2395 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2396 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2397 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2398 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2399 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2400 loadmodel->PointSuperContents = NULL;
2401 loadmodel->synctype = ST_RAND;
2403 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2404 strlcat(animname, ".psa", sizeof(animname));
2405 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2406 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2407 if (animbuffer == NULL)
2408 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2427 while (buffer < bufferend)
2429 pchunk = (pskchunk_t *)buffer;
2430 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2431 version = LittleLong(pchunk->version);
2432 recordsize = LittleLong(pchunk->recordsize);
2433 numrecords = LittleLong(pchunk->numrecords);
2434 if (developer_extra.integer)
2435 Con_DPrintf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2436 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2437 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);
2438 if (!strcmp(pchunk->id, "ACTRHEAD"))
2442 else if (!strcmp(pchunk->id, "PNTS0000"))
2445 if (recordsize != sizeof(*p))
2446 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2447 // byteswap in place and keep the pointer
2448 numpnts = numrecords;
2449 pnts = (pskpnts_t *)buffer;
2450 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2452 p->origin[0] = LittleFloat(p->origin[0]);
2453 p->origin[1] = LittleFloat(p->origin[1]);
2454 p->origin[2] = LittleFloat(p->origin[2]);
2458 else if (!strcmp(pchunk->id, "VTXW0000"))
2461 if (recordsize != sizeof(*p))
2462 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2463 // byteswap in place and keep the pointer
2464 numvtxw = numrecords;
2465 vtxw = (pskvtxw_t *)buffer;
2466 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2468 p->pntsindex = LittleShort(p->pntsindex);
2469 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2470 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2471 if (p->pntsindex >= numpnts)
2473 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2479 else if (!strcmp(pchunk->id, "FACE0000"))
2482 if (recordsize != sizeof(*p))
2483 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2484 // byteswap in place and keep the pointer
2485 numfaces = numrecords;
2486 faces = (pskface_t *)buffer;
2487 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2489 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2490 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2491 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2492 p->group = LittleLong(p->group);
2493 if (p->vtxwindex[0] >= numvtxw)
2495 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2496 p->vtxwindex[0] = 0;
2498 if (p->vtxwindex[1] >= numvtxw)
2500 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2501 p->vtxwindex[1] = 0;
2503 if (p->vtxwindex[2] >= numvtxw)
2505 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2506 p->vtxwindex[2] = 0;
2511 else if (!strcmp(pchunk->id, "MATT0000"))
2514 if (recordsize != sizeof(*p))
2515 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2516 // byteswap in place and keep the pointer
2517 nummatts = numrecords;
2518 matts = (pskmatt_t *)buffer;
2519 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2525 else if (!strcmp(pchunk->id, "REFSKELT"))
2528 if (recordsize != sizeof(*p))
2529 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2530 // byteswap in place and keep the pointer
2531 numbones = numrecords;
2532 bones = (pskboneinfo_t *)buffer;
2533 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2535 p->numchildren = LittleLong(p->numchildren);
2536 p->parent = LittleLong(p->parent);
2537 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2538 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2539 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2540 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2541 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2542 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2543 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2544 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2545 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2546 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2547 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2548 #ifdef PSKQUATNEGATIONS
2551 p->basepose.quat[0] *= -1;
2552 p->basepose.quat[1] *= -1;
2553 p->basepose.quat[2] *= -1;
2557 p->basepose.quat[0] *= 1;
2558 p->basepose.quat[1] *= -1;
2559 p->basepose.quat[2] *= 1;
2562 if (p->parent < 0 || p->parent >= numbones)
2564 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2570 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2573 if (recordsize != sizeof(*p))
2574 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2575 // byteswap in place and keep the pointer
2576 numrawweights = numrecords;
2577 rawweights = (pskrawweights_t *)buffer;
2578 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2580 p->weight = LittleFloat(p->weight);
2581 p->pntsindex = LittleLong(p->pntsindex);
2582 p->boneindex = LittleLong(p->boneindex);
2583 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2585 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2588 if (p->boneindex < 0 || p->boneindex >= numbones)
2590 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2598 while (animbuffer < animbufferend)
2600 pchunk = (pskchunk_t *)animbuffer;
2601 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2602 version = LittleLong(pchunk->version);
2603 recordsize = LittleLong(pchunk->recordsize);
2604 numrecords = LittleLong(pchunk->numrecords);
2605 if (developer_extra.integer)
2606 Con_DPrintf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2607 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2608 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);
2609 if (!strcmp(pchunk->id, "ANIMHEAD"))
2613 else if (!strcmp(pchunk->id, "BONENAMES"))
2616 if (recordsize != sizeof(*p))
2617 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2618 // byteswap in place and keep the pointer
2619 numanimbones = numrecords;
2620 animbones = (pskboneinfo_t *)animbuffer;
2621 // NOTE: supposedly psa does not need to match the psk model, the
2622 // bones missing from the psa would simply use their base
2623 // positions from the psk, but this is hard for me to implement
2624 // and people can easily make animations that match.
2625 if (numanimbones != numbones)
2626 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2627 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2629 p->numchildren = LittleLong(p->numchildren);
2630 p->parent = LittleLong(p->parent);
2631 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2632 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2633 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2634 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2635 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2636 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2637 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2638 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2639 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2640 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2641 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2642 #ifdef PSKQUATNEGATIONS
2645 p->basepose.quat[0] *= -1;
2646 p->basepose.quat[1] *= -1;
2647 p->basepose.quat[2] *= -1;
2651 p->basepose.quat[0] *= 1;
2652 p->basepose.quat[1] *= -1;
2653 p->basepose.quat[2] *= 1;
2656 if (p->parent < 0 || p->parent >= numanimbones)
2658 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2661 // check that bones are the same as in the base
2662 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2663 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2667 else if (!strcmp(pchunk->id, "ANIMINFO"))
2670 if (recordsize != sizeof(*p))
2671 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2672 // byteswap in place and keep the pointer
2673 numanims = numrecords;
2674 anims = (pskaniminfo_t *)animbuffer;
2675 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2677 p->numbones = LittleLong(p->numbones);
2678 p->playtime = LittleFloat(p->playtime);
2679 p->fps = LittleFloat(p->fps);
2680 p->firstframe = LittleLong(p->firstframe);
2681 p->numframes = LittleLong(p->numframes);
2682 if (p->numbones != numbones)
2683 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2687 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2690 if (recordsize != sizeof(*p))
2691 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2692 numanimkeys = numrecords;
2693 animkeys = (pskanimkeys_t *)animbuffer;
2694 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2696 p->origin[0] = LittleFloat(p->origin[0]);
2697 p->origin[1] = LittleFloat(p->origin[1]);
2698 p->origin[2] = LittleFloat(p->origin[2]);
2699 p->quat[0] = LittleFloat(p->quat[0]);
2700 p->quat[1] = LittleFloat(p->quat[1]);
2701 p->quat[2] = LittleFloat(p->quat[2]);
2702 p->quat[3] = LittleFloat(p->quat[3]);
2703 p->frametime = LittleFloat(p->frametime);
2704 #ifdef PSKQUATNEGATIONS
2705 if (index % numbones)
2720 // TODO: allocate bonepose stuff
2723 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2726 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2727 Host_Error("%s: missing required chunks", loadmodel->name);
2729 loadmodel->numframes = 0;
2730 for (index = 0;index < numanims;index++)
2731 loadmodel->numframes += anims[index].numframes;
2733 if (numanimkeys != numbones * loadmodel->numframes)
2734 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2736 meshvertices = numvtxw;
2737 meshtriangles = numfaces;
2739 // load external .skin files if present
2740 skinfiles = Mod_LoadSkinFiles();
2741 if (loadmodel->numskins < 1)
2742 loadmodel->numskins = 1;
2743 loadmodel->num_bones = numbones;
2744 loadmodel->num_poses = loadmodel->numframes;
2745 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2746 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2747 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2748 loadmodel->surfmesh.num_vertices = meshvertices;
2749 loadmodel->surfmesh.num_triangles = meshtriangles;
2750 // do most allocations as one merged chunk
2751 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 * loadmodel->num_bones * sizeof(short[6]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t) + ((loadmodel->surfmesh.num_vertices <= 65536) ? (loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3])) : 0);
2752 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2753 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2754 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2755 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2756 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2757 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2758 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2759 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2760 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2761 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2762 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2763 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += loadmodel->surfmesh.num_vertices * sizeof(int[4]);
2764 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[4]);
2765 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2766 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2767 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2768 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2769 if (loadmodel->surfmesh.num_vertices <= 65536)
2770 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2771 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2773 for (i = 0;i < loadmodel->numskins;i++)
2775 loadmodel->skinscenes[i].firstframe = i;
2776 loadmodel->skinscenes[i].framecount = 1;
2777 loadmodel->skinscenes[i].loop = true;
2778 loadmodel->skinscenes[i].framerate = 10;
2782 for (index = 0, i = 0;index < nummatts;index++)
2784 // since psk models do not have named sections, reuse their shader name as the section name
2785 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2786 loadmodel->sortedmodelsurfaces[index] = index;
2787 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2788 loadmodel->data_surfaces[index].num_firstvertex = 0;
2789 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2792 // copy over the vertex locations and texcoords
2793 for (index = 0;index < numvtxw;index++)
2795 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2796 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2797 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2798 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2799 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2802 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2803 for (index = 0;index < numfaces;index++)
2804 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2805 for (index = 0, i = 0;index < nummatts;index++)
2807 loadmodel->data_surfaces[index].num_firsttriangle = i;
2808 i += loadmodel->data_surfaces[index].num_triangles;
2809 loadmodel->data_surfaces[index].num_triangles = 0;
2811 for (index = 0;index < numfaces;index++)
2813 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2814 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2815 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2816 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2819 // copy over the bones
2820 for (index = 0;index < numbones;index++)
2822 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2823 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2824 if (loadmodel->data_bones[index].parent >= index)
2825 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2828 // sort the psk point weights into the vertex weight tables
2829 // (which only accept up to 4 bones per vertex)
2830 for (index = 0;index < numvtxw;index++)
2834 for (j = 0;j < numrawweights;j++)
2836 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2838 int boneindex = rawweights[j].boneindex;
2839 float influence = rawweights[j].weight;
2840 for (l = 0;l < 4;l++)
2842 if (loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] < influence)
2844 // move lower influence weights out of the way first
2846 for (l2 = 3;l2 > l;l2--)
2848 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2-1];
2849 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2-1];
2851 // store the new weight
2852 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] = influence;
2853 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l] = boneindex;
2860 for (l = 0;l < 4;l++)
2861 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l];
2862 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2864 float f = 1.0f / sum;
2865 for (l = 0;l < 4;l++)
2866 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] *= f;
2870 // set up the animscenes based on the anims
2871 for (index = 0, i = 0;index < numanims;index++)
2873 for (j = 0;j < anims[index].numframes;j++, i++)
2875 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2876 loadmodel->animscenes[i].firstframe = i;
2877 loadmodel->animscenes[i].framecount = 1;
2878 loadmodel->animscenes[i].loop = true;
2879 loadmodel->animscenes[i].framerate = 10;
2883 // calculate the scaling value for bone origins so they can be compressed to short
2885 for (index = 0;index < numanimkeys;index++)
2887 pskanimkeys_t *k = animkeys + index;
2888 biggestorigin = max(biggestorigin, fabs(k->origin[0]));
2889 biggestorigin = max(biggestorigin, fabs(k->origin[1]));
2890 biggestorigin = max(biggestorigin, fabs(k->origin[2]));
2892 loadmodel->num_posescale = biggestorigin / 32767.0f;
2893 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2895 // load the poses from the animkeys
2896 for (index = 0;index < numanimkeys;index++)
2898 pskanimkeys_t *k = animkeys + index;
2900 Vector4Copy(k->quat, quat);
2902 Vector4Negate(quat, quat);
2903 Vector4Normalize2(quat, quat);
2904 // compress poses to the short[6] format for longterm storage
2905 loadmodel->data_poses6s[index*6+0] = k->origin[0] * loadmodel->num_poseinvscale;
2906 loadmodel->data_poses6s[index*6+1] = k->origin[1] * loadmodel->num_poseinvscale;
2907 loadmodel->data_poses6s[index*6+2] = k->origin[2] * loadmodel->num_poseinvscale;
2908 loadmodel->data_poses6s[index*6+3] = quat[0] * 32767.0f;
2909 loadmodel->data_poses6s[index*6+4] = quat[1] * 32767.0f;
2910 loadmodel->data_poses6s[index*6+5] = quat[2] * 32767.0f;
2912 Mod_FreeSkinFiles(skinfiles);
2913 Mem_Free(animfilebuffer);
2914 Mod_MakeSortedSurfaces(loadmodel);
2916 // compute all the mesh information that was not loaded from the file
2917 // TODO: honor smoothing groups somehow?
2918 if (loadmodel->surfmesh.data_element3s)
2919 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2920 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2921 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2922 Mod_BuildBaseBonePoses();
2923 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2924 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);
2925 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2926 Mod_Alias_CalculateBoundingBox();
2928 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;