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, tempvec[3], modelscale;
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);
1885 // figure out scale of model from root bone, for compatibility with old zmodel versions
1886 tempvec[0] = BigFloat(poses[0]);
1887 tempvec[1] = BigFloat(poses[1]);
1888 tempvec[2] = BigFloat(poses[2]);
1889 modelscale = VectorLength(tempvec);
1891 for (i = 0;i < loadmodel->num_bones * numposes * 12;i++)
1893 f = fabs(BigFloat(poses[i]));
1894 biggestorigin = max(biggestorigin, f);
1896 loadmodel->num_posescale = biggestorigin / 32767.0f;
1897 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
1898 for (i = 0;i < numposes;i++)
1900 const float *frameposes = (float *) (pheader->lump_poses.start + pbase) + 12*i*loadmodel->num_bones;
1901 for (j = 0;j < loadmodel->num_bones;j++)
1904 matrix4x4_t posematrix;
1905 for (k = 0;k < 12;k++)
1906 pose[k] = BigFloat(frameposes[j*12+k]);
1907 //if (j < loadmodel->num_bones)
1908 // Con_Printf("%s: bone %i = %f %f %f %f : %f %f %f %f : %f %f %f %f : scale = %f\n", loadmodel->name, j, pose[0], pose[1], pose[2], pose[3], pose[4], pose[5], pose[6], pose[7], pose[8], pose[9], pose[10], pose[11], VectorLength(pose));
1909 // scale child bones to match the root scale
1910 if (loadmodel->data_bones[j].parent >= 0)
1912 pose[3] *= modelscale;
1913 pose[7] *= modelscale;
1914 pose[11] *= modelscale;
1916 // normalize rotation matrix
1917 VectorNormalize(pose + 0);
1918 VectorNormalize(pose + 4);
1919 VectorNormalize(pose + 8);
1920 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
1921 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
1925 //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1926 verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1927 vertdata = (zymvertex_t *) (pheader->lump_verts.start + pbase);
1928 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
1929 // (converting from weight-blending skeletal animation to
1930 // deformation-based skeletal animation)
1931 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
1932 for (i = 0;i < loadmodel->num_bones;i++)
1935 for (k = 0;k < 12;k++)
1936 m[k] = BigFloat(poses[i*12+k]);
1937 if (loadmodel->data_bones[i].parent >= 0)
1938 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
1940 for (k = 0;k < 12;k++)
1941 bonepose[12*i+k] = m[k];
1943 for (j = 0;j < pheader->numverts;j++)
1945 // this format really should have had a per vertexweight weight value...
1946 // but since it does not, the weighting is completely ignored and
1947 // only one weight is allowed per vertex
1948 int boneindex = BigLong(vertdata[j].bonenum);
1949 const float *m = bonepose + 12 * boneindex;
1950 float relativeorigin[3];
1951 relativeorigin[0] = BigFloat(vertdata[j].origin[0]);
1952 relativeorigin[1] = BigFloat(vertdata[j].origin[1]);
1953 relativeorigin[2] = BigFloat(vertdata[j].origin[2]);
1954 // transform the vertex bone weight into the base mesh
1955 loadmodel->surfmesh.data_vertex3f[j*3+0] = relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + m[ 3];
1956 loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7];
1957 loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11];
1958 // store the weight as the primary weight on this vertex
1959 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
1960 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = 1;
1963 // normals and tangents are calculated after elements are loaded
1965 //zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1966 outtexcoord2f = loadmodel->surfmesh.data_texcoordtexture2f;
1967 intexcoord2f = (float *) (pheader->lump_texcoords.start + pbase);
1968 for (i = 0;i < pheader->numverts;i++)
1970 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1971 // flip T coordinate for OpenGL
1972 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1975 //zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1976 //loadmodel->alias.zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1977 //memcpy(loadmodel->alias.zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
1979 //zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1980 //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)
1981 // byteswap, validate, and swap winding order of tris
1982 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1983 if (pheader->lump_render.length != count)
1984 Host_Error("%s renderlist is wrong size (%i bytes, should be %i bytes)", loadmodel->name, pheader->lump_render.length, count);
1985 renderlist = (int *) (pheader->lump_render.start + pbase);
1986 renderlistend = (int *) ((unsigned char *) renderlist + pheader->lump_render.length);
1988 for (i = 0;i < loadmodel->num_surfaces;i++)
1990 int firstvertex, lastvertex;
1991 if (renderlist >= renderlistend)
1992 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1993 count = BigLong(*renderlist);renderlist++;
1994 if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
1995 Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
1997 loadmodel->sortedmodelsurfaces[i] = i;
1998 surface = loadmodel->data_surfaces + i;
1999 surface->texture = loadmodel->data_textures + i;
2000 surface->num_firsttriangle = meshtriangles;
2001 surface->num_triangles = count;
2002 meshtriangles += surface->num_triangles;
2004 // load the elements
2005 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2006 for (j = 0;j < surface->num_triangles;j++, renderlist += 3)
2008 outelements[j*3+2] = BigLong(renderlist[0]);
2009 outelements[j*3+1] = BigLong(renderlist[1]);
2010 outelements[j*3+0] = BigLong(renderlist[2]);
2012 // validate the elements and find the used vertex range
2013 firstvertex = meshvertices;
2015 for (j = 0;j < surface->num_triangles * 3;j++)
2017 if ((unsigned int)outelements[j] >= (unsigned int)meshvertices)
2018 Host_Error("%s corrupt renderlist (out of bounds index)", loadmodel->name);
2019 firstvertex = min(firstvertex, outelements[j]);
2020 lastvertex = max(lastvertex, outelements[j]);
2022 surface->num_firstvertex = firstvertex;
2023 surface->num_vertices = lastvertex + 1 - firstvertex;
2025 // since zym models do not have named sections, reuse their shader
2026 // name as the section name
2027 shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32;
2028 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername);
2030 Mod_FreeSkinFiles(skinfiles);
2031 Mem_Free(vertbonecounts);
2033 Mod_MakeSortedSurfaces(loadmodel);
2035 // compute all the mesh information that was not loaded from the file
2036 if (loadmodel->surfmesh.data_element3s)
2037 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2038 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2039 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2040 Mod_BuildBaseBonePoses();
2041 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2042 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);
2043 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2045 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2048 void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2050 dpmheader_t *pheader;
2054 unsigned char *pbase;
2055 int i, j, k, meshvertices, meshtriangles;
2056 skinfile_t *skinfiles;
2057 unsigned char *data;
2059 float biggestorigin, tempvec[3], modelscale;
2063 pheader = (dpmheader_t *)buffer;
2064 pbase = (unsigned char *)buffer;
2065 if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16))
2066 Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name);
2067 if (BigLong(pheader->type) != 2)
2068 Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name);
2070 loadmodel->modeldatatypestring = "DPM";
2072 loadmodel->type = mod_alias;
2073 loadmodel->synctype = ST_RAND;
2076 pheader->type = BigLong(pheader->type);
2077 pheader->filesize = BigLong(pheader->filesize);
2078 pheader->mins[0] = BigFloat(pheader->mins[0]);
2079 pheader->mins[1] = BigFloat(pheader->mins[1]);
2080 pheader->mins[2] = BigFloat(pheader->mins[2]);
2081 pheader->maxs[0] = BigFloat(pheader->maxs[0]);
2082 pheader->maxs[1] = BigFloat(pheader->maxs[1]);
2083 pheader->maxs[2] = BigFloat(pheader->maxs[2]);
2084 pheader->yawradius = BigFloat(pheader->yawradius);
2085 pheader->allradius = BigFloat(pheader->allradius);
2086 pheader->num_bones = BigLong(pheader->num_bones);
2087 pheader->num_meshs = BigLong(pheader->num_meshs);
2088 pheader->num_frames = BigLong(pheader->num_frames);
2089 pheader->ofs_bones = BigLong(pheader->ofs_bones);
2090 pheader->ofs_meshs = BigLong(pheader->ofs_meshs);
2091 pheader->ofs_frames = BigLong(pheader->ofs_frames);
2093 if (pheader->num_bones < 1 || pheader->num_meshs < 1)
2095 Con_Printf("%s has no geometry\n", loadmodel->name);
2098 if (pheader->num_frames < 1)
2100 Con_Printf("%s has no frames\n", loadmodel->name);
2104 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2105 loadmodel->DrawSky = NULL;
2106 loadmodel->DrawAddWaterPlanes = NULL;
2107 loadmodel->Draw = R_Q1BSP_Draw;
2108 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2109 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2110 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2111 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2112 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2113 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2114 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2115 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2116 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2117 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2118 loadmodel->PointSuperContents = NULL;
2121 for (i = 0;i < 3;i++)
2123 loadmodel->normalmins[i] = pheader->mins[i];
2124 loadmodel->normalmaxs[i] = pheader->maxs[i];
2125 loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
2126 loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
2127 loadmodel->rotatedmins[i] = -pheader->allradius;
2128 loadmodel->rotatedmaxs[i] = pheader->allradius;
2130 loadmodel->radius = pheader->allradius;
2131 loadmodel->radius2 = pheader->allradius * pheader->allradius;
2133 // load external .skin files if present
2134 skinfiles = Mod_LoadSkinFiles();
2135 if (loadmodel->numskins < 1)
2136 loadmodel->numskins = 1;
2141 // gather combined statistics from the meshes
2142 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2143 for (i = 0;i < (int)pheader->num_meshs;i++)
2145 int numverts = BigLong(dpmmesh->num_verts);
2146 meshvertices += numverts;
2147 meshtriangles += BigLong(dpmmesh->num_tris);
2151 loadmodel->numframes = pheader->num_frames;
2152 loadmodel->num_bones = pheader->num_bones;
2153 loadmodel->num_poses = loadmodel->numframes;
2154 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
2155 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2156 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2157 // do most allocations as one merged chunk
2158 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));
2159 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2160 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2161 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2162 loadmodel->surfmesh.num_vertices = meshvertices;
2163 loadmodel->surfmesh.num_triangles = meshtriangles;
2164 loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2165 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
2166 loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
2167 loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2168 loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
2169 loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
2170 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
2171 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
2172 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
2173 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2174 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2175 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2176 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2177 if (meshvertices <= 65536)
2178 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
2179 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2181 for (i = 0;i < loadmodel->numskins;i++)
2183 loadmodel->skinscenes[i].firstframe = i;
2184 loadmodel->skinscenes[i].framecount = 1;
2185 loadmodel->skinscenes[i].loop = true;
2186 loadmodel->skinscenes[i].framerate = 10;
2189 // load the bone info
2190 bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
2191 for (i = 0;i < loadmodel->num_bones;i++)
2193 memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
2194 loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
2195 loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
2196 if (loadmodel->data_bones[i].parent >= i)
2197 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
2201 frames = (dpmframe_t *) (pbase + pheader->ofs_frames);
2202 // figure out scale of model from root bone, for compatibility with old dpmodel versions
2203 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2204 tempvec[0] = BigFloat(poses[0]);
2205 tempvec[1] = BigFloat(poses[1]);
2206 tempvec[2] = BigFloat(poses[2]);
2207 modelscale = VectorLength(tempvec);
2209 for (i = 0;i < loadmodel->numframes;i++)
2211 memcpy(loadmodel->animscenes[i].name, frames[i].name, sizeof(frames[i].name));
2212 loadmodel->animscenes[i].firstframe = i;
2213 loadmodel->animscenes[i].framecount = 1;
2214 loadmodel->animscenes[i].loop = true;
2215 loadmodel->animscenes[i].framerate = 10;
2216 // load the bone poses for this frame
2217 poses = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2218 for (j = 0;j < loadmodel->num_bones*12;j++)
2220 f = fabs(BigFloat(poses[j]));
2221 biggestorigin = max(biggestorigin, f);
2223 // stuff not processed here: mins, maxs, yawradius, allradius
2225 loadmodel->num_posescale = biggestorigin / 32767.0f;
2226 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2227 for (i = 0;i < loadmodel->numframes;i++)
2229 const float *frameposes = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
2230 for (j = 0;j < loadmodel->num_bones;j++)
2233 matrix4x4_t posematrix;
2234 for (k = 0;k < 12;k++)
2235 pose[k] = BigFloat(frameposes[j*12+k]);
2236 // scale child bones to match the root scale
2237 if (loadmodel->data_bones[j].parent >= 0)
2239 pose[3] *= modelscale;
2240 pose[7] *= modelscale;
2241 pose[11] *= modelscale;
2243 // normalize rotation matrix
2244 VectorNormalize(pose + 0);
2245 VectorNormalize(pose + 4);
2246 VectorNormalize(pose + 8);
2247 Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
2248 Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
2252 // load the meshes now
2253 dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
2256 // reconstruct frame 0 matrices to allow reconstruction of the base mesh
2257 // (converting from weight-blending skeletal animation to
2258 // deformation-based skeletal animation)
2259 poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
2260 bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
2261 for (i = 0;i < loadmodel->num_bones;i++)
2264 for (k = 0;k < 12;k++)
2265 m[k] = BigFloat(poses[i*12+k]);
2266 if (loadmodel->data_bones[i].parent >= 0)
2267 R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
2269 for (k = 0;k < 12;k++)
2270 bonepose[12*i+k] = m[k];
2272 for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
2274 const int *inelements;
2276 const float *intexcoord;
2277 msurface_t *surface;
2279 loadmodel->sortedmodelsurfaces[i] = i;
2280 surface = loadmodel->data_surfaces + i;
2281 surface->texture = loadmodel->data_textures + i;
2282 surface->num_firsttriangle = meshtriangles;
2283 surface->num_triangles = BigLong(dpmmesh->num_tris);
2284 surface->num_firstvertex = meshvertices;
2285 surface->num_vertices = BigLong(dpmmesh->num_verts);
2286 meshvertices += surface->num_vertices;
2287 meshtriangles += surface->num_triangles;
2289 inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
2290 outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
2291 for (j = 0;j < surface->num_triangles;j++)
2293 // swap element order to flip triangles, because Quake uses clockwise (rare) and dpm uses counterclockwise (standard)
2294 outelements[0] = surface->num_firstvertex + BigLong(inelements[2]);
2295 outelements[1] = surface->num_firstvertex + BigLong(inelements[1]);
2296 outelements[2] = surface->num_firstvertex + BigLong(inelements[0]);
2301 intexcoord = (float *) (pbase + BigLong(dpmmesh->ofs_texcoords));
2302 for (j = 0;j < surface->num_vertices*2;j++)
2303 loadmodel->surfmesh.data_texcoordtexture2f[j + surface->num_firstvertex * 2] = BigFloat(intexcoord[j]);
2305 data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts));
2306 for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++)
2310 int numweights = BigLong(((dpmvertex_t *)data)->numbones);
2311 data += sizeof(dpmvertex_t);
2312 for (k = 0;k < numweights;k++)
2314 const dpmbonevert_t *vert = (dpmbonevert_t *) data;
2315 int boneindex = BigLong(vert->bonenum);
2316 const float *m = bonepose + 12 * boneindex;
2317 float influence = BigFloat(vert->influence);
2318 float relativeorigin[3], relativenormal[3];
2319 relativeorigin[0] = BigFloat(vert->origin[0]);
2320 relativeorigin[1] = BigFloat(vert->origin[1]);
2321 relativeorigin[2] = BigFloat(vert->origin[2]);
2322 relativenormal[0] = BigFloat(vert->normal[0]);
2323 relativenormal[1] = BigFloat(vert->normal[1]);
2324 relativenormal[2] = BigFloat(vert->normal[2]);
2325 // blend the vertex bone weights into the base mesh
2326 loadmodel->surfmesh.data_vertex3f[j*3+0] += relativeorigin[0] * m[0] + relativeorigin[1] * m[1] + relativeorigin[2] * m[ 2] + influence * m[ 3];
2327 loadmodel->surfmesh.data_vertex3f[j*3+1] += relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + influence * m[ 7];
2328 loadmodel->surfmesh.data_vertex3f[j*3+2] += relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + influence * m[11];
2329 loadmodel->surfmesh.data_normal3f[j*3+0] += relativenormal[0] * m[0] + relativenormal[1] * m[1] + relativenormal[2] * m[ 2];
2330 loadmodel->surfmesh.data_normal3f[j*3+1] += relativenormal[0] * m[4] + relativenormal[1] * m[5] + relativenormal[2] * m[ 6];
2331 loadmodel->surfmesh.data_normal3f[j*3+2] += relativenormal[0] * m[8] + relativenormal[1] * m[9] + relativenormal[2] * m[10];
2334 // store the first (and often only) weight
2335 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = influence;
2336 loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex;
2340 // sort the new weight into this vertex's weight table
2341 // (which only accepts up to 4 bones per vertex)
2342 for (l = 0;l < 4;l++)
2344 if (loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] < influence)
2346 // move weaker influence weights out of the way first
2348 for (l2 = 3;l2 > l;l2--)
2350 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2-1];
2351 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2-1];
2353 // store the new weight
2354 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] = influence;
2355 loadmodel->surfmesh.data_vertexweightindex4i[j*4+l] = boneindex;
2360 data += sizeof(dpmbonevert_t);
2363 for (l = 0;l < 4;l++)
2364 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l];
2365 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2367 float f = 1.0f / sum;
2368 for (l = 0;l < 4;l++)
2369 loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] *= f;
2373 // since dpm models do not have named sections, reuse their shader name as the section name
2374 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername);
2376 Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__);
2379 Mod_FreeSkinFiles(skinfiles);
2380 Mod_MakeSortedSurfaces(loadmodel);
2382 // compute all the mesh information that was not loaded from the file
2383 if (loadmodel->surfmesh.data_element3s)
2384 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2385 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2386 Mod_BuildBaseBonePoses();
2387 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);
2388 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2390 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
2393 // no idea why PSK/PSA files contain weird quaternions but they do...
2394 #define PSKQUATNEGATIONS
2395 void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
2397 int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
2398 int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
2399 fs_offset_t filesize;
2404 pskboneinfo_t *bones;
2405 pskrawweights_t *rawweights;
2406 pskboneinfo_t *animbones;
2407 pskaniminfo_t *anims;
2408 pskanimkeys_t *animkeys;
2409 void *animfilebuffer, *animbuffer, *animbufferend;
2410 unsigned char *data;
2412 skinfile_t *skinfiles;
2413 char animname[MAX_QPATH];
2415 float biggestorigin;
2417 pchunk = (pskchunk_t *)buffer;
2418 if (strcmp(pchunk->id, "ACTRHEAD"))
2419 Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name);
2421 loadmodel->modeldatatypestring = "PSK";
2423 loadmodel->type = mod_alias;
2424 loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices;
2425 loadmodel->DrawSky = NULL;
2426 loadmodel->DrawAddWaterPlanes = NULL;
2427 loadmodel->Draw = R_Q1BSP_Draw;
2428 loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
2429 loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
2430 loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
2431 loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
2432 loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
2433 loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
2434 loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
2435 loadmodel->DrawLight = R_Q1BSP_DrawLight;
2436 loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
2437 loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine;
2438 loadmodel->PointSuperContents = NULL;
2439 loadmodel->synctype = ST_RAND;
2441 FS_StripExtension(loadmodel->name, animname, sizeof(animname));
2442 strlcat(animname, ".psa", sizeof(animname));
2443 animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
2444 animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
2445 if (animbuffer == NULL)
2446 Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
2465 while (buffer < bufferend)
2467 pchunk = (pskchunk_t *)buffer;
2468 buffer = (void *)((unsigned char *)buffer + sizeof(pskchunk_t));
2469 version = LittleLong(pchunk->version);
2470 recordsize = LittleLong(pchunk->recordsize);
2471 numrecords = LittleLong(pchunk->numrecords);
2472 if (developer_extra.integer)
2473 Con_DPrintf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2474 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2475 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);
2476 if (!strcmp(pchunk->id, "ACTRHEAD"))
2480 else if (!strcmp(pchunk->id, "PNTS0000"))
2483 if (recordsize != sizeof(*p))
2484 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2485 // byteswap in place and keep the pointer
2486 numpnts = numrecords;
2487 pnts = (pskpnts_t *)buffer;
2488 for (index = 0, p = (pskpnts_t *)buffer;index < numrecords;index++, p++)
2490 p->origin[0] = LittleFloat(p->origin[0]);
2491 p->origin[1] = LittleFloat(p->origin[1]);
2492 p->origin[2] = LittleFloat(p->origin[2]);
2496 else if (!strcmp(pchunk->id, "VTXW0000"))
2499 if (recordsize != sizeof(*p))
2500 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2501 // byteswap in place and keep the pointer
2502 numvtxw = numrecords;
2503 vtxw = (pskvtxw_t *)buffer;
2504 for (index = 0, p = (pskvtxw_t *)buffer;index < numrecords;index++, p++)
2506 p->pntsindex = LittleShort(p->pntsindex);
2507 p->texcoord[0] = LittleFloat(p->texcoord[0]);
2508 p->texcoord[1] = LittleFloat(p->texcoord[1]);
2509 if (p->pntsindex >= numpnts)
2511 Con_Printf("%s: vtxw->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2517 else if (!strcmp(pchunk->id, "FACE0000"))
2520 if (recordsize != sizeof(*p))
2521 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2522 // byteswap in place and keep the pointer
2523 numfaces = numrecords;
2524 faces = (pskface_t *)buffer;
2525 for (index = 0, p = (pskface_t *)buffer;index < numrecords;index++, p++)
2527 p->vtxwindex[0] = LittleShort(p->vtxwindex[0]);
2528 p->vtxwindex[1] = LittleShort(p->vtxwindex[1]);
2529 p->vtxwindex[2] = LittleShort(p->vtxwindex[2]);
2530 p->group = LittleLong(p->group);
2531 if (p->vtxwindex[0] >= numvtxw)
2533 Con_Printf("%s: face->vtxwindex[0] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[0], numvtxw);
2534 p->vtxwindex[0] = 0;
2536 if (p->vtxwindex[1] >= numvtxw)
2538 Con_Printf("%s: face->vtxwindex[1] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[1], numvtxw);
2539 p->vtxwindex[1] = 0;
2541 if (p->vtxwindex[2] >= numvtxw)
2543 Con_Printf("%s: face->vtxwindex[2] %i >= numvtxw %i\n", loadmodel->name, p->vtxwindex[2], numvtxw);
2544 p->vtxwindex[2] = 0;
2549 else if (!strcmp(pchunk->id, "MATT0000"))
2552 if (recordsize != sizeof(*p))
2553 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2554 // byteswap in place and keep the pointer
2555 nummatts = numrecords;
2556 matts = (pskmatt_t *)buffer;
2557 for (index = 0, p = (pskmatt_t *)buffer;index < numrecords;index++, p++)
2563 else if (!strcmp(pchunk->id, "REFSKELT"))
2566 if (recordsize != sizeof(*p))
2567 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2568 // byteswap in place and keep the pointer
2569 numbones = numrecords;
2570 bones = (pskboneinfo_t *)buffer;
2571 for (index = 0, p = (pskboneinfo_t *)buffer;index < numrecords;index++, p++)
2573 p->numchildren = LittleLong(p->numchildren);
2574 p->parent = LittleLong(p->parent);
2575 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2576 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2577 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2578 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2579 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2580 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2581 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2582 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2583 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2584 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2585 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2586 #ifdef PSKQUATNEGATIONS
2589 p->basepose.quat[0] *= -1;
2590 p->basepose.quat[1] *= -1;
2591 p->basepose.quat[2] *= -1;
2595 p->basepose.quat[0] *= 1;
2596 p->basepose.quat[1] *= -1;
2597 p->basepose.quat[2] *= 1;
2600 if (p->parent < 0 || p->parent >= numbones)
2602 Con_Printf("%s: bone->parent %i >= numbones %i\n", loadmodel->name, p->parent, numbones);
2608 else if (!strcmp(pchunk->id, "RAWWEIGHTS"))
2611 if (recordsize != sizeof(*p))
2612 Host_Error("%s: %s has unsupported recordsize", loadmodel->name, pchunk->id);
2613 // byteswap in place and keep the pointer
2614 numrawweights = numrecords;
2615 rawweights = (pskrawweights_t *)buffer;
2616 for (index = 0, p = (pskrawweights_t *)buffer;index < numrecords;index++, p++)
2618 p->weight = LittleFloat(p->weight);
2619 p->pntsindex = LittleLong(p->pntsindex);
2620 p->boneindex = LittleLong(p->boneindex);
2621 if (p->pntsindex < 0 || p->pntsindex >= numpnts)
2623 Con_Printf("%s: weight->pntsindex %i >= numpnts %i\n", loadmodel->name, p->pntsindex, numpnts);
2626 if (p->boneindex < 0 || p->boneindex >= numbones)
2628 Con_Printf("%s: weight->boneindex %i >= numbones %i\n", loadmodel->name, p->boneindex, numbones);
2636 while (animbuffer < animbufferend)
2638 pchunk = (pskchunk_t *)animbuffer;
2639 animbuffer = (void *)((unsigned char *)animbuffer + sizeof(pskchunk_t));
2640 version = LittleLong(pchunk->version);
2641 recordsize = LittleLong(pchunk->recordsize);
2642 numrecords = LittleLong(pchunk->numrecords);
2643 if (developer_extra.integer)
2644 Con_DPrintf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
2645 if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
2646 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);
2647 if (!strcmp(pchunk->id, "ANIMHEAD"))
2651 else if (!strcmp(pchunk->id, "BONENAMES"))
2654 if (recordsize != sizeof(*p))
2655 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2656 // byteswap in place and keep the pointer
2657 numanimbones = numrecords;
2658 animbones = (pskboneinfo_t *)animbuffer;
2659 // NOTE: supposedly psa does not need to match the psk model, the
2660 // bones missing from the psa would simply use their base
2661 // positions from the psk, but this is hard for me to implement
2662 // and people can easily make animations that match.
2663 if (numanimbones != numbones)
2664 Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name);
2665 for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++)
2667 p->numchildren = LittleLong(p->numchildren);
2668 p->parent = LittleLong(p->parent);
2669 p->basepose.quat[0] = LittleFloat(p->basepose.quat[0]);
2670 p->basepose.quat[1] = LittleFloat(p->basepose.quat[1]);
2671 p->basepose.quat[2] = LittleFloat(p->basepose.quat[2]);
2672 p->basepose.quat[3] = LittleFloat(p->basepose.quat[3]);
2673 p->basepose.origin[0] = LittleFloat(p->basepose.origin[0]);
2674 p->basepose.origin[1] = LittleFloat(p->basepose.origin[1]);
2675 p->basepose.origin[2] = LittleFloat(p->basepose.origin[2]);
2676 p->basepose.unknown = LittleFloat(p->basepose.unknown);
2677 p->basepose.size[0] = LittleFloat(p->basepose.size[0]);
2678 p->basepose.size[1] = LittleFloat(p->basepose.size[1]);
2679 p->basepose.size[2] = LittleFloat(p->basepose.size[2]);
2680 #ifdef PSKQUATNEGATIONS
2683 p->basepose.quat[0] *= -1;
2684 p->basepose.quat[1] *= -1;
2685 p->basepose.quat[2] *= -1;
2689 p->basepose.quat[0] *= 1;
2690 p->basepose.quat[1] *= -1;
2691 p->basepose.quat[2] *= 1;
2694 if (p->parent < 0 || p->parent >= numanimbones)
2696 Con_Printf("%s: bone->parent %i >= numanimbones %i\n", animname, p->parent, numanimbones);
2699 // check that bones are the same as in the base
2700 if (strcmp(p->name, bones[index].name) || p->parent != bones[index].parent)
2701 Host_Error("%s: this loader only supports animations with the same bones as the mesh", animname);
2705 else if (!strcmp(pchunk->id, "ANIMINFO"))
2708 if (recordsize != sizeof(*p))
2709 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2710 // byteswap in place and keep the pointer
2711 numanims = numrecords;
2712 anims = (pskaniminfo_t *)animbuffer;
2713 for (index = 0, p = (pskaniminfo_t *)animbuffer;index < numrecords;index++, p++)
2715 p->numbones = LittleLong(p->numbones);
2716 p->playtime = LittleFloat(p->playtime);
2717 p->fps = LittleFloat(p->fps);
2718 p->firstframe = LittleLong(p->firstframe);
2719 p->numframes = LittleLong(p->numframes);
2720 if (p->numbones != numbones)
2721 Con_Printf("%s: animinfo->numbones != numbones, trying to load anyway!\n", animname);
2725 else if (!strcmp(pchunk->id, "ANIMKEYS"))
2728 if (recordsize != sizeof(*p))
2729 Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id);
2730 numanimkeys = numrecords;
2731 animkeys = (pskanimkeys_t *)animbuffer;
2732 for (index = 0, p = (pskanimkeys_t *)animbuffer;index < numrecords;index++, p++)
2734 p->origin[0] = LittleFloat(p->origin[0]);
2735 p->origin[1] = LittleFloat(p->origin[1]);
2736 p->origin[2] = LittleFloat(p->origin[2]);
2737 p->quat[0] = LittleFloat(p->quat[0]);
2738 p->quat[1] = LittleFloat(p->quat[1]);
2739 p->quat[2] = LittleFloat(p->quat[2]);
2740 p->quat[3] = LittleFloat(p->quat[3]);
2741 p->frametime = LittleFloat(p->frametime);
2742 #ifdef PSKQUATNEGATIONS
2743 if (index % numbones)
2758 // TODO: allocate bonepose stuff
2761 Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
2764 if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
2765 Host_Error("%s: missing required chunks", loadmodel->name);
2767 loadmodel->numframes = 0;
2768 for (index = 0;index < numanims;index++)
2769 loadmodel->numframes += anims[index].numframes;
2771 if (numanimkeys != numbones * loadmodel->numframes)
2772 Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
2774 meshvertices = numvtxw;
2775 meshtriangles = numfaces;
2777 // load external .skin files if present
2778 skinfiles = Mod_LoadSkinFiles();
2779 if (loadmodel->numskins < 1)
2780 loadmodel->numskins = 1;
2781 loadmodel->num_bones = numbones;
2782 loadmodel->num_poses = loadmodel->numframes;
2783 loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
2784 loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
2785 loadmodel->num_texturesperskin = loadmodel->num_surfaces;
2786 loadmodel->surfmesh.num_vertices = meshvertices;
2787 loadmodel->surfmesh.num_triangles = meshtriangles;
2788 // do most allocations as one merged chunk
2789 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);
2790 data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
2791 loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
2792 loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
2793 loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
2794 loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2795 loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
2796 loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2797 loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2798 loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2799 loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
2800 loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
2801 loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += loadmodel->surfmesh.num_vertices * sizeof(int[4]);
2802 loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[4]);
2803 loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
2804 loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
2805 loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
2806 loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
2807 if (loadmodel->surfmesh.num_vertices <= 65536)
2808 loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
2809 loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
2811 for (i = 0;i < loadmodel->numskins;i++)
2813 loadmodel->skinscenes[i].firstframe = i;
2814 loadmodel->skinscenes[i].framecount = 1;
2815 loadmodel->skinscenes[i].loop = true;
2816 loadmodel->skinscenes[i].framerate = 10;
2820 for (index = 0, i = 0;index < nummatts;index++)
2822 // since psk models do not have named sections, reuse their shader name as the section name
2823 Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
2824 loadmodel->sortedmodelsurfaces[index] = index;
2825 loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
2826 loadmodel->data_surfaces[index].num_firstvertex = 0;
2827 loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
2830 // copy over the vertex locations and texcoords
2831 for (index = 0;index < numvtxw;index++)
2833 loadmodel->surfmesh.data_vertex3f[index*3+0] = pnts[vtxw[index].pntsindex].origin[0];
2834 loadmodel->surfmesh.data_vertex3f[index*3+1] = pnts[vtxw[index].pntsindex].origin[1];
2835 loadmodel->surfmesh.data_vertex3f[index*3+2] = pnts[vtxw[index].pntsindex].origin[2];
2836 loadmodel->surfmesh.data_texcoordtexture2f[index*2+0] = vtxw[index].texcoord[0];
2837 loadmodel->surfmesh.data_texcoordtexture2f[index*2+1] = vtxw[index].texcoord[1];
2840 // loading the faces is complicated because we need to sort them into surfaces by mattindex
2841 for (index = 0;index < numfaces;index++)
2842 loadmodel->data_surfaces[faces[index].mattindex].num_triangles++;
2843 for (index = 0, i = 0;index < nummatts;index++)
2845 loadmodel->data_surfaces[index].num_firsttriangle = i;
2846 i += loadmodel->data_surfaces[index].num_triangles;
2847 loadmodel->data_surfaces[index].num_triangles = 0;
2849 for (index = 0;index < numfaces;index++)
2851 i = (loadmodel->data_surfaces[faces[index].mattindex].num_firsttriangle + loadmodel->data_surfaces[faces[index].mattindex].num_triangles++)*3;
2852 loadmodel->surfmesh.data_element3i[i+0] = faces[index].vtxwindex[0];
2853 loadmodel->surfmesh.data_element3i[i+1] = faces[index].vtxwindex[1];
2854 loadmodel->surfmesh.data_element3i[i+2] = faces[index].vtxwindex[2];
2857 // copy over the bones
2858 for (index = 0;index < numbones;index++)
2860 strlcpy(loadmodel->data_bones[index].name, bones[index].name, sizeof(loadmodel->data_bones[index].name));
2861 loadmodel->data_bones[index].parent = (index || bones[index].parent > 0) ? bones[index].parent : -1;
2862 if (loadmodel->data_bones[index].parent >= index)
2863 Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
2866 // sort the psk point weights into the vertex weight tables
2867 // (which only accept up to 4 bones per vertex)
2868 for (index = 0;index < numvtxw;index++)
2872 for (j = 0;j < numrawweights;j++)
2874 if (rawweights[j].pntsindex == vtxw[index].pntsindex)
2876 int boneindex = rawweights[j].boneindex;
2877 float influence = rawweights[j].weight;
2878 for (l = 0;l < 4;l++)
2880 if (loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] < influence)
2882 // move lower influence weights out of the way first
2884 for (l2 = 3;l2 > l;l2--)
2886 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2-1];
2887 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2-1];
2889 // store the new weight
2890 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] = influence;
2891 loadmodel->surfmesh.data_vertexweightindex4i[index*4+l] = boneindex;
2898 for (l = 0;l < 4;l++)
2899 sum += loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l];
2900 if (sum && fabs(sum - 1) > (1.0f / 256.0f))
2902 float f = 1.0f / sum;
2903 for (l = 0;l < 4;l++)
2904 loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] *= f;
2908 // set up the animscenes based on the anims
2909 for (index = 0, i = 0;index < numanims;index++)
2911 for (j = 0;j < anims[index].numframes;j++, i++)
2913 dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
2914 loadmodel->animscenes[i].firstframe = i;
2915 loadmodel->animscenes[i].framecount = 1;
2916 loadmodel->animscenes[i].loop = true;
2917 loadmodel->animscenes[i].framerate = 10;
2921 // calculate the scaling value for bone origins so they can be compressed to short
2923 for (index = 0;index < numanimkeys;index++)
2925 pskanimkeys_t *k = animkeys + index;
2926 biggestorigin = max(biggestorigin, fabs(k->origin[0]));
2927 biggestorigin = max(biggestorigin, fabs(k->origin[1]));
2928 biggestorigin = max(biggestorigin, fabs(k->origin[2]));
2930 loadmodel->num_posescale = biggestorigin / 32767.0f;
2931 loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
2933 // load the poses from the animkeys
2934 for (index = 0;index < numanimkeys;index++)
2936 pskanimkeys_t *k = animkeys + index;
2938 Vector4Copy(k->quat, quat);
2940 Vector4Negate(quat, quat);
2941 Vector4Normalize2(quat, quat);
2942 // compress poses to the short[6] format for longterm storage
2943 loadmodel->data_poses6s[index*6+0] = k->origin[0] * loadmodel->num_poseinvscale;
2944 loadmodel->data_poses6s[index*6+1] = k->origin[1] * loadmodel->num_poseinvscale;
2945 loadmodel->data_poses6s[index*6+2] = k->origin[2] * loadmodel->num_poseinvscale;
2946 loadmodel->data_poses6s[index*6+3] = quat[0] * 32767.0f;
2947 loadmodel->data_poses6s[index*6+4] = quat[1] * 32767.0f;
2948 loadmodel->data_poses6s[index*6+5] = quat[2] * 32767.0f;
2950 Mod_FreeSkinFiles(skinfiles);
2951 Mem_Free(animfilebuffer);
2952 Mod_MakeSortedSurfaces(loadmodel);
2954 // compute all the mesh information that was not loaded from the file
2955 // TODO: honor smoothing groups somehow?
2956 if (loadmodel->surfmesh.data_element3s)
2957 for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
2958 loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
2959 Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
2960 Mod_BuildBaseBonePoses();
2961 Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true);
2962 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);
2963 Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
2964 Mod_Alias_CalculateBoundingBox();
2966 loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;