I'm having some issues clamping a 3d to barycentric triangle. I've searched for some time now and keep seeing the same results, that (u,v,w) should be clamped between 0 and 1. But when I clamp those values, I'm getting very weird results as it saying it's always intersecting. Maybe I'm just clamping the wrong values or what I'm doing wrong.
The issue is that I'm projecting a point on a normal from a given triangle, then testing if the point is inside the triangle, if it is, test if it's inside the sphere. Everything works great except when the sphere center is no longer above/in front of the triangle, so the spheres edge can pass through the edge of the triangle beings that the spheres center is no longer above it. Any help with how I'm supposed to clamp the position inside of the triangle would be much appreciated.
Here is a snippet of the triangle/sphere intersect method:
public boolean CollidesWithMesh(MeshCollider other) { float sphereRadius = gameObject.scale * (bounds.Scale().Max()) / 2f; boolean collided = false; RawMesh mesh = other.gameObject.meshRenderer.mesh.rawMesh; for(int i = 0; i < mesh.triangles.length; i++) { //Store the verts used in the triangle int first = i++; Vector3 vert1 = mesh.vertices[(int) mesh.triangles[first]].Add(other.gameObject.position); Vector3 vert2 = mesh.vertices[(int) mesh.triangles[i++]].Add(other.gameObject.position); Vector3 vert3 = mesh.vertices[(int) mesh.triangles[i]].Add(other.gameObject.position); //Project a point along the normal closest to the spheres center Vector3 normal = mesh.normals[(int) mesh.triangles[first]]; float dot = Vector3.Dot(normal, gameObject.position.Subtract(vert1)); Vector3 d = normal.Multiply(dot); Vector3 point = gameObject.position.Subtract(d); //If the point is not inside the triangle, continue Vector3 v0 = vert3.Subtract(vert1); Vector3 v1 = vert2.Subtract(vert1); Vector3 v2 = point.Subtract(vert1); float dot00 = Vector3.Dot(v0, v0); float dot01 = Vector3.Dot(v0, v1); float dot02 = Vector3.Dot(v0, v2); float dot11 = Vector3.Dot(v1, v1); float dot12 = Vector3.Dot(v1, v2); float invDenom = 1 / (dot00 * dot11 - dot01 * dot01); float u = (dot11 * dot02 - dot01 * dot12) * invDenom; float v = (dot00 * dot12 - dot01 * dot02) * invDenom; if(!((u >= 0.0) && (v >= 0.0) && (u + v <= 1))) continue; //If the sphere does not encapsulates the point, continue if(!Contains(point)) continue; //Respond to the collision Vector3 responseNormal = point.Subtract(gameObject.position).Normalized().Multiply(sphereRadius - (point.Subtract(gameObject.position)).Length()); Vector3.Subtract(gameObject.position, responseNormal); if(normal.y > 0.75) isGrounded = true; if(normal.y < -0.75) hitCeiling = true; collided = true; } return collided; }