在 OpenTK C# 中获取对象的方向

Get orientation of object in OpenTK C#

我曾经在多个阶段旋转一个对象,但无法弄清楚如何获得对象的实际方向(欧拉角)。

GL.Rotate(rotateCAx, new Vector3d(1, 0, 0));
GL.Rotate(rotateCAy, new Vector3d(0, 1, 0));
GL.Rotate(rotateCAz, new Vector3d(0, 0, 1));
GL.Rotate(xRot, new Vector3d(1, 0, 0));
GL.Rotate(yRot, new Vector3d(0, 1, 0));
GL.Rotate(zRot, new Vector3d(0, 0, 1));

现在对象的方向是什么

我建议在将角度应用到当前矩阵时更改角度的顺序:

GL.Rotate(rotateCAz, new Vector3d(1, 0, 0));
GL.Rotate(rotateCAy, new Vector3d(0, 1, 0));
GL.Rotate(rotateCAx, new Vector3d(0, 0, 1));
GL.Rotate(zRot, new Vector3d(1, 0, 0));
GL.Rotate(yRot, new Vector3d(0, 1, 0));
GL.Rotate(xRot, new Vector3d(0, 0, 1));

要么从GPU读回当前矩阵:

Matrix4 currentModelView;
GL.GetFloat(GetPName.ModelviewMatrix, out currentModelView);

或计算具有相同旋转的变换矩阵:

Matrix4 currentModelView = 
    Matrix4.CreateRotationX(xRot * (float)Math.PI / 180.0f) *
    Matrix4.CreateRotationY(yRot * (float)Math.PI / 180.0f) *
    Matrix4.CreateRotationZ(zRot * (float)Math.PI / 180.0f) * 
    Matrix4.CreateRotationX(rotateCAx * (float)Math.PI / 180.0f) *
    Matrix4.CreateRotationY(rotateCAy * (float)Math.PI / 180.0f) *
    Matrix4.CreateRotationZ(rotateCAz * (float)Math.PI / 180.0f);

转换Matrix4 to a Quaternion的旋转分量:

Quaternion q = currentModelView.ExtractRotation();

计算 Pitch, yaw, and roll angles from the Quaternion. An algorithm fro that can be found at Maths - Conversion Quaternion to Euler. I've used the OpenGL Mathematics implementation for glm::pitch, glm::yaw and glm::roll:

const double epsi = 0.0001;
double y = 2.0 * (q.Y * q.Z + q.W * q.X);
double x = q.W * q.W - q.X * q.X - q.Y * q.Y + q.Z * q.Z;

double pitch = (Math.Abs(q.X) < epsi && Math.Abs(q.Y) < epsi) ? 2.0 * Math.Atan2(q.X, q.W) : Math.Atan2(y, x);
double yaw = Math.Asin(Math.Min(Math.Max(-2.0 * (q.X * q.Z - q.W * q.Y), -1.0), 1.0));
double roll = Math.Atan2(2.0 * (q.X * q.Y + q.W * q.Z), q.W * q.W + q.X * q.X - q.Y * q.Y - q.Z * q.Z);

角度 pitchyawroll 对应于当前围绕 x、y 和 z 轴的旋转(在视图 space 中)。

float rot_x = pitch * 180.0f / (float)Math.PI; 
float rot_y = yaw   * 180.0f / (float)Math.PI; 
float rot_z = roll  * 180.0f / (float)Math.PI;