From c52207b637082149889c7800bd6e8e379fbf25f1 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 7 Feb 2007 16:32:14 +0000 Subject: [PATCH] Added new Transform::ReferenceType enum ABSOLUTE_RF_INHERIT_VIEWPOINT to support internal RTT cameras that wish to use the main cameras view/eye point for LOD and other distance based tests. --- include/osg/CullStack | 3 +- include/osg/Transform | 9 ++++- src/osg/CollectOccludersVisitor.cpp | 2 +- src/osg/CullStack.cpp | 41 +++++++++++++++++++++-- src/osg/Transform.cpp | 2 +- src/osgPlugins/osg/Transform.cpp | 13 ++++++-- src/osgPlugins/txp/TXPNode.cpp | 4 ++- src/osgUtil/CullVisitor.cpp | 51 ++++++++++------------------- src/osgUtil/IntersectVisitor.cpp | 37 +++++++++++---------- src/osgUtil/Optimizer.cpp | 2 +- src/osgUtil/SceneView.cpp | 4 +-- 11 files changed, 104 insertions(+), 64 deletions(-) diff --git a/include/osg/CullStack b/include/osg/CullStack index 7bf2d66da..bb8764c4d 100644 --- a/include/osg/CullStack +++ b/include/osg/CullStack @@ -18,6 +18,7 @@ #include #include #include +#include namespace osg { @@ -47,7 +48,7 @@ class OSG_EXPORT CullStack : public osg::CullSettings void pushProjectionMatrix(osg::RefMatrix* matrix); void popProjectionMatrix(); - void pushModelViewMatrix(osg::RefMatrix* matrix); + void pushModelViewMatrix(osg::RefMatrix* matrix, Transform::ReferenceFrame referenceFrame); void popModelViewMatrix(); inline float getFrustumVolume() { if (_frustumVolume<0.0f) computeFrustumVolume(); return _frustumVolume; } diff --git a/include/osg/Transform b/include/osg/Transform index c88dc0f8c..c18b3d5b9 100644 --- a/include/osg/Transform +++ b/include/osg/Transform @@ -90,7 +90,8 @@ class OSG_EXPORT Transform : public Group enum ReferenceFrame { RELATIVE_RF, - ABSOLUTE_RF + ABSOLUTE_RF, + ABSOLUTE_RF_INHERIT_VIEWPOINT }; /** Set the transform's ReferenceFrame, either to be relative to its @@ -104,6 +105,12 @@ class OSG_EXPORT Transform : public Group * deep in the scene graph. It is therefore recommended to only use * absolute Transforms at the top of the scene, for such things as * heads up displays. + * ABSOLUTE_RF_INHERIT_VIEWPOINT is the same as ABSOLUTE_RF except it + * adds the ability to use the parents view points position in world coordinates + * as its local viewpoint in the new coordinates frame. This is useful for + * Render to texture Cameras that wish to use the main views LOD range computation + * (which uses the viewpoint rather than the eye point) rather than use the local + * eye point defined by the this Transforms' abosolute view matrix. */ void setReferenceFrame(ReferenceFrame rf); diff --git a/src/osg/CollectOccludersVisitor.cpp b/src/osg/CollectOccludersVisitor.cpp index d54f2b08f..573c6345c 100644 --- a/src/osg/CollectOccludersVisitor.cpp +++ b/src/osg/CollectOccludersVisitor.cpp @@ -89,7 +89,7 @@ void CollectOccludersVisitor::apply(osg::Transform& node) ref_ptr matrix = createOrReuseMatrix(getModelViewMatrix()); node.computeLocalToWorldMatrix(*matrix,this); - pushModelViewMatrix(matrix.get()); + pushModelViewMatrix(matrix.get(), node.getReferenceFrame()); handle_cull_callbacks_and_traverse(node); diff --git a/src/osg/CullStack.cpp b/src/osg/CullStack.cpp index ff0dc352a..71648ab0e 100644 --- a/src/osg/CullStack.cpp +++ b/src/osg/CullStack.cpp @@ -13,6 +13,9 @@ #include #include +#include +#include + using namespace osg; CullStack::CullStack() @@ -187,8 +190,10 @@ void CullStack::popProjectionMatrix() popCullingSet(); } -void CullStack::pushModelViewMatrix(RefMatrix* matrix) +void CullStack::pushModelViewMatrix(RefMatrix* matrix, Transform::ReferenceFrame referenceFrame) { + osg::RefMatrix* originalModelView = _modelviewStack.empty() ? 0 : _modelviewStack.back().get(); + _modelviewStack.push_back(matrix); pushCullingSet(); @@ -196,8 +201,37 @@ void CullStack::pushModelViewMatrix(RefMatrix* matrix) osg::Matrix inv; inv.invert(*matrix); - _eyePointStack.push_back(inv.getTrans()); - _viewPointStack.push_back(getReferenceViewPoint() * inv); + + switch(referenceFrame) + { + case(Transform::RELATIVE_RF): + _eyePointStack.push_back(inv.getTrans()); + _referenceViewPoints.push_back(getReferenceViewPoint()); + _viewPointStack.push_back(getReferenceViewPoint() * inv); + break; + case(Transform::ABSOLUTE_RF): + _eyePointStack.push_back(inv.getTrans()); + _referenceViewPoints.push_back(osg::Vec3(0.0,0.0,0.0)); + _viewPointStack.push_back(_eyePointStack.back()); + break; + case(Transform::ABSOLUTE_RF_INHERIT_VIEWPOINT): + { + _eyePointStack.push_back(inv.getTrans()); + + osg::Vec3 referenceViewPoint = getReferenceViewPoint(); + if (originalModelView) + { + osg::Matrix viewPointTransformMatrix; + viewPointTransformMatrix.invert(*originalModelView); + viewPointTransformMatrix.postMult(*matrix); + referenceViewPoint = referenceViewPoint * viewPointTransformMatrix; + } + + _referenceViewPoints.push_back(referenceViewPoint); + _viewPointStack.push_back(getReferenceViewPoint() * inv); + break; + } + } osg::Vec3 lookVector = getLookVectorLocal(); @@ -215,6 +249,7 @@ void CullStack::popModelViewMatrix() _modelviewStack.pop_back(); _eyePointStack.pop_back(); + _referenceViewPoints.pop_back(); _viewPointStack.pop_back(); popCullingSet(); diff --git a/src/osg/Transform.cpp b/src/osg/Transform.cpp index 5b44e3b73..349e87222 100644 --- a/src/osg/Transform.cpp +++ b/src/osg/Transform.cpp @@ -68,7 +68,7 @@ class TransformVisitor : public NodeVisitor { const osg::Camera* camera = dynamic_cast(*ritr); if (camera && - (camera->getReferenceFrame()==osg::Transform::ABSOLUTE_RF || camera->getParents().empty())) + (camera->getReferenceFrame()!=osg::Transform::RELATIVE_RF || camera->getParents().empty())) { break; } diff --git a/src/osgPlugins/osg/Transform.cpp b/src/osgPlugins/osg/Transform.cpp index 24d057c0a..46b551a66 100644 --- a/src/osgPlugins/osg/Transform.cpp +++ b/src/osgPlugins/osg/Transform.cpp @@ -50,13 +50,19 @@ bool Transform_readLocalData(Object& obj, Input& fr) if (fr[0].matchWord("referenceFrame")) { - if (fr[1].matchWord("RELATIVE_TO_ABSOLUTE") || fr[1].matchWord("ABSOLUTE") ) + if (fr[1].matchWord("RELATIVE_TO_ABSOLUTE") || fr[1].matchWord("ABSOLUTE") || fr[1].matchWord("ABSOLUTE_RF")) { transform.setReferenceFrame(Transform::ABSOLUTE_RF); fr += 2; iteratorAdvanced = true; } - if (fr[1].matchWord("RELATIVE_TO_PARENTS") || fr[1].matchWord("RELATIVE")) + if (fr[1].matchWord("RELATIVE_TO_ABSOLUTE") || fr[1].matchWord("ABSOLUTE_RF_INHERIT_VIEWPOINT") ) + { + transform.setReferenceFrame(Transform::ABSOLUTE_RF_INHERIT_VIEWPOINT); + fr += 2; + iteratorAdvanced = true; + } + if (fr[1].matchWord("RELATIVE_TO_PARENTS") || fr[1].matchWord("RELATIVE") || fr[1].matchWord("RELATIVE_RF")) { transform.setReferenceFrame(Transform::RELATIVE_RF); fr += 2; @@ -78,6 +84,9 @@ bool Transform_writeLocalData(const Object& obj, Output& fw) case Transform::ABSOLUTE_RF: fw << "ABSOLUTE\n"; break; + case Transform::ABSOLUTE_RF_INHERIT_VIEWPOINT: + fw << "ABSOLUTE_RF_INHERIT_VIEWPOINT\n"; + break; case Transform::RELATIVE_RF: default: fw << "RELATIVE\n"; diff --git a/src/osgPlugins/txp/TXPNode.cpp b/src/osgPlugins/txp/TXPNode.cpp index 353def14c..b082b61da 100644 --- a/src/osgPlugins/txp/TXPNode.cpp +++ b/src/osgPlugins/txp/TXPNode.cpp @@ -103,9 +103,10 @@ void TXPNode::traverse(osg::NodeVisitor& nv) osg::ref_ptr tileMapper = new TileMapper; tileMapper->setLODScale(cv->getLODScale()); + tileMapper->pushReferenceViewPoint(cv->getReferenceViewPoint()); tileMapper->pushViewport(cv->getViewport()); tileMapper->pushProjectionMatrix(&(cv->getProjectionMatrix())); - tileMapper->pushModelViewMatrix(&(cv->getModelViewMatrix())); + tileMapper->pushModelViewMatrix(&(cv->getModelViewMatrix()), osg::Transform::RELATIVE_RF); // traverse the scene graph to search for valid tiles accept(*tileMapper); @@ -113,6 +114,7 @@ void TXPNode::traverse(osg::NodeVisitor& nv) tileMapper->popModelViewMatrix(); tileMapper->popProjectionMatrix(); tileMapper->popViewport(); + tileMapper->popReferenceViewPoint(); //std::cout<<" found " << tileMapper._tileMap.size() << std::endl; diff --git a/src/osgUtil/CullVisitor.cpp b/src/osgUtil/CullVisitor.cpp index f02a51a3c..cd05c35de 100644 --- a/src/osgUtil/CullVisitor.cpp +++ b/src/osgUtil/CullVisitor.cpp @@ -961,7 +961,7 @@ void CullVisitor::apply(Transform& node) ref_ptr matrix = createOrReuseMatrix(getModelViewMatrix()); node.computeLocalToWorldMatrix(*matrix,this); - pushModelViewMatrix(matrix.get()); + pushModelViewMatrix(matrix.get(), node.getReferenceFrame()); handle_cull_callbacks_and_traverse(node); @@ -1117,40 +1117,29 @@ void CullVisitor::apply(osg::Camera& camera) osg::RefMatrix* projection = 0; osg::RefMatrix* modelview = 0; - if (camera.getReferenceFrame()==osg::Transform::ABSOLUTE_RF) + if (camera.getReferenceFrame()==osg::Transform::RELATIVE_RF) { + if (camera.getTransformOrder()==osg::Camera::POST_MULTIPLY) + { + projection = createOrReuseMatrix(getProjectionMatrix()*camera.getProjectionMatrix()); + modelview = createOrReuseMatrix(getModelViewMatrix()*camera.getViewMatrix()); + } + else // pre multiply + { + projection = createOrReuseMatrix(camera.getProjectionMatrix()*getProjectionMatrix()); + modelview = createOrReuseMatrix(camera.getViewMatrix()*getModelViewMatrix()); + } + } + else + { + // an absolute reference frame projection = createOrReuseMatrix(camera.getProjectionMatrix()); modelview = createOrReuseMatrix(camera.getViewMatrix()); } - else if (camera.getTransformOrder()==osg::Camera::POST_MULTIPLY) - { - projection = createOrReuseMatrix(getProjectionMatrix()*camera.getProjectionMatrix()); - modelview = createOrReuseMatrix(getModelViewMatrix()*camera.getViewMatrix()); - } - else // pre multiply - { - projection = createOrReuseMatrix(camera.getProjectionMatrix()*getProjectionMatrix()); - modelview = createOrReuseMatrix(camera.getViewMatrix()*getModelViewMatrix()); - } - bool localReferenceViewPoint = true; - if (localReferenceViewPoint) - { - // put the reference view point into the new camera eye coordinates - osg::Vec3 referenceViewPoint = getReferenceViewPoint(); - if (originalModelView.valid()) - { - osg::Matrix matrix; - matrix.invert(originalModelView); // note should this be view.getCamera()->getViewMatrix() ?? - matrix.postMult(*modelview); - referenceViewPoint = referenceViewPoint * matrix; - } - pushReferenceViewPoint(referenceViewPoint); - } - pushProjectionMatrix(projection); - pushModelViewMatrix(modelview); + pushModelViewMatrix(modelview, camera.getReferenceFrame()); if (camera.getRenderOrder()==osg::Camera::NESTED_RENDER) @@ -1277,12 +1266,6 @@ void CullVisitor::apply(osg::Camera& camera) } } - - if (localReferenceViewPoint) - { - // restore the previous reference view point - popReferenceViewPoint(); - } // restore the previous model view matrix. popModelViewMatrix(); diff --git a/src/osgUtil/IntersectVisitor.cpp b/src/osgUtil/IntersectVisitor.cpp index b2c014b24..1f0753b40 100644 --- a/src/osgUtil/IntersectVisitor.cpp +++ b/src/osgUtil/IntersectVisitor.cpp @@ -804,7 +804,26 @@ void PickVisitor::apply(osg::Camera& camera) { if (!camera.isRenderToTextureCamera()) { - if (camera.getReferenceFrame()==osg::Camera::ABSOLUTE_RF) + if (camera.getReferenceFrame()==osg::Camera::RELATIVE_RF) + { + if (camera.getTransformOrder()==osg::Camera::POST_MULTIPLY) + { + runNestedPickVisitor( camera, + camera.getViewport() ? camera.getViewport() : _lastViewport.get(), + _lastProjectionMatrix * camera.getProjectionMatrix(), + _lastViewMatrix * camera.getViewMatrix(), + _mx, _my ); + } + else // PRE_MULTIPLY + { + runNestedPickVisitor( camera, + camera.getViewport() ? camera.getViewport() : _lastViewport.get(), + camera.getProjectionMatrix() * _lastProjectionMatrix, + camera.getViewMatrix() * _lastViewMatrix, + _mx, _my ); + } + } + else { runNestedPickVisitor( camera, camera.getViewport() ? camera.getViewport() : _lastViewport.get(), @@ -812,21 +831,5 @@ void PickVisitor::apply(osg::Camera& camera) camera.getViewMatrix(), _mx, _my ); } - else if (camera.getTransformOrder()==osg::Camera::POST_MULTIPLY) - { - runNestedPickVisitor( camera, - camera.getViewport() ? camera.getViewport() : _lastViewport.get(), - _lastProjectionMatrix * camera.getProjectionMatrix(), - _lastViewMatrix * camera.getViewMatrix(), - _mx, _my ); - } - else // PRE_MULTIPLY - { - runNestedPickVisitor( camera, - camera.getViewport() ? camera.getViewport() : _lastViewport.get(), - camera.getProjectionMatrix() * _lastProjectionMatrix, - camera.getViewMatrix() * _lastViewMatrix, - _mx, _my ); - } } } diff --git a/src/osgUtil/Optimizer.cpp b/src/osgUtil/Optimizer.cpp index 95b854fe6..76e3d2c92 100644 --- a/src/osgUtil/Optimizer.cpp +++ b/src/osgUtil/Optimizer.cpp @@ -789,7 +789,7 @@ class CollectLowestTransformsVisitor : public BaseOptimizerVisitor if (transform) { if (transform->getDataVariance()==osg::Transform::DYNAMIC) _moreThanOneMatrixRequired=true; - else if (transform->getReferenceFrame()==osg::Transform::ABSOLUTE_RF) _moreThanOneMatrixRequired=true; + else if (transform->getReferenceFrame()!=osg::Transform::RELATIVE_RF) _moreThanOneMatrixRequired=true; else { if (_transformSet.empty()) transform->computeLocalToWorldMatrix(_firstMatrix,0); diff --git a/src/osgUtil/SceneView.cpp b/src/osgUtil/SceneView.cpp index b0a146a30..3c5af7e52 100644 --- a/src/osgUtil/SceneView.cpp +++ b/src/osgUtil/SceneView.cpp @@ -659,7 +659,7 @@ void SceneView::cullStage(const osg::Matrixd& projection,const osg::Matrixd& mod _collectOccludersVisistor->pushViewport(getViewport()); _collectOccludersVisistor->pushProjectionMatrix(proj.get()); - _collectOccludersVisistor->pushModelViewMatrix(mv.get()); + _collectOccludersVisistor->pushModelViewMatrix(mv.get(),osg::Transform::ABSOLUTE_RF); // traverse the scene graph to search for occluder in there new positions. for(unsigned int i=0; i< _camera->getNumChildren(); ++i) @@ -736,7 +736,7 @@ void SceneView::cullStage(const osg::Matrixd& projection,const osg::Matrixd& mod cullVisitor->pushViewport(getViewport()); cullVisitor->pushProjectionMatrix(proj.get()); - cullVisitor->pushModelViewMatrix(mv.get()); + cullVisitor->pushModelViewMatrix(mv.get(),osg::Transform::ABSOLUTE_RF); // traverse the scene graph to generate the rendergraph.