drop


計算で物体を動かす

 簡単なニュートン物理を使って物体の移動軌跡を計算し、それに従って物体を動かすアニメーションを作成してみます。
 スクリプト言語仕様のmodelaを使うと計算はお手の物ですが、ちょっと難しいところがあります。


計算する

 物体の自由落下を計算してみたいと思います。ある物体があって、それが重力に引かれて地面へ向かって落下する、と想定します。

freef

 地上では、全ての物体は重力加速度:g=9.8[m/s2]で地面へ向かう加速度がついています。初速度v0=0[m/s]だった場合、時間:t[s]後には、落下速度:v(t)=v0+g×tとなります。
 物体の初期座標:pz0、地面から上空へ向かう方向がz軸の正方向と仮定すると、pz=pz0−∫v(t) dtです。
 この∫v(t) dtの計算が面倒ですね。

アニメーションデータ

 実は、今回の自由落下ではv(t)が比較的簡単な式であるため、数学的に計算して∫v(t) dt=1/2×g×t2とする方法もあるのですが、応用が利きにくいので、微小時間dt毎にvとpzを更新していく方法で座標を計算していきます。
 今回は、30fps(Frames Per Second)のアニメーションを作ろうと思いますので、微小時間dtを1/30[s]に設定します。現在時刻の落下速度:v(t)、z座標:pz(t)とし、この位置からdt時間後の座標をpz(t+dt)=pz(t)−v(t)×dt と近似します。同じくdt時間後の落下速度:v(t+dt)=v(t)+g×dt と、近似します。この近似はdt→0で実際の値に漸近します。
 さて、v(t+dt)の計算も、pz(t+dt)の計算も、1つ前の時間におけるv(t)、pz(t)を使用することがわかります。
 Xi-TRACEのアニメーションについては、このデータで解説しました。1フレームの計算の度にmodelaはプログラム全体を実行し、一旦終了してからレイトレーシングを実行します。modelaは毎回リセットされ、最初から実行しなおすため、nフレームの処理を実行する時には(n−1)フレームの計算結果はリセットされて消えてしまっています。つまり、v(t)とpz(t)を計算に使おうにも、無いわけです。
 やむを得ず、毎回最初から計算をやり直す方法にしました。

frame

 毎回最初から計算しなおすため、後ろの方のフレームになればなるほど座標計算に時間を要します。対象記述は以下です。

  var idx=0;
  while (idx<fn)
  {
   c=500 - pz_#(idx2);
   if (c<0)
   {
     // 天井の内部に居る間は、v0で等速直線運動
     b=-g;
   }
   elif (c<mp)
   {
     // 天井から顔を出した辺りから、重力に引かれ始める
     b=-g*(mp - c)/mp;
   }
   else
   {
     // 落下を始めると、空気抵抗を受ける
     b=k*v_#(idx2);
   }
   a=g + b;
   v_#(idx2)=v_#(idx2) + a/frate;
   pz_#(idx2)=pz_#(idx2) + v_#(idx2)/frate;
   idx=idx + 1;
  }


 落下物がn_drop(=64)ケあるので、pz_#(idx2)の様に配列変数もどきを使っています。
 毎回最初から計算しなおすのはスマートではありませんので、もう少しスマートに取り扱えるよう、modelaの機能を拡張予定です。
 シーンとしては、天井があって、そこから液体状の落下物がポトポト滴り落ちているイメージです。view命令で天地を反転させているので、逆に空へ登っていくような映像になっています。

  // 天地を反転(上方向ベクタが(0,0,-1))しているので、落下物が
  // 空へ登っていくように見える。
  view 20, 0,0,-1, 0,0,500 - mp, 0,-500,400, 5;


完成映像

 完成したデータと動画をご覧に入れます。

  Xi-TRACEデータ:drop.xitr



 ちなみに、データ中、重力加速度:g=9.8を使いました。地球上と想定すると、単位は[m/s2]ですので、データ中の1という座標値は1[m]を表していることになります。落下物が天井を離れると、小さな球体になって落下しているのが見えると思いますが、この球の直径が1[m]です。思いのほか巨大な球体が落下している映像だったわけです。


home

download

gallery