2016-08-07 4 views
1

Мне нужно триангулировать трехмерный многоугольник (плоское множество упорядоченных вершин). Чтобы сделать это, я поворачиваю многоугольник в плоскость 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)}

enter image description here

И повернутое полигон ПР = {(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)}.

enter image description here

Y-компонента повернутых вершин равна 1, поэтому многоугольник лежит в X/Z плоскости, то будет правильно. Но форма повернутого многоугольника выглядит совершенно иначе, по сравнению с невращающимся многоугольником, и я не знаю почему.

+0

Вы используете Point или FPoint? Используйте FPoint, который является арифметикой с плавающей запятой. Точка будет округлять число до целых чисел, которые могут учитывать изменение формы. – jdweng

+0

Внутренний тип данных всех классов - double – NMO

+0

Попробуйте: new Vector3m (0.0, 0.0, 1.0) – jdweng

ответ

0

Я забыл нормализовать базисные векторы. Так должно быть:

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; 
} 
Смежные вопросы