【VRChat】楽にBlenderでお着換えしたくてスクリプトに手を出した話
Attention
・こちらの記事を読んでからだとよりわかる気がするよ!
・気ままにキーを叩いたせいでだらだら紆余曲折があるから、結論だけ先に読みたい人は目次から5. まで飛ぶといいよ!
1. はじめに
昨年習得したぶれんだーすきる(笑)とやらを使ってちょくちょく非対応服を着せていた私(@uminekotatsu)ですが、ある時気づきました。
さて、ここで頂点グループについて……(省略)……とあるボーンを動かすと、そのボーンと同一の名称を持つ頂点グループ上でウエイトを塗られた部分が動きます。……(省略)……衣装のメッシュに作成されている頂点グループ名を素体のボーン名称に合わせてあげることで、素体のボーンの動きに合わせて衣装のメッシュが動くようになります。……(省略)……対応する衣装側の頂点グループの名称を素体側のボーン名称に合わせていきましょう。一文字でも違うと追従しませんので、気を付けてください。手作業となるため場合によっては労力がかかりますが、頑張りましょう。
出典:【VRChat】へっぽこでもできるBlenderを使った雑お着換えガイド
……ボーン名称を変えてあげたほうが楽なのでは……?
2. つまりどういうことだってばよ
頂点グループの名称ってボーン名称と1:1になるようにできているので、リギング後にボーン名称を変えると対応する頂点グループの名称も変わってくれるんですよね。
つまり、まず最初に素体側のボーン名称の体系に合わせて服側のボーン名称を整えてあげれば、いちいちオブジェクト毎に頂点グループ名称を変更する必要がなくなるんですね。なんで気づかなかったんですか私。
(気分的にはここに横山三国志の”お気づきになりましたか”画像を貼りたい)
3. 人間って怠けるために頑張る生き物だよね
オブジェクト毎に頂点グループ名称を変更する手間を削減できるようになって早n日(n=>100)、もっと楽したいなーって思うようになりました。
(こんなBlenderプラグインを知ってる人が居たら教えてください。私がとても喜びます。)
BlenderプラグインってPythonで書けるんだよなー、書くかー、いやでもめんどいなーってなったせいで4-5か月寝かせました。あえてね?
4. 自分で作るなら「顧客が本当に必要だったもの」をゴールに設定できる……というわけでもない
さて、いっちょPython書いてみましょう。
ただし、そのまま作り始めると迷子になりがちなので、ある程度の要件を定めましょう。職業病とか言ってはいけません。
理想としては3. で引用した通りの内容が実現できることですが、理想のものを作ろうとしてしまうと、途中でやる気が尽きてしまったりぜんぜん完成しなかったりと泥沼化することが目に見えています。そのため、本当に必要なものを考え、要件を絞ってみましょう。
7/8の自分のつぶやきを見返すと、
①素体側のボーン名称にリネームする
②素体と重複しているボーンを削除する
③素体と服のボーン接合
④リギング
⑤不要な頂点グループ一括削除
の、5つに分けることができます。この①~⑤それぞれについて、もう少し考えてみます。
①は、2. で述べた手法を自動化することですね。素体側のボーン体系を調べてそれに合わせてあげれば良さそう。
②は、名称だけ同一でもボーンの位置などが異なるために削除したくないケースがあるかもしれませんし、削除は自動化すると恐いです。
③は、結合そのものはすぐにできますが、服側のトランスフォームを維持したまま結合できない気がします。また、本機能は②とセットで実行されるべき機能です。
④は、リギング前に服の位置調整を行う必要があり、スクリプトにはできない機能と思われます。”いい感じの位置に服側メッシュを合わせる”なんて、手動でしかできそうにありませんね。
⑤は、Google先生に尋ねるといい感じのスクリプトが落ちています。
①~⑤を連続して実行するならともかく、⑤単体で使う分にはこれで十分です。
次に、「仮に自動化できた場合、手動で行ったときに比べてどのくらい楽できるか?」を考えてみます。手動時の操作の面倒くささなどから、⑤>①>②>③>④の順で自動化出来たら楽になることでしょう(個人差があります)。
しかしながら先述したように、⑤の機能を持つスクリプトはすでにありますので、①の機能を実装してみることにします。
5. プロトタイピングは作ることが重要とはいうけれど、ちゃんと動かなきゃダメだよ?
そんなわけで「服のボーン名称を素体のボーン名称に合わせてくれるBlenderスクリプト」を作成しました。
仕組みを簡単に説明します。本スクリプトは大きく4ブロックに分かれて処理を行っています。以下に、それぞれについて簡単に説明します。
素体側のボーン体系取得
まずは素体側のボーン名称を取得します。とはいえすべてのボーン名称を取得するのではなく、モデルごとに表記ゆれがある肩、上腕、前腕、手、上腿、下腿、足、つま先の8つを取得します。取得したボーン名称は左右に分けた2次元配列に格納しています。
服側のボーン名称取得
素体側と同様にボーン名称を取得します。服側のボーン名称取得~服側のボーン名称リネームを1セットで実行しています。
比較
取得した服側のボーン名称を素体側のボーン名称(配列)と比較します。比較前に「これは左上腕だよー」とか「これは右足だよー」とかわかるようにして投げてあげます。なお、この判断も力業です。かなしいね。
服側のボーン名称リネーム
服側の対象ボーンを素体側ボーンの名称にリネームします。特に言うことはないです。
やっていることは単純ですね。
6. Hyouki-Yure
本スクリプトは前述しましたように、それぞれのボーン名称を取得、比較して素体側のボーン名称に統一しているだけです。こう書いてしまうと29字ですが、実際はそう単純ではありません。
表記ゆれ(Hyouki-Yure)です。
本スクリプトの最も重要な部分は「対象のボーンか?」を判断するところです。判断するためには条件を定めてあげる必要があり、モデルごとにボーン名称に表記ゆれがあることでなかなかに大変です。どのくらい表記ゆれがあるか、前腕のボーン名称を例に説明しますと、私がこれまでに見たパターンはこんな感じ。
・Lower Arm.L
・Lower_Arm.L
・LowerArm.L
・Left Lower Arm
・Fore Arm.L
・Left Fore Arm
以下略
にゃーん(社会性フィルター)。
上記のようなバリエーションの中、どうやって対象のボーンか判断しているかというと、力業です。いい方法考えたいけど棚上げしてスパゲッティ(※)にしました。行数が増える増える。
※スパゲッティコードの意
7. Blenderスクリプトの使い方
ググればわかることですが、ググるのもめんどくさいぞーって人向けにBlenderスクリプトの使い方を書いておきます。
まずBlenderを起動し、LayoutからScriptingに移行します。
するとウインドウ中央にテキストエディタが開かれますので、上部にある開くを押下して、5. のリンク先からダウンロードしたPythonファイルを読み込みます。
Pythonスクリプトを読み込ませると、テキストエディタ右上に表示されるスクリプト実行を押下してください。
なお、スクリプト実行前には必ずファイルを保存しておき、いつでも戻れるようにしておいてください。正しく動作しなかった場合、元に戻すのが大変です。
ちなみにBlenderのバージョンについて、私は2.8x系を使用していますが、多分2.9x系でも3.0x系でも動くんじゃないでしょうか。動作確認はしてないのでご了承くださいね。
8. おわりに
というわけで、楽したくてスクリプトを書いた話でした。ソースが汚いのでリファクタリングしたいなーとか、UIつけたいなーとか考えてますが、それはおいおい。
特に、対象のボーンか判断する部分については何とかしたいですね。事前に辞書のようなものを作っておくのが良いかなーとかいろいろ考えてはいるのですが、なんともかんともいかんとも。
Pythonつよつよニキー、もしくはネキー。プルリクお待ちしていまーす。
また、スクリプトはご自由にお使いください。一応MITライセンスにしています。
スクリプトを使ってうまく動かなかったりとかエラーが起きたりとかの報告もお待ちしています。うみねこたつ(@uminekotatsu)宛にDMください。渋い顔をしながらデバッグします。
それでは、良きお着換えライフを!