Collision Detection and Ellipsoids Tutorial

advertisement
Collision Detection and Ellipsoids Tutorial
By: Clifton Sweeney
Collision Detection in Games covers:
Car crashes, shooting, kicking, punching, beating, whacking, smashing, hitting, chopping, dicing,
slicing, julienne fries…
Expensive – Algorithm reaches Order N2
Collision detection in games is carried out into two easy steps:
1. Determine which pairs of shapes need to be tested for collision.
2. Determine collision results for each pair identified in step 1.
In a virtual plane designers must take into account - Gravity
- Bounce
- Friction
Psuedo code for intersection of a ray with a plane:
double intersect(Point pOrigin, Vector pNormal, Point rOrigin,
Vector rVector)
{
double d = -(planeNormal * planeOrigin);
double numer = planeNormal * rayOrigin + d;
double denom = planeNormal * rayVector;
return -(numer / denom);
}
Determining collision points for your Ellipsoids:
 Find the bounding box of your sphere, centered on the source position
 Find the bounding box of your sphere, centered on the destination position
 Find the bounding box of those two bounding boxes
 Find all polygons that intersect that final bounding box
Determining the closest point on a polygon:
Point closestPointOnTriangle(Point a, Point b, Point c, Point p)
{
Point Rab = closestPointOnLine(a, b, p);
Point Rbc = closestPointOnLine(b, c, p);
Point Rca = closestPointOnLine(c, a, p);
return closest [Rab, Rbc, Rca] to p;
}
Point closestPointOnLine(Point a, Point b, Point p)
{
// Determine t (the length of the vector from ‘a’ to ‘p’)
Vector c = p - a;
Vector V = Normalized vector [b – a];
double d = distance from a to b;
double t = V * c;
// Check to see if ‘t’ is beyond the extents of the line segment
if (t < 0) return a;
if (t > d) return b;
// Return the point between ‘a’ and ‘b’
set length of V to t;
return a + V;
}
Turn your sphere into an Ellipsoid
This is a sphere turned into an ellipse with a radius vector of [3,6]. This
results in an ellipse that is 6 units wide and 12 units tall.
// The collision detection entry point
collisionDetection(Point sourcePoint, Vector velocityVector,
Vector gravityVector)
{
velocityVector += gravityVector;
call collideWithWorld(sourcePoint, velocityVector);
}
// The collision detection recursive routine
collideWithWorld(Point sourcePoint, Vector velocityVector)
{
// How far do we need to go?
Double distanceToTravel = length of velocityVector;
// Do we need to bother?
if (distanceToTravel < EPSILON) return;
Point destinationPoint = sourcePoint + velocityVector;
// Whom might we collide with?
List
potentialColliders = determine list of potential colliders;
// If there are none, we can safely move to the destination and bail
if (potentialColliders is empty)
{
sourcePoint += velocityVector;
return;
}
// Determine the nearest collider from the list potentialColliders
bool
firstTimeThrough = true;
Double nearestDistance = -1.0;
Poly
nearestCollider = NULL;
Point nearestIntersectionPoint = NULL;
Point nearestPolygonIntersectionPoint = NULL;
for (each polygon in potentialColliders)
{
// Plane origin/normal
Point pOrigin = any vertex from the current polygon;
Vector pNormal = surface normal from the current polygon;
// Determine the distance from the plane to the source
Double pDist = intersect(source, -pNormal, pOrigin, pNormal);
Point sphereIntersectionPoint;
Point planeIntersectionPoint;
// The radius of the ellipsoid (in the direction of pNormal)
Vector directionalRadius = -pNormal * radiusVector;
Double radius = length of directionalRadius;
// Is the plane embedded?
if (fabs(pDist) <= radius)
{
// Calculate the plane intersection point
Vector temp = -pNormal with length set to pDist;
planeIntersectionPoint = source + temp;
}
else {
// Calculate the ellipsoid intersection point
Vector temp = -pNormal with length set to radius;
ellipsoidIntersectionPoint = source + temp;
// Calculate the plane intersection point
Ray
ray(sphereIntersectionPoint, Velocity);
Double t = intersect(ellipsoidIntersectionPoint, Velocity, pOrigin, pNormal);
// Calculate the plane intersection point
Vector V = velocityVector with length set to t;
planeIntersectionPoint = ellipsoidIntersectionPoint + V;
}
// Unless otherwise stated, our polygonIntersectionPoint is the
// same point as planeIntersectionPoint
Point
polygonIntersectionPoint = planeIntersectionPoint;
if (planeIntersectionPoint is not within the current polygon)
{
polygonIntersectionPoint = nearest point on polygon's perimeter to
planeIntersectionPoint;
}
// Invert the velocity vector
Vector negativeVelocityVector = -velocityVector;
Double t = intersectEllipse(sourcePoint, radiusVector,
polygonIntersectionPoint, negativeVelocityVector);
if (t >= 0.0 && t <= distanceToTravel)
{
Vector V = negativeVelocityVector with length set to t;
Vector intersectionPoint = polygonIntersectionPoint + V;
// Closest intersection thus far?
if (firstTimeThrough || t < nearestDistance)
{
nearestDistance = t;
nearestCollider = current collider;
nearestIntersectionPoint = intersectionPoint;
nearestPolygonIntersectionPoint =
polygonIntersectionPoint;
firstTimeThrough = false;
}
}
}
if (firstTimeThrough)
{
sourcePoint += velocityVector;
return;
}
// Move to the nearest collision
Vector V = velocityVector with length set to (nearestDistance - EPSILON);
sourcePoint += V;
// Determine the sliding plane (we do this now, because we're about to
// change sourcePoint)
Point slidePlaneOrigin = nearestPolygonIntersectionPoint;
Vector slidePlaneNormal = nearestPolygonIntersectionPoint - sourcePoint;
Double time = intersect(destinationPoint, slidePlaneNormal,
slidePlaneOrigin, slidePlaneNormal);
Set length of slidePlaneNormal to time;
Vector destinationProjectionNormal = slidePlaneNormal;
Point newDestinationPoint = destination + destinationProjectionNormal;
// Generate the slide vector, which will become our new velocity vector
// for the next iteration
Vector newVelocityVector = newDestinationPoint –
nearestPolygonIntersectionPoint;
// Recursively slide (without adding gravity)
collideWithWorld(sourcePoint, newVelocityVector);
}
Resources:
http://www.cc.gatech.edu/classes/AY2004/cs4455_fall/Lectures/08CollDet.ppt
http://www.cs.unc.edu/~geom/collide/index.shtml
http://www.gamedev.net/reference/articles/article1026.asp
Download