スポンサーサイト

--年--月--日 --:--

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

ペルトマッピングあれこれ その2

2006年09月19日 17:54

前回からの続き~!
ってことでペルトマッピングのこと書きます。


前回はエッジの処理方法まで書きました。

後は各頂点間をバネモデルで結び、カッティングエッジ部分を外側に引っ張るだけです。


これだけなんですけど、そう簡単には行きません。

まず問題点を列挙しましょう。
・各頂点間を結ぶ時、どうやって新しく生成したエッジの頂点を対応させるか?
・カッティングエッジ部分を引っ張る方向はどうやってきめるのか?

この2つが大まかな問題として存在します。


それでは順に説明しましょう。
まず「どうやって新しく生成したエッジの頂点に対応させるか?」は、前回生成したエッジの座標系を使用します。
まず、カッティングエッジで使用されている頂点を含む三角形だけ処理します。
それ以外は単純にバネモデルで結ぶだけでOKです。

ちょっと長ったらしいので カッティングエッジで使用されている頂点 を TweakVert と呼称します。



さて、TweakVert を含む三角形には4つの場合があります。
・TweakVert を3つ含む三角形(カッティングエッジを2つ含む三角形)
・カッティングエッジを1つ含む三角形
・カッティングエッジは含まないけど TweakVert を2つ含む三角形
・TweakVert を1つ含む三角形


一番特殊なのは TweakVert を3つ含む三角形ですね。
この場合、「カッティングエッジの1筆書きリスト」で連続して3つ全ての頂点が出ている箇所を調べ(かならずあるはずです)
その対応頂点でバネモデルを作成します。


次に特殊なのは2番目のカッティングエッジを一つ含む三角形。
この場合は、TweakVert じゃない頂点がエッジ座標系のX軸との内積が正か負かで対応頂点(たとえば逆向きの方でX軸との内積が正だった場合、新しく生成された頂点になる)を決めます。


次はカッティングエッジは含まないけど TweakVert を2つ含む場合。
この場合だとほぼ次の TweakVert を1つ含む場合と一緒に処理できます。
用は、きちんと対応する TweakVert を探せば言い訳なので、一番近いエッジを探し、座標系のX軸との内積が正か負かを調べればOKです。
正の場合は順、負の場合は逆になるので、対応する頂点を設定します。


これで、バネモデルの構築は終わりました。



次の問題は TweakVert の引っ張る方向です。
コレに関してもエッジの座標系のX軸を使います。

まず下準備として TweakVert で「共分散行列を対角化する行列」を求めます。
要は「最適な姿勢のバウンティングボックス」を求めます。
なぜ求めるか?は「共分散行列を対角化する行列」を求める最中に、「一番偏りが少ない軸」を見つけることが出来るからです。
「一番偏りが少ない軸」を「面法線とする平面」は、投影するにはもってこいなわけです。


次に、エッジを構成している TweakVert にその TweakVert が使用しているエッジの座標系のX軸を累積加算していきます。
全ての TweakVert に対して処理が終わったら、加算結果を正規化し方向にします。

その後、各 TweakVert の位置から先ほど求めた平面に最短線を引きます。
また、モデル中央からも同様に平面に最短線を引きます。


次からは全てこの平面上で行う処理です。


先ほど求めた TweakVert の方向ベクトル、これをそのまま使用するだけじゃ綺麗に放射状に広がりません。
同じく先ほど求めたモデル中央からの最短線でぶつかった点と TweakVert の各位置から引いた最短線がぶつかった点で方向ベクトルを求めます。
これをいい割合で TweakVert の方向ベクトルに加算してやることで綺麗に放射する方向ベクトルが手に入ります。


ちょっとわかりにくいのでまとめてみると、、、
 ★「共分散行列を対角化する行列」から一番偏りが少ない軸を求め、
  その軸を法線とする平面を定義する。
 ①各 TweakVert が使用しているエッジの座標系のX軸を平均化した方向ベクトル
 ②モデル中央と★の平面との一番近い点 から 各 TweakVert と★の平面との一番近い点
  への方向ベクトル

 ①と②をステキな割合(あるけは ①:② = 1:2.5で設定しました)で
 混合した方向ベクトルを求める。


です。

後は展開先の平面の法線方向の射影を引いた分をこれまた正規化してやって方向を求めます。

そして、モデル中央と平面との一番近い点から求めた各 TweakVert の方向ベクトルを適当な距離だけ倍してやると綺麗に放射状に広がる引っ張り位置を求めることが出来ます。

要は、TweakVert の引っ張り位置を放射状におきたいわけです。
各自いいと思うアイディアでやってみてください。

あるけがやった方法は答えではありません。一種の提案です。
無論、これより結果がいい方法があるでしょう。




さて、出来上がったツールはというと、、、。

pelt0.jpg


pelt1.jpg



こんな感じになりました。

これは球体をペルト(展開)している様をあらわしています。


ってことで、後はUIとかを作ればツールとして完成だけど、面倒だから一旦放置w


次はなにやろうかなー(・∀・)y‐┛~~



blog_rank

スポンサーサイト

ペルトマッピングあれこれ その1

2006年09月08日 23:24

プライベートのことで色々あったせいか、ちょっとブログ書く元気がありません。。

google とかから検索で飛んできてくれた人やこんなページでもブックマークしてくれている奇特な人に大変申し訳ないです( ;Д⊂ヽ


ってことで、ブログを閉鎖します!


・・・・っていうのはウソですw


書く元気がないからって何もやってないわけじゃないですよ(・∀・)
あ、けど Closure のことはもうちょっと元気が出た時にでも書きますね。
あれは説明するのも労力が必要なので( ;Д⊂ヽ


今日は今やってることなんかをちょっとまとめるために書きます。


今は PeltMapping っていう処理をやっています。
これは、モデルデータのUVを「アジのヒラキ」みたいに展開(Unfold)する処理です。
3D Studio Max 8 の UV Pelt Mapping 機能ですね。


2000年ぐらいの Siggraph に出てた論文を元に作っています。
・・・っていうけど、原理は恐ろしいほど強引で簡単なんですけどねw

とりあえず、参考になるURLを上げておきます。
http://www.cgl.uwaterloo.ca/~krmoule/talks/pelt/intro.html

ちなみに、Model Pelting のプラグインは Maya のはフリーでありますし、 XSI のも多分あるでしょう。確かめてないけどw

なので、デザイナーさんが使う分にはメインストリームのソフトウェアでサポートされているので1から作る必要はそんなにないわけです。


ならなぜ作るのか?
もちろん自分が作ったツールでUVを気にしないでモデルに対して陰影のテクスチャを張ったりペイントしたりをやりたいからです!
テキストエディターを作ったのと同じ理由ですね(´ω`)



さて、原理はというと、上でも「簡単」で「強引」と書きましたが、物凄い簡単で物凄い強引です。
まず、「アジのヒラキ」を作る場合やらないといけないことはなんでしょうか?

切れ目を入れることですね。

PeltMapping も同じです。
UVを展開する時に展開元となる切れ目のエッジを選択します。

その後何をするかというと、、、
物理演算を行いながら実際に皮を剥ぐようにメッシュを展開していくんですねw
強引過ぎますw 考えた人単純すぎw
けど、理にかなってます。


やり方は、、、
 1:UVの展開を行うために切れ目を作成します。
 2:メッシュの頂点間を結ぶ線(エッジ)を全てばねモデルにします。。
 3:1の切れ目を引っ張ります
 4:後は布シミュレーションを行うようにばねモデルを解決しちゃえばOKです。

こう書くと簡単そうですね~。


実際は結構面倒な処理があります( ;Д⊂ヽ



まずはエッジの生成処理。

maya とかじゃ線を選択して切断コマンドしちゃえば出来ちゃいますが、自力でやる場合案外面倒です。


何が面倒なのか?
エッジでメッシュを切断した場合、当たり前ですけど切断部分の点が出来ます。
これはエッジに沿って切った場合も同様です。


切断後に出来た点をメッシュが崩れないように切断部分のポリゴンを再連結する処理がまず面倒でした。

あるけ は最近頭がなまってるせいか、あまりいい考えが思い浮かばず強引にやることにしました。
まず、切断点の頂点(これはメッシュが保持している既存の頂点になっています)のインデックスを使って、カットするエッジを用意します。
(用意の仕方はとりあえず置いておきます。まだ実装してないので( ;Д⊂ヽ
多分GUIを用意することになるでしょう。2点間の最短エッジを結ぶとかメッシュを調査して自動的にカットする部分を見つけるとか)


次に一筆書きの順番になるように切断する点を整列します。

このとき、往復で考えるところがミソです。
たとえば、
 1->2, 2->3, 3->4
と切断点が指定された場合
 1->2, 2->1, 2->3, 3->2, 3->4, 4->3
と往復でカットするエッジを配列に入れておくわけです。

この例を一筆書きの順番に並べてみると
 1->2, 2->3, 3->4, 4->3, 3->2, 2->1
になります。


こんなの簡単じゃんとか思う人いると思います。
それじゃカットするエッジが十字にクロスしてた場合を考えて見ましょう。

   4
   |
 3-2-5
   |
   1

こんな感じにですね。

この場合、一筆書きで書こうとすると、(CCW でいきます)
 1->2, 2->5, 5->2, 2->4, 4->2, 2->3, 3->2, 2->1
となります。


これを生成するところまでが第一関門。


まぁ、単純に考えて直線の為す角度を利用すればいいわけです。
為す角度っていうと内積。
けど、ただ内積を取るだけじゃ CW 方向なのか CCW 方向なのかわかりません。
そこで、あるけ はエッジに座標系を持たせました。

この座標系、一意に求まらないとダメです。
ここでもちょっと躓きました。
なんでかっていうと、1->2 のベクトルをたとえばZ軸として座標系を作成しようとしても
それは 1->2 のベクトルの周りに無限に存在することになっちゃいます。
これじゃ、使い物になりません。
Z軸だけが固定だけじゃX軸だと思って使ってても、Y軸が反転すればX軸も反転しちゃうので・・・。


それじゃどうするのか?
1->2 ベクトルを使うポリゴンを全て列挙して、そのポリゴンの面法線を加算して単位化して使いました。

こうすれば2つ(1->2 ベクトルと面法線の平均のベクトル)のベクトル(しかも必ず交差する)により座標系を固定できるんです。


後は為す角度を求めるだけです。
求め方を上記の例(クロスさせたやつ)をもとに説明しましょう。
1->2 ベクトル(以降Aベクトル)と 2->5 ベクトル(以降Bベクトル)を例にとって見ますと、
まず内積で余弦が出るので、acos( A・B ) で角度が求まります。
次に A ベクトルの座標系 M のX軸ベクトル(これをxベクトルとします)と B ベクトルで内積を取ります。
内積の方向でどっち周りなのかがわかるわけですね。
これで acos( A・B ) が CW なのか CCW なのかがわかるわけです。


さて、後は単純に角度を調べて、CCW に一番近いエッジを選んでいけばOKです。
・・・ってワケにも実は行きませんw
A ベクトルと B ベクトルの内積の結果と x ベクトルとの内積の符号、場合により x ベクトルの内積の大きさと座標系 M のY軸ベクトル y との内積の符号も使わないと実際の方向は出ないわけです。

たとえば、A・B == A・C となる C ベクトルがあったとします。
そうすると、C != B となるベクトルであった時、必ずどちらかが先に処理されるように求めなければいけません。
X ベクトルとの内積の符号だけみれば回転方向はわかりますが、回転方向が同じで A・B == A・C だった場合、先に処理された方が隣接辺と判定されてしまうでしょう。

そこで、X ベクトルとの内積の大きさと Y ベクトルとの内積の符号も使用します。
実際、A・B == A・C の時だけ判定すればいいのであまり無いかもしれません。
A・B == A・C の場合に X ベクトルとの内積と、Y・B と Y・C の符号を使って為す角度を求めます。
ちなみに、 A・B == A・C かつ X・B == X・C の場合 B == C となるので、この場合はエッジの指定方法またはポリゴン事態がおかしなデータになります。

これで一筆書きのカットするエッジリストが手に入ります。



とりあえず今日はここまで。
また気が向いたら続きを書きますw




blog_rank



最近の記事


上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。