// static BoundingBox3f BoundingBox3f::unite( const BoundingBox3f& b0, const BoundingBox3f& b1 ) { Vector3f b0Min = b0.minimum(); Vector3f b0Max = b0.maximum(); Vector3f b1Min = b1.minimum(); Vector3f b1Max = b1.maximum(); Vector3f newMin( min( b0Min.x, b1Min.x ), min( b0Min.y, b1Min.y ), min( b0Min.z, b1Min.z ) ); Vector3f newMax( max( b0Max.x, b1Max.x ), max( b0Max.y, b1Max.y ), max( b0Max.z, b1Max.z ) ); return BoundingBox3f( newMin, newMax ); }
// static BoundingBox3f BoundingBox3f::intersect( const BoundingBox3f& b0, const BoundingBox3f& b1 ) { Vector3f b0Min = b0.minimum(); Vector3f b0Max = b0.maximum(); Vector3f b1Min = b1.minimum(); Vector3f b1Max = b1.maximum(); Vector3f newMin( max( b0Min.x, b1Min.x ), max( b0Min.y, b1Min.y ), max( b0Min.z, b1Min.z ) ); Vector3f newMax( min( b0Max.x, b1Max.x ), min( b0Max.y, b1Max.y ), min( b0Max.z, b1Max.z ) ); for(int i = 0; i < 3; ++i) newMax[i] = max(newMax[i], newMin[i]); return BoundingBox3f( newMin, newMax ); }
bool BoundingBox3f::overlaps( const BoundingBox3f& other ) { bool bOverlapsInDirection[3]; Vector3f otherMin = other.minimum(); Vector3f otherMax = other.maximum(); for( int i = 0; i < 3; ++i ) { bool bMinInside0 = ( otherMin[i] >= m_min[i] ) && ( otherMin[i] <= m_max[i] ); bool bMinInside1 = ( m_min[i] >= otherMin[i] ) && ( m_min[i] <= otherMax[i] ); bool bMaxInside0 = ( otherMax[i] >= m_min[i] ) && ( otherMax[i] <= m_max[i] ); bool bMaxInside1 = ( m_max[i] >= otherMin[i] ) && ( m_max[i] <= otherMax[i] ); bool bMinInside = bMinInside0 || bMinInside1; bool bMaxInside = bMaxInside0 || bMaxInside1; bOverlapsInDirection[i] = bMinInside || bMaxInside; } return bOverlapsInDirection[0] && bOverlapsInDirection[1] && bOverlapsInDirection[2]; }
// virtual Matrix4f DirectionalLight::lightMatrix( const Camera& camera, const BoundingBox3f& sceneBoundingBox ) { const float feather = 1.01; Matrix3f lightLinear = lightBasis(); Vector3f eye = camera.getEye(); // get the corners of the view frustum in light coordinates // with the z = 0 plane at the eye QVector< Vector3f > frustumCorners = camera.getFrustumCorners(); BoundingBox3f frustumBB; for( int i = 0; i < frustumCorners.size(); ++i ) frustumBB.enlarge(frustumCorners[i]); BoundingBox3f sceneAndFrustum = BoundingBox3f::intersect(frustumBB, sceneBoundingBox); QVector< Vector3f > sceneCorners = sceneBoundingBox.corners(); QVector< Vector3f > sceneAndFrustumCorners = sceneAndFrustum.corners(); for( int i = 0; i < sceneAndFrustumCorners.size(); ++i ) { sceneAndFrustumCorners[ i ] = lightLinear * ( sceneAndFrustumCorners[ i ] - eye ); sceneCorners[ i ] = lightLinear * ( sceneCorners[ i ] - eye ); } BoundingBox3f inLightCoordinates; for(int i = 0; i < sceneAndFrustumCorners.size(); ++i) inLightCoordinates.enlarge(sceneAndFrustumCorners[i]); Vector3f maxCorner = inLightCoordinates.maximum(); Vector3f minCorner = inLightCoordinates.minimum(); Vector3f center = inLightCoordinates.center(); maxCorner = center + feather * (maxCorner - center); minCorner = center + feather * (minCorner - center); // add eye point for(int j = 0; j < 3; ++j) { maxCorner[j] = qMax( maxCorner[ j ], 0.0f ); minCorner[j] = qMin( minCorner[ j ], 0.0f ); } // bound the near plane to the scene for( int i = 0; i < sceneCorners.size(); ++i ) { minCorner[2] = qMin( minCorner[2], sceneCorners[ i ][ 2 ] ); } // finally, compute the full light matrix Matrix4f lightMatrix; lightMatrix.setSubmatrix3x3( 0, 0, lightLinear ); Vector3f origin = 0.5 * ( minCorner + maxCorner ); origin[2] = minCorner[2]; lightMatrix.setCol( 3, Vector4f( -origin, 1.f ) - Vector4f( lightLinear * eye, 0.f ) ); for(int i = 0; i < 3; ++i) { lightMatrix.setRow( i, lightMatrix.getRow( i ) * ( ( i == 2 ) ? 1.f : 2.f ) / ( maxCorner[i] - minCorner[i] ) ); } return lightMatrix; }