2010年10月

2010年10月29日

PhysX for Max やってみた その1 3dsMax 2011 Subscription Advantage Pack

この程サブスクリプション契約者向けにアドバンテージパックが提供された。中身は次の3つ。

  • Substance プロシージャル テクスチャ
  • PhysX リジッドボディ ダイナミクス
  • iray フォトリアリスティック レンダラ

今回はこの中からPhysXを調べてみたい。

まずは簡単なところから。

PhysXプラグインをインストールすると下のようなツールバーが追加される。

fig01

もしこのツールバーが出てないならどこかのツールバーの余白を右クリックしてPhysXToolbarをONにするか、

fig02

メニューバーのPhysXからShow UI→Show PhysX Toolbarを選べば出てくる。

さて、作成パネルからティーポットを選んで作成し、移動ツールで上に持ち上げる。

fig03

PhysXToolbarから「Create Dynamic Rigid Body」をクリックする。もし出てなければフライアウトボタンを押しっぱなしにしてプルダウンから選ぶ。

fig04

次にツールバーから「Start Simulation」ボタンを押す。

fig05

これでティーポットが落下するシミュレーションが実行される。

fig06

Start Simurationのボタンは2つあって1つはMax側のタイムスライダも動くものとPhysX側の時刻しか変化しないもの。このまま放置しておくといつまでもシミュレーションをし続けるのでStartボタンをもう一度クリックしてシミュレーションを停止する。

ティーポットがいきなり下に向かって加速して、何も無いY軸0付近で何かに衝突したように止まったのはPhysXのPhysXToolsパネルの初期設定で「GravityEnabled」と「Use Ground Plane」がONになっていたからだ。Gravityは重力でGroundPlaneは床ね。このパネルはPhysXToolBarの一番左のボタンを押すか、PhysXメニューのShowUIの「Show PhysX Tools」を選べば出てくるよ。

fig07

自分で床を用意すれば、仮想の床を使う必要は無い。例えば「Use Ground Plane」のチェックを外して、こんな球体を作成して、

fig08

球体を選択したままPhysXToolbarから「Create Static Rigid Body」ボタンを押せば、球は動かない剛体になる。

fig09

そしてこれが「Start Simulation」ボタンを押してシミュレーションした結果。

fig10

今度は仮想の床をOFFにしたからティーポットは球にぶつかった後、下にどんどん落ちて行く。

PhysXで扱えるリジッドボディはDynamicとKinematicとStaticの3種類。Staticは動かない物体でDynamicはシミュレーションによって挙動が計算される物体だ。じゃあKinematicは何かと言うと、こっちでアニメーションをつけて操作する物体だ。例えばバットでボールを打つ事を考えると、地面がStaticでボールがDynamic、バットがKinematicって感じだ。ボールは重力で地面に落ちるかバットで打たれるかで動きが決まる。地面は動かない。バットは人間が振るわけだね。実際はStaticなRigidBodyもアニメーションさせる事は可能なんだけど、PhysX内での評価の仕方が異なってくる。下のGIFアニメは動いている板の上にティーポットを落下させたものだ。上が板をKinematicにしたもので、下がStaticにしたもの。

Kinematicの場合

fig11

Staticの場合

fig12

両者の違いはstaticがティーポットと板との衝突をティーポットの運動と板の衝突時の位置関係だけで計算しているのに対して、kinematicでは板の運動も計算に含めているところだ。staticの時のティーポットの挙動は衝突時の板の位置で板が静止していても動いていても同じになってしまう。あくまで静止している物体として扱っているわけだ。下の板を動かさなかったアニメーションと比較してみるとよくわかる。

fig13

両者の違いはこのほかに窪んでいる形状を評価できるかどうかというところもある。この話の前にPhysXではオブジェクトどうしの当たり判定を以下のタイプのメッシュで行っているという事を知る必要がある。

fig14PhysXでは計算を単純化するためにメッシュそのものを当たり判定に使う方法を含めて6通りの方法が用意されている。

Sphereは球体。当たり判定としては中心点からの距離だけで計算できるからとても単純で高速化が可能だけど平らな板がありえない転がり方しちゃったりするので単独での使い道は限定的。半径の調整ができる。

fig15



BOXは直方体。高さ、幅、奥行きの調整が出来る。

fig16

Capsuleは円柱の両端が半球状のカプセル。円柱の高さと半径が調整できる。

fig17

Convexはオリジナルの形状の外側の点を結ぶ凸形状。オリジナルの形状から凸形状を生成する時にオリジナルからサンプリングするポイントの数と、オリジナルに対してどのくらい膨れているかを調整できる。サンプリングするポイント数は大きく出来ても、生成される凸形状のポイントの最大値は32になる。

fig18

Originalはメッシュそのものを当たり判定に使う。ただし窪んでいる部分が検出できるのはStaticの時だけ。

Customは選択したオブジェクトから当たり判定メッシュを生成する。一度生成されたメッシュはサンプリングしたメッシュとは独立したものになるので、オリジナルのメッシュを動かしても生成したメッシュは追従しない。オリジナルにあわせて生成したメッシュを更新したい場合は「Update from Custom Mesh」ボタンを押す必要がある。

以上を理解したところで、こんな窪んだ形状のオブジェクトがあったとして、これのメッシュタイプをoriginalにすると、この形状が当たり判定に使われる事になる。

fig19

ところがDynamicもKinematicも窪んだ形状には対応していないので、このように窪んだ部分は無視されて衝突判定されてしまう。

fig20

これに対してStaticの場合は窪んだ部分も判定可能なので、窪んだオブジェクトをkinematicからStaticに変えると、このように窪んだ部分もちゃんと判定されるようになる。

fig21

PysiXはリアルタイム計算を目的にしているので精度の面では粗いけど、そのぶん処理は抜群に速いので、扱いやすい。

動きがついたらPhysXメニューのRigidBodysの「Bake Selected to Keyframes」を選べば選択したオブジェクトにPhysXの計算結果がキーフレームとしてベイクされ、Maxのキーフレームアニメーションに変換される。Unbakeの方は生成したキーフレームの除去だ。

続きはまた来週。

maxまとめページ



take_z_ultima at 11:30|この記事のURLComments(0)TrackBack(0)3ds Max | CG

2010年10月28日

年賀状向けにスカイツリーのCGを作りたい その4 modo 401 SP4

スカイツリーはとうとう上部のアンテナを残して一番上まで達したようだね。ここから空中回廊がある展望台を作って、アンテナは真ん中の塔の中を引き上げて上に出てくるらしい。

前回は外塔の外側のトラスを作ってみたけど、まだ内部に複雑な構造が残っているわけで、改めて掲載するとこんな構造らしい。

fig01


fig02

外塔の外側の縦に走るパイプが24本で、その内側が12本。そこに外側から水平と斜めにパイプが接続されて、そこからさらに内側の塔に放射状に接続されている。内側の形状は写真を見てもわからないので適当に作るしかないけど、写真をよく見ると鼎トラスの内側の柱(?)は土台の三角形の切り込みから見てだいぶ内側に入っている感じで、逆に切り込みの三角形の頂点付近を見るとリブトラスの奥行きが少ない。外塔の内側の構造は外側より円に近い感じのようだ。

fig04

ところでようやくスカイツリーの立面イラストが手に入ったので、さっそくmodoのバックドロップアイテムに読み込んでモデルを作り直してみたい。

スカイツリーは634mという高さだとわかっているので、実寸でモデリングするならばバックドロップアイテムに表示するイラストも高さ634mにしなくちゃならない。そこでバックドロップアイテムの大きさはどうやって決まるのか調べてみたら、初期設定パネルの表示のOpenGLのバックドロップアイテムの項目にピクセルサイズという設定が見つかった。どうやらこれが1ピクセルの大きさを決める値で、例えばイラストのサイズが縦634ピクセルだったらここを1mにすればイラストのサイズが縦634mになるってわけだ。

テンプレートで使おうと思っているイラストの縦のサイズが1600ピクセルなので、これが634mになるには1ピクセルあたりどのくらいのサイズにすればいいかは634/1600でいいわけだ。modoは数値入力のところで式を使う事が出来るからわざわざ計算しないでそのまま入力すればいい。

さっそくメニューバー→初期設定で初期設定パネルを出して、ピクセルサイズに634・1600mと入力した。Enterを押すと396.25mmになった。

fig01

次にアイテムリストで(新規アイテム)をクリックし、「バックドロップアイテム」を選択し、プロパティの「画像」をクリックして「画像の読み込み」を選んでテンプレート画像を読み込んだら、イラストの物凄いアップが出たのでAキーを押してビューポートを調整したらこのようになった。

fig02

これが本当に634mあるかどうかはプロパティの位置Yに634/2mを入力してみるとわかる。イラストの底辺が原点に来た。これは間違いなく634mあるようだ。

fig03

このイラストは横梁の位置も出ているのでスライスに使った平面をこれで調整してやれば良さそうだ。

まったりやってるとあっという間に年末になりそうだから、そろそろ頑張らないとw

それではまた次回。

modoカテゴリー別ページ 



take_z_ultima at 11:30|この記事のURLComments(5)TrackBack(0)modo | CG

2010年10月27日

modoからFLASHへ書き出してみた その31 modo 401 SP4 ActionScript 3.0

ムービークリップの使い方が分かってきたので、アニメーションコントローラを球体に組み込んで、そこにムービークリップを貼ってコントロールしてみることにした。

以前に修正したクラスはオリジナルに戻したよ。考えてみれば新しいクラスを作って変更部分だけ被せちゃえば良かったんだよね・・・orz

まずは張り付けるためのムービークリップ

平常(mc_all)

fig03

怒り(mc_angry)

fig04

笑い(mc_smile)

fig05

を作成してライブラリに登録した(背景の矩形のサイズ1600x800)。

そしてウインドウメニュー→サンプルライブラリ→ボタンを選んで、ボタンライブラリの「buttons rect flat」から2つボタンを選んでステージにドラッグ&ドロップして、それぞれのボタンに「btn_smile」、「btn_angry」というインスタンス名を付けた。

fig01

ボタンをそれぞれダブルクリックして編集モードに入り、タイムラインのtextレイヤーのロックを解除してからボタンのテキストをsmileとangryに書き換える。

fig02

ドキュメントのプロパティでクラスをMcTest04にして横の鉛筆ボタンを押してスクリプトの編集モードに切り替える。

新規にクラスが生成されたら「McTest04.as」として保存する。

さらに新規でActionScript3.0クラスを作成して、クラス名を「ClipTestObject」にする。そしてファイル名「ClipTestObject.as」として保存する。

中身はこんな感じ。Sphereを継承して作ってあるよ。

package  {
 import org.papervision3d.core.proto.*;
 import org.papervision3d.objects.DisplayObject3D;
 import org.papervision3d.core.render.data.RenderSessionData;
 import org.papervision3d.objects.primitives.Sphere;
 import org.papervision3d.core.controller.AnimationController;
 import org.papervision3d.materials.MovieAssetMaterial;
 import flash.display.MovieClip;
 import org.papervision3d.materials.utils.MaterialsList;
 import org.papervision3d.events.AnimationEvent;
 import flash.utils.Dictionary;
 
 public class ClipTestObject extends Sphere{
  public var animation:AnimationController;
  private var clipByName:Dictionary;

  public function ClipTestObject(materiallist:MaterialsList,radius:Number=100,segmentsW:int=8,segmentsH:int=6) {
   clipByName = materiallist.materialsByName;
   var material:MaterialObject3D=materiallist.getMaterialByName("all");
   super(material,radius,segmentsW,segmentsH);
   animation=new AnimationController();
   animation.addEventListener(AnimationEvent.START,clipHandler);
   animation.addEventListener(AnimationEvent.COMPLETE,clipHandler);
  }
  
  public override function project(parent:DisplayObject3D, renderSessionData:RenderSessionData):Number
  {
   animation.update();
   return super.project(parent, renderSessionData);
  }

  private function clipHandler(e:AnimationEvent){
   var clip:MaterialObject3D;
   switch(e.type){
    case "animationStart":
     clip=clipByName[e.clip];
     this.material=clip;
     MovieClip(MovieAssetMaterial(clip).movie).gotoAndPlay(0);
     break;
    case "animationComplete":
     clip=clipByName["all"];
     this.material=clip;
     MovieClip(MovieAssetMaterial(clip).movie).gotoAndStop(0);
     break;
   }
  }
 }
}

そしてこっちがMcTest04.as。球は左右に回転するようにしてあるよ。

package  {
 import org.papervision3d.core.proto.*;
 import org.papervision3d.objects.DisplayObject3D;
 import org.papervision3d.core.render.data.RenderSessionData;
 import org.papervision3d.objects.primitives.Sphere;
 import org.papervision3d.core.controller.AnimationController;
 import org.papervision3d.materials.MovieAssetMaterial;
 import flash.display.MovieClip;
 import org.papervision3d.materials.utils.MaterialsList;
 import org.papervision3d.events.AnimationEvent;
 import flash.utils.Dictionary;
 
 public class ClipTestObject extends Sphere{
  public var animation:AnimationController;
  private var clipByName:Dictionary;
  public function ClipTestObject(materiallist:MaterialsList,radius:Number=100,segmentsW:int=8,segmentsH:int=6) {
   clipByName = materiallist.materialsByName;
   var material:MaterialObject3D=materiallist.getMaterialByName("all");
   super(material,radius,segmentsW,segmentsH);
   animation=new AnimationController();
   animation.addEventListener(AnimationEvent.START,clipHandler);
   animation.addEventListener(AnimationEvent.COMPLETE,clipHandler);
  }
  
  public override function project(parent:DisplayObject3D, renderSessionData:RenderSessionData):Number
  {
   animation.update();
   return super.project(parent, renderSessionData);
  }

  private function clipHandler(e:AnimationEvent){
   var clip:MaterialObject3D;
   switch(e.type){
    case "animationStart":
     clip=clipByName[e.clip];
     this.material=clip;
     MovieClip(MovieAssetMaterial(clip).movie).gotoAndPlay(0);
     break;
    case "animationComplete":
     clip=clipByName["all"];
     this.material=clip;
     MovieClip(MovieAssetMaterial(clip).movie).gotoAndStop(0);
     break;
   }
  }
 }
}

そしてFLASHでPaperVision3Dが使えるように、FLASHの環境設定のActionScriptの項目の言語:「ActionScript3.0設定」でソースパスにPaperVision3Dをインストールした「src」フォルダのパスを設定してあるよ。

これがその結果。下のボタンをクリックするとムービークリップが再生される。

Adobe Flash Player を取得

ファイルはアップしてあるのでFLASH CS5を持っていたらダウンロードしてみてね。

中身についての話はまた次回。

modoカテゴリー別ページ



take_z_ultima at 11:30|この記事のURLComments(0)TrackBack(0)modo | FLASH

2010年10月26日

clothやってみた その6 3dsmax 2011

ジェイムズ・P・ホーガン亡くなってたのかよ・・・orz

SF作家ジェイムズ・P・ホーガン逝去

ご冥福をお祈りします。

前回は布地のプリセットにボールをぶつけた時の挙動を比較して性質の違いを比較してみた。今回はもう少し詳細に各パラメータについて調べてみたい。

まず、いまいちよくわからないベンドとカーブの違い。デフォルトではベンド5、カーブ0に設定されている。

fig02

下のGIFアニメは布の下端を固定しておいて、床に落ちる布に円柱を押し付けてみたものだ。

ベンドは曲げに対する抵抗力で、これがベンド5で

fig01

これがベンド50

fig07

そしてこれがベンド200にしたもの。

fig06

ベンドは曲げに対する抵抗力だからちょっとでも曲がろうとすると働きだして、原型を維持しようとする。下はさらにベンドを6000にしたもの。ベンドが大きくなるほど布地にモッサリ感が出てきて、厚手で強い感じの布地の感じになってくる。

fig08


それに対してカーブの方は接続するポリゴンどうしの成す角度が小さくなって行くと発生する抵抗力で、ある程度急峻に折れ曲がるまで殆ど発生しない。

これも値を変えて比較してみると、

まずこれがデフォルトのままシミュレートしてみたもの。

fig01

そしてこっちがカーブを5に設定してシミュレートしてみたもの。カーブが0のものに比べて皺のループが大きくなっている。

fig04

さらにカーブを10にしたもの。カーブを大きくするとシミュレーションが破綻しやすくなるみたいで、このシミュレーションではサブサンプルを40まで上げた。

fig05

このようにカーブの方は値を大きくして行っても皺が大きくなるだけで布の厚みは増した感じがしない。ベンドを大きくするとゴワゴワした感じになるけど、カーブを大きくしてもゴワゴワした感じにはならず、薄手で柔軟なシルクみたいな感じの生地になっていくみたいだ。

ストレッチは伸びに対する抵抗力で、圧縮は縮みに対する抵抗力。両者は逆向きの抵抗力のように感じる。しかし実際はそうでもない。

下のGIFアニメは上から引き続き布が圧縮される時の挙動だ。布が圧縮方向に力を受けると縮むより座屈して曲がる。曲がる時には曲がる外側は伸び、曲がる内側は縮む方向の力が働く。だから両者のバランスで圧縮に対しての挙動が変わってくる。

下のGIFアニメはストレッチを10、圧縮を300と圧縮の抵抗力の方を大きく取った場合。圧縮しずらいぶんだけ曲がって逃げようとして皺が増える。 

fig06

逆にストレッチ300、圧縮10にして引っ張りに対する抵抗の方を増やすと曲がるより縮もうとするから皺が出来ても縮んで解消されていく。

fig07

また、伸びの場合はシアーパラメータによって伸びと直角方向に縮みの力が発生するので同じシアーの値でも圧縮の抵抗力が小さいと下のGIFアニメのように縮む。ストレッチ10、圧縮10、シアー500

fig07

圧縮の抵抗力を増やすと縮みが少なくなる。
ストレッチ10、圧縮200、シアー500

fig09

ダンピングは速度に対する抵抗力だ。上の例のように伸縮の抵抗力を減らすと伸び縮みで振動が続くけど、ダンピングの値を増やせば振動が減衰して安定する。下のGIFアニメは上のストレッチ10、圧縮10、シアー500の状態でダンピングを0.01から0.5に変えたものだ。振動がすぐに収束しているのがわかる。

fig10

Clothは服飾メーカーでドローネメッシュを生成するとなかなかいい皺が出るね。

続きはまた次回。

maxまとめページ



take_z_ultima at 11:30|この記事のURLComments(0)TrackBack(0)3ds Max | CG

2010年10月25日

Maximaを使ってみた その15

前回はハウスホルダー行列Hでこんなベクトルを

fig01

こんなベクトルに変換できるのがわかった。

fig02

ただしa11≠ 0の時、

fig03

ところで行列をベクトルの集まりだと考えると(例えば4X4の行列で)、

fig01

これにa1をb1に変換するハウスホルダー行列をかけると

fig03

となって行列の一部を0にする事が出来る。 いま、

fig04

と置くと、H1で変換後のA行列は、

fig05

と見る事が出来る。このA1の一番左の列[b22,b32,b42]^Tを[c11,0,0]^Tに変換するハウスホルダー行列をH2'とすると、

fig06

これを使ってH2を

fig07

とする。これを行列AをH1で変換したものにかけてさらに変換すると、

fig08

となる。これを繰り返して行けば最終的に行列は上三角行列(対角の下側が全部0)の行列になっていくのがわかる。

fig09

ここでH2’がハウスホルダー行列なのでH2’はエルミート行列であり、

fig10

かつ、ユニタリー行列である。

fig11

よって、H2行列もエルミート行列であり、

fig12


ユニタリー行列である。

fig13

よって 

fig14

同様にH3,H4もエルミートかつユニタリー行列。よって行列Aの上三角行列への変換式は、

fig15


と変形できる(逆行列がオリジナルと同じだからね)。ここで、

fig16

とすると、

fig17

となり、Qはユニタリー行列。よってこれは行列AのQR分解である。

fig18

ここまではa1からb1へのベクトルの変換でa11≠0がかつa1≠0が前提だったけど、a1が0ベクトルじゃない場合でa11=0なら、

fig03

の式は計算出来なくなっちゃうけど、ハウスホルダー行列が原点を通る平面を境に面対称に点を移すものだから、a11が0のベクトルでもしかるべき対称面をとれば[b11,0,0,・・・]に移せる事は明らかで、それは原点からの距離が等しいベクトルになるはずで、

fig19

となればいいはずだ。これが以下の条件を満たせばハウスホルダー行列が存在するので、

fig04

調べてみると、

fig20

だからハウスホルダー行列は存在する。

また、a1が0ベクトルの場合やa1のa11以外の要素が0の場合は変換する必要がなく、Hは単位ベクトルでいい。

今回はMaximaの出番が無かったけど、次回はこれらをMaximaで組み立ててみたい。

それではまた次回。



take_z_ultima at 11:30|この記事のURLComments(0)TrackBack(0)Maxima 
Archives