为什么我的顺时针排序Vector3s不一致?

时间:2011-09-30 06:22:05

标签: math xna xna-4.0

我试图为Vector3s(或者更确切地说,VertexPositionNormalTextures)编写一个Comparer类,它将按顺时针顺序对它们的列表进行排序,以便修复我的背面剔除问题。我试图在网络上采用一种非常常见的方法,它在两个向量之间得到一个有符号的角度。但是,在运行时,我的列表抱怨排序方法不一致,也就是说两个项目在不同的传递上不一致地进行比较,或者一个项目与自身进行比较而不相等。

这是比较者类:

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 个答案:

答案 0 :(得分:1)

如果你有一个带顶点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)