创建逆旋转矩阵时出错
Bug in creating inverse rotation matrix
我需要对 3D 多边形(一组平面的有序顶点)进行三角剖分。为此,我将多边形旋转到 X/Z 平面中,并对旋转的顶点应用剪耳算法。之后,我将顶点旋转回来,得到一个三角多边形。
但是,我的轮换似乎有错误。
要将我的多边形旋转到 X/Z 平面,我执行以下操作:
首先,我采用多边形的法向量并从中创建一个逆旋转矩阵
internal static Matrix4 CreateInverseRotationMatrix(Vector3 up) // up is normal vector of polygon
{
Vector3 right;
// take the longer axis and calculate a normal vector
if (up.X.AbsoluteValue > up.Z.AbsoluteValue)
right = up.Cross(new Vector3(0, 0, 1));
else
right = up.Cross(new Vector3(1, 0, 0));
// create the third vector of the matrix
var backward = right.Cross(up);
// create inverse rotation matrix
Matrix4<Rational> m = new Matrix4<Rational>(right.X, right.Y, right.Z, 0, up.X, up.Y, up.Z, 0, backward.X, backward.Y, backward.Z, 0, 0, 0, 0, 1);
return m;
}
之后,我将每个顶点与逆旋转矩阵相乘:
private List<Vector2> CreateRotatedVertexList(List<Vertex3> contourVertices, Vector3 up)
{
var matrix = Matrix4.CreateInverseRotationMatrix(up);
List<Vector2> points = new List<Vector2>();
foreach (var vertex in contourVertices)
{
var rotatedVertex = Matrix4.Multiply(matrix, vertex.Vector3);
var point = new Vector2m(rotatedVertex.X, rotatedVertex.Z);
points.Add(point);
}
return points;
}
Matrix4.Multiply 看起来像这样:
public static Vector3 Multiply(Matrix4 m, Vector3 vec4)
{
Vector3 res = Vector3.Zero();
res.X = m.M11 * vec4.X + m.M12 * vec4.Y + m.M13 * vec4.Z + m.M14;
res.Y = m.M21 * vec4.X + m.M22 * vec4.Y + m.M23 * vec4.Z + m.M24;
res.Z = m.M31 * vec4.X + m.M32 * vec4.Y + m.M33 * vec4.Z + m.M34;
var w = m.M41*vec4.X + m.M42*vec4.Y + m.M43*vec4.Z + m.M44;
return res;
}
我在 Blender 中绘制了一个示例多边形。例如,多边形 P ={(-1 1 1), (-0.5 1 0.5), (0 1 0), (0.5 0.5 0), (1 0 0), (1 -0.5 0.5), (1 - 1 1)}
并且旋转后的多边形PR = {(0 1 -4) (0,5 1 -2,5) (1 1 -1) (0,5 1 0,5) (0 1 2) (- 1 1 2) (-2 1 2)}。
旋转顶点的y轴分量均为1,所以多边形位于X/Z平面内,没错。但是与未旋转的多边形相比,旋转的多边形的形状看起来明显不同,我不知道为什么。
我忘了标准化基向量。所以应该是:
internal static Matrix4 CreateInverseRotationMatrix(Vector3 up) // up is normal vector of polygon
{
Vector3 right;
up = up.Unit();
// take the longer axis and calculate a normal vector
if (up.X.AbsoluteValue > up.Z.AbsoluteValue)
right = up.Cross(new Vector3(0, 0, 1));
else
right = up.Cross(new Vector3(1, 0, 0));
right = right.Unit();
// create the third vector of the matrix
var backward = right.Cross(up);
// create inverse rotation matrix
Matrix4<Rational> m = new Matrix4<Rational>(right.X, right.Y, right.Z, 0, up.X, up.Y, up.Z, 0, backward.X, backward.Y, backward.Z, 0, 0, 0, 0, 1);
return m;
}
我需要对 3D 多边形(一组平面的有序顶点)进行三角剖分。为此,我将多边形旋转到 X/Z 平面中,并对旋转的顶点应用剪耳算法。之后,我将顶点旋转回来,得到一个三角多边形。 但是,我的轮换似乎有错误。 要将我的多边形旋转到 X/Z 平面,我执行以下操作:
首先,我采用多边形的法向量并从中创建一个逆旋转矩阵
internal static Matrix4 CreateInverseRotationMatrix(Vector3 up) // up is normal vector of polygon
{
Vector3 right;
// take the longer axis and calculate a normal vector
if (up.X.AbsoluteValue > up.Z.AbsoluteValue)
right = up.Cross(new Vector3(0, 0, 1));
else
right = up.Cross(new Vector3(1, 0, 0));
// create the third vector of the matrix
var backward = right.Cross(up);
// create inverse rotation matrix
Matrix4<Rational> m = new Matrix4<Rational>(right.X, right.Y, right.Z, 0, up.X, up.Y, up.Z, 0, backward.X, backward.Y, backward.Z, 0, 0, 0, 0, 1);
return m;
}
之后,我将每个顶点与逆旋转矩阵相乘:
private List<Vector2> CreateRotatedVertexList(List<Vertex3> contourVertices, Vector3 up)
{
var matrix = Matrix4.CreateInverseRotationMatrix(up);
List<Vector2> points = new List<Vector2>();
foreach (var vertex in contourVertices)
{
var rotatedVertex = Matrix4.Multiply(matrix, vertex.Vector3);
var point = new Vector2m(rotatedVertex.X, rotatedVertex.Z);
points.Add(point);
}
return points;
}
Matrix4.Multiply 看起来像这样:
public static Vector3 Multiply(Matrix4 m, Vector3 vec4)
{
Vector3 res = Vector3.Zero();
res.X = m.M11 * vec4.X + m.M12 * vec4.Y + m.M13 * vec4.Z + m.M14;
res.Y = m.M21 * vec4.X + m.M22 * vec4.Y + m.M23 * vec4.Z + m.M24;
res.Z = m.M31 * vec4.X + m.M32 * vec4.Y + m.M33 * vec4.Z + m.M34;
var w = m.M41*vec4.X + m.M42*vec4.Y + m.M43*vec4.Z + m.M44;
return res;
}
我在 Blender 中绘制了一个示例多边形。例如,多边形 P ={(-1 1 1), (-0.5 1 0.5), (0 1 0), (0.5 0.5 0), (1 0 0), (1 -0.5 0.5), (1 - 1 1)}
并且旋转后的多边形PR = {(0 1 -4) (0,5 1 -2,5) (1 1 -1) (0,5 1 0,5) (0 1 2) (- 1 1 2) (-2 1 2)}。
旋转顶点的y轴分量均为1,所以多边形位于X/Z平面内,没错。但是与未旋转的多边形相比,旋转的多边形的形状看起来明显不同,我不知道为什么。
我忘了标准化基向量。所以应该是:
internal static Matrix4 CreateInverseRotationMatrix(Vector3 up) // up is normal vector of polygon
{
Vector3 right;
up = up.Unit();
// take the longer axis and calculate a normal vector
if (up.X.AbsoluteValue > up.Z.AbsoluteValue)
right = up.Cross(new Vector3(0, 0, 1));
else
right = up.Cross(new Vector3(1, 0, 0));
right = right.Unit();
// create the third vector of the matrix
var backward = right.Cross(up);
// create inverse rotation matrix
Matrix4<Rational> m = new Matrix4<Rational>(right.X, right.Y, right.Z, 0, up.X, up.Y, up.Z, 0, backward.X, backward.Y, backward.Z, 0, 0, 0, 0, 1);
return m;
}