Почему моя сортировка Vector3s по часовой стрелке несовместима? - PullRequest
0 голосов
/ 30 сентября 2011

Я попытался написать класс Comparer для Vector3s (или, вернее, VertexPositionNormalTextures), который будет сортировать их список по часовой стрелке, чтобы исправить проблемы с отбраковкой моей задней поверхности.Я попытался адаптировать очень распространенный метод в сети, который получает угол между двумя векторами.Тем не менее, во время выполнения мой список жалуется, что метод сортировки несовместим, то есть, что либо два элемента сравниваются непоследовательно на разных проходах, либо элемент сравнивается с самим собой и не находит равным.класс:

public class ClockwiseSorter : IComparer<VertexPositionNormalTexture>
    {
        private Vector3 center;
        public ClockwiseSorter(Vector3 c)
        {
            center = c;
        }
        public int Compare(VertexPositionNormalTexture a, VertexPositionNormalTexture b)
        {
            Vector3 normal = Vector3.Cross(a.Position - center, b.Position - center);
            normal.Normalize();
            double theta = GetSignedAngleBetween2DVectors(a.Position - center, b.Position - center, Vector3.Cross(a.Position - center, normal));

            if (theta > 0)
                return -1;
            else if (theta < 0)
                return 1;
            else
                return 0;
        }

        /// Find the angle between two vectors. This will not only give the angle difference, but the direction.
        /// For example, it may give you -1 radian, or 1 radian, depending on the direction. Angle given will be the 
        /// angle from the FromVector to the DestVector, in radians.
        /// </summary>
        /// <param name="FromVector">Vector to start at.</param>
        /// <param name="DestVector">Destination vector.</param>
        /// <param name="DestVectorsRight">Right vector of the destination vector</param>
        /// <returns>Signed angle, in radians</returns>        
        /// <remarks>All three vectors must lie along the same plane.</remarks>
        public static double GetSignedAngleBetween2DVectors(Vector3 FromVector, Vector3 DestVector, Vector3 DestVectorsRight)
        {
            FromVector.Normalize();
            DestVector.Normalize();
            DestVectorsRight.Normalize();

            float forwardDot = Vector3.Dot(FromVector, DestVector);
            float rightDot = Vector3.Dot(FromVector, DestVectorsRight);

            // Keep dot in range to prevent rounding errors
            forwardDot = MathHelper.Clamp(forwardDot, -1.0f, 1.0f);

            double angleBetween = Math.Acos(forwardDot);

            if (rightDot < 0.0f)
                angleBetween *= -1.0f;

            return angleBetween;
        }

    }

Я получаю центральный вектор, усредняя значения всех векторов:

        private Vector3 AverageVectors(List<VertexPositionNormalTexture> vectors)
    {
        Vector3 sum = Vector3.Zero;
        foreach (VertexPositionNormalTexture vector in vectors)
            sum += vector.Position;
        return (sum / vectors.Count);
    }

Я что-то напортачу, не думаю об этом правильно?Или я неправильно рассчитал нормаль или центр?Отбраковка спины была для меня только головной болью, я отчаянно пытался двигаться дальше ...

1 Ответ

1 голос
/ 30 сентября 2011

Если у вас есть треугольник с вершинами A, B и C,

, нормаль треугольника вычисляется с помощью операции перекрестного произведения

N = (B-A) x (C-A)

, теперь вы должны определить направление движенияобычный.

enter image description here

для этого может быть полезен центр меша, который вы используете в своем коде, хотя, если меш не выпуклый, он может давать ошибочные результаты.

Вы должны определить угол между нормалью и векторной структурой от центра треугольника до центра сетки.

TriangleCenter= (A+B+C) / 3;

P = MeshCenter - TriangleCenter;

P.Normalize();
N.Normalize();

the dot product  d = P.N = |P||N|.cos(alfa)

if (d>0) P and N are in the same direction  (AntiClockWise order) 
if (d<0) P and N are in opposite direction  (Clockwise order)
...