bool PlaneIntersector<real>::Intersect( const Plane<real>* plane, const Ray<real>& ray, Intersection<real>& oIntersection ) { const Vector3<real>& origin = ray.GetOrigin(); const Vector3<real>& direction = ray.GetDirection(); // Do not perform intersection if the direction of the ray is degenerated relative to the plane if ( fabs( direction.Y() ) > EPS ) { // Compute the intersection point and see if it's inside the plane bounds real t = -origin.Y() / direction.Y(); Vector3<real> intersectionPoint = origin + t * direction; bool isInsideXBounds = ( fabs( intersectionPoint.X() ) < plane->GetSizeX() * 0.5 ) ? true : false; bool isInsideZBounds = ( fabs( intersectionPoint.Z() ) < plane->GetSizeZ() * 0.5 ) ? true : false; // If the ray intersect and the intersection is in front if ( ( t > 0 ) && isInsideXBounds && isInsideZBounds ) { oIntersection.SetPosition( intersectionPoint ); oIntersection.SetNormal( Vector3<real>( 0, -sign<real>( direction.Y() ), 0 ) ); oIntersection.IsInside( false ); // Compute texture coodinates as (z=-0.5 => u=0 and x=-0.5 => v=0) real u = ( intersectionPoint.Z() + plane->GetSizeZ() * 0.5 ) / plane->GetSizeZ(); real v = ( intersectionPoint.X() + plane->GetSizeX() * 0.5 ) / plane->GetSizeX(); oIntersection.SetTextureCoordinates( Vector3<real>( u, v, 0 ) ); return true; } } return false; }
bool SphereIntersector<real>::Intersect( const Sphere<real>* sphere, const Ray<real>& ray, Intersection<real>& oIntersection ) { // Compute the equation corresponding to x²+y²+z²=0 with p+t*d to obtain a quadratic equation real a = ray.GetDirection().SquaredLength(); real b = 2.0 * ray.GetDirection() * ray.GetOrigin(); real c = ray.GetOrigin().SquaredLength() - sphere->GetRadius() * sphere->GetRadius(); real discriminant = b*b - 4*a*c; // Discriminant >= 0 => the must be at least one intersection if ( discriminant >= 0 ) { // Compute the two potential intersections and only keep the nearest real sqrtDisc = sqrt( discriminant ); real t = 0; real t1 = ( -b - sqrtDisc ) / ( 2.0 * a ); real t2 = ( -b + sqrtDisc ) / ( 2.0 * a ); if ( t1 >= 0 ) { t = t1; oIntersection.IsInside( false ); } else if ( t2 >= 0 ) { t = t2; oIntersection.IsInside( true ); } else return false; oIntersection.SetPosition( ray.GetOrigin() + t * ray.GetDirection() ); oIntersection.SetNormal( oIntersection.GetPosition().Normalized() ); oIntersection.SetTextureCoordinates( oIntersection.GetPosition().Normalized() ); // The normal must be flipped to coincide with the hit direction if ( oIntersection.IsInside() ) oIntersection.SetNormal( -oIntersection.GetNormal() ); return true; } return false; }
bool CylinderIntersector<real>::Intersect( const Cylinder<real>* cylinder, const Ray<real>& ray, Intersection<real>& oIntersection ) { real nearestDistance = std::numeric_limits<real>::max(); real distance = 0; bool hasIntersection = false; //////////////////////////////////////////// //////////////////IFT 3355////////////////// //////////////////////////////////////////// //Ici, vous calculerez l'intersection entre //le rayon "ray" et le cylindre "cylinder" //Pensez à initialiser les quatre attributs //de oIntersection (retourné par référence) //correctement si une intersection est trouvée. //////////////////////////////////////////// //////////////////IFT 3355////////////////// //////////////////////////////////////////// real halfHeight = cylinder->GetHeight() / 2; real radius = cylinder->GetRadius(); // Intersection with extremeties. Vector3<real> extremeties[2] = { Vector3<real>(0, halfHeight, 0), Vector3<real>(0, -halfHeight, 0), }; for (int k = 0; k < 2; ++k) { Vector3<real> plane = extremeties[k]; real denom = ray.GetDirection() * plane; bool intersectsPlane = fabs(denom) > EPS; // Ray intersects with the extremety. if (intersectsPlane) { // Intersection position on the infinite plane. real t = ((plane - ray.GetOrigin()) * plane) / denom; Vector3<real> intersectionPos = ray.GetOrigin() + t * ray.GetDirection(); // Ray intersects in the window. if ((plane - intersectionPos).Length() <= radius && ray.GetDirection() * plane < 0 && t > EPS && t <= nearestDistance) { oIntersection.SetNormal(plane); oIntersection.SetPosition(intersectionPos); oIntersection.SetTextureCoordinates(intersectionPos); oIntersection.IsInside(false); nearestDistance = t; hasIntersection = true; } } } // Intersection with main body Vector3<real> o = Vector3<real>(ray.GetOrigin().X(), 0, ray.GetOrigin().Z()); Vector3<real> d = Vector3<real>(ray.GetDirection().X(), 0, ray.GetDirection().Z()); real a = d*d; real b = 2 * d * o; real c = o * o - (radius*radius); real discr = b*b - 4*a*c; if (discr < -EPS) { return hasIntersection; // No intersection. } else { real t1 = (-b - sqrt(discr)) / (2*a); real t2 = (-b + sqrt(discr)) / (2*a); real t = std::min<real>(t1, t2); Vector3<real> intersectionPos = ray.GetOrigin() + t * ray.GetDirection(); if (t >= EPS && t < nearestDistance && fabs(intersectionPos.Y()) < halfHeight+EPS) { oIntersection.SetNormal(intersectionPos - Vector3<real>(0, intersectionPos.Y(), 0)); oIntersection.SetPosition(intersectionPos); oIntersection.SetTextureCoordinates(intersectionPos); oIntersection.IsInside(false); nearestDistance = t; hasIntersection = true; } } return hasIntersection; }