CG・コンテンツ制作
  1. CG・コンテンツ制作トップ
  2. DAIKIN CG Channel
  3. UsersNotes
  4. ICE
  5. はじめての ICE Simulation その2 スプリング/コリジョン編;My First ICE Simulation No2 
SUITE USERS NOTES
Twitter 110 Followers 記念
は・じ・め・て・の ICE Simulation その2
スプリング/コリジョン編
(My First ICE Simulation)
ICE_kine_01
ritaro_ml

プロローグ

前回の続き、より複雑な処理を実現させるICEによるシミュレーション機能についてに記述しようと思います。
ICE_sim_101
前頁の続きで、パーティクル間の長さが変わるので、
それに応じて骨の長さも変わるいわゆるストレッチボーンの解説を追加します。

それに続いて、Strandを利用したより複雑なコリジョン付きスプリングを紹介します。
ただし、やはり研究段階のものなので、もっともっと良い設定もあることでしょう。

ICEのスプリングやコリジョンの制御方法を学び、 位置データ制御をICEで行う際のより深い技術を習得しちゃいましょう!!

2) 位置データとしてのパーティクル
 > Spring Force の利用6

3) 位置データとしてのストランド
 > Strand の利用1
 > PreSimulation_ICETree
 > Simulstion_ICETree
 > Constraint_ICETree
 > 各ボーンのICETree
 > 髪の毛

パソコンのスペックWindowsXP SP3、Intel Core2Duo 3G、RAM; 3G、NVIDIA Quadro FX1700



位置データとしてのパーティクル
Spring Force の利用6
実は、前頁"SpringForceの利用3"の続きです。
各パーティクル間の距離は当然スプリングなので伸縮しますので、ボーンの長さもそれに応じて変化させたいところです。
ICE_sim_21
COLOR="#ff0000" > 追加情報上図ID to Location の次のGetPoinPosition のノードですが、
Deformationタブ > Getters > Get PointPosition という既存ノードでは左側に接続ポイントが無いよ?とのことで・・・、
NoNo,このGetPointPositionは、ツール タブ > DataAccess > Get Data にてPointPosition を取得したノードです。(似てるけど間違えないように・・・・)
追加情報前頁にて、データ格納用のBuildArrayFromConstantにつなぐ4x4Indentityってその名前で探すと無くて、
実はツールタブ内 > Math > Matix > 4x4Matrix というノードを取り出すと4x4Indentityって書いてあります、ややっこしーですね。

下図では[値の表示]をすると、ちゃんと骨の長さが取れているのが画面に表示されている例です。↓
変更を加えるのは、Constraint_ICETree と名付けた方です。
ICE_sim_102
まずは、5個の値が入る箱を作成しておきます。
Array>Build Linearly Interpolated Array(スカラ配列) を取り出し、
SetData内にself.BoneLengths というカスタムなパラメータを作成して接続します。
ICE_sim_103
そうしたら、その下の、パーティクルの2点間から回転値を求めた部分↓に、
今度は、ツールタブのMath > Vector > Get Distance Between っていう文字通りの間の距離を求めるノードに接続して距離を取得します。
それを、Set in Array を使ってSetDataのself.BoneLengths に接続します。
ICE_sim_104
これで、データは用意できたので、
各ボーンについているICETreeの方に、骨の長さのデータを取得して、それが反映するようにします。
GetDataでPointCloudからModel.PointCloud.BoneLengthsからボーンの長さデータを取得し、
Select in Arrayを使ってボーン自身の長さthis.length にSetDataします。
ICE_sim_105
動かしてみましょう。
ICE_sim_106
ICE_sim_107
Simulation_ICETree の方にForce > WindForce で風を設定すれば
紐や布のような動きになり、
Gridの方を動かせば、蛇やくらげの触手のような動きになります。
Constraint_ICETree の実寸全体図です。
ICE_sim_108
お次は、Strandを利用したより複雑なスプリングの話になります。




位置データとしてのストランド
Strand の利用1
さて、ここからは中級以上です。ここまで追ってきているなら大丈夫でしょう。
既に説明している部分が省きますよ。

パーティクルの一種Strandにシミュレーションを設定し、骨をそれに拘束することによって動きを得ようとする試みです。
途中、いくつもの組まれたコンパウンドが出てきます。当然それらはデフォルトでは無いノードなので、あれ?そんなん無いよ・・が出てきます。

まずは、以下のものを用意します。
ICE_sim_109
・骨の階層構造、
・制御用(マニピュレーター)の短形波表示のNull階層構造
の両方をModel(上記図ではbone04 ) 以下に置き、その中にpointcloudがあるとします。
ボーンにはおなじみのICEBoneParamsカスタムパラメーターが設定されていて、BoneID番号が付随しています。
骨構造体のGroupと制御用NullのGroupを作成しておきます。
ICE_sim_110
pointcloud に設定されているICETree も3箇所もあるので ↑、下から順に説明します。



PreSimulation_ICETree
一番下に設定したICETreeです。ここでは基本的なStrandやダイナミクスなど初期設定をしています。
ノードだけ見ると一見簡単そうに見えますが、”そんな名前のノードは存在しない↓”はずです。
ICE_sim_111
のっけからCreateBasicStrand は作成されたコンパウンドです。
それに接続されているのは、一番上のボーンであるbone01のグローバルの位置と回転値からStrandが発生されています。
CreateBasicStrand は Particles タブ > Strands > Create Strands が 元 になっています。
まずは、このCreate Strands をちゃんと動かす設定の説明から・・・・・。

*---* ここから Create Strands の試し *---*

こういった直ぐに動かないものは、
そのコンパウンドの中身を見て、なんのデータが不足して真っ赤になっているのか調べるところから始めます。

Model の中にStrandを発生させる ポリゴンのGrid を作成して下向きにし、pointcloudを作ってICETreeを設定します。
その Grid のグローバル移動値を得ておいて、Particles タブ > Strands > Create Strands を取り出します。
ICE_sim_112
ここはこしょっと ずるなんですが、答えが先に解っていて、
発生源のグローバル位置データをツールタブ > Point Cloud > Add Point を使って接続してしまいます。
ICE_sim_113
でも、まだ真っ赤です。CreateStrandコンパウンドの中身を見ると、赤や黄色でいっぱいです。
で、上から順に見ていくと、最初に真っ赤なのが、パーティクルのSelf.Orientation、つまり自分の回転値が得ていないと気が付きます。
ICE_sim_114
なので、発生源のGridからその回転値をSelf.Orientationとして接続してあげます。↓
すると、いきなり線が描画されます。セグメントの数を、長さをとしておきます。
でも、まだ真っ赤です。また、中を見てみます。
ICE_sim_115
上から見て行って、次に真っ赤のが、GetParticleSizeで、なんだよ己の大きさSelf.Sizeも解んないないのかよってことで・・
ICE_sim_116
SetDataでSizeを設定してあげます。↓すると、大きさが反映されて表示されます。
でも、まだ真っ赤です、なに?って中身を見ると、
ICE_sim_117
すると、今度は色だってわかります、色はいいやと思って、あとで削除していますが、
とりあえずここで色を反映させると、こうなります。
ICE_sim_118
Particleタブ > Setters > SetParticleColor を接続します。↓
これでようやく真っ赤が全部なくなりました。
ICE_sim_119
*---* ここまでが Create Strands の試し *---*

このような設定を済ませたものがCreate Basic Strandです。
が、色指定の部分はざっくり消去、追加でself.strandsegmentlengthself.strandUValuesとういう値を取得しています。
ICE_sim_124
Build Strand Transformsは骨のようにX軸が長さ軸になるように回転させています。実はこれもコンパウンドです。
ICE_sim_125
self.StrandOrientationにツールタブ > Conversion > Euler to Rotation で回転値にしたZ軸値90度を足し、
self.StrandPositionはSelf.PointPositionからの配列を位置データとして
SRT to Matrix でグローバル値にしてself.StrandTransformにまとめています。
スケール値は真っ赤で使用していません。
このツールタブ内の > Execution >  First Valid (最初の有効な入力) って面白くって、"最初の正しい値を使う"というノードらしいのです。
つまり、いつもは使ってないので真っ赤なんですが、その場合2個目に設定している値ここではX= 1、Y=1、Z=1を使用します。
つまりつまり、いつも何もしなくてもスケール値は1,1,1、なんです。(でも、何かスケール値を入れると、そちらを使いますと・・)

このコンパウンドが Create Basic Strand です >>  Create Basic Strand

最初の図 に戻って、次はShape Strand with Manipulatorsですが、これもやっかいなコンパウンドです。
やっていることはStrandGroup指定した制御用のNullで移動や回転を設定出来るように設定しています。
ICE_sim_120
中身を見て、一番右側の最後を見ると、self.StrandPositionを SetData していると解り、
制御用のNullグループから得たグローバルの移動値と回転値から作り出してる、と気付きます。
ICE_sim_121
Pop from Array(配列からのポップ)は一番最後の配列(Array値)つまり一番下のNullの位置
Push on Array(配列でのプッシュ)は新しい配列(Array値)を作成、
Remove from Array(配列からの削除)は"それぞれ-1ずつシフトされます"、つまり、一番上のNulの位置は捨てています。
何やってるかって言うと、並んでいるNullの位置の前後から、その位置と回転値を配列(Array値)化してself.StrandPositionというデータを作成しています。
ここは、2段目に小さく接続しているAlign Strand Segmentsも一緒になっていて、これもコンパウンドです。中と覗きます。
ICE_sim_122
すると注釈が書いてあります。
We subtract ajacent items in the array to find the vectors that go between the items in the array.
”我々は制御用Null間のベクトル(方向)を設定したっす”、と書いてあります。つまり、ここでは回転値を計算しています。
GetParticlePosition は Strandの根元の位置です。Insert in Array(配列への挿入)でさっき削除した根元の位置を追加しただけ、
で、Pop from Arrayで一番下の削除して、さっき求めたStrandPositionと1個ずれるので、
その差Subtractを例の"2点間から回転値を求める”IncrimentRotationWith2Vectorsに接続しています (前頁参照)
その結果Self.StrandOrientationとself.StrandUpVectorを求めています。

つまりShape Strand with Manipulatorsコンパウンドは、制御用のNullの影響から来る、
新しい位置;StrandPositionと回転値;StrandOrientationを作り出しています。

このコンパウンドがShape Strand with Manipulatorsです >> ShapeStrandwithManipulators

この部分↑、”配列から位置データとそこから導き出した回転値を求める”というのは、良くあるパターンなので、
覚えておくと、きっと何かの時に役に立ちます・・・・、きっと♪



最初の図 に戻って、次最後のInit Strand Dynamicsもコンパウンドです。
Particle タブ > Strand Dynamics > Init Strand Dynamics で、ダイナミクスに必要なものを準備してくれてます。

このコンパウンドはデフォルトであるはずです。念の為 Init Strand Dynamics.1.1 です >> InitStrandDynamics_1_1
ICE_sim_123
CreateStrandノードを使用している後では、
必要とするパラメーター(self.StrandCount,Self.StrandLength、Self.StrandPosition、Self.StrandOrientation)は揃っているので
設定はうまくいくはずです。

お疲れさん、ここまでが最初のPreSimulation_ICETreeでした。



Simulstion_ICETree
2番目に設定したICETreeです。ここではいよいよダイナミクスを作成しています。
Force を使っていることから解るように、通常のパーティクルのようにForceを接続できるStrandDynamicsFrameworkを使用しています。
 真っ赤なのは、コリジョンとして設定しているShpereがシーン内から外してあるからで、複数のオブジェクトを設定できます。
ICE_sim_130
ここではStrandにダイナミクスを設定して、シミュレーションを実行していきます。

また上から順に見ていきましょう。
Calc Local Rotation from Manipulatorsは、制御用のNullのグループから各Nullの回転値を計算しています。
これはこのまま、こうすれば配列からローカルの回転値が得られるのか・・と公式のように応用してしまいましょう。
最終的にSelf.StrandLocalOrientationという変数に格納されています。
ICE_sim_131
このコンパウンド作れそうですが Calc Local Rotation from Manipulators です
 >> CalcLocalRotationfromManipulators

お次のConstrain Particle to Objectは、最初の制御用のNullにStrandの最初の部分をくっ付けています。
これで一番上だけですが、制御用のNullでStrandを固定しています。
やっていることは最初の制御用Nullのグローバルの位置と回転値をSelf.PointPositionSelf.Orientationに代入しています。
ICE_sim_132
ここの大本命、StrandDynamicsFrameworkです。
これ1つではたりと下にたれ、バネの強さにもなり、衝突するものも指定できます。
これはデフォルトで存在するもので、Particlesタブ内 > Strand Dynamics > StrandDynamicsFramework です。
今は、数が個、コリジョンのオフセットが0.01、硬さが0.12になっています。
ICE_sim_133
接続しているフォースを上からみると・・・

Strand Gravity ForceはY軸に-20のベクトル値を設定しています。
Particle タブ内 > Strand Dynamics > Strand Gravity Forceがあります。
ICE_sim_134
通常パーティクルで使うGravity Forceと比べると中身が違います。
self.StrandCountは前述のCreate Basic StrandsNumSegment で6個と書いた数字が入ります。
つまり6個にそれぞれ1個ずつ-20の影響をさせています。
ICE_sim_135
お次の、Strand Drag Force はParticle タブ内 > Strand Dynamics > Strand Drag Force です。
強さとして0.1が設定されています。
ICE_sim_136
これもパーティクルで使うDrag Forceとは全く異なり、中身を見ると、
なにやら前フレームの位置・・・・時間・・ああ、バネねと前頁を思い出せば理解できます。ここはこのまま使いましょう。
ICE_sim_137
最後の、Null Controller ForceはParticle タブ内 > Forces > Null Controller Forceです。
一番上の制御用Nullの方向で多少なりともなびく方向性を持たせたかっただけです。
でも、このコンパウンドの中身を見るとたいへんです。見なかったことにしましょう♪♪♪
ICE_sim_138
最初の図に戻って、
一番下のBuild Strand Transformsは、また骨のようにX軸が長さ軸になるように回転させて、
中身も同じでself.StrandTransformにまとめています。
ICE_sim_139
これでシミュレーションの設定は完了です。
ICE_sim_140

この状態でアニメーションを再生させると、
既にびよよーんと Strand だけが動き、
制御用のNull を動かすと曲がってくれます。
最後のICETree では
このStrandの動きにボーンがくっ付いていくように設定しています。




Constraint_ICETree
3番目に設定したICETreeです。ボーンを Strand の位置と回転値に合わせる配列のデータ(BoneTransforms )を用意しています。
おや!!と気が付いた方は、そうもう見慣れて来ましたか? < ここまで追って来てくれた方ですね、ありがとうです。 > 
ハイ、例のArrayを使ってボーンを設定する、IKやパーティクルの時と同じやり方です。
ボーンのグループからその BoneID値 を取得してSet in Array で接続してください。
後は、前頁やICE IKの頁 を参照してください。
終わりです。
ICE_sim_141
次は各ボーンに個別位置を設定したICETree を設定します。



各ボーンのICETree
さて最後です。個々のボーンに以下のような ICETree を設定してStrandの位置にくっ付けています。
これもあれ!!・・・ですね。
そう同じです。己の BoneID番号 を取得して、PointCloud に溜め込んだBoneTransforms から Select in Arrayを使って取得し、
それをグローバル値として自分に設定しています。
ICE_sim_142
お疲れ様です!!これで全て、設定完了です。
あとは、そのシーンに合った都合の良いものに変えてください。



髪の毛
コリジョンの設定
さて球や円柱を衝突物として設定して動かしてみます。ちゃんと反映されます。
ただし、当たり判定している点はSize で大きさが変えられるものの大きくなると邪魔なので、
レイヤ分けしておき、非表示やレンダリングしないレイヤに入れて置くと良いです。
あと、当たり判定が球状なので滑ってしまい、スカートの当たり判定先が足のような丸いものにはむかないかもしれません。
スカートは布的なICE処理の方が良いでしょう。
ICE_sim_150
ということで、髪の毛に使ってみました。またキャラですみませんが・・・

どのくらいの処理速度で動かせるのかも実験で、こんなにたくさん設定してみました。↓
赤いポリゴンが頭を想定した当たり判定用のポリゴンでレンダリングされないレイヤに入っていて、Neckボーンの子供になっています。
各Strandの位置を設定する制御用の Null もNeckボーンの子供になっていて、尚且つ位置と方向のコンストレイントが付いています。
ICE_sim_151

その時の設定は以下の通りです。

ICE_sim_152
動く方向とか、当たり判定のポリゴンの形状とか色々ありますが、こんな動きになりました。。


影のレンダリング設定では、微妙な色のグラデーションを実現してみました。
胸は前頁のパーティクルのICEスプリングで揺らしてます。(あまりやるとボインボインになってしまうので程ほどに・・)
ギターはとあさんですなせココに使う・・


みなさんならもっとまともな所にでも使ってみてください。
そして、そのシーンに合うようにカスタマイズをしていってください。

追加情報パーティクルの動きに追従していたオブジェクトの動きを取りたい場合、Plotを実行して通常のファンクションカーブにすることができます。
ですが、そのオブジェクトに ICETree が設定されている状態ですとファンクションカーブのデータで動きません。
ICETreeを削除するか、無効にすると、ファンクションカーブの動きが有効になります。
ICE_sim_160

今回、結構ポリゴン数の多い、サブディビジョンサーフェイスのかかったポリゴンにICEを設定して動かしても
再生しながら調整できる描画処理範囲内で動いています。
Arrayを使ったICEの位置設定方法はかなりよいパフォーマンスなのではないでしょうか。

という訳で、次回はなんとemPolygonizer 2.0になりそうです。
乞う、ご期待!!
戻る 次へ

お気軽にお問い合わせください

Daikin CG News お申し込み

CGクリエイター向けのセミナー・イベントやキャンペーン、製品情報をメールマガジンでお届けします。(登録無料)

Twitter

ページの先頭へ