シミュレーションのグラフィック化は各物理モデルを考えるよりも難しい印象。
最初2D版で試してみた。竿の角度、撓り、46個の配置、PID応答、安全停止を短い開発周期で確認できることを優先した。物理が固まる前に3Dへ進むと、座標変換・カメラ・メッシュ・照明の不具合と物理バグが混在して切り分けが難しくなるためである。
3D化はOpenGL 3.3/ModernGLを用いて竿、横竹、46提灯、人体、床面、御幣を描画した。Pygameはウィンドウ・イベント・2D HUDに継続利用し、HUD面をテクスチャとしてOpenGL画面へ合成することにした。
3Dのレンダリングの順序は、
| 順序 |
処理 |
| 1 | Physics stepでPitch/Roll、FEM変位、提灯振り子、人体姿勢を更新 |
| 2 | Scene3Dで物理状態を描画用座標・Segment/Poseへ変換 |
| 3 | 共通VAO/VBOを用い、竿・横竹・人体・提灯をOpenGL描画 |
| 4 | 提灯ごとに文字デカール、蝋燭、炎を必要に応じて追加 |
| 5 | Pygame HUDをRGBAテクスチャへ転送し、3D画面へ合成 |
| 6 | カメラ・UI入力を次フレームの表示状態へ反映 |
提灯の描画は、46個それぞれに独立メッシュを生成すると無駄が多いため、提灯形状は起動時に1個の共通メッシュを生成し、各個体ではモデル行列だけを変えて描画する。上下非対称の輪郭プロファイルを回転させたメッシュへ変更し、実物の「下側が少し細い」形を表現した。
「若」は透明PNGのデカールとして提灯面へ重ねる。提灯シェルは暖色系のemissiveを持つ材質として描き、内部の蝋燭・炎と合わせて「和紙越しにぼんやり明るい」印象を近似する。これはPBRの透過散乱計算ではなく、リアルタイム性を優先した視覚近似である。(ここはサボり、というか計算が追い付かない)
3D化後は、全体系を確認するだけでは人体や提灯の細部を評価できなくなった。そこで「全体表示」「人体拡大」「提灯拡大」のカメラプリセットをマウスUIへ追加した。提灯拡大は静的な別モデルではなく、実際にシミュレーション中の1個を追尾するため、振り子・蝋燭・炎・文字の関係をそのまま検証できる。
支持技もHAND/FOREHEAD/SHOULDER/HIPを画面ボタンで切り替えられるようにし、キーボード操作はデバッグ用に取っておいた。ようするに「画面を見ながらマウスだけで操作できる」ことを優先した。
顕在化した問題点
■物理的に正しくても、見た目が不自然になる
数値上は正しい位置に46個の質点が存在していても、描画が球や単純楕円だと実物の竿燈には見えない。逆に見た目を実物へ寄せるために物理モデルまで過度に複雑化するとリアルタイム性を失う。このため「力学上必要な自由度」と「見た目に必要なメッシュ」を分離する必要があった。
■描画負荷の増大(GPU/CPU)
1個の提灯にシェル、吊り紐、文字デカール、蝋燭、炎を持たせると、46個分のdraw call、モデル行列更新、テクスチャ描画が増える。さらにHUDをPygame surfaceからOpenGL textureへ毎フレーム転送するため、物理計算だけが速くてもFPSが落ちる。
■透明・発光表現は「明るければ正しい」わけではない
提灯の内照は明るくしすぎるとネオンのようになり、弱すぎると蝋燭が見えない。御幣も白RGBを指定しても、細い円柱や面が照明を受けると暗背景上で灰色に見える。材質値だけでなく、形状の太さ、面の向き、emissive、カメラ距離を合わせて評価する必要があった。
■世界鉛直とローカル姿勢の混同
提灯が振れると、内部の蝋燭は提灯に固定されて一緒に傾く。一方、炎は重力・浮力に対して上を向く。両方を世界鉛直にすると蝋燭が提灯内部を滑っているように見え、両方を提灯ローカル姿勢にすると炎が横を向く。この違いは3D化して初めて目立った。
いやぁ、実際に画面で表示させてからこんな問題点がわかった・・・。