예제 #1
0
// static
FrustumUtils::IntersectionResult FrustumUtils::intersectBoundingBox( const BoundingBox3f& box, Plane3f planes[ 6 ] )
{
	auto boxCorners = box.corners();

	// by default, we assume the box is completely inside
	IntersectionResult result = INSIDE;

	// and keep track, for each corner of the box
	// how many vertices are inside vs outside
	int nVerticesInside;
	int nVerticesOutside;

	// for each plane do ...
	for( int i = 0; i < 6; ++i )
	{
		// reset counters for corners nVerticesInside and nVerticesOutside
		nVerticesInside = 0;
		nVerticesOutside = 0;

		// for each corner of the box do ...
		// get nVerticesOutside of the cycle as soon as a box as corners
		// both inside and nVerticesOutside of the frustum
		for( int k = 0; k < 8 && ( nVerticesInside == 0 || nVerticesOutside == 0 ); k++ )
		{
			// is the corner inside or outside?
			float d = planes[ i ].distance( boxCorners[ k ] );
			if( d < 0 )
			{
				++nVerticesInside;
			}
			else
			{
				++nVerticesOutside;
			}
		}

		// if none of the box corners are on the inside halfspace
		// then it's guaranteed to be outside, done
		if( nVerticesInside == 0 )
		{
			return OUTSIDE;
		}
		// otherwise, at least some of them are inside
		// but if some of them are *also* outside
		// then we know for now that it intersects this plane
		// (but it's not guaranteed to actually intersect the entire frustum)
		else if( nVerticesOutside != 0 )
		{
			result = INTERESECTING;
		}
		// otherwise, we know that some vertices are inside
		// and none are outside
		// --> this box is completely inside (for this plane anyway)
		else
		{
			assert( nVerticesInside == 8 );
			assert( nVerticesOutside == 0 );
		}
	}

	return result;
}
예제 #2
0
// 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;
}