DirectXとOpenGLの回転行列、回転軸、回転方向
はじめに
こんにちは!
ハンドスピナーを最近買ったなたでです!
今日も勉強会をしましょう。
本日は、DirectXとOpenGLの軸の違いに焦点をあてて
回転行列をおさらいしてみましょう。
掛ける順序
3D環境といえば、DirectX、OpenGLです。
今回、回転用の標準関数を調査して比較していきたいと思います。
比較する前に基本的な掛け算のおさらいをしましょう。
上記を確認してください。
これは、DirectX と OpenGL の計算方法の違いを表しています。
DirectX では、横行列に対して正方行列を掛け算して、横行列を求めます。
OpenGL では、正方行列に縦行列を掛け算して、縦行列を求めます。
標準関数の中身
3D環境といえば、DirectX、OpenGLです。
それぞれ、回転用の標準関数が用意されています。
.
DirectX
DirectXでは回転させる命令として、
D3DXMatrixRotation(D3DXMatrixRotationX/D3DXMatrixRotationY/D3DXMatrixRotationZ) が用意されています。
トランスフォーム (Direct3D 9) より
.
OpenGL
OpenGLでは、
glRotate(glRotated/glRotatef) が用意されています。
OpenGL Programming Guide に、標準関数の中の回転行列が書いてあります。
一見、DirectXの回転行列の転置行列となっていますが、
OpenGLでは、「掛ける順序」のように異なるため、この違いは吸収されます。
混乱しないように、DirectXのように掛け算した場合を考えたいと思います。
.
回転行列の特徴
X、Y、Zを順番に見ていくと、
対角成分が1となっている箇所があります。
回転行列は、ベクトルに掛け算することで回転させることができますが、
1となっている部分は、以前の位置と変わらないことを示します。
例えば、ベクトルa=[x,y,z]に行列rotateYをかけた場合、
a[y] の位置は1を掛けるだけであるため、変わらないわけです。
たしかに、Y軸を中心に回転させるので、yの値が変わってしまうのはおかしいですよね。
ところで、Wikipediaを見ると2次元の回転行列が書いてあります。
Wikipediaの2次元の回転行列は、θはどちらの方向に回転するのでしょうか
Wikipediaでは、下記のように書いてあります。
> ユークリッド空間の2次元空間では、原点中心の θ 回転(反時計回りを正とする)の回転行列」
この記述はすこし正確ではありませんが(後述)、
教科書でよくある次のような座標系での反時計回りを指します。
.
転置行列の特徴
Wikipediaの2次元の回転行列と、
D3DXMatrixRotationやglRotateの回転行列は似ています。
具体的には、転置行列のような関係になっていることに気が付くと思います。
ところで、回転行列は、直行行列です。
直行行列の特徴は、転置させると逆行列となります。
ここから、単純に考えるとWikipediaの2次元の回転行列は、反時計回りなので、
その転置行列に似た、D3DXMatrixRotationやglRotateは、時計回り?といった疑問がわきます。
.
回転方向
D3DXMatrixRotationやglRotateは、
実際にどのような回転方向になっているでしょうか。
同様の行列のため、同じ回転方向なのでは?
と一見思えるかもしれません……が
実はこれを考えるためには、
軸の方向の定義を考える必要があります。
例えば、
上記のような場合と
上記のような場合の2種類の座標系があった場合、
X軸の正方向で時計回りした場合、
上の図と下の図とで、体感的に回転方向が変わってくるはずです。
つまり、X軸での時計回りについては、
Y軸とZ軸の正の方向を定義しないといけません。
そして、先ほど触れた Wikipediaに記述されている
「 ユークリッド空間の2次元空間では、原点中心の θ 回転(反時計回りを正とする)」
という記述は、右がX、上がYと定義しておかないと、
「反時計回りを正とする」とは言えないのです……。
軸の定義
DirectXが左手座標系
OpenGLは右手座標系
です。
座標系 (Direct3D 9) より
.
DirectXの座標系
座標系 (Direct3D 9)を見ると、
次のような座標系となることが分かります。
上の図の座標系で各軸の方向を考慮すると、
DirectX の回転は次のようになります。
D3DXMatrixRotationX
回転方向のプラスは、原点からX軸の正の方向を向いたときに、反時計回りをさす。
D3DXMatrixRotationY
回転方向のプラスは、原点からY軸の正の方向を向いたときに、反時計回りをさす。
D3DXMatrixRotationZ
回転方向のプラスは、原点からZ軸の正の方向を向いたときに、反時計回りをさす。
図に表すとこのようになります。
先ほどの数式を見る限り、時計回りに回転すると思いきや、
軸を考慮すると反時計回りをしめしていることが分かります。
.
OpenGLの座標系
OpenGL座標系は、右手座標系です。
これも同様に、
OpenGL の glRotate をあてはめると、
glRotate X
回転方向のプラスは、原点からX軸の正の方向を向いたときに、時計回りをさす。
glRotate Y
回転方向のプラスは、原点からY軸の正の方向を向いたときに、時計回りをさす。
glRotate Z
回転方向のプラスは、原点からZ軸の正の方向を向いたときに、時計回りをさす。
図に表すとこのようになります。
右ねじの法則のようですね。
座標系の違いと回転行列
回転行列を見ると、DirectXとOpenGLは同じにみえました。
しかし、座標系が異なっており、
Z軸のみが反転している関係があることから、
DirectXとOpenGLとで回転の向きが逆向きになっています。
ただし!
反時計回りとは言っても
Z軸のみに関しては、そもそも方向自体が逆にになっているため、
見た目上の動きは、DirectXとOpenGLとで同様の回転方向に見えます。
おわりに
今回、DirectXとOpenGLの標準関数の回転行列の式の解説、
そして、DirectXとOpenGLの座標系を比べて、
正方向が時計回りか反時計回りかを調べました。
DirectXとOpenGLは、Z軸の方向が逆という話はよくききますが、
見た目上の回転方向にも違いがあるという点はそんなにききません。
両方を考える場合は、これらを注意する必要があります。