Android 为什么矩阵是顺时针旋转的?
我很困惑,为什么android的矩阵类的multiplyMV方法似乎是顺时针旋转我的向量坐标,而我认为它是逆时针的 在此代码中,pos是向量坐标,设置为,矩阵将围绕Z轴旋转坐标向量-45度。我希望结果向量坐标位于象限中,即。但是,它将坐标旋转到相反的方向,即象限,即Android 为什么矩阵是顺时针旋转的?,android,math,vector,matrix,Android,Math,Vector,Matrix,我很困惑,为什么android的矩阵类的multiplyMV方法似乎是顺时针旋转我的向量坐标,而我认为它是逆时针的 在此代码中,pos是向量坐标,设置为,矩阵将围绕Z轴旋转坐标向量-45度。我希望结果向量坐标位于象限中,即。但是,它将坐标旋转到相反的方向,即象限,即 Matrix4 mtxRot = Matrix4.InitRotateEulerXYZ(0.0f, 0.0f, -45f); pos.Set(0.0f, 5.0f ,0.0f); mtxRot.TransformCoordVec(p
Matrix4 mtxRot = Matrix4.InitRotateEulerXYZ(0.0f, 0.0f, -45f);
pos.Set(0.0f, 5.0f ,0.0f);
mtxRot.TransformCoordVec(pos);
这是我在Matrix4.InitRotateEulerXYZ中的位置
public static Matrix4 InitRotateEulerXYZ(float x, float y, float z)
{
Matrix4 rotMatrix = new Matrix4();
/* XYZ = | cz*cy, sz*cx + cz*sy*sx, sz*sx - cz*sy*cx |
| -sz*cy, cz*cx - sz*sy*sx, cz*sx + sz*sy*cx |
| sy, -cy*sx, cy*cx | */
// Convert from degrees to radians
x = MathHelper.DegreesToRadians(x);
y = MathHelper.DegreesToRadians(y);
z = MathHelper.DegreesToRadians(z);
rotMatrix.GetArray()[0] = MathHelper.Cos(z) * MathHelper.Cos(y);
rotMatrix.GetArray()[1] = -MathHelper.Sin(z) * MathHelper.Cos(y);
rotMatrix.GetArray()[2] = MathHelper.Sin(y);
rotMatrix.GetArray()[4] = (MathHelper.Sin(z) * MathHelper.Cos(x)) + (MathHelper.Cos(z) * MathHelper.Sin(y) * MathHelper.Sin(x));
rotMatrix.GetArray()[5] = (MathHelper.Cos(z) * MathHelper.Cos(x)) - (MathHelper.Sin(z) * MathHelper.Sin(y) * MathHelper.Sin(x));
rotMatrix.GetArray()[6] = -(MathHelper.Cos(y) * MathHelper.Sin(x));
rotMatrix.GetArray()[8 ] = (MathHelper.Sin(z) * MathHelper.Sin(x)) - (MathHelper.Cos(z) * MathHelper.Sin(y) * MathHelper.Cos(x));
rotMatrix.GetArray()[9 ] = (MathHelper.Cos(z) * MathHelper.Sin(x)) + (MathHelper.Sin(z) * MathHelper.Sin(y) * MathHelper.Cos(x));
rotMatrix.GetArray()[10] = MathHelper.Cos(y) * MathHelper.Cos(x);
return rotMatrix;
}
public static Matrix4 InitRotateEulerXYZ(float x, float y, float z)
{
Matrix4 rotMatrix = new Matrix4();
// Convert from degrees to radians
x = MathHelper.DegreesToRadians(x);
y = MathHelper.DegreesToRadians(y);
z = MathHelper.DegreesToRadians(z);
rotMatrix.matrix[0] = MathHelper.Cos(z) * MathHelper.Cos(y);
rotMatrix.matrix[1] = (MathHelper.Sin(z) * MathHelper.Cos(x)) + (MathHelper.Cos(z) * MathHelper.Sin(y) * MathHelper.Sin(x));
rotMatrix.matrix[2] = (MathHelper.Sin(z) * MathHelper.Sin(x)) - (MathHelper.Cos(z) * MathHelper.Sin(y) * MathHelper.Cos(x));
rotMatrix.matrix[4] = -MathHelper.Cos(y) * MathHelper.Sin(z);
rotMatrix.matrix[5] = (MathHelper.Cos(z) * MathHelper.Cos(x)) - (MathHelper.Sin(z) * MathHelper.Sin(y) * MathHelper.Sin(x));
rotMatrix.matrix[6] = (MathHelper.Cos(z) * MathHelper.Sin(x)) + (MathHelper.Sin(z) * MathHelper.Sin(y) * MathHelper.Cos(x));
rotMatrix.matrix[8 ] = MathHelper.Sin(y);
rotMatrix.matrix[9 ] = -(MathHelper.Cos(y) * MathHelper.Sin(x));
rotMatrix.matrix[10] = MathHelper.Cos(y) * MathHelper.Cos(x);
return rotMatrix;
}
这是我的Matrix4.TransformCoordVec方法
public Vector3 TransformCoordVec(Vector3 vec3)
{
Matrix4.inVec[0] = vec3.X;
Matrix4.inVec[1] = vec3.Y;
Matrix4.inVec[2] = vec3.Z;
Matrix4.inVec[3] = 1.0f; // homogeneousCoord
Matrix.multiplyMV(Matrix4.outVec, 0, this.matrix, 0, Matrix4.inVec, 0);
vec3.X = Matrix4.outVec[0]; vec3.Y = Matrix4.outVec[1]; vec3.Z = Matrix4.outVec[2];
return vec3;
}
非常感谢您的帮助
固定的
InitRotateEulerXYZ和我的四元数ToMatrix()方法需要进行转置,以便对正角度进行逆时针旋转。以下是正确的方法
四元数
/**Converts a quanternion to its equivilant matrix form**/
public Matrix4 ToMatrix()
{
// First, lets check if we need to re-normalize our quaternion
if(normalRegenerationCount <= 1000)
{
Normalize();
}
float x2 = x * x;
float y2 = y * y;
float z2 = z * z;
float xy = x * y;
float xz = x * z;
float yz = y * z;
float wx = w * x;
float wy = w * y;
float wz = w * z;
Matrix4 result = new Matrix4();
// This calculation would be a lot more complicated for non-unit length quaternions
// Note: The constructor of Matrix4 expects the Matrix in column-major format like expected by
// OpenGL
result.Set_11(1.0f - (2.0f * (y2 + z2)));
result.Set_12(2.0f * (xy + wz));
result.Set_13(2.0f * (xz - wy));
result.Set_14(0.0f);
result.Set_21(2.0f * (xy - wz));
result.Set_22(1.0f - (2.0f * (x2 + z2)));
result.Set_23(2.0f * (yz + wx));
result.Set_24(0.0f);
result.Set_31(2.0f * (xz + wy));
result.Set_32(2.0f * (yz - wx));
result.Set_33(1.0f - (2.0f * (x2 + y2)));
result.Set_34(0.0f);
result.Set_41(0.0f);
result.Set_42(0.0f);
result.Set_43(0.0f);
result.Set_44(1.0f);
return result;
}
通过在
InitRotateEulerXYZ
中将X和Y设置为0作为参数,并乘以(0,5,0,0),简化已创建的矩阵,可以得到:
代入θ=-π/4,得到的矢量如下所示:
| 5*sin(-π/4) | | -5*sin(π/4) |
| 5*cos(-π/4) | | 5*cos(π/4) |
| 0 | = | 0 |
| 0 | | 0 |
这正是你所看到的答案。所以,我建议Android矩阵乘法例程没有问题。您应该重新检查矩阵乘法的推导,或者简单地选择其中一个并相应地调整代码
或者,您可以使用内置方法,让系统为您生成它。您只需要确保矩阵乘法的顺序与您的意图一致,因为有多种方法可以生成这些矩阵
另一个要考虑的是,使用欧拉旋转矩阵通常是一种很差的通用旋转方法,因为它们受到GimBuffer之类的东西的影响。您可能想考虑其中之一,或通过使用。如果您愿意使用其中的一种方法,Android库似乎有问题。尝试聚合对其中一种rotateM方法的调用序列,以生成最终的旋转矩阵,并注意与您的方法相比的差异(如果有)。不管是哪种方式,都可以在这里发布新代码。试着乘以这个矩阵的转置,看看是否可以修复它。谢谢,你让我开心了!我的推论是错误的。我想它们是为左手坐标系设计的。我很高兴android方法没有问题。实际上,我也使用四元数和角度轴。事实上,当我注意到四元数向量旋转与四元数生成的旋转矩阵旋转的角度相反时,我遇到了这个问题。
| 5*sin(-π/4) | | -5*sin(π/4) |
| 5*cos(-π/4) | | 5*cos(π/4) |
| 0 | = | 0 |
| 0 | | 0 |