3Dとは?
3Dとは3次元の空間上で表現される事です。
ただ完成した絵を表示するモニターは2Dなのでプログラムで下記の工程が行われています。
- ローカル座標系からワールド座標系に変換する
- ワールド座標系からビュー座標系に変換する
- ビュー座標系からプロジェクション座標系に変換する
- プロジェクション座標系からスクリーン座標系に変換する
座標系の向きについて
3Dの座標系には右手座標系と左手座標系があります。
このように座標系の違いによりZ軸の向きが異なります。
又、回転方向もそれぞれ異なります。
左手座標系では時計回り、右手座標系では反時計回りが正の回転方向として定められています。
どちらの座標系が採用されているかは環境によって異なりますが、基本的には右手座標系が標準とされています。
DirectXでは非標準の左手座標系が採用されています。
OpenGLは右手座標系や3Dツールなどは右手座標系が採用されていることが多いです。
ローカル座標系とは?
基本的に3Dのオブジェクトは自身を中心として作成されます。
例えば敵のモデルが(X:10, Y:0, Z:10)の座標に表示されるからモデルを作ってもらう時にそこの位置に作ってもらうなんて事はしないのです。
そうやって作ってしまうとちょっと場所を変えようと思うと毎回モデルデータを修正する必要がありますし、ゲーム上で動かす時も実際の場所が分からなくなってしまいます。
なのでモデルはそれぞれが自身を中心としたローカル座標系で作成されています。
ワールド座標系とは?
ワールド座標系とはゲーム内の空間上での座標を表す座標系です。
プレイヤーや敵の位置などがここで決まるので最も多く制御する部分だと思います。
今どこにいるのか絶対値で制御することになります。
現実世界と同じような考え方なので理解もしやすい部分ではないでしょうか。
ビュー座標系
ビュー座標系とはカメラを基準として計算された空間のことです。
簡単に言うとカメラから見た空間ということです。
全てがカメラからの相対的な値として計算されます。
プロジェクション座標系
ビュー座標系ではまだカメラから見た3D空間上の値でした。
実際に画面に映るのはカメラから画角を考慮して見た視錐台(台形)の範囲です。
ただ画面は2Dなので台形は表示できないので、奥行はあるけど縦横が同じの長方形に変換します。
この際に奥にあるものほど小さく遠近感を持って見えるようにしています。
又、画面比率や奥行の範囲を絞っています。
スクリーン座標系
表示する際の画面上の位置と合わせた2D座標系です。
スケーリング等はこのタイミングに簡単に行えます。
このページでは座標系の変換について記載していきます。
基本的に座標系の変換は行列による計算で行われています。
その為、3Dのゲームを作るには行列の計算について最低限の事は理解する必要があります。
今回の座標変換の中で最低限の必要な知識を紹介していきます。
ローカル座標系からワールド座標系に変換
ローカル座標からワールド座標に変換するには主に3つの計算で行われます。
内容は拡大縮小・回転・移動の3つです。
行列の計算は意外と簡単になっています。
ローカル座標と行列を掛け合わせるだけでワールド座標に変換することができます。
ただし、注意点が一つあります。
普通の掛け算は掛ける順番によって結果は変わりませんが、行列は掛け合わせる順番に依存するのです。
なので今回の場合は下記の順番で掛けることになります。
ワールド座標変換の計算
ワールド座標 = ローカル座標 * 拡縮行列 * 回転行列 * 移動行列
ローカル座標→拡大→回転→移動
それぞれ座標の計算の順番を変えた場合はどういった結果になるか見てみましょう。
ローカル座標→拡大→移動→回転(NG例)
元々あるはずの位置から下にズレました。
これは移動してから回転したことで移動した座標も一緒に回転したからです。
このように行列の掛け合わせる順番は気を付けなくてはいけません。
ワールド座標系からビュー座標系に変換する
ビュー座標系への変換はカメラを原点とした座標にする行列を使って変換します。
カメラの原点に移動した上でカメラの向きに合わせて回転することで実現してます。
ワールド座標系→ビュー座標系
→
DirectXではいくつかの情報からビュー変換行列を作成する関数が用意されています。
ビュー座標系からプロジェクション座標系に変換する
プロジェクション座標系ではNearクリップとFarクリップに挟まれた視錐台と呼ばれる範囲を-1~1の値に納められるように変換します。
この-1~1の範囲から外に出た部分は描画前に弾かれるようになっています。
描画をクリップする空間なのでクリップ空間と呼ばれたりもします。
クリップ空間とはNearとFarの間が視錐台です。
プロジェクション座標系からスクリーン座標系に変換する
プロジェクション座標系で-1~1に納められるようにしていますが、表示先は解像度等に合わせて異なるサイズです。
ここではビューポート(表示範囲)の設定に合わせてスケーリングします。
スクリーン座標系までくれば2D描画と同じになるので実際に絵を描画することができます。
今回は実際のコードは載せていませんが、重要な内容になるので3Dのプログラムをする上で必須になります。
※余談ですが今回の記事は全て3Dで記事の処理を実装してキャプチャーした画像をしています。