Help requested on Ray Triangle Collision

Started by
2 comments, last by clb 11 years, 9 months ago
(Sorry if the post says Ray triangle, I was first trying with a ray first, but that wouldn't work with my airplane, so I'm trying sphere triangle now.)


Hi I am new to 3D and I'm trying to create a sphere triangle collision detection. I want to use this method because I have an airplane flying above a plane which is not flat. What I would want to check is if the airplane is crashing on one of the triangles of my plane. I have been researching all around and recapping my vector math a bit, and came up with this implementation. The problem of this implementation is that the dot product with the vertices gives me a negative number ( (pointB - pointA).Dot(pointA) > 0 && (pointC - pointA).Dot(pointA) > 0) which is smaller than 0, so it returns as a hit, which is not. But the distance to the faces works fine, and the distance to the vertices too. But it actually only finds a hit on one specific point on my plane which is strange. If someone could give me some suggestions what is wrong with this implementation I would be glad.

Below I have the implementation. I load in an obj model and then push all the vertices in the vertex list which is a std vector, and all the triangles in the triangle list. the vertex list is a list of vector3 and the triangle list is a list of triangles which are compound out of three int indices. Thanks in advance.

I got this implementation from this site:
http://realtimecolli...net/blog/?p=103



// sphere - plane collision. face, edge, vertex acurate
bool Game::isColliding(MeshObject* object, float radius, MeshObject* plane)
{
for(int f = 0; f < plane->mesh->triangleList.size(); f++)
{
vector3 spherePos = object->position;

vector3 vertex0 = plane->mesh->verticeList.at(plane->mesh->triangleList[f].m_Indices[0]);
vector3 vertex1 = plane->mesh->verticeList.at(plane->mesh->triangleList[f].m_Indices[1]);
vector3 vertex2 = plane->mesh->verticeList.at(plane->mesh->triangleList[f].m_Indices[2]);

vector3 pointA = vertex0 - spherePos;
vector3 pointB = vertex1 - spherePos;
vector3 pointC = vertex2 - spherePos;

// -------------*** Face checks ***------------
// facedistance check
float distanceFace = abs(pointA.Dot(plane->mesh->triangleList[f].m_Normal));
// face separation check
float separatedf;
if(distanceFace > radius)
{ separatedf = 1;}else {separatedf = 0;}

// ----------*** end face checks ***------------

// ----------*** Vertex checks ***-------------

// vertexdistance check
float distanceVertex0 = sqrt(pointA.Dot(pointA));
float distanceVertex1 = sqrt(pointB.Dot(pointB));
float distanceVertex2 = sqrt(pointC.Dot(pointC));

// vertex separation checks
float separatedv0;
if(distanceVertex0 > radius && (pointB - pointA).Dot(pointA) > 0 && (pointC - pointA).Dot(pointA) > 0)
{separatedv0 = 1;}else{separatedv0 = 0;}
float separatedv1;
if(distanceVertex1 > radius && (pointB - pointA).Dot(pointB) > 0 && (pointC - pointB).Dot(pointB) > 0)
{separatedv1 = 1;}else{separatedv1 =0;}
float separatedv2;
if(distanceVertex2 > radius && (pointC - pointA).Dot(pointC) > 0 && (pointC - pointB).Dot(pointC) > 0)
{separatedv2 = 1;}else{separatedv2 =0;}

float separatedv = separatedv0 || separatedv1 || separatedv2;

// --------*** end vertex check ***-------------

// ----------*** Edges checks ***--------------
// B - A
vector3 ABEdge = vertex1 - vertex0;
float ABT = ((spherePos - pointA).Dot(ABEdge)) / (ABEdge.Dot(ABEdge));
vector3 projA = pointA + ABT * ABEdge; // projection center sphere onto plane edge A
vector3 SphereProjA = spherePos - projA;
vector3 v2Proj = pointC - projA;

float separatedEdgeA;
if(sqrt(SphereProjA.Dot(v2Proj)) > radius && SphereProjA.Dot(v2Proj))
{separatedEdgeA = 1;}else{separatedEdgeA = 0;}

// C - B
vector3 BCEdge = vertex2 - vertex1;
float BCT = ((spherePos - pointB).Dot(BCEdge)) / (BCEdge.Dot(BCEdge));
vector3 projB = pointB + BCT * BCEdge; // projection center sphere onto plane edge B
vector3 SphereProjB = spherePos - projB;
vector3 v0Proj = pointA - projB;

float separatedEdgeB;
if(sqrt(SphereProjB.Dot(v0Proj)) > radius && SphereProjB.Dot(v0Proj))
{separatedEdgeB = 1;}else{separatedEdgeB = 0;}

// A - C
vector3 CAEdge = vertex0 - vertex2;
float CAT = ((spherePos - pointC).Dot(CAEdge)) / (CAEdge.Dot(CAEdge));
vector3 projC = pointC + CAT * CAEdge; // projection center sphere onto plane edge C
vector3 SphereProjC = spherePos - projC;
vector3 v1Proj = pointB - projC;

float separatedEdgeC;
if(sqrt(SphereProjC.Dot(v1Proj)) > radius && SphereProjC.Dot(v1Proj))
{separatedEdgeC = 1;}else{separatedEdgeC = 0;}

// edge separation check
float separatede = separatedEdgeA || separatedEdgeB || separatedEdgeC;

// ----------*** end edge check ***-------------------

if(separatedf || separatedv || separatede)
{
return false;
}
else
{
return true;
}
}
}
Advertisement
Your implementation resembles more of a "is a point in front of or behind a plane?" test.

If you need ray-triangle intersection testing, I recommend taking using a published and tested method. The Möller-Trumbore test is a good one I prefer. An implementation of that can be found from MathGeoLib (code).

If you are actually looking for a point behind/infrontof test, then try the Plane::SignedDistance function.
I just can't seem to get this implementation right.. does anyone have some other great example of sphere triangle collision? or maybe point out what is wrong with this implementation. Thanks
Christer Ericson has a triangle-sphere collision routine in his book Real-Time Collision detection. The algorithm is implemented in MathGeoLib here.

This topic is closed to new replies.

Advertisement