mod_md3_sin[i] = sin(i * M_PI * 2.0f / 256.0);
}
-void Mod_Skeletal_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
+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)
{
#define MAX_BONES 256
// vertex weighted skeletal
int i, k;
int blends;
- float desiredscale[3];
float boneposerelative[MAX_BONES][12];
- float *matrix, m[12], bonepose[MAX_BONES][12];
+ float m[12], bonepose[MAX_BONES][12];
- // interpolate matrices and concatenate them to their parents
- for (i = 0;i < model->num_bones;i++)
+ if (skeleton && !skeleton->relativetransforms)
+ skeleton = NULL;
+
+ // interpolate matrices
+ if (skeleton)
{
- for (k = 0;k < 12;k++)
- m[k] = 0;
- VectorClear(desiredscale);
- for (blends = 0;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++)
+ for (i = 0;i < model->num_bones;i++)
{
- matrix = model->data_poses + (frameblend[blends].subframe * model->num_bones + i) * 12;
- for (k = 0;k < 12;k++)
- m[k] += matrix[k] * frameblend[blends].lerp;
- desiredscale[0] += frameblend[blends].lerp * VectorLength(matrix );
- desiredscale[1] += frameblend[blends].lerp * VectorLength(matrix + 4);
- desiredscale[2] += frameblend[blends].lerp * VectorLength(matrix + 8);
+ Matrix4x4_ToArray12FloatD3D(&skeleton->relativetransforms[i], m);
+ if (model->data_bones[i].parent >= 0)
+ R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
+ else
+ for (k = 0;k < 12;k++)
+ bonepose[i][k] = m[k];
+
+ // create a relative deformation matrix to describe displacement
+ // from the base mesh, which is used by the actual weighting
+ R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]);
}
- VectorNormalize(m );
- VectorNormalize(m + 4);
- VectorNormalize(m + 8);
- VectorScale(m , desiredscale[0], m );
- VectorScale(m + 4, desiredscale[1], m + 4);
- VectorScale(m + 8, desiredscale[2], m + 8);
- if (i == r_skeletal_debugbone.integer)
- m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
- m[3] *= r_skeletal_debugtranslatex.value;
- m[7] *= r_skeletal_debugtranslatey.value;
- m[11] *= r_skeletal_debugtranslatez.value;
- if (model->data_bones[i].parent >= 0)
- R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
- else
+ }
+ else
+ {
+ float originscale = model->num_posescale;
+ float x,y,z,w,lerp;
+ const short *pose6s;
+ for (i = 0;i < model->num_bones;i++)
+ {
for (k = 0;k < 12;k++)
- bonepose[i][k] = m[k];
- // create a relative deformation matrix to describe displacement
- // from the base mesh, which is used by the actual weighting
- R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]);
+ m[k] = 0;
+ for (blends = 0;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++)
+ {
+ pose6s = model->data_poses6s + 6 * (frameblend[blends].subframe * model->num_bones + i);
+ lerp = frameblend[blends].lerp;
+ x = pose6s[3] * (1.0f / 32767.0f);
+ y = pose6s[4] * (1.0f / 32767.0f);
+ z = pose6s[5] * (1.0f / 32767.0f);
+ w = 1.0f - (x*x+y*y+z*z);
+ w = w > 0.0f ? -sqrt(w) : 0.0f;
+ m[ 0] += (1-2*(y*y+z*z)) * lerp;
+ m[ 1] += ( 2*(x*y-z*w)) * lerp;
+ m[ 2] += ( 2*(x*z+y*w)) * lerp;
+ m[ 3] += (pose6s[0] * originscale) * lerp;
+ m[ 4] += ( 2*(x*y+z*w)) * lerp;
+ m[ 5] += (1-2*(x*x+z*z)) * lerp;
+ m[ 6] += ( 2*(y*z-x*w)) * lerp;
+ m[ 7] += (pose6s[1] * originscale) * lerp;
+ m[ 8] += ( 2*(x*z-y*w)) * lerp;
+ m[ 9] += ( 2*(y*z+x*w)) * lerp;
+ m[10] += (1-2*(x*x+y*y)) * lerp;
+ m[11] += (pose6s[2] * originscale) * lerp;
+ }
+ VectorNormalize(m );
+ VectorNormalize(m + 4);
+ VectorNormalize(m + 8);
+ if (i == r_skeletal_debugbone.integer)
+ m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
+ m[3] *= r_skeletal_debugtranslatex.value;
+ m[7] *= r_skeletal_debugtranslatey.value;
+ m[11] *= r_skeletal_debugtranslatez.value;
+ if (model->data_bones[i].parent >= 0)
+ R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
+ else
+ for (k = 0;k < 12;k++)
+ bonepose[i][k] = m[k];
+ // create a relative deformation matrix to describe displacement
+ // from the base mesh, which is used by the actual weighting
+ R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]);
+ }
}
+
// blend the vertex bone weights
// 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)
// special case for the first bone because it avoids the need to memset the arrays before filling
}
}
-void Mod_MD3_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
+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)
{
// vertex morph
int i, numblends, blendnum;
}
}
-void Mod_MDL_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
+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)
{
// vertex morph
int i, numblends, blendnum;
}
}
-int Mod_Alias_GetTagMatrix(const dp_model_t *model, int poseframe, int tagindex, matrix4x4_t *outmatrix)
+int Mod_Alias_GetTagMatrix(const dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, int tagindex, matrix4x4_t *outmatrix)
{
- const float *boneframe;
- float tempbonematrix[12], bonematrix[12];
+ matrix4x4_t temp;
+ matrix4x4_t parentbonematrix;
+ matrix4x4_t tempbonematrix;
+ matrix4x4_t bonematrix;
+ matrix4x4_t blendmatrix;
+ int blendindex;
+ int parenttagindex;
+ int k;
+ float lerp;
+ const float *input;
+ float blendtag[12];
*outmatrix = identitymatrix;
- if (model->num_bones)
+ if (skeleton && skeleton->relativetransforms)
+ {
+ if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
+ return 4;
+ *outmatrix = skeleton->relativetransforms[tagindex];
+ while ((tagindex = model->data_bones[tagindex].parent) >= 0)
+ {
+ temp = *outmatrix;
+ Matrix4x4_Concat(outmatrix, &skeleton->relativetransforms[tagindex], &temp);
+ }
+ }
+ else if (model->num_bones)
{
if (tagindex < 0 || tagindex >= model->num_bones)
return 4;
- if (poseframe >= model->num_poses)
- return 6;
- boneframe = model->data_poses + poseframe * model->num_bones * 12;
- memcpy(bonematrix, boneframe + tagindex * 12, sizeof(float[12]));
- while (model->data_bones[tagindex].parent >= 0)
+ Matrix4x4_Clear(&blendmatrix);
+ for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
{
- memcpy(tempbonematrix, bonematrix, sizeof(float[12]));
- R_ConcatTransforms(boneframe + model->data_bones[tagindex].parent * 12, tempbonematrix, bonematrix);
- tagindex = model->data_bones[tagindex].parent;
+ lerp = frameblend[blendindex].lerp;
+ Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
+ parenttagindex = tagindex;
+ while ((parenttagindex = model->data_bones[parenttagindex].parent) >= 0)
+ {
+ Matrix4x4_FromBonePose6s(&parentbonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + parenttagindex));
+ tempbonematrix = bonematrix;
+ Matrix4x4_Concat(&bonematrix, &parentbonematrix, &tempbonematrix);
+ }
+ Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
}
- Matrix4x4_FromArray12FloatD3D(outmatrix, bonematrix);
+ *outmatrix = blendmatrix;
}
else if (model->num_tags)
{
if (tagindex < 0 || tagindex >= model->num_tags)
return 4;
- if (poseframe >= model->num_tagframes)
- return 6;
- Matrix4x4_FromArray12FloatGL(outmatrix, model->data_tags[poseframe * model->num_tags + tagindex].matrixgl);
+ for (k = 0;k < 12;k++)
+ blendtag[k] = 0;
+ for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
+ {
+ lerp = frameblend[blendindex].lerp;
+ input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
+ for (k = 0;k < 12;k++)
+ blendtag[k] += input[k] * lerp;
+ }
+ Matrix4x4_FromArray12FloatGL(outmatrix, blendtag);
}
if(!mod_alias_supporttagscale.integer)
return 0;
}
-int Mod_Alias_GetExtendedTagInfoForIndex(const dp_model_t *model, unsigned int skin, int poseframe, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
+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)
{
- const float *boneframe;
-
- if(skin >= (unsigned int)model->numskins)
- skin = 0;
+ int blendindex;
+ int k;
+ float lerp;
+ matrix4x4_t bonematrix;
+ matrix4x4_t blendmatrix;
+ const float *input;
+ float blendtag[12];
- if (model->num_bones)
+ if (skeleton && skeleton->relativetransforms)
{
- if(tagindex >= model->num_bones || tagindex < 0)
+ if (tagindex < 0 || tagindex >= skeleton->model->num_bones)
+ return 1;
+ *parentindex = skeleton->model->data_bones[tagindex].parent;
+ *tagname = skeleton->model->data_bones[tagindex].name;
+ *tag_localmatrix = skeleton->relativetransforms[tagindex];
+ return 0;
+ }
+ else if (model->num_bones)
+ {
+ if (tagindex < 0 || tagindex >= model->num_bones)
return 1;
- if (poseframe >= model->num_poses)
- return 2;
-
- boneframe = model->data_poses + poseframe * model->num_bones * 12;
*parentindex = model->data_bones[tagindex].parent;
*tagname = model->data_bones[tagindex].name;
- Matrix4x4_FromArray12FloatD3D(tag_localmatrix, boneframe + tagindex * 12);
+ Matrix4x4_Clear(&blendmatrix);
+ for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
+ {
+ lerp = frameblend[blendindex].lerp;
+ Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
+ Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
+ }
+ *tag_localmatrix = blendmatrix;
return 0;
}
-
- if (model->num_tags)
+ else if (model->num_tags)
{
- if(tagindex >= model->num_tags || tagindex < 0)
+ if (tagindex < 0 || tagindex >= model->num_tags)
return 1;
- if (poseframe >= model->num_tagframes)
- return 2;
+ *parentindex = -1;
*tagname = model->data_tags[tagindex].name;
- Matrix4x4_FromArray12FloatGL(tag_localmatrix, model->data_tags[poseframe * model->num_tags + tagindex].matrixgl);
+ for (k = 0;k < 12;k++)
+ blendtag[k] = 0;
+ for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
+ {
+ lerp = frameblend[blendindex].lerp;
+ input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl;
+ for (k = 0;k < 12;k++)
+ blendtag[k] += input[k] * lerp;
+ }
+ Matrix4x4_FromArray12FloatGL(tag_localmatrix, blendtag);
return 0;
}
static void Mod_BuildBaseBonePoses(void)
{
- int i, k;
- double scale;
- float *basebonepose;
- float *in12f = loadmodel->data_poses;
- float *out12f;
- float *outinv12f = loadmodel->data_baseboneposeinverse;
+ int boneindex;
+ matrix4x4_t *basebonepose;
+ float *outinvmatrix = loadmodel->data_baseboneposeinverse;
+ matrix4x4_t bonematrix;
+ matrix4x4_t tempbonematrix;
if (!loadmodel->num_bones)
return;
- out12f = basebonepose = (float *) Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(float[12]));
- for (i = 0;i < loadmodel->num_bones;i++, in12f += 12, out12f += 12, outinv12f += 12)
+ basebonepose = (matrix4x4_t *)Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(matrix4x4_t));
+ for (boneindex = 0;boneindex < loadmodel->num_bones;boneindex++)
{
- if (loadmodel->data_bones[i].parent >= 0)
- R_ConcatTransforms(basebonepose + 12 * loadmodel->data_bones[i].parent, in12f, out12f);
- else
- for (k = 0;k < 12;k++)
- out12f[k] = in12f[k];
-
- // invert The Matrix
-
- // we only support uniform scaling, so assume the first row is enough
- // (note the lack of sqrt here, because we're trying to undo the scaling,
- // this means multiplying by the inverse scale twice - squaring it, which
- // makes the sqrt a waste of time)
- scale = 1.0 / (out12f[ 0] * out12f[ 0] + out12f[ 1] * out12f[ 1] + out12f[ 2] * out12f[ 2]);
-
- // invert the rotation by transposing and multiplying by the squared
- // recipricol of the input matrix scale as described above
- outinv12f[ 0] = (float)(out12f[ 0] * scale);
- outinv12f[ 1] = (float)(out12f[ 4] * scale);
- outinv12f[ 2] = (float)(out12f[ 8] * scale);
- outinv12f[ 4] = (float)(out12f[ 1] * scale);
- outinv12f[ 5] = (float)(out12f[ 5] * scale);
- outinv12f[ 6] = (float)(out12f[ 9] * scale);
- outinv12f[ 8] = (float)(out12f[ 2] * scale);
- outinv12f[ 9] = (float)(out12f[ 6] * scale);
- outinv12f[10] = (float)(out12f[10] * scale);
-
- // invert the translate
- outinv12f[ 3] = -(out12f[ 3] * outinv12f[ 0] + out12f[ 7] * outinv12f[ 1] + out12f[11] * outinv12f[ 2]);
- outinv12f[ 7] = -(out12f[ 3] * outinv12f[ 4] + out12f[ 7] * outinv12f[ 5] + out12f[11] * outinv12f[ 6]);
- outinv12f[11] = -(out12f[ 3] * outinv12f[ 8] + out12f[ 7] * outinv12f[ 9] + out12f[11] * outinv12f[10]);
+ Matrix4x4_FromBonePose6s(&bonematrix, loadmodel->num_posescale, loadmodel->data_poses6s + 6 * boneindex);
+ if (loadmodel->data_bones[boneindex].parent >= 0)
+ {
+ tempbonematrix = bonematrix;
+ Matrix4x4_Concat(&bonematrix, basebonepose + loadmodel->data_bones[boneindex].parent, &tempbonematrix);
+ }
+ basebonepose[boneindex] = bonematrix;
+ Matrix4x4_Invert_Simple(&tempbonematrix, basebonepose + boneindex);
+ Matrix4x4_ToArray12FloatD3D(&tempbonematrix, outinvmatrix + 12*boneindex);
}
Mem_Free(basebonepose);
}
radius = 0;
for (frameblend[0].subframe = 0;frameblend[0].subframe < loadmodel->num_poses;frameblend[0].subframe++)
{
- loadmodel->AnimateVertices(loadmodel, frameblend, vertex3f, NULL, NULL, NULL);
+ loadmodel->AnimateVertices(loadmodel, frameblend, NULL, vertex3f, NULL, NULL, NULL);
for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
{
if (firstvertex)
for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
{
frameblend[0].subframe = i;
- loadmodel->AnimateVertices(loadmodel, frameblend, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
+ loadmodel->AnimateVertices(loadmodel, frameblend, NULL, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
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);
// encode the svector and tvector in 3 byte format for permanent storage
for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
}
}
-static void Mod_MDLMD2MD3_TraceLine(dp_model_t *model, int frame, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask)
+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)
{
int i;
float segmentmins[3], segmentmaxs[3];
- frameblend_t frameblend[MAX_FRAMEBLENDS];
msurface_t *surface;
static int maxvertices = 0;
static float *vertex3f = NULL;
trace->fraction = 1;
trace->realfraction = 1;
trace->hitsupercontentsmask = hitsupercontentsmask;
- memset(frameblend, 0, sizeof(frameblend));
- frameblend[0].subframe = frame;
- frameblend[0].lerp = 1;
if (maxvertices < model->surfmesh.num_vertices)
{
if (vertex3f)
segmentmaxs[0] = max(start[0], end[0]) + 1;
segmentmaxs[1] = max(start[1], end[1]) + 1;
segmentmaxs[2] = max(start[2], end[2]) + 1;
+ model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
- {
- model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL);
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);
- }
}
-static void Mod_MDLMD2MD3_TraceBox(dp_model_t *model, int frame, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask)
+static int maxvertices = 0;
+static float *vertex3f = NULL;
+
+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)
{
int i;
vec3_t shiftstart, shiftend;
float segmentmins[3], segmentmaxs[3];
- frameblend_t frameblend[MAX_FRAMEBLENDS];
msurface_t *surface;
- static int maxvertices = 0;
- static float *vertex3f = NULL;
- colbrushf_t *thisbrush_start, *thisbrush_end;
+ colboxbrushf_t thisbrush_start, thisbrush_end;
vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
if (VectorCompare(boxmins, boxmaxs))
{
VectorAdd(start, boxmins, shiftstart);
VectorAdd(end, boxmins, shiftend);
- Mod_MDLMD2MD3_TraceLine(model, frame, trace, start, end, hitsupercontentsmask);
+ Mod_MDLMD2MD3_TraceLine(model, frameblend, skeleton, trace, start, end, hitsupercontentsmask);
VectorSubtract(trace->endpos, boxmins, trace->endpos);
return;
}
trace->fraction = 1;
trace->realfraction = 1;
trace->hitsupercontentsmask = hitsupercontentsmask;
- memset(frameblend, 0, sizeof(frameblend));
- frameblend[0].subframe = frame;
- frameblend[0].lerp = 1;
if (maxvertices < model->surfmesh.num_vertices)
{
if (vertex3f)
VectorAdd(start, boxmaxs, boxstartmaxs);
VectorAdd(end, boxmins, boxendmins);
VectorAdd(end, boxmaxs, boxendmaxs);
- thisbrush_start = Collision_BrushForBox(boxstartmins, boxstartmaxs, 0, 0, NULL);
- thisbrush_end = Collision_BrushForBox(boxendmins, boxendmaxs, 0, 0, NULL);
- for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
+ Collision_BrushForBox(&thisbrush_start, boxstartmins, boxstartmaxs, 0, 0, NULL);
+ Collision_BrushForBox(&thisbrush_end, boxendmins, boxendmaxs, 0, 0, NULL);
+ if (maxvertices < model->surfmesh.num_vertices)
{
- if (maxvertices < model->surfmesh.num_vertices)
- {
- if (vertex3f)
- Z_Free(vertex3f);
- maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
- vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
- }
- model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL);
- Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_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);
+ if (vertex3f)
+ Z_Free(vertex3f);
+ maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
+ vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
}
+ model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
+ for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
+ 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);
}
static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
//texture->textureflags = 0;
texture->basematerialflags = MATERIALFLAG_WALL;
- if (texture->currentskinframe->fog)
+ if (texture->currentskinframe->hasalpha)
texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
texture->currentmaterialflags = texture->basematerialflags;
+ texture->specularscalemod = 1;
+ texture->specularpowermod = 1;
}
-static void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
+void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
{
int i;
skinfileitem_t *skinfileitem;
// leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw"
if (!strcmp(skinfileitem->name, meshname))
{
- Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
+ Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
break;
}
}
}
}
else
- Mod_LoadTextureFromQ3Shader(skin, shadername, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
+ Mod_LoadTextureFromQ3Shader(skin, shadername, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
}
#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);
loadmodel->Draw = R_Q1BSP_Draw;
loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
+ loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
loadmodel->Draw = R_Q1BSP_Draw;
loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
+ loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
loadmodel->num_texturesperskin = loadmodel->num_surfaces;
loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
- Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
+ Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS);
}
else
{
loadmodel->Draw = R_Q1BSP_Draw;
loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
+ loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
zymtype1header_t *pinmodel, *pheader;
unsigned char *pbase;
int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements;
- float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose;
+ float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose, f, biggestorigin, tempvec[3], modelscale;
zymvertex_t *verts, *vertdata;
zymscene_t *scene;
zymbone_t *bone;
loadmodel->Draw = R_Q1BSP_Draw;
loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
+ loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
loadmodel->num_texturesperskin = loadmodel->num_surfaces;
- 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(float[12]) + loadmodel->num_bones * sizeof(float[12]));
+ 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]));
loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
- loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
if (loadmodel->surfmesh.num_vertices <= 65536)
loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
+ loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
//zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
poses = (float *) (pheader->lump_poses.start + pbase);
- for (i = 0;i < pheader->lump_poses.length / 4;i++)
- loadmodel->data_poses[i] = BigFloat(poses[i]);
+ // figure out scale of model from root bone, for compatibility with old zmodel versions
+ tempvec[0] = BigFloat(poses[0]);
+ tempvec[1] = BigFloat(poses[1]);
+ tempvec[2] = BigFloat(poses[2]);
+ modelscale = VectorLength(tempvec);
+ biggestorigin = 0;
+ for (i = 0;i < loadmodel->num_bones * numposes * 12;i++)
+ {
+ f = fabs(BigFloat(poses[i]));
+ biggestorigin = max(biggestorigin, f);
+ }
+ loadmodel->num_posescale = biggestorigin / 32767.0f;
+ loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
+ for (i = 0;i < numposes;i++)
+ {
+ const float *frameposes = (float *) (pheader->lump_poses.start + pbase) + 12*i*loadmodel->num_bones;
+ for (j = 0;j < loadmodel->num_bones;j++)
+ {
+ float pose[12];
+ matrix4x4_t posematrix;
+ for (k = 0;k < 12;k++)
+ pose[k] = BigFloat(frameposes[j*12+k]);
+ //if (j < loadmodel->num_bones)
+ // 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));
+ // scale child bones to match the root scale
+ if (loadmodel->data_bones[j].parent >= 0)
+ {
+ pose[3] *= modelscale;
+ pose[7] *= modelscale;
+ pose[11] *= modelscale;
+ }
+ // normalize rotation matrix
+ VectorNormalize(pose + 0);
+ VectorNormalize(pose + 4);
+ VectorNormalize(pose + 8);
+ Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
+ Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
+ }
+ }
//zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
for (i = 0;i < loadmodel->num_bones;i++)
{
- const float *m = loadmodel->data_poses + i * 12;
+ float m[12];
+ for (k = 0;k < 12;k++)
+ m[k] = BigFloat(poses[i*12+k]);
if (loadmodel->data_bones[i].parent >= 0)
R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
else
void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
{
dpmheader_t *pheader;
- dpmframe_t *frame;
+ dpmframe_t *frames;
dpmbone_t *bone;
dpmmesh_t *dpmmesh;
unsigned char *pbase;
skinfile_t *skinfiles;
unsigned char *data;
float *bonepose;
+ float biggestorigin, tempvec[3], modelscale;
+ float f;
+ float *poses;
pheader = (dpmheader_t *)buffer;
pbase = (unsigned char *)buffer;
loadmodel->Draw = R_Q1BSP_Draw;
loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
+ loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
loadmodel->num_texturesperskin = loadmodel->num_surfaces;
// do most allocations as one merged chunk
- 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(float[12]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
+ 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));
loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
- loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
if (meshvertices <= 65536)
loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
+ loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
for (i = 0;i < loadmodel->numskins;i++)
{
}
// load the frames
- frame = (dpmframe_t *) (pbase + pheader->ofs_frames);
+ frames = (dpmframe_t *) (pbase + pheader->ofs_frames);
+ // figure out scale of model from root bone, for compatibility with old dpmodel versions
+ poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
+ tempvec[0] = BigFloat(poses[0]);
+ tempvec[1] = BigFloat(poses[1]);
+ tempvec[2] = BigFloat(poses[2]);
+ modelscale = VectorLength(tempvec);
+ biggestorigin = 0;
for (i = 0;i < loadmodel->numframes;i++)
{
- const float *poses;
- memcpy(loadmodel->animscenes[i].name, frame->name, sizeof(frame->name));
+ memcpy(loadmodel->animscenes[i].name, frames[i].name, sizeof(frames[i].name));
loadmodel->animscenes[i].firstframe = i;
loadmodel->animscenes[i].framecount = 1;
loadmodel->animscenes[i].loop = true;
loadmodel->animscenes[i].framerate = 10;
// load the bone poses for this frame
- poses = (float *) (pbase + BigLong(frame->ofs_bonepositions));
+ poses = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
for (j = 0;j < loadmodel->num_bones*12;j++)
- loadmodel->data_poses[i * loadmodel->num_bones*12 + j] = BigFloat(poses[j]);
+ {
+ f = fabs(BigFloat(poses[j]));
+ biggestorigin = max(biggestorigin, f);
+ }
// stuff not processed here: mins, maxs, yawradius, allradius
- frame++;
+ }
+ loadmodel->num_posescale = biggestorigin / 32767.0f;
+ loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
+ for (i = 0;i < loadmodel->numframes;i++)
+ {
+ const float *frameposes = (float *) (pbase + BigLong(frames[i].ofs_bonepositions));
+ for (j = 0;j < loadmodel->num_bones;j++)
+ {
+ float pose[12];
+ matrix4x4_t posematrix;
+ for (k = 0;k < 12;k++)
+ pose[k] = BigFloat(frameposes[j*12+k]);
+ // scale child bones to match the root scale
+ if (loadmodel->data_bones[j].parent >= 0)
+ {
+ pose[3] *= modelscale;
+ pose[7] *= modelscale;
+ pose[11] *= modelscale;
+ }
+ // normalize rotation matrix
+ VectorNormalize(pose + 0);
+ VectorNormalize(pose + 4);
+ VectorNormalize(pose + 8);
+ Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
+ Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
+ }
}
// load the meshes now
// reconstruct frame 0 matrices to allow reconstruction of the base mesh
// (converting from weight-blending skeletal animation to
// deformation-based skeletal animation)
+ poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions));
bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
for (i = 0;i < loadmodel->num_bones;i++)
{
- const float *m = loadmodel->data_poses + i * 12;
+ float m[12];
+ for (k = 0;k < 12;k++)
+ m[k] = BigFloat(poses[i*12+k]);
if (loadmodel->data_bones[i].parent >= 0)
R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
else
skinfile_t *skinfiles;
char animname[MAX_QPATH];
size_t size;
+ float biggestorigin;
pchunk = (pskchunk_t *)buffer;
if (strcmp(pchunk->id, "ACTRHEAD"))
loadmodel->Draw = R_Q1BSP_Draw;
loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
+ loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass;
loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap;
loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
version = LittleLong(pchunk->version);
recordsize = LittleLong(pchunk->recordsize);
numrecords = LittleLong(pchunk->numrecords);
- if (developer.integer >= 100)
- Con_Printf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
+ if (developer_extra.integer)
+ Con_DPrintf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
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);
if (!strcmp(pchunk->id, "ACTRHEAD"))
version = LittleLong(pchunk->version);
recordsize = LittleLong(pchunk->recordsize);
numrecords = LittleLong(pchunk->numrecords);
- if (developer.integer >= 100)
- Con_Printf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
+ if (developer_extra.integer)
+ Con_DPrintf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords);
if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0)
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);
if (!strcmp(pchunk->id, "ANIMHEAD"))
loadmodel->surfmesh.num_vertices = meshvertices;
loadmodel->surfmesh.num_triangles = meshtriangles;
// do most allocations as one merged chunk
- 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(float[12]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t) + ((loadmodel->surfmesh.num_vertices <= 65536) ? (loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3])) : 0);
+ 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);
data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += loadmodel->surfmesh.num_vertices * sizeof(int[4]);
loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[4]);
- loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
if (loadmodel->surfmesh.num_vertices <= 65536)
loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
+ loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
for (i = 0;i < loadmodel->numskins;i++)
{
}
}
+ // calculate the scaling value for bone origins so they can be compressed to short
+ biggestorigin = 0;
+ for (index = 0;index < numanimkeys;index++)
+ {
+ pskanimkeys_t *k = animkeys + index;
+ biggestorigin = max(biggestorigin, fabs(k->origin[0]));
+ biggestorigin = max(biggestorigin, fabs(k->origin[1]));
+ biggestorigin = max(biggestorigin, fabs(k->origin[2]));
+ }
+ loadmodel->num_posescale = biggestorigin / 32767.0f;
+ loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
+
// load the poses from the animkeys
for (index = 0;index < numanimkeys;index++)
{
pskanimkeys_t *k = animkeys + index;
- matrix4x4_t matrix;
- Matrix4x4_FromOriginQuat(&matrix, k->origin[0], k->origin[1], k->origin[2], k->quat[0], k->quat[1], k->quat[2], k->quat[3]);
- Matrix4x4_ToArray12FloatD3D(&matrix, loadmodel->data_poses + index*12);
+ float quat[4];
+ Vector4Copy(k->quat, quat);
+ if (quat[3] > 0)
+ Vector4Negate(quat, quat);
+ Vector4Normalize2(quat, quat);
+ // compress poses to the short[6] format for longterm storage
+ loadmodel->data_poses6s[index*6+0] = k->origin[0] * loadmodel->num_poseinvscale;
+ loadmodel->data_poses6s[index*6+1] = k->origin[1] * loadmodel->num_poseinvscale;
+ loadmodel->data_poses6s[index*6+2] = k->origin[2] * loadmodel->num_poseinvscale;
+ loadmodel->data_poses6s[index*6+3] = quat[0] * 32767.0f;
+ loadmodel->data_poses6s[index*6+4] = quat[1] * 32767.0f;
+ loadmodel->data_poses6s[index*6+5] = quat[2] * 32767.0f;
}
Mod_FreeSkinFiles(skinfiles);
Mem_Free(animfilebuffer);