ray/plane collisions

Started by
19 comments, last by endo 22 years ago
Following the tutorials I ahve been trying to write some collision detection code and have reached a problem, again. I have a line and a plane defined like this: Vector3d points[ 2 ]; points[ 0 ].setValues( 0, 60, 0 ); points[ 1 ].setValues( 0, -40, 0 ); Vector3d plane[ 3 ]; plane[ 0 ].setValues( 0, -50, 50 ); plane[ 1 ].setValues( -50, -50, -50 ); plane[ 2 ].setValues( 50, -50, -50 ); Oow using code derived from the line/plane tutorial this is apparently causing an intersection between the line and the plane - obviously not true! This is the intersectPlane(...) function I more or less copied: bool intersectPlane( Vector3d* poly, Vector3d* line ) { float distance1 = 0, distance2 = 0; Vector3d normal = crossProduct( (poly[ 1 ] - poly[ 0 ]), (poly[ 2 ] - poly[ 0 ]) ); normal.normalise( ); ofstream out( "test.txt" ); out << "normal : " << normal << endl; float originDistance = planeDistance( normal, poly[ 0 ] ); //using the plane equation we can now get the 2 distances //from the ends of the line and substituting originDistance for D distance1 = ( (normal.triple[ X ] + line[ 0 ].triple[ X ]) + (normal.triple[ Y ] + line[ 0 ].triple[ Y ]) + (normal.triple[ Z ] + line[ 0 ].triple[ Z ]) ) + originDistance; distance2 = ( (normal.triple[ X ] + line[ 1 ].triple[ X ]) + (normal.triple[ Y ] + line[ 1 ].triple[ Y ]) + (normal.triple[ Z ] + line[ 1 ].triple[ Z ]) ) + originDistance; out << "originDistance : " << originDistance << endl; out << "distance1 : " << distance1 << endl; out << "distance2 : " << distance2 << endl << endl; if( distance1 * distance2 >= 0 ) { cout << "returning false" << endl; return false; //points must be on same side of the plane } cout << "returning true" << endl; return true; //points on the either side of plane } Can someone tell me what is wrong, and if possible give me a run down of what the variable values should be? ie what the normal should be, what the distance to the origin is and the values of distance1 and distance2. I know thats asking alot but I''ve worked through this on paper and the answer I get still tells me they are intersecting
Advertisement
quote:Original post by endo
Following the tutorials I ahve been trying to write some collision detection code and have reached a problem, again.


There''s some confusing stuff going on with originDistance and the calculation of distance1 and distance2. That''s where the error is, but I''m not going to spend any time to fix it. I''d use a slightly different line/plane intersection function that is actually simpler and easier to read/understand. I assume you have a dotProduct function that takes two Vector3d objects. Try this function instead. I''ve annotated to give some clarification.


  bool intersectPlane( Vector3d* poly, Vector3d* line ){  float distance1 = 0, distance2 = 0;  Vector3d normal = crossProduct( (poly[ 1 ] - poly[ 0 ]), (poly[ 2 ] - poly[ 0 ]) );  normal.normalise( );// normal can be considered to be a vector pointing towards one// one side of the plane as measured from *any* origin point on// the plane. There is no need to go an compute the origin// distance as the original function did. For convenience, we''ll// choose poly[0] to be the origin point on the plane.// to get the perpendicular distance from any point to the plane,// we merely find a vector from the point to the plane origin// point that we chose, and dot that with normal. Our new vector// is relative to the same origin point as normal, and so they// line up at the start of the vector. We can simply take the// dot product. Since normal is a unit vector, and is also// perpendicular to the plane, the dot product of the new vector// and normal is the perpendicular distance we are looking// for. This distance is signed---positive if the point is on// the side of the plane that normal points to, and negative// if the point is on the other side.// In code, for our two line points, it looks like this:  distance1 = dotProduct(normal, line[0] - poly[0]);  distance2 = dotProduct(normal, line[1] - poly[0]);// the end of the function is the same as the original function.  if( distance1 * distance2 >= 0 )  {   return false; //points must be on same side of the plane  }  return true;   //points on the either side of plane}  


Graham Rhodes
Senior Scientist
Applied Research Associates, Inc.
Graham Rhodes Moderator, Math & Physics forum @ gamedev.net
Thanks very much, I''ll give that a try. I would still like someone to correct me where I am going wrong as these functions are the basis of the more complex ray/polygon and polygon/sphere collisions that I am really interested in. Here is the original data again and the appropriate values that I am getting, which seem to be correct when I work them out on paper:

Vector3d points[ 2 ];
points[ 0 ].setValues( 0, 60, 0 );
points[ 1 ].setValues( 0, -40, 0 );

Vector3d plane[ 3 ];
plane[ 0 ].setValues( 0, -50, 50 );
plane[ 1 ].setValues( -50, -50, -50 );
plane[ 2 ].setValues( 50, -50, -50 );

variable values:
normal : ( 0 , -1 , 0 )
originDistance : -50
distance1 : 9
distance2 : -91

I would really appreciate someone letting me know which of these is wrong so that I can correct the appropriate function.

tia
btw Mr Rhodes, that function you gave works perfectly without any changes, thanks very much :D
No problem. Actually, usually I make at least one type, so I''m amazed at my own prowess, .

Also, I''m Graham not Mr. Rhodes, .

Graham Rhodes
Senior Scientist
Applied Research Associates, Inc.
Graham Rhodes Moderator, Math & Physics forum @ gamedev.net
ok Graham it is then!

And seeing as your last function was so much easier than the other I had do you have a better alternative to finind an intersection point? This is why I need the plane distance - or an alternative method

here is my current code:


Vector3d intersectionPoint( Vector3d& normal, Vector3d* line, double& distance )
{
Vector3d point, lineDirection;

//get vector from 2 points on line
lineDirection = line[ 1 ] - line[ 0 ];
lineDirection.normalise( );

double numerator = 0, denominator = 0, dist = 0;

//using a point on line, get the distance to the plane
//uses plane equation again
//negated so that we can go backwards from point to plane later
numerator = -( (normal.triple[ X ] * line[ 0 ].triple[ X ]) +
(normal.triple[ Y ] * line[ 0 ].triple[ Y ]) +
(normal.triple[ Z ] * line[ 0 ].triple[ Z ]) + distance );

normal.normalise( ); //just in case its not a unit vector

//get offset of point from plane
denominator = dotProduct( normal, lineDirection );

//if line is on plane answer is 0, infinite number of points on plane
//so return any point on line
if( denominator == 0.0f )
{
return line[ 0 ];
}

dist = numerator / denominator;

point.triple[ X ] = float( (line[ 0 ].triple[ X ] + (lineDirection.triple[ X ] * dist)) );
point.triple[ Y ] = float( (line[ 0 ].triple[ Y ] + (lineDirection.triple[ Y ] * dist)) );
point.triple[ Z ] = float( (line[ 0 ].triple[ Z ] + (lineDirection.triple[ Z ] * dist)) );

return point;
}
ps How do I format the code better in these forums?
quote:Original post by endo
ps How do I format the code better in these forums?


There is some information in the forum FAQ, see this link:

http://www.gamedev.net/community/forums/showfaq.asp?forum_id=20

And more information in the general forum FAQ, here:

http://www.gamedev.net/community/forums/faq.asp


Graham Rhodes
Senior Scientist
Applied Research Associates, Inc.

[edited by - grhodes_at_work on April 27, 2002 1:44:13 PM]
Graham Rhodes Moderator, Math & Physics forum @ gamedev.net
quote:Original post by endo
And seeing as your last function was so much easier than the other I had do you have a better alternative to finind an intersection point? This is why I need the plane distance - or an alternative method


Let me think about how to present this. I might take a slightly different approach to find the actual intersection point. In the process, another technique to check for the existence of an intersection would emerge. I''ll get back to you.

Graham Rhodes
Senior Scientist
Applied Research Associates, Inc.
Graham Rhodes Moderator, Math & Physics forum @ gamedev.net
Wow, all that code looks confusing!


    // Slight psuedocodevoid getIntersect(vec3_t p1, vec3_t p2, vec3_t normal, float distance){    // Normal vectors are relatiave to origin, with distance being how far along the normal line the plane actually exists    vec3_t line = Normalize(p2 - p1);    float height_p1 = abs(DotProduct(normal, p1) - distance);    float height_p2 = abs(DotProduct(normal, p2) - distance);    float ratio = height_p1 / (height_p1 + height_p2);    vec3_t intersection = (line * ratio) + p1;}    

Simply put, we find the height of the imaginary "triangle" formed with the two points, get the ratio beteen the distance of p1 to the normal, and the total "triangle" height, and multiply that times the unit vector line, add the original point, and get the intersection. It has to do with the fact that the sides of similar triangles are in definite ratios.

EDIT: Of course you want to make sure the dot products of both points have opposite signs before you do the math. Otherwise you'll generate intersection points that don't exist!

[edited by - Zipster on April 27, 2002 5:21:13 PM]

This topic is closed to new replies.

Advertisement