beedama_slope.jpg


ビー玉がスロープを跳ね落ちる

 ビー玉をデザインして、それがスロープを跳ねながら落ちていく動画を作ってみようと思います。

ビー玉をデザインする

 昔、おもちゃ箱にいくつか紛れ込んでいましたが、今は手元にありません。ですので、イメージで、作ってみます。自由落下させるときに、重力加速度[m/s2]をそのまま使おうと思っていますので、単位は[m](メートル)とします。ビー玉って、直径2cm位ですか?だとすると、半径は0.01に設定します。
 基本は球体なので、球面を使って、内部に下図の様に十字にクロスする構造物を挿入します。

bee_struct.png

 球体部分は透明なガラスで、内部の構造物だけに着色します。構造物は、斜め上から見ると円盤状の物体が、十字にクロスしています。

beedama_slope.jpg

 いかがですか?かなり単純にモデル化してみましたが、なんとなく、ビー玉に見えませんか?単なる色ガラスの球体と異なり、複雑な模様・色合いを表現することができました。

スロープを跳ねる座標計算

 スロープを作っておいて、その少し上方からビー玉を落としてみます。最初しばらくは自由落下して、スロープに衝突すると、ポンと跳ねて落ちていきます。
 平らな地面に落とした場合は、その場で跳ねながらだんだん跳ね返る高さが低くなって、いずれ停止します。スロープに衝突した場合は、スロープの角度に従って斜めに跳ね返り、スロープが低くなっている側に飛び跳ねながら、再び重力に引かれて加速して行きます。以下図にスロープで跳ね返る時のモデルを示します。

slope_bound.png

 スロープの法線ベクタnに対して、入射角と等しい角度で跳ね返ります。→→→これは、ビー玉とスロープとの衝突が完全弾性衝突だった場合。今回は、弾性衝突係数eを設定してあります。通常、衝突のエネルギの一部がスロープに吸収されるため、e<1です。
 さて、上図に戻ると、ビー玉がスロープに衝突した時点の速度vに関して、法線ベクタn方向の成分vnを分離することができます。衝突した時、跳ね返った後のvn’が、vn’=−e×vnとなる、モデルを使うことにします。スロープに平行な方向の成分は変化しないと考えます。

 衝突するのが平らな地面だった場合の処理については、「座標計算(別法)」のページで解説済みです。以下の様な方法でした。

  1. 最初の実行時に1回だけ座標計算して、座標ファイルに書き出す。
  2. その後のレイトレーシングでは、座標ファイルから座標値を拾って物体定義する。
  3. 動画のフレームレート(30FPS等)では、粗すぎてうまく計算できないので、さらに細かく分割して計算する。

 今回追加になるのは、衝突する相手が、「スロープ」と「地面」の2つに増えただけですので、データを眺めてみてください。スロープに関しては、高さlbと傾きlaを設定して、スロープの横幅がx軸方向、スロープの傾きがy軸方向、高さがz軸方向になるように想定しています。従って、y-z平面に投影すると、z=la×y+lbと言う直線になっています。

slope_equ.png

 ベクタ計算をチマチマ実施すれば跳ね返りベクタは求まりますが、今回は、以下の様に一次変換を使って計算しています。

  1. 速度vと中心座標pに関して、スロープが水平になる様に回転させ、座標変換を実施する。
  2. 水平になったので、v.z’=−e×v.zで跳ね返りを計算できる(一次元、簡単(1^^))。
  3. 跳ね返り計算を終えた速度v’と中心座標p’に関して、1.と逆の回転変換を実施して元に戻す。

 実際のリストを抜き出すと、以下の様になっています。

  // スロープの傾き方向ベクタ
  static : vect3 sv;
  vlet sv, 0,1,la;
  vnorm sv;

  // スロープが水平になる様に座標変換
  unit;
  lever sv.x,sv.y,sv.z, 0,1,0, 0,0,lb;
  linear v.x,v.y,v.z;
  linear p.x,p.y,p.z;
  // 跳ね返り計算
  v.z=-e*v.z;
  p.z=R + 2*lb - (p.z - R);
  // スロープを元に戻す座標変換
  unit;
  lever 0,1,0, sv.x,sv.y,sv.z, 0,0,lb;
  linear v.x,v.y,v.z;
  linear p.x,p.y,p.z;

100個落とす

 ビー玉の外形は球そのもの、ですので、そんなに計算時間はかからないだろうし、ド〜ンと100個落としてみようと思います。さすがにレイトレーシングで動画を作成して、動きを確認するのは計算時間がバカにならないので、計算した座標(ビー玉の動き)の検証を2Dのグラフィックで確認できるようにして見ました。

 enbd2d=true;に設定して実行すると、下のような感じの動画が完成します。



 最初から最後までの間に、バラバラと、100個のビー玉が転がり落ちます。動画の上部にそのフレームで描画したビー玉の数をカウントして表示してあります。ビー玉が落下を始めるタイミングをずらしてあり、また、転がって画面の外にはみ出たビー玉はカウントから外れていくので、最大で50個程度のビー玉がレンダリング対象となっていることがわかりました。ただし、落下タイミングは乱数任せのため、「現在の乱数系列では」という条件です。乱数系列(rseed命令に与える数値)を変えた場合は、変わる可能性があります。

 肝心な「動き」の確認ですが、良いようです。ちゃんと「スロープ」と「地面」で跳ね返っています。発生するタイミングをランダムに決定しているので、少し偏りやぎこちない感じがありますが、まあ、ランダムだと、こんな感じでしょう。
 丁度、最初のビー玉が発生してから、最後のビー玉が転がって画面の外に飛び出すまで範囲に収まっていて、切りも良いです。

 レイトレーシングする時と全く同じ座標ファイルを使って描画していますので、このままレイトレーシングすると、100個のビー玉は、三次元空間で同じ動きをします。


完成動画

 完成したデータと動画です。

Xi-TRACEデータ beedama_slope.xitr

 Xi-TRACE R13での追加機能を存分に使用していますので、最新版をDLしてお使いください。DLは下のリンクより。



 重力加速度gを地球の地表面における加速度=9.8[m/s2]に設定すると、落下速度が速すぎたため、火星表面の加速度=3.7[m/s2]に設定しましたが、まだ、速いですね……。と、いう事なのでこの動画は、「スロープを火星に設置して、ビー玉を落としてみたもの」です。

 動画では、「実時間」→「スロー」→「実時間」の順で繰り返してあります。


home

download

gallery