try to lerp angles properly.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5028 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2016-12-05 13:35:10 +00:00
parent 732a89f7c1
commit 4925e5f842

View file

@ -248,79 +248,49 @@ int HLMod_BoneForName(model_t *mod, char *name)
=======================================================================================================================
HL_CalculateBones - calculate bone positions - quaternion+vector in one function
=======================================================================================================================
note, while ender may be proud of this function, it lacks the fact that interpolating eular angles is not as acurate as interpolating quaternions.
it is faster though.
*/
void HL_CalculateBones
(
int offset,
int frame1,
int frame2,
float lerpfrac,
int frame,
vec4_t adjust,
hlmdl_bone_t *bone,
hlmdl_anim_t *animation,
float *destination
float *organg
)
{
/*~~~~~~~~~~*/
int i;
vec3_t angle;
float lerpifrac = 1-lerpfrac;
/*~~~~~~~~~~*/
/* For each vector */
for(i = 0; i < 3; i++)
for(i = 0; i < 6; i++)
{
/*~~~~~~~~~~~~~~~*/
int o = i + offset; /* Take the value offset - allows quaternion & vector in one function */
/*~~~~~~~~~~~~~~~*/
organg[i] = bone->value[i]; /* Take the bone value */
angle[i] = bone->value[o]; /* Take the bone value */
if(animation->offset[o] != 0)
if(animation->offset[i] != 0)
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
int tempframe;
hlmdl_animvalue_t *animvalue = (hlmdl_animvalue_t *) ((qbyte *) animation + animation->offset[o]);
short f1, f2;
hlmdl_animvalue_t *animvalue = (hlmdl_animvalue_t *) ((qbyte *) animation + animation->offset[i]);
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/* find values including the required frame */
tempframe = frame1;
tempframe = frame;
while(animvalue->num.total <= tempframe)
{
tempframe -= animvalue->num.total;
animvalue += animvalue->num.valid + 1;
}
f1 = animvalue[min(animvalue->num.valid-1, tempframe)+1].value;
/* frame2 is always higher than frame1, so keep searching for it, if its in a different block */
tempframe += frame2-frame1;
while(animvalue->num.total <= tempframe)
{
tempframe -= animvalue->num.total;
animvalue += animvalue->num.valid + 1;
}
f2 = animvalue[min(animvalue->num.valid-1, tempframe)+1].value;
angle[i] += (f1 * lerpifrac + lerpfrac * f2) * bone->scale[o];
}
if(bone->bonecontroller[o] != -1)
{ /* Add the programmable offset. */
angle[i] += adjust[bone->bonecontroller[o]];
}
}
if(offset < 3)
{
VectorCopy(angle, destination); /* Just a standard vector */
}
if (tempframe >= animvalue->num.valid)
tempframe = animvalue->num.valid;
else
{
QuaternionGLAngle(angle, destination); /* A quaternion */
tempframe += 1;
organg[i] += animvalue[tempframe].value * bone->scale[i];
}
if(bone->bonecontroller[i] != -1)
{ /* Add the programmable offset. */
organg[i] += adjust[bone->bonecontroller[i]];
}
}
}
@ -377,8 +347,10 @@ void HL_SetupBones(hlmodel_t *model, int seqnum, int firstbone, int lastbone, fl
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
int i;
float matrix[3][4];
static vec3_t positions[2];
static vec4_t quaternions[2], blended;
vec3_t organg1[2];
vec3_t organg2[2];
vec3_t organgb[2];
vec4_t quat1, quat2, quatb;
int frame1, frame2;
@ -490,16 +462,35 @@ void HL_SetupBones(hlmodel_t *model, int seqnum, int firstbone, int lastbone, fl
subblendfrac = 1;
for(i = firstbone; i < lastbone; i++)
{
HL_CalculateBones(0, frame1, frame2, frametime, model->adjust, model->bones + i, animation + i, positions[0]);
HL_CalculateBones(3, frame1, frame2, frametime, model->adjust, model->bones + i, animation + i, quaternions[0]);
//calc first blend (writes organgb+quatb)
HL_CalculateBones(frame1, model->adjust, model->bones + i, animation + i, organgb[0]);
QuaternionGLAngle(organgb[1], quatb); /* A quaternion */
if (frame1 != frame2)
{
HL_CalculateBones(frame2, model->adjust, model->bones + i, animation + i, organg2[0]);
QuaternionGLAngle(organg2[1], quat2); /* A quaternion */
HL_CalculateBones(3, frame1, frame2, frametime, model->adjust, model->bones + i, animation + i + model->header->numbones, quaternions[1]);
QuaternionSlerp(quatb, quat2, frametime, quatb);
VectorInterpolate(organgb[0], frametime, organg2[0], organgb[0]);
}
QuaternionSlerp(quaternions[0], quaternions[1], subblendfrac, blended);
QuaternionGLMatrix(blended[0], blended[1], blended[2], blended[3], matrix);
matrix[0][3] = positions[0][0];
matrix[1][3] = positions[0][1];
matrix[2][3] = positions[0][2];
//calc first blend (writes organg1+quat1)
HL_CalculateBones(frame1, model->adjust, model->bones + i, animation + i + model->header->numbones, organg1[0]);
QuaternionGLAngle(organg1[1], quat1); /* A quaternion */
if (frame1 != frame2)
{
HL_CalculateBones(frame2, model->adjust, model->bones + i, animation + i + model->header->numbones, organg2[0]);
QuaternionGLAngle(organg2[1], quat2); /* A quaternion */
QuaternionSlerp(quat1, quat2, frametime, quat1);
VectorInterpolate(organg1[0], frametime, organg2[0], organg1[0]);
}
//blend the two
QuaternionSlerp(quatb, quat1, subblendfrac, quat1);
FloatInterpolate(organgb[0][0], subblendfrac, organg1[0][0], matrix[0][3]);
FloatInterpolate(organgb[0][0], subblendfrac, organg1[0][1], matrix[1][3]);
FloatInterpolate(organgb[0][0], subblendfrac, organg1[0][2], matrix[2][3]);
/* If we have a parent, take the addition. Otherwise just copy the values */
if(model->bones[i].parent>=0)
@ -511,25 +502,28 @@ void HL_SetupBones(hlmodel_t *model, int seqnum, int firstbone, int lastbone, fl
memcpy(transform_matrix[i], matrix, 12 * sizeof(float));
}
}
}
else
{
for(i = firstbone; i < lastbone; i++)
{
/*
* There are two vector offsets in the structure. The first seems to be the
* positions of the bones, the second the quats of the bone matrix itself. We
* convert it inside the routine - Inconsistant, but hey.. so's the whole model
* format.
*/
HL_CalculateBones(0, frame1, frame2, frametime, model->adjust, model->bones + i, animation + i, positions[0]);
HL_CalculateBones(3, frame1, frame2, frametime, model->adjust, model->bones + i, animation + i, quaternions[0]);
HL_CalculateBones(frame1, model->adjust, model->bones + i, animation + i, organg1[0]);
QuaternionGLAngle(organg1[1], quat1); /* A quaternion */
if (frame1 != frame2)
{
HL_CalculateBones(frame2, model->adjust, model->bones + i, animation + i, organg2[0]);
QuaternionGLAngle(organg2[1], quat2); /* A quaternion */
QuaternionGLMatrix(quaternions[0][0], quaternions[0][1], quaternions[0][2], quaternions[0][3], matrix);
matrix[0][3] = positions[0][0];
matrix[1][3] = positions[0][1];
matrix[2][3] = positions[0][2];
//lerp the quats properly rather than poorly lerping eular angles.
QuaternionSlerp(quat1, quat2, frametime, quat1);
VectorInterpolate(organg1[0], frametime, organg2[0], organg1[0]);
}
//we probably ought to keep them as quats or something.
QuaternionGLMatrix(quat1[0], quat1[1], quat1[2], quat1[3], matrix);
matrix[0][3] = organg1[0][0];
matrix[1][3] = organg1[0][1];
matrix[2][3] = organg1[0][2];
/* If we have a parent, take the addition. Otherwise just copy the values */
if(model->bones[i].parent>=0)
@ -649,6 +643,7 @@ void R_HL_BuildFrame(hlmodel_t *model, hlmdl_model_t *amodel, entity_t *curent,
st[vert][0] = order[2] * tex_s;
st[vert][1] = order[3] * tex_t;
/*fixme: build vertex normals in the base pose and transform them using the same bone matricies (just discard the origin part)*/
norm[vert][0] = 1;
norm[vert][1] = 1;
norm[vert][2] = 1;