eulerFromMat3の導出
今回のオイラー角は全てExtrinsic (毎回ワールド軸回りに回す)とする
Three.jsはIntrinsic (軸ごとぶん回す)なので逆よ
行列の各項は以下のように呼称する 忘れがちなので書いておく
$ M = \begin{bmatrix} M_{11} & M_{12} & M_{13} \\ M_{21} & M_{22} & M_{23} \\ M_{31} & M_{32} & M_{33} \end{bmatrix}
$ Rは純粋な回転行列(スケールなし)とする
いったんXYZ
$ R
$ = R_z(\theta_z) R_y(\theta_z) R_x(\theta_x)
$ = \begin{bmatrix} \cos(\theta_z) & -\sin(\theta_z) & 0 \\ \sin(\theta_z) & \cos(\theta_z) & 0 \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} \cos(\theta_y) & 0 & \sin(\theta_y) \\ 0 & 1 & 0 \\ -\sin(\theta_y) & 0 & \cos(\theta_y) \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 \\ 0 & \cos(\theta_x) & -\sin(\theta_x) \\ 0 & \sin(\theta_x) & \cos(\theta_x) \end{bmatrix}
$ = \begin{bmatrix} \cos(\theta_z) \cos(\theta_y) & -\sin(\theta_z) & \cos(\theta_z) \sin(\theta_y) \\ \sin(\theta_z) \cos(\theta_y) & \cos(\theta_z) & \sin(\theta_z) \sin(\theta_y) \\ -\sin(\theta_y) & 0 & \cos(\theta_y) \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 \\ 0 & \cos(\theta_x) & -\sin(\theta_x) \\ 0 & \sin(\theta_x) & \cos(\theta_x) \end{bmatrix}
$ = \begin{bmatrix} \cos(\theta_z) \cos(\theta_y) & -\sin(\theta_z) \cos(\theta_x) + \cos(\theta_z) \sin(\theta_y) \sin(\theta_x) & \sin(\theta_z) \sin(\theta_x) + \cos(\theta_z) \sin(\theta_y) \cos(\theta_z) \\ \sin(\theta_z) \cos(\theta_y) & \cos(\theta_z) \cos(\theta_x) + \sin(\theta_z) \sin(\theta_y) \sin(\theta_x) & -\cos(\theta_z) \sin(\theta_x) + \sin(\theta_z) \sin(\theta_y) \cos(\theta_x) \\ -\sin(\theta_y) & \cos(\theta_y) \sin(\theta_x) & \cos(\theta_y) \cos(\theta_x) \end{bmatrix}
$ R_{31} = -\sin(\theta_y)がなんかかわいいですね
$ \theta_y = -{\rm asin}(R_{31})と解釈しちゃってオッケー
この時点で$ \theta_yは$ -\frac{\pi}{2}から$ \frac{\pi}{2}の範囲 デカすぎない
$ R_{32} = \cos(\theta_y) \sin(\theta_x)と$ R_{33} = \cos(\theta_y) \cos(\theta_x)が割といい感じ
$ \theta_x = {\rm atan2}(R_{32}, R_{33})でオッケー
$ R_{11} = \cos(\theta_z) \cos(\theta_y)と$ R_{21} = \sin(\theta_z) \cos(\theta_y)もいいですね
$ \theta_z = {\rm atan2}(R_{21}, R_{11})でオッケー
ただし、$ \cos(\theta_y)が0に近すぎる場合、すなわち$ \sin(\theta_y) = R_{31}がけっこう1だった場合は要注意
この場合はz回転相当がぜんぶx回転で賄われたとして、代わりに$ R_{23} = -\sin(\theta_x)と$ R_{22} = \cos(\theta_x)をつかってやろう
$ \theta_x = {\rm atan2}(-R_{23}, R_{22})でいかがですか
回転順序が入れ替わった場合は適宜行と列の参照する箇所を入れ替えればオッケー たぶん
XZY・YXZ・ZYXの場合は、各オイラー角に-1を掛け算してやるとよい
あと、2軸ぶん回るパターンというのがある
例えば、 [-30deg, 150deg, -30deg] に対する [150deg, 30deg, 150deg] とか
$ \theta_yがデカすぎることはないので、$ \theta_xと$ \theta_zが合わせてデカすぎる場合をケアしたい
$ |\theta_x| + |\theta_z| > \piのとき、
$ \theta_x' = \theta_x + \pi
$ \theta_y' = \pi - \theta_y
$ \theta_z' = \theta_z + \pi
とすると、収まりが良くなります
絶対値が$ \piを超えちゃった箇所は、ぐるぐるして$ -\piから$ \piの範囲に抑えてやろう