何とは言わない天然水飲みたさ

Progress report 2017-W29 – 2017-W30: last-progress1

2017-W28-6 (Sat) から 2017-W30-5 (Fri) までの last-progress1 の進捗ログ。 ちょっと長くなった(というか画像がデカい)ので、日記から記事を分離した。

進捗: last-progress1

リポジトリを作りはしたが、個人開発だし feature ブランチは rebase しまくる思想を持っているので、 diff 等へのリンクは張らない。

より優れた三角形分割

優角 (concave, 180度以上の角)が1つ以内の多角形は、その角を共有する triangle fan を作ってやることで簡単に三角形分割できる。 今までは面倒だったため三角形分割は四角形に対してしか行っていなかった(何故なら優角の存在判定が楽だったから)が、これを任意の多角形に対しても行うことにした。

何故そんなことをしようと決めたかというと、表示テストで使っている(そしてゲーム本編でも使おうと考えている 中野シスターズという FBX モデルが、5角形を含んでいるからである。 勘弁してくれ。

優角の個数判定については、いつか別記事で書くことにしよう。 さて、アルゴリズムは(理論的には)問題ないはずであったが、一部の辺が短すぎるせいか、はたまた5頂点が同一平面上にないせいか、何故か優角の個数を誤って数えることがあった。

これを、 xyz のうち多角形が広がる幅が最も狭い軸を潰して xy, yz, zx 平面のいずれかに投影したのち平面上で法線を出すことで、諸問題を無視して正しく優角の個数を判定することができるようになった。

うまくいかなかった三角形分割のデバッグ出力
dots として出力されているのが、ある頂点における面の法線(隣接辺の外積)と、別の頂点における法線との内積。 当該モデルの5角形は、優角はあっても1つなので、本来は全て正か全て負か、ひとつだけ負であるかしかありえない。
5角形だけ抜き出して表示した様子
5角形だけ抜き出して、(不正確な)三角形分割後の三角形ごとに表示した様子。優角が2つある5角形は見当たらない。
成功した三角形分割のデバッグ出力
true, false は法線の向きである。いずれの5角形についても優角がたかだか1つと判定されているのがわかる。

マテリアル毎にメッシュをサブメッシュへと分割

FBX においては、単一のメッシュに対して、面ごとに別々のマテリアル(テクスチャも含む)を割り当てることができるようになっている。 よって、これを単純なシェーダで表示しようとすると、マテリアルは普通メッシュごとにひとつであるから、メッシュを分割してやらねばならない。

この作業は書くだけといえば書くだけだが、頂点配列、頂点インデックス配列、頂点インデックスインデックス配列、 UV 配列、 UV インデックス配列……といった多くのものを適切に分割する必要があるため、大変面倒だった。 (しかも UV 配列は、少なくとも {頂点, 頂点インデックス} が {UV, UV インデックス} に対応する場合の4通りのマッピングがあるため、大変ややこしく、よくエンバグした。) ここ2週間で一番面倒な作業だった。

テクスチャの wrap mode の設定

結論だけ言うと、テクスチャの wrap mode が正しくないからだった。 gfx-rs で FactoryExt::create_sampler_linear を使うと、 wrap mode として Clamp が選ばれてしまうが、 FBX 側では(ノード属性として) Repeat か Clamp か選べるようになっていて、当該モデルでは Repeat になっていた。

フラグメントシェーダでテクスチャ真っ青にしたのに肌色になってる部分……何なんだ??? https://gnusocial.cardina1.red/attachment/24547

uv.s < -0.1 || uv.s > 1.1 な部分を青にするとこうなる…… https://gnusocial.cardina1.red/attachment/24548

uv.s < -0.5 || uv.s > 1.5 にすると、こう https://gnusocial.cardina1.red/attachment/24549

uv.s < -0.8 || uv.s > 1.8 にすると、こう https://gnusocial.cardina1.red/attachment/24550

まじで uv の x 座標 1.95 とかになっとるやんけ https://gnusocial.cardina1.red/attachment/24551

0 は eRepeat だね

メッシュの描画順の制御

https://gnusocial.cardina1.red/attachment/24474 白目の部分が青くて怖いし、普通になんかバグあるなこれ

alpha が 0 の部分でクリアされてない色が見えちゃうとかそういう系かな

眼に透明テクスチャが使われてるの、予想以上に厄介だぞこれ……

やはりどうにかして虹彩の描画順を白目部分より後にしてやるしかないか

結局、指定したメッシュを後で描画するようにしたらうまくいった

ファイル名 (optional) とメッシュ名を指定して、特定のメッシュの描画を後回しにするロジックを実装することで解決した。