#define BONETYPE_UPPER 1
#define MAX_BONES 128
.float skeleton_bonetype[MAX_BONES];
+.float skeleton_fixrotatebone;
+.float skeleton_fixtargetbone;
+.float skeleton_bone;
.float skeleton_aimbone;
.float skeleton_numbones;
float s = e.skeletonindex;
float n = (e.skeleton_numbones = skel_get_numbones(s));
e.skeleton_aimbone = 0;
+ e.skeleton_fixrotatebone = 0;
+ e.skeleton_fixtargetbone = 0;
float i;
for(i = 1; i <= n; ++i)
{
t = e.(skeleton_bonetype[p-1]);
string nm = skel_get_bonename(s, i);
if(nm == "spine2")
+ {
+ e.skeleton_fixrotatebone = i;
t = BONETYPE_UPPER;
+ }
+ if(nm == "weapon" || nm == "tag_weapon" || nm == "bip01 r hand")
+ if(t == BONETYPE_UPPER)
+ e.skeleton_fixtargetbone = i;
if(nm == "upperarm_R")
e.skeleton_aimbone = i;
e.(skeleton_bonetype[i-1]) = t;
}
}
+void skel_set_bone_lerp(float skel, float bone, vector org, float strength)
+{
+ if(strength >= 1)
+ return skel_set_bone(skel, bone, org);
+
+ vector fo = v_forward;
+ vector ri = v_right;
+ vector up = v_up;
+ vector oldorg = skel_get_bonerel(skel, bone);
+
+ org = org * strength + oldorg * (1 - strength);
+ v_forward = fo * strength + v_forward * (1 - strength);
+ v_right = ri * strength + v_right * (1 - strength);
+ v_up = up * strength + v_up * (1 - strength);
+ return skel_set_bone(skel, bone, org);
+}
+
+void skeleton_fixbone(entity e, float strength)
+{
+ if(!e.skeleton_fixrotatebone)
+ return;
+ if(strength <= 0)
+ return;
+ // model:
+ // T = M_before_fixrotate * M_fixrotate * M_after_fixrotate
+ // T' = M_before_fixrotate^-1 * M_fixrotate' * M_after_fixrotate
+ // M_fixrotate' = M_before_fixrotate^-1 * T' * M_after_fixrotate^-1
+ float s = e.skeletonindex;
+
+ skel_get_boneabs(s, skel_get_boneparent(s, e.skeleton_fixrotatebone));
+ vector M_before_fixrotate = fixedvectoangles2(v_forward, v_up);
+ skel_get_boneabs(s, e.skeleton_fixrotatebone);
+ vector M_including_fixrotate = fixedvectoangles2(v_forward, v_up);
+ skel_get_boneabs(s, e.skeleton_fixtargetbone);
+ vector T = fixedvectoangles2(v_forward, v_up);
+ vector M_after_fixrotate = AnglesTransform_LeftDivide(M_including_fixrotate, T);
+ vector T_ = '0 0 0';
+ vector M_fixrotate_ = AnglesTransform_LeftDivide(M_before_fixrotate, AnglesTransform_RightDivide(T_, M_after_fixrotate));
+ vector org = skel_get_bonerel(s, e.skeleton_fixrotatebone);
+ fixedmakevectors(M_fixrotate_);
+ skel_set_bone_lerp(s, e.skeleton_fixrotatebone, org, strength);
+}
+
void free_skeleton_from_frames(entity e)
{
if(e.skeletonindex)
skel_build(s, e, m, 0, firstbone + 1, bone);
}
e.lerpfrac = savelerpfrac;
- e.lerpfrac3 = savelerpfrac;
- e.lerpfrac4 = savelerpfrac;
+ e.lerpfrac3 = savelerpfrac3;
+ e.lerpfrac4 = savelerpfrac4;
+
+ if(autocvar__animblend_fixbone)
+ {
+ float l4 = e.lerpfrac4;
+ float l3 = e.lerpfrac3;
+ float l2 = e.lerpfrac;
+ float l1 = 1 - l2 - l3 - l4;
+
+ // how much of upper body animates same way as lower body?
+ float equalamount =
+ (e.frame == e.frame2) * (l1 * l2) +
+ (e.frame == e.frame4) * (l1 * l4) +
+ (e.frame3 == e.frame2) * (l3 * l2) +
+ (e.frame3 == e.frame4) * (l3 * l4);
+ float maxequalamount = (l1 + l3) * (l2 + l4);
+
+ // now how strong is the lerp?
+ float lerpstrength = 1 - equalamount / maxequalamount;
+
+ // FIX IT
+ skeleton_fixbone(e, lerpstrength);
+ }
}