Sign in to follow this  
phb5000

[MDX] Sphere-Plane Collision

Recommended Posts

phb5000    122
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; }

Share this post


Link to post
Share on other sites
sirob    1181
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.

Share this post


Link to post
Share on other sites
phb5000    122
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)?

Share this post


Link to post
Share on other sites
xissburg    204
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

Share this post


Link to post
Share on other sites
phb5000    122
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?

Share this post


Link to post
Share on other sites
xissburg    204
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.

Share this post


Link to post
Share on other sites
phb5000    122
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[i];
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;


Share this post


Link to post
Share on other sites
sirob    1181
Geometry.IntersectTriangle returns the distance to the triangle. Seems like a simpler solution to me. :)

Share this post


Link to post
Share on other sites
phb5000    122
Im getting a weird collision, but it might have something to do with the mesh itself. Im going to make a new mesh and see what happens...

Share this post


Link to post
Share on other sites
phb5000    122
Ive come to the conclusion that everything works except for the last test:

if (s >= 0 && t >= 0 && s + t <= 1)

My s + t is NOT <= 1!

Share this post


Link to post
Share on other sites
xissburg    204
but it must be. If s+t > 1 the point is outside the triangle. Look at this . it works as a vector summing:


v1+ +v0+(v1-v0)+(v2-v0)-> so, s = 1 and t = 1, s+t > 1...point is outside
| /
| /
| /
| /
|/
vo+--------+v2


if s+t = 1, doesn't matter the values of s and t, the point will be on the segment v1 - v2

Share this post


Link to post
Share on other sites
phb5000    122
Right now Im really worried about one thing

I made two test meshes: one with textures and one without

To make my textures tile I apply a UWV map modifier

The mesh without textures had very good collision except i had to change the equation to >= instead of <=

The mesh with textures had no sense of collision detection whatsoever (however, i did not fully test it)

Could the UWV mapping somehow be interfearing with my vertex positions? :S

Share this post


Link to post
Share on other sites
xissburg    204
WooW lol :p

I really dont know...I dont use this method to get the triangles from my mesh :P...well, textures dont change the positions of the vertices...maybe there's something wrong in your code. an the UVW map modifier(are you using 3dsmax?!? :P) usually doesnt change anything on the vertex positions....

Share this post


Link to post
Share on other sites
phb5000    122
I am very close to achieving succesfull collision detection now, however, there is some slight error in the method. Since I hardly have any experience in this I am not able to figure out where exactly the error lies or in what context and cases the error occurs. However, I did manage to come to one conclusion: In a square room collusion only occurs when I hit the walls with a positive X or Z normal. There is most likely some typo in the vector manipulation in the algorithm :p

Could you please have a look :)

Thank you so much for your help!


(btw, I am now using s + t <= 1 and there was no interference with the verticies :P)

Share this post


Link to post
Share on other sites
xissburg    204
to collide with walls, you could check the y component of the normal of the triangle your sphere is penetrating(since earth gravity is (0.f, 9.81f, 0.f)...).

It the most simple method. for example, normal with a y component lower than 0.5. if the intersecting triangle has a normal with this property, you'll not be able to climb that triangle...something like that. I never developped a serious 1st person camera walking system, so I dont have many ideas about :/ ...I think, just think, that a good method would be using forces and friction but its more complex and large...

and one detail: I dont know if you are doing it but you can intersect more than one triangle at time, so pay attention to your code.

Share this post


Link to post
Share on other sites
xissburg    204
Hey...sorry!!

I've given you a wrong method to compute s and t!!confused with computing the distance between a point and a line :P...:(...I'll fix this now ;)

create two new vectors: uP which is perpendicular to both u and the triangle normal and vP which is perpendicular to both v and the triangle normal. To compute them:

uP = Vec3Cross(&u, &triangleNormal)
vP = Vec3Cross(&v, &triangleNormal)

Now, s and t will be:

s = Vec3Dot(&w, &uP) / Vec3Dot(&u, &uP);
t = Vec3Dot(&w, &vP) / Vec3Dot(&v, &vP);

Its just check if s>=0 && t>=1 && s+t<=1 is true and if yes the point is inside...

I hope theres nothing else wrong now :P...

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this