Skip to content
This repository has been archived by the owner on Mar 30, 2019. It is now read-only.

Commit

Permalink
[Mathematics] fix bug in Collision.ClosestPointPointTriangle()
Browse files Browse the repository at this point in the history
  • Loading branch information
AndrewSt committed May 18, 2016
1 parent 8a2aab2 commit 9f847c5
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 0 deletions.
12 changes: 12 additions & 0 deletions Source/SharpDX.Mathematics/Collision.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,36 +97,47 @@ 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;
if (vc <= 0.0f && d1 >= 0.0f && d3 <= 0.0f)
{
float v = d1 / (d1 - d3);
result = vertex1 + v * ab; //Barycentric coordinates (1-v,v,0)
return;
}

//Check if P in vertex region outside C
Vector3 cp = point - vertex3;
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;
if (vb <= 0.0f && d2 >= 0.0f && d6 <= 0.0f)
{
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
Expand All @@ -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)
Expand Down
47 changes: 47 additions & 0 deletions Source/Tests/SharpDX.Tests/MathCollisionTest.cs
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
1 change: 1 addition & 0 deletions Source/Tests/SharpDX.Tests/SharpDX.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="MathCollisionTest.cs" />
<Compile Include="MathUtilNearEqualTests.cs" />
<Compile Include="MathUtilWrapTests.cs" />
<Compile Include="RayTests.cs" />
Expand Down

0 comments on commit 9f847c5

Please sign in to comment.