今回は、kangaroo2 を使用して、上画像の様にものにぶつかりながら落下する球体を生成していきます。kangaroo2 で実装できる基本的なものとなっております。是非ご参考ください。こちらのチュートリアルは動画化しておりますので、動画の方がよい方は以下のリンクからどうぞ。
概要
上画像がプログラムの全体像となっております。各ブロックごとに説明していこうと思います。
基準サーフェイスの生成
- CenterBox コンポーネントで直方体を生成します。各辺の長さは 6×100×100 としています。
- Deconstruct Brep コンポーネントでサーフェイスに分割し、List Item コンポーネント一番面積の大きい面を取得します。
基準サーフェイスを変形
- 生成したサーフェイスを面外方向に変形させていき、凹凸をつけていきます。Divide Surface コンポーネントでサーフェイスを分割していきます。u,v 方向 45 分割しています。出力端子の point と normal は Flatten しておきます。
- 先ほど取得した分割点を法線方向に移動させていきます。Move コンポーネントにポイントをつなぎ、Divide Surface コンポーネントの Normal ベクトルを Amplitude コンポーネントで大きさを変えていきます。
- List Length コンポーネントで分割点の数を取得し、Random コンポーネントで分割点数分のランダムな値を取得します。今回は-7 ~ 7 までのランダム値をしゅとくしていきます。これを Amplitude コンポーネントに接続すると、各分割点が法線方向にランダムに移動します。
- 長方形の端部の変形を 0 にしたいので、その処理を実装していきます。Curve コンポーネントでサーフェイスのエッジをポリラインで取得し、Point in Curve コンポーネントでエッジ上にある点のインデックス番号を取得します。
- Point in Curve コンポーネントはカーブ上にある点は 1 を出力するので、MemberIndex コンポーネントで値が 1 のインデックス番号を取得します。
- 先ほど生成した Random コンポーネントから出力されるランダムな値のリストから、Replace Items コンポーネントで MemberIndex コンポーネントで取得したインデックス番号の値を 0 に置き換えます。
- これを Amplitude コンポーネントにつなぎなおせば、端部の変形を 0 にできます。
- Surface from Points コンポーネントで移動させた点から再度サーフェイスを生成します。入力端子 U は Expression で「x+1」と入力し、Divide Surface コンポーネントで分割した際の 45 を接続します。上画像の様にサーフェイスが変形していれば OK です。
変形させたサーフェイスを切断し切断面を取得
- 先ほど生成した変形させたサーフェイスを切断していきます。まずは切断に用いるサーフェイスですが、基準サーフェイスを x 方向に 1 移動させたサーフェイスを使用します。
- Brep | Brep コンポーネントで変形させたサーフェイスを切断に用いるサーフェイスの交線を取得します。
- Boundary Surfaces コンポーネントで取得した交線をサーフェイス化します。これで切断面を取得できました。
切断面の押し出し
- 取得した切断面を押し出していきます。Extrude コンポーネントで X 方向に押し出します。押し出す距離は、一番最初に Center Box コンポーネントで直方体の X 方向の長さ 6 で押し出しています。
- 後々のために押し出したオブジェクトを-X 方向に 1 だけ移動させておきます。上画像の様になっていれば OK です。
外側の Box と球体がぶつかる部分を生成
- 次に、球体を流し込むための外側の Box を生成します。List Item コンポーネントで Deconstruct Brep コンポーネントで、最初に直方体を分割して取得したサーフェイスから下面を取得します。
- Extrude コンポーネントで Z 方向に 1 押し出します。これで Box の下面は完成です。
- 次に、下面以外の 4 方向を生成します。下面のサーフェイスに Curve コンポーネントを接続し、サーフェイスエッジをポリラインとして取得します。
- Offset Curve コンポーネントで-1 オフセットすることで、先ほど取得したエッジを内部側に 1 オフセットしたエッジを取得しまます。
- Boundary サーフェイスの入力端子を Flatten して、2 つのエッジをつなぐことで、ロの字型のサーフェイスが生成されます。
- Extrude コンポーネントで Z 方向に押し出します。今回は 105 押し出しています。上画像の様に、上面に穴が開いた Box が生成できていれば OK です。
Box の外側部分を生成
- 前項で生成した Box は球体とのあたり判定に使うものなので、実際には見えてきません。見えてくる部分の Box を生成します。
- Brep Edge コンポーネントで先ほ Box のエッジを取得し、List Item コンポーネントで 0,1,3 番目のエッジ(下面の長方形の帳面以外の3辺)を取得します。
- Join Curves コンポーネントで3辺を結合し、ポリライン化します。
- Offset Curve コンポーネントでポリラインを外側に1オフセットします。
- Loft コンポーネントでオフセット前と後のポリラインを間にサーフェイスを張ります。
- Extrude コンポーネントで Z 方向に押し出します。105 押し出しています。
見え係部分の色付け
- わかりやすいように、見え係部分を色付けします。外側の Box、下面の直方体、以前生成したいびつな形状のジオメトリを、Custom Preview コンポーネントと Colour Swatch コンポーネントで白にしときます。
落下させる球体の中心点を生成
- 落下させる球体の中心点を生成します。List Item コンポーネントで一番最初に生成した直方体の上面を取得します。
- Brep Edge コンポーネントで直方体のエッジを取得し、List Length コンポーネントで長さが短い順にリストを並べ替えます。
- List Item コンポーネントで 0 番目と 1 番目を取得することで、短い 2 辺が取得でき、Curve Middle コンポーネントでそれぞれの中点を取得し、Line コンポーネントで中点同士を結ぶ直線を生成します。
- DivideCurve コンポーネントで生成した直線を 15 分割し、16 の分割点を取得します。
- Cull Index コンポーネントで 0 番目と-1 番目の分割点を消去し 14 点とします。
- Liner Array コンポーネントで 14 点を Z 方向に 2 間隔で複製します。今回は 50 複製しているので、700 点生成しました。
- Move コンポーネントで 700 点を全体的に Z 方向に移動させておきます。+ Z 方向に 5 だけ移動させました
kangaroo2 ゴールオブジェクトの設定(球体同士の衝突判定)
- それでは kangaroo2 の設定をしていきます。まずは球体同士の値判定を設定していきます。Sphere Collide コンポーネントで先ほど取得した 700 点を接続し、入力端子 R には 1、Strength には十分大きな値を接続するため、適当に 10000 を入力しておきます。
- これで入力した 700 点を中心とした、仮想の半径 1 の球体が生成され、生成された球体同士がぶつかるようになります。
kangaroo2 ゴールオブジェクトの設定(Box と球体の衝突判定)
- 以前生成した、衝突判定に使用するロの字型のサーフェイスを押し出したジオメトリ、Box 下面のジオメトリ、内部のいびつな形状のジオメトリを Merge コンポーネントでまとめ、それらと先ほど生成した 700 点とのあたり判定を設定していきます。
- SolidPointCollide コンポーネントで入力端子 Solid に Merge でまとめておいたジオメトリを接続し、Points コンポーネントには以前生成した 700 点を接続します。Strength には十分大きな値を接続しておきます。
- これで、生成したジオメトリと 700 点がぶつかるようになります。
kangaroo2 ゴールオブジェクトの設定(球体を落下させる)
- 生成した 700 点に対して、-Z 方向に力を与えていきます。Load コンポーネントに 700 点を接続し、-0.01 の Z 方向のベクトルを接続します。
- これで 700 点は落下するようになります。
Solver の設定
- Entwine コンポーネントで設定した Goal オブジェクトをまとめます。
- Solver の設定を行っていきます。今回は演算結果の過程をアニメーションで見ていきたいので、Bouncy Solver コンポーネントを使用します。
- BouncySolver で演算を開始すると、上画像の様に 700 点がぶつかりながら落下していくかと思います。
球体の生成
- 一度演算を止め、ぶつかりながら落下した点を中心とした球体を生成します。Bouncy Solver コンポーネントの出力端子 V から移動した点を取得できるので、MeshSphere コンポーネントでその点を中心に球体メッシュを生成します。UV 方向の分割数は 10 とし、半径は SphereCollide で使用したときの 1 とします。今回 hMeshSphere で球体を生成しているのは、Brep にすると非常に処理が重くなるためです。
- SolidPointCollide コンポーネントで設定したあたり判定はあくまで点とジオメトリのあたり判定になります。つまり、実際ぶつかっているのは中心点とジオメトリがぶつかっているので、そのぶつかった点を中心とすると、球体が Z 方向に半径 1 ぶんめり込んでしまいます。なので生成した Mesh 球を Move コンポーネントで Z 方向に 1 移動させます。X 方向 Y 方向に関しては、白いジオメトリの内部に、ロの字形サーフェイスを押し出したジオメトリを生成し、そのジオメトリと点のあたり判定を設定したかと思います。なので外側の白いジオメトリの内部に、透明な厚さ 1 の壁が 4 方に張られていて、それと点のあたり判定を実施することで、壁にめり込まないようにしています。
球体の色付け
- 最後に MeshSphere に色付けしていきます。MeshColor コンポーネントに接続し Graft しておきます。
- 今回はランダムに色を生成したいので、Random コンポーネントで 0 ~ 255 までのランダム値を整数で取得し、球体の数だけランダムな色を生成しています。
- Graft して MeshColor コンポーネントに接続すれば完成です。
完成
以上になります。kangaroo2 の記事は他にもいくつか書いてますので、ご興味あれば是非ご参考ください。