// static Box3f Box3f::united( const Box3f& b0, const Box3f& b1 ) { Vector3f unitedMin = libcgt::core::math::minimum( b0.leftBottomBack(), b1.leftBottomBack() ); Vector3f unitedMax = libcgt::core::math::maximum( b0.rightTopFront(), b1.rightTopFront() ); return{ unitedMin, unitedMax - unitedMin }; }
bool intersectLine( const Box3f& box, const Vector3f& rayOrigin, const Vector3f& rayDirection, float& tNear, float& tFar ) { assert( box.isStandard() ); assert( !box.isEmpty() ); // Compute t to each face. Vector3f rcpDir = 1.0f / rayDirection; // Three "bottom" faces (min of the box). Vector3f tBottom = rcpDir * ( box.origin - rayOrigin ); // three "top" faces (max of the box) Vector3f tTop = rcpDir * ( box.rightTopFront() - rayOrigin ); // find the smallest and largest distances along each axis Vector3f tMin = libcgt::core::math::minimum( tBottom, tTop ); Vector3f tMax = libcgt::core::math::maximum( tBottom, tTop ); // tNear is the largest tMin tNear = libcgt::core::math::maximum( tMin ); // tFar is the smallest tMax tFar = libcgt::core::math::minimum( tMax ); return tFar > tNear; }
// static bool Box3f::intersect( const Box3f& b0, const Box3f& b1, Box3f& intersection ) { Vector3f minimum = libcgt::core::math::maximum( b0.leftBottomBack(), b1.leftBottomBack() ); Vector3f maximum = libcgt::core::math::minimum( b0.rightTopFront(), b1.rightTopFront() ); if( minimum.x < maximum.x && minimum.y < maximum.y && minimum.z < maximum.z ) { intersection.origin = minimum; intersection.size = maximum - minimum; return true; } return false; }
bool carefulIntersectBoxRay( const Box3f& box, const Vector3f& rayOrigin, const Vector3f& rayDirection, float& t0, float& t1, int& t0Face, int& t1Face, float rayTMin, float rayTMax ) { assert( box.isStandard() ); assert( !box.isEmpty() ); t0 = rayTMin; t1 = rayTMax; t0Face = -1; t1Face = -1; // Compute t to each face. Vector3f rcpDir = 1.0f / rayDirection; Vector3f boxMax = box.rightTopFront(); for( int i = 0; i < 3; ++i ) { // Compute the intersection between the line and the slabs along the // i-th axis, parameterized as [tNear, tFar]. float rcpDir = 1.0f / rayDirection[ i ]; float tNear = rcpDir * ( box.origin[ i ] - rayOrigin[ i ] ); float tFar = rcpDir * ( boxMax[ i ] - rayOrigin[ i ] ); // Which face we're testing against. int nearFace = 2 * i; int farFace = 2 * i + 1; // Swap such that tNear < tFAr. if( tNear > tFar ) { std::swap( tNear, tFar ); std::swap( nearFace, farFace ); } // Compute the set intersection between [tNear, tFar] and [t0, t1]. if( tNear > t0 ) { t0 = tNear; t0Face = nearFace; } if( tFar < t1 ) { t1 = tFar; t1Face = farFace; } // Early abort if the range is empty. if( t0 > t1 ) { return false; } } return true; }