読者です 読者をやめる 読者になる 読者になる

趣味プログラマによるOSS開発日誌

趣味で作っているOSSソフトウェアの紹介や関連技術の紹介、楽曲製作、Webデザイン勉強状況を紹介します。

3Dモデルを2D座標指定で表示する方法

2DのSTGでも最近のゲームは、敵や背景を3Dにして表示することが多い。

eriKsも敵を3Dで描画する予定であったが、一時的に敵の2D画像を用意してゲームのテストを行っていた。
そしてモデリングデータが完成し始めてきたので、この際に3Dモデルに切り替えを徐々に行うことにした。
しかし、eriKsの基盤になっているゲームエンジンでは、2D座標指定で敵の表示などを行っているために、3Dモデルを2D座標指定で表示する必要が出てくる。
久しぶりに数学と格闘したが無事実装できたので、今回は「3Dモデルを2D座標指定で表示する方法」を紹介する。

まず最初に理解する必要があるのは、3D座標で設定した頂点座標がスクリーン座標に変換されるまでの一連の流れであるため、簡単におさらいしておこう。

頂点座標は、ワールド座標変換-ビュー変換-射影変換-ビューポート変換を経て、ワールド座標からスクリーン座標へ変換される。
ワールド座標変換とは、並列移動・回転・拡大の変換を行い、3D空間にモデルを配置する変換のことを言う。
ビュー変換とは、カメラの傾きや注視点・カメラの位置から、3D空間内でカメラが映し出す映像を作成するための変換のことである。
射影変換は、カメラのズームの度合いや立体感を出すために行われる変換である。
これにより左上が(-1,-1)、左下が(1,1)の座標に変換される。
これからスクリーン座標に変換を行うために行われるのが、ビューポート変換である。
ビューポート変換により、例えば640×480のウィンドウなら左上が(0,0)、右上が(640,480)となる。

変換前の頂点座標を\mathbf{x}、変換後の頂点座標を\mathbf{x'}、ワールド座標変換行列をM_{World}、ビュー変換行列をM_{View}、射影変換行列をM_{Proj}、ビューポート変換行列をM_{VP}とすれば、以下の式が成り立つ。

\mathbf{x'} = \mathbf{x} M_{World} M_{View} M_{Proj} M_{VP}

今回は2D座標指定をする必要があるので、変換前の頂点座標\mathbf{x}が欲しいことになる。
従って上記式を変形すると、以下の式が成り立つ。

\mathbf{x} = \mathbf{x'} M^{-1}_{VP} M^{-1}_{Proj} M^{-1}_{View} M^{-1}_{World}

ここでM^{-1}_{World}は、モデル表示時に与えるパラメータであるため、逆行列をかける必要は無い。
また、ビューポート変換もワールド座標変換に組み込んでしまえば、上の式はさらに単純化できる。

\mathbf{x} = \mathbf{x'} M'_{World} M^{-1}_{Proj} M^{-1}_{View}

M'_{World}はビューポート変換行列の逆行列を独自に改変した、ワールド座標変換行列である。
独自に改変する部分は、ウィンドウサイズが640×480であれば、並列移動変換行列を作る際にx座標、y座標を以下のように変換すればよい。
x',y'を変換後のx座標、y座標とする。
x' = x / ( 640.0f / 2 ) - 1.0f
y' = y / ( 480.0f / 2 ) + 1.0f


以上の変換を行うことで、eriKsでも3Dモデルを2D座標指定で表示することが出来た。
スクリーンショットでは分かりづらいが。)

[参考]
http://marupeke296.com/DXG_No48_PointGroundInScreen.html