右手系と左手系の違い
Direct3Dでプログラムを書くといつも気になるのが左手系であること。 私は最初に3DCGを学んだのがOpenGLであったこともあり、右手系に慣れていたし、学生の頃に学んだ数学も右手系であったはず。 あと、ゲーム機のGLライクなAPIも右手系が多かったと思います。 なのに、Direct3Dが左手系を採用したことで、複雑な3DCGがさらに複雑になったと思います。
右手系と左手系は行列計算が異なるだけと思っている人も多いと思いますが、一番大きな違いは、Zバッファの定義が変わることです。 右手系が-1~1の範囲であるのが、左手系では0~1の範囲になります。これに合わせて、射影変換行列が変わり、 クリッピングの範囲が変わり、外積計算のベクトルの向きが変わり、ポリゴンの面の向きが変わります。 正直、プログラムを読んだだけでは、何が正しいコードなのか良く分からなくなります。
なぜ、Direct3Dは左手系を採用したのか知っていますか?
私の記憶が正しければ、射影変換の計算やZバッファの計算が、ちょっとだけ軽かったからだと思います。 それでOpenGLとの差別化を図りたかったとのではないかと。 ハードワイヤードの時代の話で、1クロックでも早く計算したかった時代です。 今となっては射影変換もシェーダーで行うようになって、数クロックなんて気にする人はいません。 それだけのメリットのために、ゲームエンジンやCGツールを作るエンジニアは苦労しているのです。
どうせシェーダーで行列計算するのだから、シェーダーで右手系→左手系の変換をすればいいのではないか、と思ったりしますが、 左手系で作られたゲームエンジンやCGツールもあって、今更、右手系に統一することができない状態になっています。
まとめサイトを探してみたところ、こんな感じです。
https://zenn.dev/it_ks/articles/cbe27860548ea1
右手系と左手系だけでなく、Y-upなのかZ-upなのかもあって、もう統一できる状態ではないですね。
UnityやUEも左手系ですが、Y-upとZ-upの違いがありますね。(ChatGPTはUEは右手系と言ってますが、どちらが正しいのでしょうか。) CGデータは右手系が多いので、左手系のゲームエンジンはインポート時に変換しているのでしょう。
メッシュだけならシンプルに変換できますが、アニメーションが入ってくると問題が起きやすいです。 特に、3軸の回転角をアニメーションさせたデータは、簡単に変換できないです。 データをリサンプリングして、アニメーションデータを作り直せば動くと思いますが、それでもジンバルロックが起きたりします。
独自のゲームエンジンを作っている人はどうしているのですかね。マルチプラットフォームが多いことを考えると、右手系で作っていることが 多いのではと思っていますが、Direct3Dがベースのところは左手系を採用していたりするのですかね。