void NodeIntersector<real>::TransformIntersectionToGlobalCoordinates( const CoreLib::Node<real>* node, Intersection<real>& ioIntersection ) { // newPosition = M * position // newNormal = M^{-T} * normal const Matrix4<real>& localToGlobal = node->GetLocalToGlobal(); Matrix4<real> localToGlobalForNormals = node->GetGlobalToLocal(); localToGlobalForNormals.Transpose(); ioIntersection.SetPosition( localToGlobal * ioIntersection.GetPosition() ); ioIntersection.SetNormal( localToGlobalForNormals ^ ioIntersection.GetNormal() ); }
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; }