[MDX] Sphere-Plane Collision

Started by
17 comments, last by xissburg 18 years, 1 month ago
I know this topic is discused everywhere, but I cant seem to be able to find a simple, concrete solution to my problem! Here is my situation: + I have a sphere (representing my first person camera) + I have a mesh (representing my level) On checking collision I want to check my sphere with every face that my mesh consists of. I use a generated Plane from the face data. I then use the Plane Normal to calculate the distance between the plane and the sphere center. However, when I try to use this method I get strange collision detections in places that are not supposed be collisions. I have one question. Does a Plane represent a terminating rectangle or is it never-ending? If it is never-ending then wouldn't I have to make sure my sphere is within the area of the three verticies making up the face? Here is my Collision Method: public static bool IsCameraPlaneCollision(dxFpCamera obj, SingleFace[] faces) { Vector3 spherePos = obj.Position; float sphereRadius = obj.Radius; foreach (SingleFace face in faces) { Plane plane = face.GetFacePlaneNormal(); plane = Plane.Normalize(plane); float distance = plane.Dot(spherePos); distance = Math.Abs(distance); if (distance <= sphereRadius) return true; } return false; }
Advertisement
Quote:Original post by phb5000
I have one question. Does a Plane represent a terminating rectangle or is it never-ending? If it is never-ending then wouldn't I have to make sure my sphere is within the area of the three verticies making up the face?


A plane is not limited to a certain area, but is, as you put it "never-ending". I'd recommend using Geometry.IntersectTriangle to perform this kind of collision detection.

Hope this helps.
Sirob Yes.» - status: Work-O-Rama.
How can I calculate the distance to a face (triangle) using that method?

Would I have to calculate a ray angle using the center of the face and the position of the sphere (the camera)?
I'm not a MDX programmer (just DX :P) but I'll help you with math though. To compute the distance between a plane and a point you must just:

distance = Vec3Dot( (point - pointOnPlane), planeNormal)
//obs: planeNormal must be normalized

just that. but then, you need to know if your sphere is penetrating the plane. isnt it that? So, do it: if the distance be lower than the sphere radius(the sphere is already penetrating the infinite plane), proceed to test if the sphere is really penetrating the finite plane which is usually a triangle. first, put the sphere center on the plane by subtracting form is the distance time the planeNormal so:

pointOnPlane2 = sphereCenter - distance * planeNormal

Now pointOnPlane2 is the projection of the sphereCenter on the plane, or better, triangle. We must compute if the point is really inside the triangle. To do it, lets use the plane parametric equation:

P(s, t) = v0 + s(v1-v0) + t(v2-v0)

P is the point, vo v1 v2 are the 3 vertices of the triangle and s and t are real numbers. If s>=0 and t>=0 and s+t<=1 the point is inside the triangle, otherwise it is not. So what you must do is solve the above equation to get s and t, just that :) .....................


I'll show you a shortcut :)
Consider the vectors u = v1 - v0, v = v2 - v0 and w = P - v0
P(s,t) = v0 + su + tv

s = Vec3Dot(w, u) / Vec3Dot(u, u)
t = Vec3Dot(w, v) / Vec3Dot(v, v)

test if s and t satisfies the condition above and if yes, the sphere is really penetrating the triangle. this is a simple method. it will not always say you the truth but it seems sufficient for your usage here.

hope this helps :)...cya
.
Lol...Im' back here...I forgot to give you a nice source for algorithms which will certainly help you: Soft Surfer
.
A Plane consists of A, B, C, D correct?

Would the normal (as a vector) therefore be:
Plane.Normalize()
Vector3 normal = new Vector3(Plane.A, Plane.B, Plane.C);


Quote: "distance = Vec3Dot( (point - pointOnPlane), planeNormal)"

What do you mean by pointOnPlane?
Wouldnt that have to be the center of the face Im checking against?
the plane equation is:

ax + by + cz + d = 0

the vector [a, b, c] is a point on the plane, any point on the plane. the vector [x, y, z] is the plane normal(normalized ;)) and d is the distance from the origin. So we get planeNormal*pointOnPlane + d = 0, where '*' is the dotproduct.

I was looking the documentation and I've seen the Plane.Normalize() returns the normal of the plane in the a b and c components of the structure so you can use it to get the normal.

and about pointOnPlane, is any point contained on the plane surface.
.
This is what I came to:
Im testing right now

Vector3 spherePos = obj.Position;float sphereRadius = obj.Radius;outDistance = 0;for (int i = 0; i < 1; i++){  SingleFace face = faces;  Plane plane = face.GetFacePlane();  Vector3 normal = face.singleNormal;  Vector3 pointOnPlane = face.singleVertex;  float distance = Vector3.Dot((spherePos - pointOnPlane), normal);  outDistance = distance;  if (Math.Abs(distance) < sphereRadius)  {    Vector3 pointOnPlane2 = spherePos - distance * normal;    Vector3 u = face.positions[1] - face.positions[0];    Vector3 v = face.positions[2] - face.positions[0];    Vector3 w = pointOnPlane - face.positions[0];    float s = Vector3.Dot(w, u) / Vector3.Dot(u, u);    float t = Vector3.Dot(w, v) / Vector3.Dot(v, v);    if (s >= 0 && t >= 0 && s + t <= 1)      return true;  }}return false;
and? is it working?
.
Geometry.IntersectTriangle returns the distance to the triangle. Seems like a simpler solution to me. :)
Sirob Yes.» - status: Work-O-Rama.

This topic is closed to new replies.

Advertisement