乗物を進行方向に向ける
非物理でも llSetKeyfaramedMotion を用いることで、スムースな動きを作ることができます。このときに姿勢を進行方向に合わせるにはどうするかという質問があったので、ここにその方法を説明します。乗物が現在向いている方向 now_arrow を、移動先を向く方向 new_arrow に回転させる new_rotation は llRotBetween関数を使って次のように求められます。
new_rotation = llRotBetween(now_arrow, new_arrow);
移動がX-Y平面に限られる場合は、これでOKです。
移動が上下方向にも動く場合は、やっかいな問題が生じます。上記の方法で回転させると、向きの回転に伴って乗物の前後軸(X軸)を中心にする回転、ロール(roll)が生じます。下手をすると車体が裏返しになったりしてしまいます。
ロールなしに向きだけ変えるには、まず水平(X-Y平面上)で回転させたのちに上下方向の傾きを加えるようにします。
目標地点があまりに近いときや、ほぼ垂直移動の場合に向きがコロコロ変わるのも防いでおかねばなりません。
float TOO_CLOSE = 1.0; //meter, skip rotation
float SMALL_TILT = 0.1; //0.0-1.0, skip rotation when horizontal movement is small
vector STD_ARROW = <1.0, 0.0, 0.0>; //headding east
rotation new_rotation(vector pos)
{
vector now_pos = llGetPos();
rotation now_rot = llGetRot();
rotation new_rot = ZERO_ROTATION;
vector now_arrow = STD_ARROW*now_rot;
vector arrow = pos - now_pos;
vector h_arrow = arrow;
h_arrow.z = 0.0;
h_arrow = llVecNorm(h_arrow);
if ( llVecMag(arrow) < TOO_CLOSE ) return ZERO_ROTATION;
if ( llVecMag(h_arrow) < SMALL_TILT ) return ZERO_ROTATION;
new_rot = llRotBetween(STD_ARROW, h_arrow)*llRotBetween(h_arrow, arrow)/now_rot;
return new_rot;
}
基本は上記のようなやり方になります。これに急角度に曲がることに制限を加えたり、気球のようにZ軸の姿勢は動かさない場合とか、曲がるときにバンクを加えたりなどのアレンジはもう少し複雑になります。
Edit - Delete