BOOL Plane::GetTriplePlaneIntersection(const Plane &p2, const Plane &p3, Vect &intersection) const { Vect rayOrigin, rayDir; if(GetDoublePlaneIntersection(p2, rayOrigin, rayDir)) { float fT; if(p3.GetRayIntersection(rayOrigin, rayDir, fT)) { intersection = rayOrigin + (rayDir*fT); return TRUE; } } return FALSE; }
// yes, I realize this breaks on caps when the ray origin is inside the cylinder. // it's not like it's actually going to be in there anyway. BOOL CylinderRayCollision(const Vect ¢er, float radius, float height, const Vect &rayOrig, const Vect &rayDir, Vect *collision, Plane *collisionPlane) { Vect collisionValue; BOOL bHit = FALSE; float fT; Plane axisPlane(0.0f, 1.0f, 0.0f, center.y); //--------------------------------------- // test the cap if(fabs(rayDir.y) > EPSILON) { BOOL bUnder = (rayDir.y<0.0f); Plane planeCap; planeCap.Dir.Set(0.0f, bUnder ? 1.0f : -1.0f, 0.0f); planeCap.Dist = (bUnder ? center.y : -center.y)+height; if(rayOrig.DistFromPlane(planeCap) > 0.0f) { if(planeCap.GetRayIntersection(rayOrig, rayDir, fT)) { collisionValue = rayOrig+(rayDir*fT); Vect CapCenter = center+(planeCap.Dir*height); if(collisionValue.Dist(CapCenter) <= radius) { if(collisionPlane) *collisionPlane = planeCap; bHit = TRUE; } } } } if(!bHit && ((1.0f-fabs(rayDir.y)) > EPSILON)) { //--------------------------------------- // test the body Vect adjDir, adjCenter; adjDir.Set(rayDir.x, 0.0f, rayDir.z).Norm(); adjCenter.Set(center.x, rayOrig.y, center.z); Vect l = (adjCenter-rayOrig); float d = l | adjDir; //distance from adjDir Plane float l2 = l | l; //c-o distance squared float r2 = radius*radius; if(l2 < r2) //if inside the cylinder, fail return FALSE; if((d < 0.0f) && (l2 > r2)) //if the plane distance is negative, and return FALSE; //the distance is over the radius, fail float m2 = l2 - (d*d); //distance from the cylinder center to //the closest ray point if(m2 > r2) //if m2 is larger than the radius, fail return FALSE; float q = sqrt(r2-m2); //real distance from the edge of the //cylinder to the cloest ray point //(forms a sort of triangle) fT = (l2 > r2) ? (d-q) : (d+q); //if the distance is over the radius, //d-q = T, else d+q=T //distance fT /= (adjDir|rayDir); //divide by angle to get the proper //value collisionValue = rayOrig+(rayDir*fT); if(fabs(collisionValue.DistFromPlane(axisPlane)) >= height) return FALSE; if(collisionPlane) { Vect temp = collisionValue; temp.y = center.y; collisionPlane->Dir = (temp-center).Norm(); collisionPlane->Dist = collisionPlane->Dir|temp; } bHit = TRUE; } if(!bHit) return FALSE; if(collision) *collision = collisionValue; return TRUE; }