クソフマス2020に寄稿したRhythms of Neon、Rosemary's Nocturne、およびINeedUにおける3Dモデル (ActorMultiVertex, 以下AMV) 製作に利用したluaであるところのGIMP_AMV.luaについて簡単な解説です。
Table of Contents
1. 具体例
2. コンセプト
3. 原理
4. 将来展望
5. 使い方
おらんと思いますが万が一使いたい人がいたら一番下を参照してください。
1. 具体例
こんなものが作れます。
実際にはこんなに複雑な形のモデルをAMVでまとめて作るのは難しいので、8つのAMVからなるパーツを複数組み合わせて作成しています。具体的には矢印が13パーツ、ランタンが3パーツ、鳥が7パーツ、右上のキャラは30パーツ、下のキャラは37パーツ (内33パーツに利用) で構成されています。頂点数は数えてないですが、下のキャラで2000~3000頂点くらいだと思います。
これが慣れれば1パーツあたり5分くらいで作れるので、まあ3時間弱でこれくらいの人型が作れるというのはそこそこ効率いいんじゃないかと思います。パーツ稼働させるとたいがい事故るのが難点です。
2. コンセプト
「平面図をそのまま3Dに」が本来のコンセプトになっています。
これはかなり初期*1の試作品です。ゲームのスクショをそのままテクスチャとして利用して、さらに3D化して各パーツを壊れたマリオネットのように動かせるというProof of Conceptとして作成したものです。これを使えば色んなオブジェクトをそこそこのクオリティでStepMania上に再現することができるので、別に絵が描けなくても何かしら作り出せるというのは中々デカいのではないかと思います。
INeedUのときはmorphさんにお願いして三面図を用意してもらい、かなり精度の高いモデリングができました。46パーツ、だいたい3時間での作成になっています。平面図をそのままテクスチャとして利用する関係上、特に真正面からの見た目が完全に二次元のイラストになるのが強みだと思います。
3. 原理
昔作った画像で恐縮なんですが基本的な原理はほとんど変わらないのでそのまま再掲します。簡単に言えば、正面および側面から見た時の輪郭をそのまま四角柱にして、その断面を八角形に補完することでそれっぽく見せています。
なので、基本的には細長い物体、それこそ長髪の一束や腕/脚に特に威力を発揮する手法になっています。一方で太い物体 (例えばINeedUのスカートのすそ) などでは八角形が限度という制約からローポリっぷりが露呈する欠点があります (パーツ分割してやればいい話ですが、それはそれで処理が重い) 。
断面の形は八角形ならば正八角形に限らないので、かなり融通は効く方です (ランタンの例では八角形を上手く調整して正方形にしたり、矢印の例ではずいぶんと変な断面を生成しています) 。要は使い方次第ってことです。
4. 将来展望
現状は影の描き込みをテクスチャ側に頼っているのですが、リアルタイムでレンダリングできるようにする予定です。
リアルタイムで面の角度から光の反射を計算して反映させる奴 (面光源版) pic.twitter.com/XicxRBauw0
— paraphrohn (@paraphrohn) 2021年1月2日
リアルタイムで面の角度から光の反射を計算して反映させる奴 (点光源版) pic.twitter.com/q8edfkJ28k
— paraphrohn (@paraphrohn) 2021年1月2日
上の例だと処理がクソ重いので実用に至ってないですが、幾分か処理を軽くする方法も思い浮かんでいるのでそのうち実装してみます。
また現状は断面が八角形固定のところを、任意の4n角形に指定できるようにもしたいですね。lua書くのがめんどくさいだけなんですが、影のレンダリングを行う場合、八角形だとちょっと無茶が出そうなのでそのうち実装することになる気がします。
それとポリゴンのフレーム表示。現状だと斜めの線が入って汚いのでちゃんとメッシュ表示できるようにしてみたいです。ただの趣味ですけど。
あとは全パーツが剛体になっているところを多少柔らかくしたかったり。ある程度の振れ幅を指定して頂点が揺れるようにすればもう少し「マシ」な3Dモデルになると思うんですけど。これはかなり難しそうなので最終目標になりそうです。
5. 使い方
機能増やしすぎて自分でも把握しきれてないので極めて基本的な部分のみです。多分読んでも意味不明だと思うので、もし使いたい人がいたらINeedUのluaとにらめっこするといいと思います。いや使う人おらんと思うけど。
① 正面、側面図をパスで囲む
基本的には一番上からスタートして、反時計回りにパスで囲んでいきます。自分がGIMPしか使えないのでGIMPの名を冠していますが、別に他のソフトでも問題無いです。
この際いくつか制約事項があって、
・正面図と側面図で、パスの点数を等しく、偶数にする
・一番上から一番下までの「往路」と、その逆の「復路」にある点数は同じにする
・正面図、側面図において、一番太い部分をたどったパスを追加で用意する
あたりがあります。基本的には上手く行きますが、慣れないと上手く行かないことが多いです。
おおざっぱには、バナナの輪切りをして指定していくと失敗しにくいです。上の画像では正面図を8等分していますが、側面図も同様に8等分して指定することでほぼほぼ上手く行きます。点数が一致するというメリットもあります。この場合、輪郭線は16点、太い部分をなぞった「追加パス」は9点になります。追加パスの点数を2倍にして2を引けば輪郭線の点数に一致するはずです。
② xy座標をluaに書き写す
そのまま、パスの各頂点の座標をluaに書き写していきます。
正面図の輪郭点はxy = {{x1,y1}, {x2,y2}, ...}
側面図の輪郭点はzy = {{x1,y1}, {x2,y2}, ...}
正面図の追加パスはxyb = {{x1,y1}, {x2,y2} ...}
側面図の追加パスはzyb = {{x1,y1}, {x2,y2} ...}
といったように写していきます。数が多くなると大変なので、パスを出力して変換できる仕組みを整えておくと楽になります。自分はsedを使ってGIMPのエクスポートパスを変換できるようにしています。こんな奴です。
1,10d
$d
s/C/ /g
s/ *//g
s/ .*//g
s/^/{/g
s/$/},/g
sedの導入については
WindowsでLinuxのコマンドが使える「BusyBox」 - 頑張らないために頑張る
この辺りを参考にbusybox64.exeを導入・起動し、上のスクリプトを例えばgimp_amv.sedとでも保存しておいて、busybox64上で
みたいに入力すれば大丈夫だと思います。ちなみにこれでも改行が残るので一括置換の必要があります……誰か助けてください。
③ パラメータ指定
テクスチャの画像名、サイズ、輪郭線の太さ、等を指定します。
意味分からん・・・・・・・・・・・・・・・・・・・・・・・・・自分で作ったのに・・・・・・・・・・・・・・・・・・・・
・raux
断面の形を指定します。後述しますが、このluaではすべてのAMVを八角柱として出力するので、その八角形がどんな形になるのかです。例えば√2/2 = 0.707を指定すると比較的形の綺麗な八角柱になり、0.5よりも小さい値を指定すれば星型になります。(下図上側)。
実際には値は2個×4セットの8つの値を指定する必要がありますが……これはそれぞれのセットがx方向 (横向き)、z方向 (奥向き) それぞれにどれだけ「尖っているか」を指定する値になっていて、これが左奥、右奥、右手前、左手前の順に4セット必要となっているためです (下図、下側)。すみません説明がめんどくさ難しいのでなんとなく察してください。よっぽどのことがない限り全部0.75くらいにしておけば問題無いです。
・color
基本的にテクスチャ側で色が付くので{1,1,1,1}で問題無いです。
・s
テクスチャのサイズです。正面図の横、縦がx、yに、側面図の横がzに相当します。基本2の累乗じゃないとズレます。
・base_xyz
パーツを稼働させたいときに、回転の中心となる座標です。例えば上腕を稼働させたい場合は、肩のあたりの点を指定します。
・actor
これなんなんですかね。ゴミですが指定する必要があります。パーツの名前入れておけばいいと思います。
・texture/texture2
テクスチャの画像名です。裏側に異なるテクスチャを使いたい場合はtexture2も指定する必要があります。ちなみにactor指定が無いと貼られません。そのうち直します。
・line_color
輪郭線の色です。実際にはテクスチャの色にここの色を掛けた値になります。例えばテクスチャの色が{1,0.5,0.5,1}で、line_colorが{0.5,0.5,0.5,1}だった場合、その部分の輪郭線の色は{0.5,0.25,0.25,1}になります。指定ない場合のデフォルトは{0.4,0.4,0.4,1}。
・outline
輪郭線の太さです。指定ない場合のデフォルトはテクスチャ横幅/192。
・outlier/outlier2
つむじ周辺など、輪郭線があるとごちゃごちゃするので消したいな~って時に。ここで指定した数値だけ、上側からの頂点で輪郭線を消せます。outlier2は下側から輪郭線を消せます。
・invert
なんかモデル全体が暗くなった場合はinvert = trueを指定すると直ります。モデルの表裏がひっくり返ってる場合にひっくり返し直す指示です。
・command
現状動作しません。カス。
・symmetry
モデルが左右、上下、前後に対称性を持つ際に、輪郭線を半分だけ指定すれば残りを保管してくれる機能です。INeedUのhead.luaとかを見ればわかると思います。
・xduplicate
現状ゴミです。一応、左右前後対称なモデルの場合のみ使えます。zoom-1で対応幅が広がることが分かったので、そのうち直します。
④ テクスチャ用意
サイズは2の累乗になるように、影とかはここに描き込むといいです。基本的に輪郭線はモデル側で補完してくれるので邪魔になります。輪郭線を塗りつぶしてやるといい感じになります。下の画像は胴体用のテクスチャ用意例。
⑤ SM5で読み込む
基本的にlocal af = Def.ActorFrame{}とActorFrameを宣言して、SetModel(af, {パラメータ類})してreturn afしたluaを用意してやればいいです。すみません具体例を見てください。
*1:最初期、パーツごとの頂点数が28固定だったのを改善した直後