From 9f847c5de9c3e22619c315b877f399c0e11788c5 Mon Sep 17 00:00:00 2001 From: AndrewSt Date: Thu, 19 May 2016 00:31:09 +0300 Subject: [PATCH] [Mathematics] fix bug in Collision.ClosestPointPointTriangle() --- Source/SharpDX.Mathematics/Collision.cs | 12 +++++ .../Tests/SharpDX.Tests/MathCollisionTest.cs | 47 +++++++++++++++++++ .../Tests/SharpDX.Tests/SharpDX.Tests.csproj | 1 + 3 files changed, 60 insertions(+) create mode 100644 Source/Tests/SharpDX.Tests/MathCollisionTest.cs diff --git a/Source/SharpDX.Mathematics/Collision.cs b/Source/SharpDX.Mathematics/Collision.cs index bbcf85b12..8f7d552b9 100644 --- a/Source/SharpDX.Mathematics/Collision.cs +++ b/Source/SharpDX.Mathematics/Collision.cs @@ -97,14 +97,20 @@ public static void ClosestPointPointTriangle(ref Vector3 point, ref Vector3 vert float d1 = Vector3.Dot(ab, ap); float d2 = Vector3.Dot(ac, ap); if (d1 <= 0.0f && d2 <= 0.0f) + { result = vertex1; //Barycentric coordinates (1,0,0) + return; + } //Check if P in vertex region outside B Vector3 bp = point - vertex2; float d3 = Vector3.Dot(ab, bp); float d4 = Vector3.Dot(ac, bp); if (d3 >= 0.0f && d4 <= d3) + { result = vertex2; // Barycentric coordinates (0,1,0) + return; + } //Check if P in edge region of AB, if so return projection of P onto AB float vc = d1 * d4 - d3 * d2; @@ -112,6 +118,7 @@ public static void ClosestPointPointTriangle(ref Vector3 point, ref Vector3 vert { float v = d1 / (d1 - d3); result = vertex1 + v * ab; //Barycentric coordinates (1-v,v,0) + return; } //Check if P in vertex region outside C @@ -119,7 +126,10 @@ public static void ClosestPointPointTriangle(ref Vector3 point, ref Vector3 vert float d5 = Vector3.Dot(ab, cp); float d6 = Vector3.Dot(ac, cp); if (d6 >= 0.0f && d5 <= d6) + { result = vertex3; //Barycentric coordinates (0,0,1) + return; + } //Check if P in edge region of AC, if so return projection of P onto AC float vb = d5 * d2 - d1 * d6; @@ -127,6 +137,7 @@ public static void ClosestPointPointTriangle(ref Vector3 point, ref Vector3 vert { float w = d2 / (d2 - d6); result = vertex1 + w * ac; //Barycentric coordinates (1-w,0,w) + return; } //Check if P in edge region of BC, if so return projection of P onto BC @@ -135,6 +146,7 @@ public static void ClosestPointPointTriangle(ref Vector3 point, ref Vector3 vert { float w = (d4 - d3) / ((d4 - d3) + (d5 - d6)); result = vertex2 + w * (vertex3 - vertex2); //Barycentric coordinates (0,1-w,w) + return; } //P inside face region. Compute Q through its Barycentric coordinates (u,v,w) diff --git a/Source/Tests/SharpDX.Tests/MathCollisionTest.cs b/Source/Tests/SharpDX.Tests/MathCollisionTest.cs new file mode 100644 index 000000000..bc9176ffb --- /dev/null +++ b/Source/Tests/SharpDX.Tests/MathCollisionTest.cs @@ -0,0 +1,47 @@ +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using NUnit.Framework; + +namespace SharpDX.Tests +{ + [TestFixture] + public class MathCollisionTest + { + [Test] + public void ClosestPointPointTriangleTest() + { + Assert.AreEqual(ClosestPointPointTriangle(new Vector3(0, 0, 0), new Vector3(1, 1, 0), new Vector3(2, 2, 0), new Vector3(3, 1, 0)), new Vector3(1, 1, 0)); + Assert.AreEqual(ClosestPointPointTriangle(new Vector3(1, 1, 0), new Vector3(1, 1, 0), new Vector3(2, 2, 0), new Vector3(3, 1, 0)), new Vector3(1, 1, 0)); + Assert.AreEqual(ClosestPointPointTriangle(new Vector3(2, 3, 0), new Vector3(1, 1, 0), new Vector3(2, 2, 0), new Vector3(3, 1, 0)), new Vector3(2, 2, 0)); + Assert.AreEqual(ClosestPointPointTriangle(new Vector3(4, 1, 0), new Vector3(1, 1, 0), new Vector3(2, 2, 0), new Vector3(3, 1, 0)), new Vector3(3, 1, 0)); + Assert.AreEqual(ClosestPointPointTriangle(new Vector3(1, 2, 0), new Vector3(1, 1, 0), new Vector3(2, 2, 0), new Vector3(3, 1, 0)), new Vector3(1.5f, 1.5f, 0)); + Assert.AreEqual(ClosestPointPointTriangle(new Vector3(3, 2, 0), new Vector3(1, 1, 0), new Vector3(2, 2, 0), new Vector3(3, 1, 0)), new Vector3(2.5f, 1.5f, 0)); + Assert.AreEqual(ClosestPointPointTriangle(new Vector3(2, 0, 0), new Vector3(1, 1, 0), new Vector3(2, 2, 0), new Vector3(3, 1, 0)), new Vector3(2, 1, 0)); + + Assert.AreEqual(ClosestPointPointTriangle(new Vector3(2, 1.5f, 1), new Vector3(1, 1, 0), new Vector3(2, 2, 0), new Vector3(3, 1, 0)), new Vector3(2, 1.5f, 0)); + } + private static Vector3 ClosestPointPointTriangle(Vector3 point, Vector3 vertex1, Vector3 vertex2, Vector3 vertex3) + { + Vector3 result; + Collision.ClosestPointPointTriangle(ref point, ref vertex1, ref vertex2, ref vertex3, out result); + return result; + } + } +} \ No newline at end of file diff --git a/Source/Tests/SharpDX.Tests/SharpDX.Tests.csproj b/Source/Tests/SharpDX.Tests/SharpDX.Tests.csproj index 44033824d..aac42fcde 100644 --- a/Source/Tests/SharpDX.Tests/SharpDX.Tests.csproj +++ b/Source/Tests/SharpDX.Tests/SharpDX.Tests.csproj @@ -46,6 +46,7 @@ +