diff --git a/include/osg/Matrix b/include/osg/Matrix index c444f92af..152c41151 100644 --- a/include/osg/Matrix +++ b/include/osg/Matrix @@ -299,7 +299,7 @@ inline Matrix Matrix::rotate(const Vec3& from, const Vec3& to ) return m; } -inline Matrix inverse( const Matrix& matrix) +inline Matrix Matrix::inverse( const Matrix& matrix) { Matrix m; m.invert(matrix); diff --git a/include/osgUtil/CullVisitor b/include/osgUtil/CullVisitor index 0d889df15..5ffba59c3 100644 --- a/include/osgUtil/CullVisitor +++ b/include/osgUtil/CullVisitor @@ -171,9 +171,9 @@ class OSGUTIL_EXPORT CullVisitor : public osg::NodeVisitor return _rootRenderStage.get(); } - const float getCalculatedNearPlane() const { return _calculated_znear; } + const float getCalculatedNearPlane() const { return _computed_znear; } - const float getCalculatedFarPlane() const { return _calculated_zfar; } + const float getCalculatedFarPlane() const { return _computed_zfar; } protected: @@ -197,11 +197,6 @@ class OSGUTIL_EXPORT CullVisitor : public osg::NodeVisitor else acceptNode->accept(*this); } - inline osg::Matrix* getCurrentMatrix() - { - return _modelviewStack.back().get(); - } - inline const osg::Vec3& getEyeLocal() const { return _eyePointStack.back(); @@ -245,8 +240,7 @@ class OSGUTIL_EXPORT CullVisitor : public osg::NodeVisitor return !_modelviewClippingVolumeStack.back().contains(bb,mode); } - void updateCalculatedNearFar(const osg::BoundingBox& bb); - + void updateCalculatedNearFar(const osg::Matrix& matrix,const osg::Drawable& drawable); void updateCalculatedNearFar(const osg::Vec3& pos); /** Add a drawable to current render graph.*/ @@ -392,8 +386,17 @@ class OSGUTIL_EXPORT CullVisitor : public osg::NodeVisitor float _LODBias; - float _calculated_znear; - float _calculated_zfar; + + enum ComputeNearFarMode + { + DO_NOT_COMPUTE_NEAR_FAR = 0, + COMPUTE_NEAR_FAR_USING_BOUNDING_VOLUMES, + COMPUTE_NEAR_FAR_USING_PRIMITIVES + }; + + ComputeNearFarMode _computeNearFar; + float _computed_znear; + float _computed_zfar; osg::ref_ptr _earthSky; diff --git a/src/osgUtil/CullVisitor.cpp b/src/osgUtil/CullVisitor.cpp index eb00099cf..5e9efa22c 100644 --- a/src/osgUtil/CullVisitor.cpp +++ b/src/osgUtil/CullVisitor.cpp @@ -93,8 +93,9 @@ CullVisitor::CullVisitor() _tsm = OBJECT_EYE_POINT_DISTANCE; - _calculated_znear = FLT_MAX; - _calculated_zfar = -FLT_MAX; + _computeNearFar = COMPUTE_NEAR_FAR_USING_BOUNDING_VOLUMES; + _computed_znear = FLT_MAX; + _computed_zfar = -FLT_MAX; _impostorActive = true; _depthSortImpostorSprites = false; @@ -132,8 +133,9 @@ void CullVisitor::reset() // reset the calculated near far planes. - _calculated_znear = FLT_MAX; - _calculated_zfar = -FLT_MAX; + _computeNearFar = COMPUTE_NEAR_FAR_USING_BOUNDING_VOLUMES; + _computed_znear = FLT_MAX; + _computed_zfar = -FLT_MAX; osg::Vec3 lookVector(0.0,0.0,-1.0); @@ -196,6 +198,32 @@ void CullVisitor::pushProjectionMatrix(Matrix* matrix) void CullVisitor::popProjectionMatrix() { + + if (_computed_zfar>0.0f) + { + + // adjust the projection matrix so that it encompases the local coords. + // so it doesn't cull them out. + osg::Matrix& projection = *_projectionStack.back(); + + double desired_znear = _computed_znear*0.95; + double desired_zfar = _computed_zfar*1.05; + + double min_near_plane = _computed_zfar*0.0005f; + if (desired_znear_calculated_zfar) _calculated_zfar = d_far; + if (d_near<_computed_znear) _computed_znear = d_near; + if (d_far>_computed_zfar) _computed_zfar = d_far; } else { @@ -302,9 +312,10 @@ void CullVisitor::updateCalculatedNearFar(const osg::BoundingBox& bb) } // note, need to reverse the d_near/d_far association because they are // the wrong way around... - if (d_far<_calculated_znear) _calculated_znear = d_far; - if (d_near>_calculated_zfar) _calculated_zfar = d_near; + if (d_far<_computed_znear) _computed_znear = d_far; + if (d_near>_computed_zfar) _computed_zfar = d_near; } + } void CullVisitor::updateCalculatedNearFar(const osg::Vec3& pos) @@ -320,8 +331,8 @@ void CullVisitor::updateCalculatedNearFar(const osg::Vec3& pos) d = -pos.z(); } - if (d<_calculated_znear) _calculated_znear = d; - if (d>_calculated_zfar) _calculated_zfar = d; + if (d<_computed_znear) _computed_znear = d; + if (d>_computed_zfar) _computed_zfar = d; } void CullVisitor::setCullingMode(CullViewState::CullingMode mode) @@ -374,7 +385,7 @@ void CullVisitor::apply(Geode& node) StateSet* node_state = node.getStateSet(); if (node_state) pushStateSet(node_state); - Matrix* matrix = getCurrentMatrix(); + Matrix& matrix = getModelViewMatrix(); for(int i=0;igetStateSet(); @@ -400,15 +411,7 @@ void CullVisitor::apply(Geode& node) if (isTransparent) { - Vec3 center; - if (matrix) - { - center = (drawable->getBound().center())*(*matrix); - } - else - { - center = drawable->getBound().center(); - } + Vec3 center = (drawable->getBound().center())*matrix; float depth; switch(_tsm) @@ -419,14 +422,14 @@ void CullVisitor::apply(Geode& node) } if (stateset) pushStateSet(stateset); - addDrawableAndDepth(drawable,matrix,depth); + addDrawableAndDepth(drawable,&matrix,depth); if (stateset) popStateSet(); } else { if (stateset) pushStateSet(stateset); - addDrawable(drawable,matrix); + addDrawable(drawable,&matrix); if (stateset) popStateSet(); } @@ -462,12 +465,19 @@ void CullVisitor::apply(Billboard& node) // need to modify isCulled to handle the billboard offset. // if (isCulled(drawable->getBound())) continue; - updateCalculatedNearFar(pos); - Matrix* billboard_matrix = createOrReuseMatrix(modelview); node.getMatrix(*billboard_matrix,eye_local,pos); + Vec3 center; + center = pos*modelview; + + if (_computeNearFar) + { + float d = center.z(); + if (d<_computed_znear) _computed_znear = d; + if (d>_computed_zfar) _computed_zfar = d; + } StateSet* stateset = drawable->getStateSet(); @@ -475,8 +485,6 @@ void CullVisitor::apply(Billboard& node) if (isTransparent) { - Vec3 center; - center = pos*modelview; float depth; switch(_tsm) @@ -512,11 +520,11 @@ void CullVisitor::apply(LightSource& node) StateSet* node_state = node.getStateSet(); if (node_state) pushStateSet(node_state); - Matrix* matrix = getCurrentMatrix(); + Matrix& matrix = getModelViewMatrix(); Light* light = node.getLight(); if (light) { - addLight(light,matrix); + addLight(light,&matrix); } // pop the node's state off the geostate stack. @@ -596,6 +604,14 @@ void CullVisitor::apply(Projection& node) StateSet* node_state = node.getStateSet(); if (node_state) pushStateSet(node_state); + + // record previous near and far values. + float previous_znear = _computed_znear; + float previous_zfar = _computed_zfar; + + _computed_znear = FLT_MAX; + _computed_zfar = -FLT_MAX; + ref_ptr matrix = createOrReuseMatrix(node.getMatrix()); pushProjectionMatrix(matrix.get()); @@ -603,6 +619,10 @@ void CullVisitor::apply(Projection& node) popProjectionMatrix(); + _computed_znear = previous_znear; + _computed_zfar = previous_zfar; + + // pop the node's state off the render graph stack. if (node_state) popStateSet(); @@ -709,7 +729,7 @@ void CullVisitor::apply(Impostor& node) // within the impostor distance threshold therefore attempt // to use impostor instead. - Matrix* matrix = getCurrentMatrix(); + Matrix& matrix = getModelViewMatrix(); // search for the best fit ImpostorSprite; ImpostorSprite* impostorSprite = node.findBestImpostorSprite(eyeLocal); @@ -743,7 +763,7 @@ void CullVisitor::apply(Impostor& node) if (impostorSprite) { - updateCalculatedNearFar(impostorSprite->getBound()); + if (_computeNearFar) updateCalculatedNearFar(matrix,*impostorSprite); StateSet* stateset = impostorSprite->getStateSet(); @@ -751,15 +771,7 @@ void CullVisitor::apply(Impostor& node) if (_depthSortImpostorSprites) { - Vec3 center; - if (matrix) - { - center = node.getCenter()*(*matrix); - } - else - { - center = node.getCenter(); - } + Vec3 center = node.getCenter()*matrix; float depth; switch(_tsm) @@ -769,11 +781,11 @@ void CullVisitor::apply(Impostor& node) default: depth = center.length2();break; } - addDrawableAndDepth(impostorSprite,matrix,depth); + addDrawableAndDepth(impostorSprite,&matrix,depth); } else { - addDrawable(impostorSprite,matrix); + addDrawable(impostorSprite,&matrix); } if (stateset) popStateSet(); @@ -805,7 +817,7 @@ ImpostorSprite* CullVisitor::createImpostorSprite(Impostor& node) // projection matrix... bool isPerspectiveProjection = true; - Matrix* matrix = getCurrentMatrix(); + const Matrix& matrix = getModelViewMatrix(); const BoundingSphere& bs = node.getBound(); osg::Vec3 eye_local = getEyeLocal(); int eval = node.evaluate(eye_local,_LODBias); @@ -818,7 +830,7 @@ ImpostorSprite* CullVisitor::createImpostorSprite(Impostor& node) Vec3 eye_world(0.0,0.0,0.0); - Vec3 center_world = bs.center()*(*matrix); + Vec3 center_world = bs.center()*matrix; // no appropriate sprite has been found therefore need to create // one for use. @@ -888,25 +900,10 @@ ImpostorSprite* CullVisitor::createImpostorSprite(Impostor& node) Vec3 top_local ( center_local+up_local); Vec3 right_local ( center_local+sv_local); - Vec3 near_world; - Vec3 far_world; - Vec3 top_world; - Vec3 right_world; - - if (matrix) - { - near_world = near_local * (*matrix); - far_world = far_local * (*matrix); - top_world = top_local * (*matrix); - right_world = right_local * (*matrix); - } - else - { - near_world = near_local; - far_world = far_local; - top_world = top_local; - right_world = right_local; - } + Vec3 near_world = near_local * matrix; + Vec3 far_world = far_local * matrix; + Vec3 top_world = top_local * matrix; + Vec3 right_world = right_local * matrix; float znear = (near_world-eye_world).length(); float zfar = (far_world-eye_world).length(); diff --git a/src/osgUtil/SceneView.cpp b/src/osgUtil/SceneView.cpp index 588de76e8..09738f1d5 100644 --- a/src/osgUtil/SceneView.cpp +++ b/src/osgUtil/SceneView.cpp @@ -279,11 +279,6 @@ void SceneView::cull() _cullVisitor->setTraversalMask(_cullMask); cullStage(projection.get(),modelview.get(),_cullVisitor.get(),_rendergraph.get(),_renderStage.get()); } - - if (_camera.valid() && _calc_nearfar) - { - _camera->setNearFar(_near_plane,_far_plane); - } } @@ -313,11 +308,6 @@ void SceneView::cullStage(osg::Matrix* projection,osg::Matrix* modelview,osgUtil cullVisitor->setRenderGraph(rendergraph); cullVisitor->setRenderStage(renderStage); -// // SandB -// //now make it compute "clipping directions" needed for detailed culling -// if(cullVisitor->getDetailedCulling()) -// cullVisitor->calcClippingDirections();//only once pre frame - renderStage->reset(); // comment out reset of rendergraph since clean is more efficient. @@ -382,37 +372,6 @@ void SceneView::cullStage(osg::Matrix* projection,osg::Matrix* modelview,osgUtil } - if (_calc_nearfar) - { - _near_plane = cullVisitor->getCalculatedNearPlane(); - _far_plane = cullVisitor->getCalculatedFarPlane(); - - if (_near_plane<=_far_plane) - { - // shift the far plane slight further away from the eye point. - // and shift the near plane slightly near the eye point, this - // will give a little space betwenn the near and far planes - // and the model, crucial when the naer and far planes are - // coincedent. - _far_plane *= 1.05; - _near_plane *= 0.95; - -// // if required clamp the near plane to prevent negative or near zero -// // near planes. -// if(!cullVisitor->getDetailedCulling()) -// { - float min_near_plane = _far_plane*0.0005f; - if (_near_plane