Я попытался написать класс 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);
}
Я что-то напортачу, не думаю об этом правильно?Или я неправильно рассчитал нормаль или центр?Отбраковка спины была для меня только головной болью, я отчаянно пытался двигаться дальше ...