🌅

Mayaで左右対応する頂点の取得する(SymmetryTable)

2022/12/18に公開

Symmetry Tableって?

そもそもSymmetryTableという呼び名が正しいのかわからないけど、所謂、左右対称の対応する頂点の情報。MayaのSymmetrical TopologyやZbrushのPosableSymmetryのデータ(?)に相当するもの。

きっかけ

MayaにはTopoloical Symmetryというsymmetryオプションがあり、これがとても便利。ただ普段自分がキャラモデリングなんかをやってて思うのは、これをONにしたままモデリングすることは意外と少なくて、なにかしらをミラーしたい時だけわざわざオンにして終わったらまたOFFにするということがが多い。さらに、SymmetrizeやFlipはあるけど、Checkはないとか、左右対称データがあるなら各種デフォーマーウェイトやUVもそれでミラーしてくれよ、等々色々思うようになった。結局そのデータさえ寄越してくれればこっちでなんとかするよ、と思うわけだが、調べてもそのデータにアクセスする方法がない。となると、作るしかないかなと。

Symmetry Table

これがある程度出来上がったプラグイン。いくつか適当なモデルでテストしたけど概ね思ったとおりに動いたが、バグはまだあるかもしれない。

https://github.com/minoue/symmetryTable

自分がとった具体的なプロセスはこう。

まずトポロジー的に対象なモデルを用意する。トポロジー的に非対称なモデルにはまったく使えないのでこの話はここでお終い。しかし標準素体のようなものであれば大抵左右対称のはず。
今回はただのpolyPlane、その中央のシームを選択する。

そのエッジに接続されている左右のフェイスの頂点をとる。

[15, 16, 27, 26]
[16, 17, 28, 27]

この時、最初に選択したエッジの頂点は、

[16, 27]

この連続した数字が前者のリストには入っているが、後者には入っていない。この時、両方とも時計回り。
頂点順序を左右対称にするには両方とも16 -> 27方向に進んでいなければならない。

なので後者のセットを反転、

[27, 28, 17, 16]

そして両者を16を起点に回転する。

[16, 27, 26, 15]
[16, 27, 28, 17]

これで、

(16, 16)
(27, 27)
(26, 28)
(15, 17)

と対になるセットができる。
(今回は中央のシームを含むのでうち二つのセットは同じ数字)

同様の処理をエッジにも行う。
そして遂になるエッジを2つ選び、つながっているフェイスを選び、最初に戻り同じことする。それをずっと繰り返す。

文章にするととても分かりづらい。自分の文章力では限界があるのでイメージ画像にするとこんな感じ。

最初はPythonの再帰関数で組んだが再帰が深くなりすぎたり遅かったりで実用的ではなかった。Pythonでスマートに最適化するのもよくわからないし、いっそC++でそのまま同じものを書いたほうが早くなって楽なんじゃない?って思いC++で書き直した。ただ再帰だけはやめてstd::dequeを使用した。

案の定、速度はかなり向上した。33万頂点のキャラクターで試したところ約0.6秒だった。10秒以上かかっていたPythonに比べるとかなり早いし1秒を切っているので概ね実用出来るレベルだろうか。

結果は、

# Result: [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 21, 20, 19, 18, 17, 16 ... ]

のような形のリストで帰ってくる。
これは、頂点順序0番目のVertexに対応する反対側の頂点は10、1番目は9、2番目は8と続き、11番目は21ということ。

このデータはそのままだと使いづらいので加工する。

vtxs = cmds.createSymmetryTable(half=True)
numVert = len(vtxs)
d = {n: int(vtxs[n]) for n in range(numVert) if vtxs[n] != -1}

のように変更すると

print(d)
# Result: {6: 4, 7: 3, 8: 2, 9: 1, 10: 0, 17: 15, 18: 14, 19: 13, ....}

という辞書になり、キーが片方、値が反対側に頂点に対応することになる。
こうすれば片側のみをループして何かしらの情報を取得、反対側に転送といったことができる。
基本的にはこれがやりたかったこと。

で、これで何ができるの?

上で述べたようにミラーリングツール的なものが作れる。

かつてabSymMeshというmelスクリプトがあった。

いや、今もあるけど。今でも使っている人はいるかもしれないが、MayaにSymmetrizeとFlipが実装されたときから自分の中ではお役御免となった。abSymMeshは左右対称をチェックしてくれたり、非対称頂点を見つけて選択してくれたり、そしてそれを修正してくれたりと、ちょうど「そうそうこういうのでいいんだよ」的なツールだった。しかし前述のMayaの新機能と、いくつかの深刻な問題で使わなくなった。一つは事前に左右対称メッシュを用意しておかなければならないこと、二つ目はある程度のポリ数になると遅すぎて実用に耐えないということ。よって、「abSymMeshのTopologicalSymmetry版でめっちゃ早くなったやつ」が欲しかった。

miSymMesh

そこで上のプラグインのパチもんを作ってみた。

https://github.com/minoue/miSymMesh

現状は全然出来上がってない未完成品で、まだ頂点のチェック、ミラー、フリップしかできない。
これだけだとMayaの標準機能で出来ることとさほど変わらないが、一応チェック機能はある。
このチェック機能が地味に欲しかった。というのも、例えば仕事でデジタルダブルを作るとき、首から上は当然左右非対称で作る。だが衣服で覆われている首より下は色々と楽だからという理由で左右対称で作ってしまう。なので首以下の部分で非対称部分をさくっと見つけて修正したい。Mayaの標準のTopologicalSymmetryをオンにして首からしたの頂点全選択してSymmetrizeすれば同じじゃんって思うかもしれないが、ちがうそうじゃない。これはもう気持ちの問題かもしれない。

ということを考えている間に、キャラモデリングの仕事が終わってしまい。差し迫ってツールが必要というわけでもなくなってしまったので現在放置中。いつの日か、また再開する日が来るかもしれない。

Discussion