bool DebugShadowMap::ViewData::DebugBoundingBox ( const osg::BoundingBox & bb, const char * name ) { bool result = false; #if defined( _DEBUG ) || defined( DEBUG ) if( !name ) name = ""; osg::BoundingBox & bb_prev = _boundingBoxMap[ std::string( name ) ]; result = bb.center() != bb_prev.center() || bb.radius() != bb_prev.radius(); if( result ) std::cout << "Box<" << name << "> (" << ( bb._max._v[0] + bb._min._v[0] ) * 0.5 << " " << ( bb._max._v[1] + bb._min._v[1] ) * 0.5 << " " << ( bb._max._v[2] + bb._min._v[2] ) * 0.5 << ") [" << ( bb._max._v[0] - bb._min._v[0] ) << " " << ( bb._max._v[1] - bb._min._v[1] ) << " " << ( bb._max._v[2] - bb._min._v[2] ) << "] " << std::endl; bb_prev = bb; #endif return result; }
void MxCore::lookAtAndFit( const osg::BoundingBox& bb ) { // We'll get the view matrix to project the bounding box, so pre-configure it // to point at the box center. Eye position doesn't matter at this point (we // compute the eye position at the end of the function). osg::Vec3d newDir = bb.center() - _position; newDir.normalize(); setDir( newDir ); // Ttransform the bounding box vertices into eye space, // then determine their x and y extents. We'll compare the eye // space bb aspect ratio against the projection _aspect to // determine the critical axis to fit. osg::ref_ptr< osg::Vec3Array > corners = new osg::Vec3Array; corners->resize( 8 ); ( *corners )[ 0 ].set( bb._min ); ( *corners )[ 1 ].set( bb._max.x(), bb._min.y(), bb._min.z() ); ( *corners )[ 2 ].set( bb._max.x(), bb._min.y(), bb._max.z() ); ( *corners )[ 3 ].set( bb._min.x(), bb._min.y(), bb._max.z() ); ( *corners )[ 4 ].set( bb._max ); ( *corners )[ 5 ].set( bb._min.x(), bb._max.y(), bb._max.z() ); ( *corners )[ 6 ].set( bb._min.x(), bb._max.y(), bb._min.z() ); ( *corners )[ 7 ].set( bb._max.x(), bb._max.y(), bb._min.z() ); osgwTools::transform( getInverseMatrix(), corners.get() ); // The 'corners' array of bb verts are now in eye space. // Determine max and min values for eye space x and y osg::Vec2 minEC( FLT_MAX, FLT_MAX ), maxEC( FLT_MIN, FLT_MIN ); unsigned int idx; for( idx=0; idx<8; idx++ ) { const osg::Vec3& v( ( *corners )[ idx ] ); minEC[ 0 ] = osg::minimum< float >( v.x(), minEC[ 0 ] ); minEC[ 1 ] = osg::minimum< float >( v.y(), minEC[ 1 ] ); maxEC[ 0 ] = osg::maximum< float >( v.x(), maxEC[ 0 ] ); maxEC[ 1 ] = osg::maximum< float >( v.y(), maxEC[ 1 ] ); } // aspect is width (x) over height (y). const double ecWidth( maxEC[ 0 ] - minEC[ 0 ] ); const double ecHeight( maxEC[ 1 ] - minEC[ 1 ] ); const double ecAspect = ecWidth / ecHeight; // We'll store half the extent of interest into a dummy bounding sphere's radius. // We'll store the analogous fov in bestFov. osg::BoundingSphere bs; double bestFov; if( ecAspect > _aspect ) { // Fit eye space x to the view bs.radius() = ecWidth * .5; bestFov = _aspect * _fovy; } else { // Fit eye space y to the view bs.radius() = ecHeight * .5; bestFov = _fovy; } // The wrap-up code sets the eye position at the best distance from // the bb center. Extra distance is added in to account for the fact // that the input bound probably has a larger radius than the eye coord // bound that we're passing to computeInitialDistanceFromFOVY(). const double extraDistance = bb.radius() - bs.radius(); const double distance = extraDistance + osgwMx::computeInitialDistanceFromFOVY( bs, bestFov ); setPosition( bs.center() - ( newDir * distance ) ); }