1 .float skeleton_modelindex;
2 #define BONETYPE_LOWER 0
3 #define BONETYPE_UPPER 1
5 .float skeleton_bonetype[MAX_BONES];
6 .float skeleton_fixrotatebone;
7 .float skeleton_fixtargetbone;
9 .float skeleton_aimbone;
10 .float skeleton_numbones;
12 void skeleton_identifybones(entity e)
14 float s = e.skeletonindex;
15 float n = (e.skeleton_numbones = skel_get_numbones(s));
16 e.skeleton_aimbone = 0;
17 e.skeleton_fixrotatebone = 0;
18 e.skeleton_fixtargetbone = 0;
20 for(i = 1; i <= n; ++i)
22 float t = BONETYPE_LOWER;
23 float p = skel_get_boneparent(s, i);
25 t = e.(skeleton_bonetype[p-1]);
26 string nm = skel_get_bonename(s, i);
29 e.skeleton_fixrotatebone = i;
32 if(nm == "weapon" || nm == "tag_weapon" || nm == "bip01 r hand")
33 if(t == BONETYPE_UPPER)
34 e.skeleton_fixtargetbone = i;
35 if(nm == "upperarm_R")
36 e.skeleton_aimbone = i;
37 e.(skeleton_bonetype[i-1]) = t;
41 void skel_set_bone_lerp(float skel, float bone, vector org, float strength)
44 return skel_set_bone(skel, bone, org);
46 vector fo = v_forward;
49 vector oldorg = skel_get_bonerel(skel, bone);
51 org = org * strength + oldorg * (1 - strength);
52 v_forward = fo * strength + v_forward * (1 - strength);
53 v_right = ri * strength + v_right * (1 - strength);
54 v_up = up * strength + v_up * (1 - strength);
55 return skel_set_bone(skel, bone, org);
58 void skeleton_fixbone(entity e, float strength, float yawonly)
60 if(!e.skeleton_fixrotatebone)
65 // T = M_before_fixrotate * M_fixrotate * M_after_fixrotate
66 // T' = M_before_fixrotate^-1 * M_fixrotate' * M_after_fixrotate
67 // M_fixrotate' = M_before_fixrotate^-1 * T' * M_after_fixrotate^-1
68 float s = e.skeletonindex;
70 skel_get_boneabs(s, skel_get_boneparent(s, e.skeleton_fixrotatebone));
71 vector M_before_fixrotate = fixedvectoangles2(v_forward, v_up);
72 skel_get_boneabs(s, e.skeleton_fixrotatebone);
73 vector M_including_fixrotate = fixedvectoangles2(v_forward, v_up);
74 skel_get_boneabs(s, e.skeleton_fixtargetbone);
75 vector T = fixedvectoangles2(v_forward, v_up);
76 vector M_after_fixrotate = AnglesTransform_LeftDivide(M_including_fixrotate, T);
81 T_ = '0 0 0'; // undo all
82 vector M_fixrotate_ = AnglesTransform_LeftDivide(M_before_fixrotate, AnglesTransform_RightDivide(T_, M_after_fixrotate));
83 vector org = skel_get_bonerel(s, e.skeleton_fixrotatebone);
84 fixedmakevectors(M_fixrotate_);
85 skel_set_bone_lerp(s, e.skeleton_fixrotatebone, org, strength);
88 void free_skeleton_from_frames(entity e)
92 skel_delete(e.skeletonindex);
97 void skeleton_from_frames(entity e)
99 float m = e.modelindex;
100 if(m != e.skeleton_modelindex)
104 skel_delete(e.skeletonindex);
107 m = (e.skeleton_modelindex = e.modelindex);
110 e.skeletonindex = skel_create(m);
111 skeleton_identifybones(e);
114 float s = e.skeletonindex;
118 float n = e.skeleton_numbones;
119 float savelerpfrac = e.lerpfrac;
120 float savelerpfrac3 = e.lerpfrac3;
121 float savelerpfrac4 = e.lerpfrac4;
122 for(bone = 0; bone < n; )
124 float firstbone = bone;
125 float bonetype = e.skeleton_bonetype[bone];
126 for(++bone; (bone < n) && (e.skeleton_bonetype[bone] == bonetype); ++bone)
128 if(bonetype == BONETYPE_UPPER)
130 // only show frames 1+3 (upper body)
132 e.lerpfrac3 = savelerpfrac3 * 2;
137 // only show frames 2+4 (lower body)
138 e.lerpfrac = savelerpfrac * 2;
140 e.lerpfrac4 = savelerpfrac4 * 2;
142 //print(sprintf("Run: bone %d to %d, type %d\n", firstbone + 1, bone, bonetype));
143 //print(sprintf("frame %d %d %d %d lerpfrac * %d %d %d\n", e.frame, e.frame2, e.frame3, e.frame4, e.lerpfrac, e.lerpfrac3, e.lerpfrac4));
144 skel_build(s, e, m, 0, firstbone + 1, bone);
146 e.lerpfrac = savelerpfrac;
147 e.lerpfrac3 = savelerpfrac3;
148 e.lerpfrac4 = savelerpfrac4;
150 if(autocvar__animblend_fixbone)
152 float l4 = e.lerpfrac4;
153 float l3 = e.lerpfrac3;
154 float l2 = e.lerpfrac;
155 float l1 = 1 - l2 - l3 - l4;
157 // how much of upper body animates same way as lower body?
159 (e.frame == e.frame2) * (l1 * l2) +
160 (e.frame == e.frame4) * (l1 * l4) +
161 (e.frame3 == e.frame2) * (l3 * l2) +
162 (e.frame3 == e.frame4) * (l3 * l4);
163 float maxequalamount = (l1 + l3) * (l2 + l4);
165 // now how strong is the lerp?
166 float lerpstrength = 1 - equalamount / maxequalamount;
169 skeleton_fixbone(e, lerpstrength, autocvar__animblend_fixbone >= 2);