2010年08月

2010年08月31日

CATで跳び箱跳んでみた その3 3dsmax 2011

前回までで走りのモーションはだいたい出来たから、今回はポイントに沿って走らせて見たい。

まずはCATリグの一部分を選択してモーションパネルからCATモーションエディタボタンを押してCATMotionパネルを出す。そしてグローバルカテゴリでパスノードボタンを押して、シーンのTargetポイントを選択する。これでポイントのパスノードに沿ってリグが走るようになる。

fig01

ただし、このままだとリグは横倒しの後ろ向きになっている。このリグの向きはCATリグを作成する時のCATRRigパラメータロールアウトの「ボーンの長さ軸」によって決まる。今回はデフォルトの「X軸」にしてあるので上方向がX軸になって前方がY軸になっている。

fig02

Targetポイントヘルパを選択して選択して回転ボタンを押し、X:180(−180でもOK)、Y:−90を入力してリグを跳び箱の方向に向ける。

fig03

これでパスモーションに沿って走るようになった。

fig04

ただ、足が地面に着く直前に地面近くで足がスライドして見えるようなので、もう少し上の方から地面を踏むように前に振り出す足を持ち上げるように変更した。

fig05

足プラットフォームのリフトの2と3のポイントを以下のように変更した。これで地面を蹴る時と着地直前の足が以前の設定より上がるようになった。

fig06

足プラットフォームの足プッシュ足の前後の振りをちょっと調整した。

fig07

これがその結果。前より踏み込みに勢いがついた感じ。

fig08

こんな感じで走るようになった。

fig09

次に歩きから走りに切り替わるようにCATMotionPresetsのレイヤウェイトをアニメーションさせる。フレーム0に移動して、レイヤ02のウェイトを0にする。

fig10

これで走りのモーションが消えて歩行モーションに切り替わる。

次にオートキーをONにして、キーの種類を切り替える。

fig11

そして36フレーム目に移動して、レイヤ02のウェイト値をちょっと増やしてから0に戻して値0でキーフレームを作る。同様に50フレームに移動して、レイヤ02のウェイトを100にする。ウェイトの右下のグラフ編集のボタンを押してグラフパネルを出してレイヤ02の変化グラフを確認すると、このようになっている。

fig12

これで歩きから走りに切り替わるようになった。次にリム位相の「ステップマスク」をONにして、targetポイントが停止している部分で足跡が何重にも重なって発生しないようにする。これで停止中の手の振りや身体を上下させる運動は抑えられる。確か足踏みも抑えられるはずなんだけど・・・足踏みが残っちゃったな・・・。

fig13

これが設定の結果。

fig14

これで見ると、ちょっと走りの1周期が早すぎるようなので、走りの最大歩幅を増やして、ポイントの移動が速い部分でストライドを広くすることにした。フレームをモーションが走り(レイヤ02)に切り替わる50フレーム以降に移動させ、グローバルカテゴリで、「最大歩幅」を200にした。

fig15

これがその結果。走りの歩幅が広くなって手足の振りの回数が減った。

fig16

それから、走り出しのところがちょっとつながりが悪いので、ウェイトアニメーションを調整する。下が調整前の状態。

fig17

CATモーションパネルのCATMotionPresetsの右下のグラフ編集のボタンを押して、

fig18

グラフうを出すとこのようになっているので、

fig19

45フレーム目を表示させて、

fig20

これがこのくらいになるようにグラフを調整する。ただしグラフの変更がすぐに画面に反映されないので、変更するごとにタイムスライダをスクラグして手動で更新する必要があるようだ。

fig22

で、こんな感じのグラフになった。最初のうちはレイヤ01を残しておいて、急激にレイヤ02に切り替わる感じになった。スタート地点が悪いだけかな?

fig21

で、こんな感じになった。まだ多少のぎこちなさは残ってるけどそれは最後に修正レイヤで調整すればいいので、こんなところでOKにしておく。

fig23


ちなみに作業がしやすいようにTargetポイントにカメラをペアレントして、カメラがリグといっしょに移動するようにして、ビューをカメラビューにしてみた。

それではまた次回。

maxまとめページ 



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

2010年08月30日

Maximaを使ってみた その5

前回は行列の固有値と固有ベクトルをMaximaで求めてみた。 今回はそれを使った話で、例えば3X3の行列Aがあって、その行列の固有値が「λ1、λ2、λ3」、それに対する固有ベクトルが「x1、x2、x3」だったとすると、固有値と固有ベクトルの定義から以下の3つの式が成り立つ。

fig01

これを行列のかたちでまとめると、

fig02

左辺はAをくくり出し、右辺は行列の掛け算のかたちに直すと、

fig03

行列[ x1 x2 x3 ]をPに置き換えると、

fig04

この両辺にPの逆行列をかけると、

fig05

右辺のPは逆行列とかけあわされて単位行列Eになって消えるのでこのような式になる。

fig06

これを行列Aの対角化と言う。以前にも書いたけど、この左上から右下へ向けての中心を除く部分が0になっている行列はとても扱いが楽で、この行列のn乗が対角要素の各値をそれぞれn乗したものになることがわかっているし、

fig07

行列式の値は対角成分をかけたものになる。

fig08

このように物凄くシンプルな計算に持ち込めるところが行列の対角化のメリットだ。そして、対角化の式の左右の辺に前からPを、後ろからPの逆行列をかけて整理すると、元の行列AをPと対角行列で表わす事が出来る。

fig09

この時Aのn乗は、隣あうPとPの逆行列が相殺されて消えるので、

fig10

このようなかたちになり、

fig11

結局対角行列のn乗とPとPの逆行列の乗算のかたちになる。

fig12

そこで対角行列のn乗が対角要素をそれぞれn乗したものになることを利用すれば、このように表わす事ができる。これなら何乗になっても計算量はさほど増えないで済むし、λの値を見ればこの変換が発散するのか収束するのか一目瞭然でわかる。

fig13

また行列式も、逆行列の行列式が元の行列式の逆数になることから、

fig14

行列と逆行列の行列式を掛け合わせると1になる。

fig15

これを対角化した式に適用してみると、PとPの逆行列の項が消えて対角成分の掛け算になる。

fig16

具体的にやってみると、まずは行列を入力して、

fig17

次にこの行列の固有値と固有ベクトルを求める。直前に入力したので引数は%になっている。

fig18
これでこの行列の固有値は3,2,−1の3つで重複なしで、それぞれの固有ベクトルは( 1, 8/3, -4/3) , ( 1, 3, -3) , ( 1, 0, 0)をそれぞれ任意倍したものになる。

今回は得られた固有ベクトルを1倍のまま使って変換行列Pを作ると、

fig19

これも直前に固有値ベクトルを計算したのでその結果%を使って、行列を定義した。生成された変換行列Pには3つの固有ベクトルが左から順に並んでいるよ。

対角行列は固有値を対角に並べるだけで完成。ただし順番には気をつけてね。

fig20

これで対角行列も変換行列も完成したので検証してみると、変換行列×対角行列×変換行列の逆行列は元の行列Aになるはず。

fig23

下が計算結果。上で入力した行列Aと比べてみると、同じことが確認できる。

fig21

逆に変換行列の逆行列に行列Aをかけて、それに変換行列をかければ対角行列が現れる。

fig06

fig22

また、Aの行列式を計算してみると、固有値をかけた3×2×−1=−6と一致する。

fig24

それではまた次回。



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

2010年08月27日

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

知り合いからパソコントラブルの電話が来て、延々時間を取られてしまった・・・orz

電話で聞いても相手に説明能力が無いと事態を把握することもままならないし、酷い目に遭った。こういう目にたびたび遭うと自分がサポートに問い合わせる時も相手の警戒っぷりや隔靴掻痒のやりとりやこっちの言っている事をなかなか信じない態度も、「やむなし」って思えてくるんだよねぇ。

ホントにサポートのみなさん、いつもありがとうございます。

さて、前回はモーフアニメーションをpapervision3Dの中にあったMorphControllerクラスを使ってやってみた。その際テストで作ったシーンからアニメーションのキーデータは持ってこないで、こっちで適当に入力していた。

今度はそのキーデータを取り込めないかと調べていたら、なんとベジェカーブのキーだと思っていたBezierCurveKey3Dの中身がまだ何も定義されておらず、単なるCurveKey3Dだったと言う事がわかった(まだ開発途中だったのね)。

考えてみればBezierCurveKey3Dのコンストラクタに与えるパラメータが2つしか無いのはおかしいよね。そして2つのキー間のある時刻でのカーブの値は次のように処理されていた。要するにBezierCurveKey3DもLinearCurveKey3Dも扱いは一緒で、2点間を比例配分しているだけだ。

   // Get the keys and values for this interval
   endKey = kfs[index];
   startKey = kfs[index - 1];
   
   var endValue:Number = endKey.output;
   var startValue:Number = startKey.output;
   var inputInterval : Number = endKey.input - startKey.input;
   var outputInterval : Number = endValue - startValue;
   var output:Number;
   
   // TODO: handle Bezier curves.
   if(startKey is LinearCurveKey3D || startKey is BezierCurveKey3D)
   {
    output = startValue + ((input - startKey.input) / inputInterval) * outputInterval;
   }
   else
   {
    output = startValue;
   }

   return outputOffset + output; 

だからベジェカーブを持ち込むにはこのクラスの完成を待つか、自前でプログラムを用意しないとならないみたいだ。

そこでベジェ曲線をどうやって生成すればいいか調べたら2つの通過点と2つのハンドルから2点間のベジェ曲線を得る方法がわかった。

下の図を使って説明すると、黒い曲線がP1とP4を通過するベジェ曲線で、P2とP3がP1とP4から伸びる接線ハンドル、P10がその曲線上の点だ。
P10の点は媒介パラメータtを0〜1まで変化させた時にベジェ曲線上をP1からP4まで移動する点で、ベジェ曲線はこのP10の軌跡と言う事ができる。
そのP10の位置はP8とP9の2点間をt:1−tで内分する点で、P8はP5とP6をt:1−tに内分する点で、P9はP6とP7をt:1−tで内分する点で、P5、P6、P7もそれぞれP1−P2、P2−P3、P3−P4をt:1−tで内分する点だ。

fig01

P1、P4をベジェキーとして考えて、2つの点の2次元座標は横軸を時刻startKey.input、endKey.inputに、縦軸をそれぞれのキーの値startKey.output、endKey.outputとし、接線ハンドルP2とP4はハンドルの長さをweight、ハンドルの方向をタンジェントで表わしたslopeを使って定義をすると、ハンドルの基点となる点からの相対座標は下のように計算できる。

fig02

P2の座標をコードで書けばこんな感じだ。

dx = P1.weight / ( 1 + slope ^2 )^0.5
dy = dx * P1.slope
P2.x = startKey.input + dx
P2.y = startKey.output + dy  

そしてこの2点間をt:1−tで内分する点P5はこのように求められる。

P5.x = startKey.input + dx * t
P5.y = startKey.output + dy * t

P3、P7も同様にして求められ、P6はP2とP3の座標から、

P6.x=(P3.x - P2.x) * t + P2.x
P6.y=(P3.y - P2.y) * t + P2.y

と求められる。これを繰り返してP10まで辿り着けば媒介パラメータtに対するP10のX座標が時刻、Y座標がその時刻のカーブの値として算出できる。

しかし本当に欲しいのは、媒介パラメータtから辿るXY座標じゃなくて、時刻Xから値Yを求めたいわけで、式から媒介パラメータtを消して、YをXの式として表わす必要がある。そこでMaximaを使いたいところなんだけど、時間が無くなったので続きはまた次回。

ちなみにmodoのチャンネルからキーを読み出したりする話は以前書いたのでここを見てね。

modoカテゴリー別ページ



take_z_ultima at 12:20|この記事のURLComments(0)TrackBack(0)modo | FLASH

2010年08月26日

CATで跳び箱跳んでみた その2 3dsmax 2011

今敏さんのご冥福をお祈りします。・゚・(ノД`)・゚・。

さて、前回の続きだ。前回は腰(Pelvis)の上下方向(リフト)と前後方向(プッシュ)の動きを変えて、下のようなヒョコヒョコ歩きに変えるところまでやった。

fig14

これでほんのちょっとジョギングっぽい雰囲気は出たけど、まだ競歩みたいな走り方だ。走りと歩きの決定的な違い(と言い切っていいのか知らないけどw)は、両足が地面から離れる瞬間があるかどうかなので、今度は足が着地している時間と空中にある時間の比率を変えて行こう。それは脚のLiftPlantModパラメータで調整する。グラフの濃い緑の部分と薄い緑色の部分は脚の1サイクルの半分ずつの時間で、濃い部分が足を浮かして前に振り出す側の期間で、薄い方が着地して地面を踏みしめて身体を前に押し出す側の期間を表わしている(実際に着地している期間ではなく、着地している側の半サイクルね)。

fig01

グラフは真ん中で山になっている部分が脚を浮かしている部分で、左右の平らになっている部分が着地している部分を表わしている。このグラフはあくまでイメージで、意味があるのは山の両端の2つのポイントの左右方向の位置だけだ。これら2つのポイントも直接移動させる事は出来なくて、できるのは下のスライダーを操作して両端点の位置を広げたり狭めたりする事だけだ。
標準の歩行アニメーションでは片方の足が地面を離れる前にもう片方の足が着地し、2本の脚が着地している期間が重なって存在する。上のグラフの山の両端が濃い緑のエリアの中にあると、脚を浮かす側の半サイクルに着地時間が食い込んでいる事になり、1サイクルの中の着地している期間が浮いている期間より長くなる。両脚は半サイクルずらしてあるので、この濃い緑に食い込んだグラフの平らな部分で、両足が地面に着地した状態になる。

そして走っている時は両足ともに地面から浮いている瞬間が出来るので、その状態を作り出すには、逆に山の両端を薄い緑のエリアに食い込ませればいい事がわかる。そこで下のスライダを動かして0.65にしてみた。

fig02

そしてこれがその結果。左が元の0.45で右が0.65にしたもの。両足が浮いている状態が確認できる。ただし両足が地面に接地している期間が短いので、それだけ足の前後のストロークも狭くなってしまっている。

fig03

そこで今度は足のストロークを調整してみたい。
走っている人は地面を蹴った足のかかとがおしり近くまで跳ね上がり、ヒザが曲がったまま足を前に振り出し、また着地する。ストライドも広い。こういう特徴の足の動きにするためには足の前後・上下の運動を調整する必要がある。その主なパラメータは足プラットフォームのリフト、足プッシュ、ステップシェイプだ。

まず足プラットフォームの足プッシュで足が地面から離れている間の前後方向のオフセットを調整してみる。
下が足プッシュを調整したものだ。3つのポイントのパラメータを並べて表示してみたよ。同じ形状にセットする時は下のパラメータ欄の左にある緑の矢印をクリックして選択ポイントを移動し、そのポイント番号より下にあるグレーになっていない数値を入力すればいいよ。グラフは画面からはみ出ると思うけど一番右側にルーペのボタンを押すと、グラフが画面にフィットして表示されるよ。
グラフを見ていくと、濃い緑の左のふちの1の点が足が地面を離れるところ。ここから後ろに足を蹴り上げて後ろに足が流れるのでグラフが下方向にブレ、そこから今度は前方向に移動して着地点より前方に振り上げられるのでグラフは上方向に凸になり、3のポイントで着地する。

fig04

これがその結果。地面に接地している距離は変わらず、そこから前後方向のストライドが広くなった。

fig05

次に上下方向の移動を調整する足プラットフォームのリフトを調整する。足は蹴った後でかかとが高く持ち上がり、そこから前に行きながら下がっていく感じにしてみた。

fig06

これがその結果。

fig07

最後に浮いている時の足運びを調整する足プラットフォームのステップシェイプを調整する。このパラメータで調整できるのは2つのポイントの接線の長さだけで、1が地面を蹴り上げるところで2が着地するところ。各地点での接線の長さを長くすると、そのぶんだけそこにいる時間が長くなる。足が上がっている時間は同じだから例えば1の接線長さを増やすと、足が身体の後ろの方にある時間が長くなり、そのぶんだけ足を前に振り出す時間が短くなり、足を前に運ぶ速度が速くなる。このグラフは斜め部分の角度が急なほど足を前に運ぶ速度が速くなるわけだ。
今回は1も2も接線を延ばして足を前に振り出す速度をあげてみた。

fig08

これがその結果。ちょっとわかりにくいけどね。

fig09

だいぶ足運びは調整できたけど、走りに力強さが足りない感じだ。これは重心が後ろの方にかかっているせいだ。そこで今度は重心が前がかりになるように調整する。

Pelvisのオフセット位置でYの値を20にする。これで腰の位置が前の方にオフセットされる。

fig10

これがその結果。

fig11

さらにPelvisのオフセット回転のZを10に、Ribcageのオフセット回転のZを30にして上半身を前傾姿勢にしてみた。

fig12

次に腕の振りを調整する。Ribcageグループの腕のスイングを下のように設定する。このグラフは谷の部分が腕を前に振り上げたところで山の部分が腕を後ろに振ったところだ。デフォルトではふり幅が小さすぎるので大きくして、左右のオフセットで足の振りとのタイミングも調整した。

fig13

これがその結果。腕を振るとだいぶ走りっぽくなってきた。

fig14

次に肘を曲げる部分を腕のベンドで調整する。前に振った時に肘を曲げてみた。パラメータは下の通り。ポイント2だけいじってあるよ。

fig15

これがその結果。この走りは真横からしか調整してないけど、だいぶいい感じになってきた。

fig16

さらに手首の角度が気になるので、それも調整してみた。手のひらのオフセット回転を下のように設定してみた。

fig17

これがその結果。手首の角度を変えただけなのに何か力強い走りになった。

fig18

走りのモーションはだいぶ付いて来たので、次回はこれを走らせる所からかな。それではまた次回。

maxまとめページ 



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

2010年08月25日

Maximaを使ってみた その4

Windows版のMaximaには快適に使うためのフロントエンドを持ったwxMaximaがアーカイブに同梱されていて、コマンドプロンプト版を使うより遥かに快適に作業が出来るようになっている。入力した式が数学記号に直されて整った形で表示されたりするのはとても判りやすくていい。

また、メニューバーには入力を助ける様々なメニューもあるのでうまく使うと関数名のスペルに悩まされなくて済む。

例えば行列を作成する時も、AlgebraメニューからEnterMatrixを選ぶと、

fig01

このようなダイアログが出て、サイズやそれを割り当てる変数名などが指定でき、

fig02

続いてこのような入力ダイアログで行列を入力できる。

fig03

結果としてこのようにMaximaに渡されて実行される。

fig04

この行列の固有値を求めようと思ったら、直前に入力したものなら何も入力せずにいきなりAlgebraメニューからEigenvaluesを選ぶと、

fig05

固有値を求める関数に直前の結果を表わす%が渡されて固有値が計算される。

fig06

ちなみにこの計算結果の読み方は、固有値の値が2,3,−1の3通りあって、それぞれの値は各1つずつで重複なしであるって事だ。例えば固有値が5と3と3になった場合、3が重複しているので、その場合は、

[[5,3],[1,2]]

と表示される。

関数に渡す値が直前の計算結果じゃない場合は、渡したい変数を入力してから、

fig07


メニューを選んで実行すると、

fig08

入力した値が関数に渡されて実行される。

fig09

ちょっと見え辛いのでキャプ画像を編集して表示するとこんな感じ。

fig10

これは行列Mの固有値と固有ベクトルを計算させた結果だ。前の2つのリストが固有値とその重複度で、後ろの3つが各固有値に対する固有ベクトルだ。

ちなみに固有値と固有ベクトルは行列をベクトルの変換として捉えた時、行列の変換がそのベクトルに与える変化はその長さだけになる(通常は方向も変わる)特別なベクトルと、その長さに与える倍率の事だ。行列Mの固有値をλ、それに対応する固有ベクトルをxとすると、

M=λ

が成り立つ。実際行列から固有値を求める時はこの式を変形して(Eは単位行列)、

(M−λE)

と変形してxベクトルが0ベクトル以外の解を持つことと、(M−λE)の逆行列が出来るとxは0ベクトルにその逆行列をかけたものになって0になってしまい、xが0ベクトル以外の解を持つ事と矛盾するから(M−λE)は逆行列を持たない。すなわち行列式が0になるわけで、

|M−λE|=0

の固有方程式を作って解く事になる。

fig12

行列式を展開して(ちなみにMaximaでは関数determinantで計算できるよ)、

((1−λ)(4−λ)+2)(−1−λ)=0

より、λ=−1、2、3が求められる。これを、(M−λE)x=0の式に代入すれば固有ベクトルが定められる(ただし求められるベクトルはパラメータを含んだものになっちゃうよ)。

例えばλ=−1の場合、(M−λE)x=0でxベクトルを(x1,x2,x3)とすると、

fig13

となって、x1は任意の数で、x2とx3が0となり、x1=k1とすると固有ベクトルは

fig14

になる。maximaは(1,0,0)としているけど、どうやら最初のパラメータが1になるように他のパラメータを決めているようだ。(M−λE)の自由度が1の場合、このように任意の値を持つ係数k1を1つのベクトルをかけたものが固有ベクトルになる。もしλが重解で自由度が2なら固有ベクトルは2つの任意の値を持つ係数それぞれに別々のベクトルをかけて足したものとなる。Maximaではそういう場合、片方の係数パラメータを0にした2つのベクトルとして固有ベクトルを表示するようだ。
例えばeigenvectors()関数の結果が下記のような場合、固有値が1と4で4が重解で、その重解に対して表示される2つの固有ベクトルは2つの係数パラメータの片方を0にしたもので、係数を入れた形で表わすなら下記のようになるわけだ。

fig15

これを踏まえて得た結果から、後の計算に都合がいい固有ベクトルを作り出せればいいわけだね。

さて、このように求めた固有値2に対する固有ベクトル(1,3,−3)を変数xに割り当てて(下では計算結果が入った%o3のリストの中から要素でベクトルを指定して、転置した)、それを行列Mと掛けたものと、そのベクトルに固有値2をかけたものを計算して比較してみると一致する。

fig11

ところでこれが何の役に立つかと言えば、この固有ベクトルによって行列Mの変換の見え方をとても素直なものに変える事が出来る。変換が座標軸にそって定数倍だったら簡単に計算できるからね。

それについてはまた次回。



take_z_ultima at 13:24|この記事のURLComments(0)TrackBack(0)Maxima 
Archives