インバース・キネマティクス
Sample:atan2/PI/cos/length/radiansToDegrees/clamp/座標変換
アーム2本のIK
- 図のようなオレンジとグリーンのアームをnullでコントロールするIK(Inverse Kinematiks)です。
Setup
- アームaのアンカーポイントを[A]に移動
- アームbのアンカーポイントを[B]に移動
- アームbの親をアーム[a]に設定
- アームbの端Cにnullを置き、[b]を親に設定
- IKのコントロールnull(=T)を作る。
解説
- ポイント Tがアーム先端のコントロールポイントで、TとCを一致させればIKが出来ます。
- その為にはθ1とθ2を求める必要があります。
- まず 2本のアームによって作られる三角形ABC(=ABT)において、三辺の長さは簡単に求めることが出来るので余弦定理を利用して頂点の角度を求めます。
- αは余弦定理 b*b=a*a+t*t-2*a*t*Math.cos(α) から
- α=Math.acos((a*a+t*t-b*b)/2*a*t)
- 求める角θ1はΦからα(∠CAB)を引きます。
- ここでΦはベクトルATとX軸のなす角度ですから
- Φ=Math.atan2(AT[1],AT[0])
- そしてθ2は∠ABCの外角ですからπ-∠ABCです。
- θ2=Math.PI-Math.acos((a*a+b*b-t*t)/2*a*b)
設定
- アームaの「回転」に以下の式を記述
A = toComp(anchor_point); //位置をグローバル座標に変換
B = thisComp.layer("b").toComp( thisComp.layer("b").anchorPoint);
C = thisComp.layer("C").toComp(thisComp.layer("C").anchorPoint);
T = thisComp.layer("T").toComp(thisComp.layer("T").anchorPoint);
a = length(A,B); //各辺の長さ
b = length(B,C);
t = length(T,A);
D = T - A; //ベクトルt
Fai = Math.atan2(D[1],D[0]);
A=(a*a+t*t-b*b)/(2*a*t);
alpha=Math.acos(clamp(A,-1,1));
radiansToDegrees(alpha + Fai);
アームbの「回転」に以下の式を記述
B = toComp(anchor_point);
A = thisComp.layer("a").toComp(thisComp.layer("a").anchorPoint);
C = thisComp.layer("C").toComp(thisComp.layer("C").anchorPoint);
T = thisComp.layer("T").toComp(thisComp.layer("T").anchorPoint);
a = length(A,B);
b = length(B,C);
c = length(T,A);
u=clamp((a*a+b*b-c*c)/(2*a*b),-1,1); //角度制限
beta=Math.PI-Math.acos(u);
-radiansToDegrees( beta);