Replaced tabs with spaces in examples.

This commit is contained in:
Robert Osfield
2005-11-17 20:22:55 +00:00
parent 39db6b28b3
commit 91855e7c50
36 changed files with 1471 additions and 1482 deletions

View File

@@ -4,252 +4,252 @@
#define CURRENT_CLASS DepthPartitionNode
CURRENT_CLASS::CURRENT_CLASS()
{
_distAccumulator = new DistanceAccumulator;
init();
_distAccumulator = new DistanceAccumulator;
init();
}
CURRENT_CLASS::CURRENT_CLASS(const CURRENT_CLASS& dpn, const osg::CopyOp& copyop)
: Group(dpn, copyop),
: Group(dpn, copyop),
_active(dpn._active),
_renderOrder(dpn._renderOrder),
_clearColorBuffer(dpn._clearColorBuffer)
_renderOrder(dpn._renderOrder),
_clearColorBuffer(dpn._clearColorBuffer)
{
_distAccumulator = new DistanceAccumulator;
_numCameras = 0;
_distAccumulator = new DistanceAccumulator;
_numCameras = 0;
}
CURRENT_CLASS::~CURRENT_CLASS() {}
void CURRENT_CLASS::init()
{
_active = true;
_numCameras = 0;
setCullingActive(false);
_renderOrder = osg::CameraNode::POST_RENDER;
_clearColorBuffer = true;
_active = true;
_numCameras = 0;
setCullingActive(false);
_renderOrder = osg::CameraNode::POST_RENDER;
_clearColorBuffer = true;
}
void CURRENT_CLASS::setActive(bool active)
{
if(_active == active) return;
_active = active;
if(_active == active) return;
_active = active;
}
void CURRENT_CLASS::setClearColorBuffer(bool clear)
{
_clearColorBuffer = clear;
_clearColorBuffer = clear;
// Update the render order for the first CameraNode if it exists
if(!_cameraList.empty())
{
if(clear)
_cameraList[0]->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
else
_cameraList[0]->setClearMask(GL_DEPTH_BUFFER_BIT);
}
// Update the render order for the first CameraNode if it exists
if(!_cameraList.empty())
{
if(clear)
_cameraList[0]->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
else
_cameraList[0]->setClearMask(GL_DEPTH_BUFFER_BIT);
}
}
void CURRENT_CLASS::setRenderOrder(osg::CameraNode::RenderOrder order)
{
_renderOrder = order;
_renderOrder = order;
// Update the render order for existing CameraNodes
unsigned int numCameras = _cameraList.size();
for(unsigned int i = 0; i < numCameras; i++)
{
_cameraList[i]->setRenderOrder(_renderOrder);
}
// Update the render order for existing CameraNodes
unsigned int numCameras = _cameraList.size();
for(unsigned int i = 0; i < numCameras; i++)
{
_cameraList[i]->setRenderOrder(_renderOrder);
}
}
void CURRENT_CLASS::traverse(osg::NodeVisitor &nv)
{
// If the scene hasn't been defined then don't do anything
unsigned int numChildren = _children.size();
if(numChildren == 0) return;
// If the scene hasn't been defined then don't do anything
unsigned int numChildren = _children.size();
if(numChildren == 0) return;
// If the node is not active then don't analyze it
if(!_active)
{
// Traverse the graph as usual
Group::traverse(nv);
return;
}
// If the node is not active then don't analyze it
if(!_active)
{
// Traverse the graph as usual
Group::traverse(nv);
return;
}
// If the visitor is not a cull visitor, pass it directly onto the scene.
osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
if(!cv)
{
Group::traverse(nv);
return;
}
// If the visitor is not a cull visitor, pass it directly onto the scene.
osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
if(!cv)
{
Group::traverse(nv);
return;
}
// We are in the cull traversal, so first collect information on the
// current modelview and projection matrices and viewport.
osg::RefMatrix& modelview = cv->getModelViewMatrix();
osg::RefMatrix& projection = cv->getProjectionMatrix();
osg::Viewport* viewport = cv->getViewport();
// We are in the cull traversal, so first collect information on the
// current modelview and projection matrices and viewport.
osg::RefMatrix& modelview = cv->getModelViewMatrix();
osg::RefMatrix& projection = cv->getProjectionMatrix();
osg::Viewport* viewport = cv->getViewport();
// Prepare for scene traversal.
_distAccumulator->setMatrices(modelview, projection);
_distAccumulator->setNearFarRatio(cv->getNearFarRatio());
_distAccumulator->reset();
// Prepare for scene traversal.
_distAccumulator->setMatrices(modelview, projection);
_distAccumulator->setNearFarRatio(cv->getNearFarRatio());
_distAccumulator->reset();
// Step 1: Traverse the children, collecting the near/far distances.
unsigned int i;
for(i = 0; i < numChildren; i++)
{
_children[i]->accept(*(_distAccumulator.get()));
}
// Step 1: Traverse the children, collecting the near/far distances.
unsigned int i;
for(i = 0; i < numChildren; i++)
{
_children[i]->accept(*(_distAccumulator.get()));
}
// Step 2: Compute the near and far distances for every CameraNode that
// should be used to render the scene.
_distAccumulator->computeCameraPairs();
// Step 2: Compute the near and far distances for every CameraNode that
// should be used to render the scene.
_distAccumulator->computeCameraPairs();
// Step 3: Create the CameraNodes, and add them as children.
DistanceAccumulator::PairList& camPairs = _distAccumulator->getCameraPairs();
_numCameras = camPairs.size(); // Get the number of cameras
// Step 3: Create the CameraNodes, and add them as children.
DistanceAccumulator::PairList& camPairs = _distAccumulator->getCameraPairs();
_numCameras = camPairs.size(); // Get the number of cameras
// Create the CameraNodes, and add them as children.
if(_numCameras > 0)
{
osg::CameraNode *currCam;
DistanceAccumulator::DistancePair currPair;
// Create the CameraNodes, and add them as children.
if(_numCameras > 0)
{
osg::CameraNode *currCam;
DistanceAccumulator::DistancePair currPair;
for(i = 0; i < _numCameras; i++)
{
// Create the camera, and clamp it's projection matrix
currPair = camPairs[i]; // (near,far) pair for current camera
currCam = createOrReuseCamera(projection, currPair.first,
currPair.second, i);
for(i = 0; i < _numCameras; i++)
{
// Create the camera, and clamp it's projection matrix
currPair = camPairs[i]; // (near,far) pair for current camera
currCam = createOrReuseCamera(projection, currPair.first,
currPair.second, i);
// Set the modelview matrix and viewport of the camera
currCam->setViewMatrix(modelview);
currCam->setViewport(viewport);
// Set the modelview matrix and viewport of the camera
currCam->setViewMatrix(modelview);
currCam->setViewport(viewport);
// Redirect the CullVisitor to the current camera
currCam->accept(nv);
}
// Redirect the CullVisitor to the current camera
currCam->accept(nv);
}
// Set the clear color for the first camera
_cameraList[0]->setClearColor(cv->getRenderStage()->getClearColor());
}
// Set the clear color for the first camera
_cameraList[0]->setClearColor(cv->getRenderStage()->getClearColor());
}
}
bool CURRENT_CLASS::addChild(osg::Node *child)
{
return insertChild(_children.size(), child);
return insertChild(_children.size(), child);
}
bool CURRENT_CLASS::insertChild(unsigned int index, osg::Node *child)
{
if(!Group::insertChild(index, child)) return false; // Insert child
if(!Group::insertChild(index, child)) return false; // Insert child
// Insert child into each CameraNode
unsigned int totalCameras = _cameraList.size();
for(unsigned int i = 0; i < totalCameras; i++)
{
_cameraList[i]->insertChild(index, child);
}
return true;
// Insert child into each CameraNode
unsigned int totalCameras = _cameraList.size();
for(unsigned int i = 0; i < totalCameras; i++)
{
_cameraList[i]->insertChild(index, child);
}
return true;
}
bool CURRENT_CLASS::removeChild(osg::Node *child)
{
return Group::removeChild(child);
return Group::removeChild(child);
}
bool CURRENT_CLASS::removeChild(unsigned int pos, unsigned int numRemove)
{
if(!Group::removeChild(pos, numRemove)) return false; // Remove child
if(!Group::removeChild(pos, numRemove)) return false; // Remove child
// Remove child from each CameraNode
unsigned int totalCameras = _cameraList.size();
for(unsigned int i = 0; i < totalCameras; i++)
{
_cameraList[i]->removeChild(pos, numRemove);
}
return true;
// Remove child from each CameraNode
unsigned int totalCameras = _cameraList.size();
for(unsigned int i = 0; i < totalCameras; i++)
{
_cameraList[i]->removeChild(pos, numRemove);
}
return true;
}
bool CURRENT_CLASS::setChild(unsigned int i, osg::Node *node)
{
if(!Group::setChild(i, node)) return false; // Set child
if(!Group::setChild(i, node)) return false; // Set child
// Set child for each CameraNode
unsigned int totalCameras = _cameraList.size();
for(unsigned int j = 0; j < totalCameras; j++)
{
_cameraList[j]->setChild(i, node);
}
return true;
// Set child for each CameraNode
unsigned int totalCameras = _cameraList.size();
for(unsigned int j = 0; j < totalCameras; j++)
{
_cameraList[j]->setChild(i, node);
}
return true;
}
osg::CameraNode* CURRENT_CLASS::createOrReuseCamera(const osg::Matrix& proj,
double znear, double zfar,
const unsigned int &camNum)
{
if(_cameraList.size() <= camNum) _cameraList.resize(camNum+1);
osg::CameraNode *camera = _cameraList[camNum].get();
if(!camera) // Create a new CameraNode
{
camera = new osg::CameraNode;
camera->setCullingActive(false);
camera->setRenderOrder(_renderOrder);
camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
if(_cameraList.size() <= camNum) _cameraList.resize(camNum+1);
osg::CameraNode *camera = _cameraList[camNum].get();
if(!camera) // Create a new CameraNode
{
camera = new osg::CameraNode;
camera->setCullingActive(false);
camera->setRenderOrder(_renderOrder);
camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
// We will compute the near/far planes ourselves
camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
camera->setCullingMode(osg::CullSettings::ENABLE_ALL_CULLING);
// We will compute the near/far planes ourselves
camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
camera->setCullingMode(osg::CullSettings::ENABLE_ALL_CULLING);
if(camNum == 0 && _clearColorBuffer)
camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
else
camera->setClearMask(GL_DEPTH_BUFFER_BIT);
if(camNum == 0 && _clearColorBuffer)
camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
else
camera->setClearMask(GL_DEPTH_BUFFER_BIT);
// Add our children to the new CameraNode's children
unsigned int numChildren = _children.size();
for(unsigned int i = 0; i < numChildren; i++)
{
camera->addChild(_children[i].get());
}
// Add our children to the new CameraNode's children
unsigned int numChildren = _children.size();
for(unsigned int i = 0; i < numChildren; i++)
{
camera->addChild(_children[i].get());
}
_cameraList[camNum] = camera;
}
_cameraList[camNum] = camera;
}
osg::Matrixd &projection = camera->getProjectionMatrix();
projection = proj;
osg::Matrixd &projection = camera->getProjectionMatrix();
projection = proj;
// Slightly inflate the near & far planes to avoid objects at the
// extremes being clipped out.
znear *= 0.999;
zfar *= 1.001;
// Slightly inflate the near & far planes to avoid objects at the
// extremes being clipped out.
znear *= 0.999;
zfar *= 1.001;
// Clamp the projection matrix z values to the range (near, far)
double epsilon = 1.0e-6;
if(fabs(projection(0,3)) < epsilon &&
fabs(projection(1,3)) < epsilon &&
fabs(projection(2,3)) < epsilon ) // Projection is Orthographic
{
epsilon = -1.0/(zfar - znear); // Used as a temp variable
projection(2,2) = 2.0*epsilon;
projection(3,2) = (zfar + znear)*epsilon;
}
else // Projection is Perspective
{
double trans_near = (-znear*projection(2,2) + projection(3,2)) /
(-znear*projection(2,3) + projection(3,3));
double trans_far = (-zfar*projection(2,2) + projection(3,2)) /
(-zfar*projection(2,3) + projection(3,3));
double ratio = fabs(2.0/(trans_near - trans_far));
double center = -0.5*(trans_near + trans_far);
// Clamp the projection matrix z values to the range (near, far)
double epsilon = 1.0e-6;
if(fabs(projection(0,3)) < epsilon &&
fabs(projection(1,3)) < epsilon &&
fabs(projection(2,3)) < epsilon ) // Projection is Orthographic
{
epsilon = -1.0/(zfar - znear); // Used as a temp variable
projection(2,2) = 2.0*epsilon;
projection(3,2) = (zfar + znear)*epsilon;
}
else // Projection is Perspective
{
double trans_near = (-znear*projection(2,2) + projection(3,2)) /
(-znear*projection(2,3) + projection(3,3));
double trans_far = (-zfar*projection(2,2) + projection(3,2)) /
(-zfar*projection(2,3) + projection(3,3));
double ratio = fabs(2.0/(trans_near - trans_far));
double center = -0.5*(trans_near + trans_far);
projection.postMult(osg::Matrixd(1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, ratio, 0.0,
0.0, 0.0, center*ratio, 1.0));
}
projection.postMult(osg::Matrixd(1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, ratio, 0.0,
0.0, 0.0, center*ratio, 1.0));
}
return camera;
return camera;
}
#undef CURRENT_CLASS

View File

@@ -10,66 +10,66 @@
bool precedes(const DistanceAccumulator::DistancePair &a,
const DistanceAccumulator::DistancePair &b)
{
// This results in sorting in order of descending far distances
if(a.second > b.second) return true;
else return false;
// This results in sorting in order of descending far distances
if(a.second > b.second) return true;
else return false;
}
/** Computes distance betwen a point and the viewpoint of a matrix */
double distance(const osg::Vec3 &coord, const osg::Matrix& matrix)
{
return -( coord[0]*matrix(0,2) + coord[1]*matrix(1,2) +
coord[2]*matrix(2,2) + matrix(3,2) );
return -( coord[0]*matrix(0,2) + coord[1]*matrix(1,2) +
coord[2]*matrix(2,2) + matrix(3,2) );
}
#define CURRENT_CLASS DistanceAccumulator
CURRENT_CLASS::CURRENT_CLASS()
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN),
_nearFarRatio(0.0005), _maxDepth(UINT_MAX)
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN),
_nearFarRatio(0.0005), _maxDepth(UINT_MAX)
{
setMatrices(osg::Matrix::identity(), osg::Matrix::identity());
reset();
setMatrices(osg::Matrix::identity(), osg::Matrix::identity());
reset();
}
CURRENT_CLASS::~CURRENT_CLASS() {}
void CURRENT_CLASS::pushLocalFrustum()
{
osg::Matrix& currMatrix = _viewMatrices.back();
osg::Matrix& currMatrix = _viewMatrices.back();
// Compute the frustum in local space
osg::Polytope localFrustum;
localFrustum.setToUnitFrustum(false, false);
localFrustum.transformProvidingInverse(currMatrix*_projectionMatrices.back());
_localFrusta.push_back(localFrustum);
// Compute the frustum in local space
osg::Polytope localFrustum;
localFrustum.setToUnitFrustum(false, false);
localFrustum.transformProvidingInverse(currMatrix*_projectionMatrices.back());
_localFrusta.push_back(localFrustum);
// Compute new bounding box corners
bbCornerPair corner;
corner.second = (currMatrix(0,2)<=0?1:0) |
(currMatrix(1,2)<=0?2:0) |
(currMatrix(2,2)<=0?4:0);
corner.first = (~corner.second)&7;
_bbCorners.push_back(corner);
// Compute new bounding box corners
bbCornerPair corner;
corner.second = (currMatrix(0,2)<=0?1:0) |
(currMatrix(1,2)<=0?2:0) |
(currMatrix(2,2)<=0?4:0);
corner.first = (~corner.second)&7;
_bbCorners.push_back(corner);
}
void CURRENT_CLASS::pushDistancePair(double zNear, double zFar)
{
if(zFar > 0.0) // Make sure some of drawable is visible
{
// Make sure near plane is in front of viewpoint.
if(zNear <= 0.0)
{
zNear = zFar*_nearFarRatio;
if(zNear >= 1.0) zNear = 1.0; // 1.0 limit chosen arbitrarily!
}
if(zFar > 0.0) // Make sure some of drawable is visible
{
// Make sure near plane is in front of viewpoint.
if(zNear <= 0.0)
{
zNear = zFar*_nearFarRatio;
if(zNear >= 1.0) zNear = 1.0; // 1.0 limit chosen arbitrarily!
}
// Add distance pair for current drawable
_distancePairs.push_back(DistancePair(zNear, zFar));
// Add distance pair for current drawable
_distancePairs.push_back(DistancePair(zNear, zFar));
// Override the current nearest/farthest planes if necessary
if(zNear < _limits.first) _limits.first = zNear;
if(zFar > _limits.second) _limits.second = zFar;
}
// Override the current nearest/farthest planes if necessary
if(zNear < _limits.first) _limits.first = zNear;
if(zFar > _limits.second) _limits.second = zFar;
}
}
/** Return true if the node should be traversed, and false if the bounding sphere
@@ -77,265 +77,265 @@ void CURRENT_CLASS::pushDistancePair(double zNear, double zFar)
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);
// 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;
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;
// 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 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);
// If traversal should stop, then store this node's (near,far) pair
if(!keepTraversing) pushDistancePair(zNear, zFar);
return keepTraversing;
return keepTraversing;
}
void CURRENT_CLASS::apply(osg::Node &node)
{
if(shouldContinueTraversal(node))
{
// Traverse this node
_currentDepth++;
traverse(node);
_currentDepth--;
}
if(shouldContinueTraversal(node))
{
// Traverse this node
_currentDepth++;
traverse(node);
_currentDepth--;
}
}
void CURRENT_CLASS::apply(osg::Projection &proj)
{
if(shouldContinueTraversal(proj))
{
// Push the new projection matrix view frustum
_projectionMatrices.push_back(proj.getMatrix());
pushLocalFrustum();
if(shouldContinueTraversal(proj))
{
// Push the new projection matrix view frustum
_projectionMatrices.push_back(proj.getMatrix());
pushLocalFrustum();
// Traverse the group
_currentDepth++;
traverse(proj);
_currentDepth--;
// Traverse the group
_currentDepth++;
traverse(proj);
_currentDepth--;
// Reload original matrix and frustum
_localFrusta.pop_back();
_bbCorners.pop_back();
_projectionMatrices.pop_back();
}
// Reload original matrix and frustum
_localFrusta.pop_back();
_bbCorners.pop_back();
_projectionMatrices.pop_back();
}
}
void CURRENT_CLASS::apply(osg::Transform &transform)
{
if(shouldContinueTraversal(transform))
{
// Compute transform for current node
osg::Matrix currMatrix = _viewMatrices.back();
bool pushMatrix = transform.computeLocalToWorldMatrix(currMatrix, this);
if(shouldContinueTraversal(transform))
{
// Compute transform for current node
osg::Matrix currMatrix = _viewMatrices.back();
bool pushMatrix = transform.computeLocalToWorldMatrix(currMatrix, this);
if(pushMatrix)
{
// Store the new modelview matrix and view frustum
_viewMatrices.push_back(currMatrix);
pushLocalFrustum();
}
if(pushMatrix)
{
// Store the new modelview matrix and view frustum
_viewMatrices.push_back(currMatrix);
pushLocalFrustum();
}
_currentDepth++;
traverse(transform);
_currentDepth--;
_currentDepth++;
traverse(transform);
_currentDepth--;
if(pushMatrix)
{
// Restore the old modelview matrix and view frustum
_localFrusta.pop_back();
_bbCorners.pop_back();
_viewMatrices.pop_back();
}
}
if(pushMatrix)
{
// Restore the old modelview matrix and view frustum
_localFrusta.pop_back();
_bbCorners.pop_back();
_viewMatrices.pop_back();
}
}
}
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;
// 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);
// 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())
{
// Make sure drawable will be visible in the scene
if(!_localFrusta.back().contains(bb)) continue;
const osg::BoundingBox &bb = drawable->getBound();
if(bb.valid())
{
// Make sure drawable will be visible in the scene
if(!_localFrusta.back().contains(bb)) continue;
// Compute near/far distances for current drawable
zNear = distance(bb.corner(_bbCorners.back().first),
// Compute near/far distances for current drawable
zNear = distance(bb.corner(_bbCorners.back().first),
_viewMatrices.back());
zFar = distance(bb.corner(_bbCorners.back().second),
_viewMatrices.back());
if(zNear > zFar) std::swap(zNear, zFar);
pushDistancePair(zNear, zFar);
}
}
}
zFar = distance(bb.corner(_bbCorners.back().second),
_viewMatrices.back());
if(zNear > zFar) std::swap(zNear, zFar);
pushDistancePair(zNear, zFar);
}
}
}
}
void CURRENT_CLASS::setMatrices(const osg::Matrix &modelview,
const osg::Matrix &projection)
{
_modelview = modelview;
_projection = projection;
_modelview = modelview;
_projection = projection;
}
void CURRENT_CLASS::reset()
{
// Clear vectors & values
_distancePairs.clear();
_cameraPairs.clear();
_limits.first = DBL_MAX;
_limits.second = 0.0;
_currentDepth = 0;
// Clear vectors & values
_distancePairs.clear();
_cameraPairs.clear();
_limits.first = DBL_MAX;
_limits.second = 0.0;
_currentDepth = 0;
// Initial transform matrix is the modelview matrix
_viewMatrices.clear();
_viewMatrices.push_back(_modelview);
// Initial transform matrix is the modelview matrix
_viewMatrices.clear();
_viewMatrices.push_back(_modelview);
// Set the initial projection matrix
_projectionMatrices.clear();
_projectionMatrices.push_back(_projection);
// Set the initial projection matrix
_projectionMatrices.clear();
_projectionMatrices.push_back(_projection);
// Create a frustum without near/far planes, for cull computations
_localFrusta.clear();
_bbCorners.clear();
pushLocalFrustum();
// Create a frustum without near/far planes, for cull computations
_localFrusta.clear();
_bbCorners.clear();
pushLocalFrustum();
}
void CURRENT_CLASS::computeCameraPairs()
{
// Nothing in the scene, so no cameras needed
if(_distancePairs.empty()) return;
// Nothing in the scene, so no cameras needed
if(_distancePairs.empty()) return;
// Entire scene can be handled by just one camera
if(_limits.first >= _limits.second*_nearFarRatio)
{
_cameraPairs.push_back(_limits);
return;
}
// Entire scene can be handled by just one camera
if(_limits.first >= _limits.second*_nearFarRatio)
{
_cameraPairs.push_back(_limits);
return;
}
PairList::iterator i,j;
PairList::iterator i,j;
// Sort the list of distance pairs by descending far distance
std::sort(_distancePairs.begin(), _distancePairs.end(), precedes);
// Sort the list of distance pairs by descending far distance
std::sort(_distancePairs.begin(), _distancePairs.end(), precedes);
// Combine overlapping distance pairs. The resulting set of distance
// pairs (called combined pairs) will not overlap.
PairList combinedPairs;
DistancePair currPair = _distancePairs.front();
for(i = _distancePairs.begin(); i != _distancePairs.end(); i++)
{
// Current distance pair does not overlap current combined pair, so
// save the current combined pair and start a new one.
if(i->second < 0.99*currPair.first)
{
combinedPairs.push_back(currPair);
currPair = *i;
}
// Combine overlapping distance pairs. The resulting set of distance
// pairs (called combined pairs) will not overlap.
PairList combinedPairs;
DistancePair currPair = _distancePairs.front();
for(i = _distancePairs.begin(); i != _distancePairs.end(); i++)
{
// Current distance pair does not overlap current combined pair, so
// save the current combined pair and start a new one.
if(i->second < 0.99*currPair.first)
{
combinedPairs.push_back(currPair);
currPair = *i;
}
// Current distance pair overlaps current combined pair, so expand
// current combined pair to encompass distance pair.
else
currPair.first = std::min(i->first, currPair.first);
}
combinedPairs.push_back(currPair); // Add last pair
// Current distance pair overlaps current combined pair, so expand
// current combined pair to encompass distance pair.
else
currPair.first = std::min(i->first, currPair.first);
}
combinedPairs.push_back(currPair); // Add last pair
// Compute the (near,far) distance pairs for each camera.
// Each of these distance pairs is called a "view segment".
double currNearLimit, numSegs, new_ratio;
double ratio_invlog = 1.0/log(_nearFarRatio);
unsigned int temp;
for(i = combinedPairs.begin(); i != combinedPairs.end(); i++)
{
currPair = *i; // Save current view segment
// Compute the (near,far) distance pairs for each camera.
// Each of these distance pairs is called a "view segment".
double currNearLimit, numSegs, new_ratio;
double ratio_invlog = 1.0/log(_nearFarRatio);
unsigned int temp;
for(i = combinedPairs.begin(); i != combinedPairs.end(); i++)
{
currPair = *i; // Save current view segment
// Compute the fractional number of view segments needed to span
// the current combined distance pair.
currNearLimit = currPair.second*_nearFarRatio;
if(currPair.first >= currNearLimit) numSegs = 1.0;
else
{
numSegs = log(currPair.first/currPair.second)*ratio_invlog;
// Compute the fractional number of view segments needed to span
// the current combined distance pair.
currNearLimit = currPair.second*_nearFarRatio;
if(currPair.first >= currNearLimit) numSegs = 1.0;
else
{
numSegs = log(currPair.first/currPair.second)*ratio_invlog;
// Compute the near plane of the last view segment
//currNearLimit *= pow(_nearFarRatio, -floor(-numSegs) - 1);
for(temp = (unsigned int)(-floor(-numSegs)); temp > 1; temp--)
{
currNearLimit *= _nearFarRatio;
}
}
// Compute the near plane of the last view segment
//currNearLimit *= pow(_nearFarRatio, -floor(-numSegs) - 1);
for(temp = (unsigned int)(-floor(-numSegs)); temp > 1; temp--)
{
currNearLimit *= _nearFarRatio;
}
}
// See if the closest view segment can absorb other combined pairs
for(j = i+1; j != combinedPairs.end(); j++)
{
// No other distance pairs can be included
if(j->first < currNearLimit) break;
}
// See if the closest view segment can absorb other combined pairs
for(j = i+1; j != combinedPairs.end(); j++)
{
// No other distance pairs can be included
if(j->first < currNearLimit) break;
}
// If we did absorb another combined distance pair, recompute the
// number of required view segments.
if(i != j-1)
{
i = j-1;
currPair.first = i->first;
if(currPair.first >= currPair.second*_nearFarRatio) numSegs = 1.0;
else numSegs = log(currPair.first/currPair.second)*ratio_invlog;
}
// If we did absorb another combined distance pair, recompute the
// number of required view segments.
if(i != j-1)
{
i = j-1;
currPair.first = i->first;
if(currPair.first >= currPair.second*_nearFarRatio) numSegs = 1.0;
else numSegs = log(currPair.first/currPair.second)*ratio_invlog;
}
/* Compute an integer number of segments by rounding the fractional
number of segments according to how many segments there are.
In general, the more segments there are, the more likely that the
integer number of segments will be rounded down.
The purpose of this is to try to minimize the number of view segments
that are used to render any section of the scene without violating
the specified _nearFarRatio by too much. */
if(numSegs < 10.0) numSegs = floor(numSegs + 1.0 - 0.1*floor(numSegs));
else numSegs = floor(numSegs);
/* Compute an integer number of segments by rounding the fractional
number of segments according to how many segments there are.
In general, the more segments there are, the more likely that the
integer number of segments will be rounded down.
The purpose of this is to try to minimize the number of view segments
that are used to render any section of the scene without violating
the specified _nearFarRatio by too much. */
if(numSegs < 10.0) numSegs = floor(numSegs + 1.0 - 0.1*floor(numSegs));
else numSegs = floor(numSegs);
// Compute the near/far ratio that will be used for each view segment
// in this section of the scene.
new_ratio = pow(currPair.first/currPair.second, 1.0/numSegs);
// Compute the near/far ratio that will be used for each view segment
// in this section of the scene.
new_ratio = pow(currPair.first/currPair.second, 1.0/numSegs);
// Add numSegs new view segments to the camera pairs list
for(temp = (unsigned int)numSegs; temp > 0; temp--)
{
currPair.first = currPair.second*new_ratio;
_cameraPairs.push_back(currPair);
currPair.second = currPair.first;
}
}
// Add numSegs new view segments to the camera pairs list
for(temp = (unsigned int)numSegs; temp > 0; temp--)
{
currPair.first = currPair.second*new_ratio;
_cameraPairs.push_back(currPair);
currPair.second = currPair.first;
}
}
}
void CURRENT_CLASS::setNearFarRatio(double ratio)
{
if(ratio <= 0.0 || ratio >= 1.0) return;
_nearFarRatio = ratio;
if(ratio <= 0.0 || ratio >= 1.0) return;
_nearFarRatio = ratio;
}
#undef CURRENT_CLASS

View File

@@ -23,38 +23,38 @@ const double AU = 149697900.0;
osg::Node* createScene()
{
// Create the Earth, in blue
osg::ShapeDrawable *earth_sd = new osg::ShapeDrawable;
osg::Sphere* earth_sphere = new osg::Sphere;
earth_sphere->setRadius(r_earth);
earth_sd->setShape(earth_sphere);
earth_sd->setColor(osg::Vec4(0, 0, 1.0, 1.0));
// Create the Earth, in blue
osg::ShapeDrawable *earth_sd = new osg::ShapeDrawable;
osg::Sphere* earth_sphere = new osg::Sphere;
earth_sphere->setRadius(r_earth);
earth_sd->setShape(earth_sphere);
earth_sd->setColor(osg::Vec4(0, 0, 1.0, 1.0));
osg::Geode* earth = new osg::Geode;
earth->setName("earth");
earth->addDrawable(earth_sd);
osg::Geode* earth = new osg::Geode;
earth->setName("earth");
earth->addDrawable(earth_sd);
// Create the Sun, in yellow
osg::ShapeDrawable *sun_sd = new osg::ShapeDrawable;
osg::Sphere* sun_sphere = new osg::Sphere;
sun_sphere->setRadius(r_sun);
sun_sd->setShape(sun_sphere);
sun_sd->setColor(osg::Vec4(1.0, 0.0, 0.0, 1.0));
// Create the Sun, in yellow
osg::ShapeDrawable *sun_sd = new osg::ShapeDrawable;
osg::Sphere* sun_sphere = new osg::Sphere;
sun_sphere->setRadius(r_sun);
sun_sd->setShape(sun_sphere);
sun_sd->setColor(osg::Vec4(1.0, 0.0, 0.0, 1.0));
osg::Geode* sun = new osg::Geode;
sun->setName("sun");
sun->addDrawable(sun_sd);
osg::Geode* sun = new osg::Geode;
sun->setName("sun");
sun->addDrawable(sun_sd);
// Move the sun behind the earth
osg::PositionAttitudeTransform *pat = new osg::PositionAttitudeTransform;
pat->setPosition(osg::Vec3d(0.0, AU, 0.0));
// Move the sun behind the earth
osg::PositionAttitudeTransform *pat = new osg::PositionAttitudeTransform;
pat->setPosition(osg::Vec3d(0.0, AU, 0.0));
osg::Group* scene = new osg::Group;
scene->addChild(earth);
scene->addChild(pat);
pat->addChild(sun);
osg::Group* scene = new osg::Group;
scene->addChild(earth);
scene->addChild(pat);
pat->addChild(sun);
return scene;
return scene;
}
int main( int argc, char **argv )