回転

最終更新日14 Feb 2017 02:04

2Dにおける回転では点の周りに回転量を表すθだけ。
3Dにおける回転では、軸の周りに回転量θがいる。

回転の方向

左手座標系(DirectX)では左回りが正の方向
右手座標系(OpenGL)では右回りが正の方向
(座標系参照。)

回転手法の比較

行列 オイラー角 外積 クォータニオン
点を座標空間の間で回転させる 可能 不可能 不可能1

コード

私の調べによると、glmの場合角度はdegreeで与えるようだ(radianではない。)

glm::mat4 rotation_matrix=glm::rotate(rotation_matrix,theta,axis);

任意の軸の周りを回転させる3Dの行列

nは回転軸。
θは回転角

(1)
\begin{bmatrix} n_{x}^2(1-\cos\theta)+\cos\theta&n_x n_y(1-\cos\theta)-n_z \sin\theta&n_x n_z (1-\cos\theta)+n_y \sin\theta\\ n_x n_y(1-\cos\theta)+n_z\sin\theta & n_y^2(1-\cos\theta)+\cos\theta & n_yn_z(1-cos\theta)-n_x\sin\theta\\ n_xn_z(1-\cos\theta)-n_y\sin\theta&n_yn_z(1-\cos\theta)-n_x\sin\theta&n_z^2(1-\cos\theta)+\cos\theta \end{bmatrix}

ある基本軸周りの回転

x軸周り
glRotatef(x,1,0,0);
y軸周り
glRotatef(y,0,1,0);
z軸周り
glRotatef(z,0,0,1);
(2)
\begin{align} \left[ \begin{array}{cc} 1 & 0 & 0 & 0 \\ 0 & cosx & -sinx & 0 \\ 0 & sinx & cosx & 0 \\ 0 & 0 & 0 & 1\\ \end{array} \right] \end{align}
(3)
\begin{align} \left[ \begin{array}{cc} cosy & 0 & siny & 0 \\ 0 & 1 & 0 & 0 \\ -siny & 0 & cosy & 0 \\ 0 & 0 & 0 & 1\\ \end{array} \right] \end{align}
(4)
\begin{align} \left[ \begin{array}{cc} cosz & -sinz & 0 & 0 \\ sinz & cosz & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1\\ \end{array} \right] \end{align}
void glRotateX(T radian){
    m[5]=cos(radian);m[9]=-sin(radian);
    m[6]=sin(radian);m[10]=cos(radian);
}
void glRotateY(T radian){
    m[0]=cos(radian);m[8]=sin(radian);
    m[2]=-sin(radian);m[10]=cos(radian);
}
void glRotateZ(T radian){
    m[0]=cos(radian);m[4]=-sin(radian);
    m[1]=sin(radian);m[5]=cos(radian);
}
void glRotateX(T radian){
            m[4]=m[4]*cos(_radian)+m[8]*sin(_radian);    m[8]=m[4]*-sin(_radian)+m[8]*cos(_radian);
            m[5]=m[5]*cos(_radian)+m[9]*sin(_radian);    m[9]=m[5]*-sin(_radian)+m[9]*cos(_radian);
            m[6]=m[6]*cos(_radian)+m[10]*sin(_radian);    m[10]=m[6]*-sin(_radian)+m[10]*cos(_radian);
            m[7]=m[7]*cos(_radian)+m[11]*sin(_radian);    m[11]=m[7]*-sin(_radian)+m[11]*cos(_radian);
        }
        void glRotateY(T radian){
            m[0]=m[0]*cos(_radian)+m[8]*-sin(_radian);        m[8]=m[0]*sin(_radian)+m[8]*cos(_radian);
            m[1]=m[1]*cos(_radian)+m[9]*-sin(_radian);        m[9]=m[1]*sin(_radian)+m[9]*cos(_radian);
            m[2]=m[2]*cos(_radian)+m[10]*-sin(_radian);        m[10]=m[2]*sin(_radian)+m[10]*cos(_radian);
            m[3]=m[3]*cos(_radian)+m[11]*-sin(_radian);        m[11]=m[3]*sin(_radian)+m[11]*cos(_radian);
        }
void glRotateZ(T radian){
            m[0]=m[0]*cos(radian)+m[4]*sin(radian);        m[4]=m[0]*-sin(radian)+m[4]*cos(radian);
            m[1]=m[1]*cos(radian)+m[5]*sin(radian);        m[5]=m[1]*-sin(radian)+m[5]*cos(radian);
            m[2]=m[2]*cos(radian)+m[6]*sin(radian);        m[6]=m[2]*-sin(radian)+m[6]*cos(radian);
            m[3]=m[3]*cos(radian)+m[7]*sin(radian);        m[7]=m[3]*-sin(radian)+m[7]*cos(radian);
        }

上の3つ、x,y,zの順で掛け算するとこうなる

(5)
\begin{pmatrix} cos^2\theta & -sin\theta cos\theta & \sin \theta\\ sin^2 \theta \cos \theta-cos \theta sin\theta & -sin^3 \theta+ cos^2 \theta & -sin\theta cos \theta\\ -sin \theta \cos ^2 \theta + sin^2 \theta & -sin^2 \theta cos\theta+sin\theta cos\theta & cos^2 \theta \end{pmatrix}

ソースコード

mat3 rotatematrix(vec3 axis, float angle)
{
    axis = normalize(axis);
    float s = sin(angle);
    float c = cos(angle);
    float oc = 1.0 - c;
 
    return mat3(oc * axis.x * axis.x + c,           oc * axis.x * axis.y - axis.z * s,  oc * axis.z * axis.x + axis.y * s, 
                oc * axis.x * axis.y + axis.z * s,  oc * axis.y * axis.y + c,           oc * axis.y * axis.z - axis.x * s,  
                oc * axis.z * axis.x - axis.y * s,  oc * axis.y * axis.z + axis.x * s,  oc * axis.z * axis.z + c
              );
}

x軸、y軸、z軸各々で回転する角度を指定する関数を作る

(6)
\begin{pmatrix} cos(y)cos(z) & cos(y)sin(z) & -sin(y) & 0.0\\ sin(x)sin(y)-cos(x)sin(z) & sin(x)sin(y)+cos(x)cos(z) & sin(x)cos(y) & 0.0\\ cos(x)sin(y)cos(z)+sin(x)sin(z) & cos(x)sin(y)sin(z)-sin(x)cos(z) & cos(x)cos(y) &0.0\\ 0.0 & 0.0 & 0.0 & 1.0 \end{pmatrix}
//from https://www.shadertoy.com/view/XdlGzn
mat4 rotate( float x, float y, float z )
{
    float a = sin(x); float b = cos(x); 
    float c = sin(y); float d = cos(y); 
    float e = sin(z); float f = cos(z); 
 
    float ac = a*c;
    float bc = b*c;
 
    return mat4( d*f,      d*e,       -c, 0.0,
                 ac*f-b*e, ac*e+b*f, a*d, 0.0,
                 bc*f+a*e, bc*e-a*f, b*d, 0.0,
                 0.0,      0.0,      0.0, 1.0 );
}

model-matrix rotate

サポートサイト Wikidot.com model-matrixrotate