void CURRENT_CLASS::apply(osg::Geode &geode) { // Contained drawables will only be individually considered if we are // allowed to continue traversing. if(shouldContinueTraversal(geode)) { osg::Drawable *drawable; double zNear, zFar; // Handle each drawable in this geode for(unsigned int i = 0; i < geode.getNumDrawables(); ++i) { drawable = geode.getDrawable(i); const osg::BoundingBox &bb = drawable->getBound(); if(bb.valid()) { bool containsTest = _localFrusta.back().contains(bb); // Make sure drawable will be visible in the scene if(!containsTest) continue; // Compute near/far distances for current drawable zNear = distanceDA(bb.corner(_bbCorners.back().first), _viewMatrices.back()); zFar = distanceDA(bb.corner(_bbCorners.back().second), _viewMatrices.back()); if(zNear > zFar) std::swap(zNear,zFar); pushDistancePair(zNear,zFar); } } } }
/** Return true if the node should be traversed, and false if the bounding sphere of the node is small enough to be rendered by one Camera. If the latter is true, then store the node's near & far plane distances. */ bool CURRENT_CLASS::shouldContinueTraversal(osg::Node &node) { // Allow traversal to continue if we haven't reached maximum depth. bool keepTraversing = (_currentDepth < _maxDepth); const osg::BoundingSphere &bs = node.getBound(); double zNear = 0.0, zFar = 0.0; // Make sure bounding sphere is valid and within viewing volume if(bs.valid()) { if(!_localFrusta.back().contains(bs)) keepTraversing = false; else { // Compute near and far planes for this node zNear = distance(bs._center, _viewMatrices.back()); zFar = zNear + bs._radius; zNear -= bs._radius; // If near/far ratio is big enough, then we don't need to keep // traversing children of this node. if(zNear >= zFar*_nearFarRatio) keepTraversing = false; } } // If traversal should stop, then store this node's (near,far) pair if(!keepTraversing) pushDistancePair(zNear, zFar); return keepTraversing; }
/** Return true if the node should be traversed, and false if the bounding sphere of the node is small enough to be rendered by one Camera. If the latter is true, then store the node's near & far plane distances. */ bool CURRENT_CLASS::shouldContinueTraversal(osg::Node &node) { // Allow traversal to continue if we haven't reached maximum depth. bool keepTraversing = (_currentDepth < _maxDepth); osg::BoundingSphere bs = node.getBound(); double zNear = 0.0, zFar = 0.0; // Make sure bounding sphere is valid if(bs.valid()) { // Make sure bounding sphere is within the viewing volume bool containsTest = _localFrusta.back().contains(bs); if(!containsTest) keepTraversing = false; else // Compute near and far planes for this node { // Since the view matrix could involve complex transformations, // we need to determine a new BoundingSphere that would encompass // the transformed BoundingSphere. const osg::Matrix &l2w = _viewMatrices.back(); // Get the transformed x-axis of the BoundingSphere osg::Vec3d newX = bs._center; newX.x() += bs._radius; // Get X-edge of bounding sphere newX = newX * l2w; // Get the transformed y-axis of the BoundingSphere osg::Vec3d newY = bs._center; newY.y() += bs._radius; // Get Y-edge of bounding sphere newY = newY * l2w; // Get the transformed z-axis of the BoundingSphere osg::Vec3d newZ = bs._center; newZ.z() += bs._radius; // Get Z-edge of bounding sphere newZ = newZ * l2w; // Get the transformed center of the BoundingSphere bs._center = bs._center * l2w; // Compute lengths of transformed x, y, and z axes double newXLen = (newX - bs._center).length(); double newYLen = (newY - bs._center).length(); double newZLen = (newZ - bs._center).length(); // The encompassing radius is the max of the transformed lengths bs._radius = newXLen; if(newYLen > bs._radius) bs._radius = newYLen; if(newZLen > bs._radius) bs._radius = newZLen; // Now we can compute the near & far planes, noting that for // complex view transformations (ie. involving scales) the new // BoundingSphere may be bigger than the original one. // Note that the negative sign on the bounding sphere center is // because we want distance to increase INTO the screen. zNear = -bs._center.z() - bs._radius; zFar = -bs._center.z() + bs._radius; // If near/far ratio is big enough, then we don't need to keep // traversing children of this node. if(zNear >= zFar * _nearFarRatio) keepTraversing = false; } } // If traversal should stop, then store this node's (near,far) pair if(!keepTraversing) pushDistancePair(zNear,zFar); return keepTraversing; }