From a4b0dc7426ccc2023f28fba9a4d2ccf01b423744 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 25 Apr 2017 18:04:04 +0100 Subject: [PATCH 1/5] Added missing Node::asAutoTransform() + NodeVisitor::apply(AutoTransform&). --- include/osg/NodeVisitor | 3 +++ include/osg/Transform | 3 +++ src/osg/NodeVisitor.cpp | 6 ++++++ 3 files changed, 12 insertions(+) diff --git a/include/osg/NodeVisitor b/include/osg/NodeVisitor index b3b3dc146..bf77ec975 100644 --- a/include/osg/NodeVisitor +++ b/include/osg/NodeVisitor @@ -40,6 +40,8 @@ class OccluderNode; class OcclusionQueryNode; class PagedLOD; class PositionAttitudeTransform; +class AutoTransform; +class MultiViewAutoTransform; class Projection; class ProxyNode; class Sequence; @@ -338,6 +340,7 @@ class OSG_EXPORT NodeVisitor : public virtual Object virtual void apply(CameraView& node); virtual void apply(MatrixTransform& node); virtual void apply(PositionAttitudeTransform& node); + virtual void apply(AutoTransform& node); virtual void apply(Switch& node); virtual void apply(Sequence& node); diff --git a/include/osg/Transform b/include/osg/Transform index 9fd1fdd8f..cf5b47108 100644 --- a/include/osg/Transform +++ b/include/osg/Transform @@ -91,6 +91,9 @@ class OSG_EXPORT Transform : public Group virtual PositionAttitudeTransform* asPositionAttitudeTransform() { return 0; } virtual const PositionAttitudeTransform* asPositionAttitudeTransform() const { return 0; } + virtual AutoTransform* asAutoTransform() { return 0; } + virtual const AutoTransform* asAutoTransform() const { return 0; } + enum ReferenceFrame { RELATIVE_RF, diff --git a/src/osg/NodeVisitor.cpp b/src/osg/NodeVisitor.cpp index 758e63b27..a8a150b0d 100644 --- a/src/osg/NodeVisitor.cpp +++ b/src/osg/NodeVisitor.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -161,6 +162,11 @@ void NodeVisitor::apply(PositionAttitudeTransform& node) apply(static_cast(node)); } +void NodeVisitor::apply(AutoTransform& node) +{ + apply(static_cast(node)); +} + void NodeVisitor::apply(Switch& node) { apply(static_cast(node)); From 38697140054e4d5c058633b40910bbb94d594191 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 25 Apr 2017 20:26:26 +0100 Subject: [PATCH 2/5] Added multiple view support to osgautotransform for testing multi-views --- .../osgautotransform/osgautotransform.cpp | 97 +++++++++++++++++-- 1 file changed, 91 insertions(+), 6 deletions(-) diff --git a/examples/osgautotransform/osgautotransform.cpp b/examples/osgautotransform/osgautotransform.cpp index 0d1c1bb9e..118dd6130 100644 --- a/examples/osgautotransform/osgautotransform.cpp +++ b/examples/osgautotransform/osgautotransform.cpp @@ -18,7 +18,9 @@ #include #include -#include +#include +#include +#include #include #include @@ -193,13 +195,96 @@ osg::Node* createScene() return root; } -int main(int, char**) +osgViewer::View* createView(osg::ref_ptr scenegraph, osg::ref_ptr gc, unsigned int x, unsigned int y, unsigned int width, unsigned int height) { - // construct the viewer. - osgViewer::Viewer viewer; + OSG_NOTICE<<"createView(....,x="<getCamera()->setGraphicsContext(gc); + view->getCamera()->setViewport(new osg::Viewport(x, y, width, height)); + //view->getCamera()->setProjectionMatrixAsPerspective(30.0, double(width) / double(height), 1.0, 1000.0); + view->setCameraManipulator(new osgGA::TrackballManipulator); + view->setSceneData(scenegraph); + return view; +} + +int main(int argc, char** argv) +{ + osg::ArgumentParser arguments(&argc, argv); + + // construct the viewer. + osgViewer::CompositeViewer viewer(arguments); + + + // create the scene graph that contains osg::AutoTransform nodes, see about for implementation details + osg::ref_ptr scenegraph = createScene(); + + unsigned int numViews = 1; + while (arguments.read("-n",numViews)) {} + + if (numViews<=1) + { + osgViewer::View* view = new osgViewer::View; + view->setUpViewAcrossAllScreens(); + view->setSceneData(scenegraph.get()); + view->setCameraManipulator(new osgGA::TrackballManipulator); + view->addEventHandler( new osgViewer::StatsHandler ); + viewer.addView(view); + } + else + { + osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface(); + if (!wsi) + { + osg::notify(osg::NOTICE)<<"Error, no WindowSystemInterface available, cannot create windows."<getScreenResolution(osg::GraphicsContext::ScreenIdentifier(0), width, height); + + unsigned int x=0, y=0; + while(arguments.read("--window", x, y, width, height)) {} + + osg::ref_ptr traits = new osg::GraphicsContext::Traits; + traits->x = x; + traits->y = y; + traits->width = width; + traits->height = height; + traits->windowDecoration = true; + traits->doubleBuffer = true; + traits->sharedContext = 0; + + + osg::ref_ptr gc = osg::GraphicsContext::createGraphicsContext(traits.get()); + if (!gc) + { + osg::notify(osg::NOTICE)<<" GraphicsWindow has not been created successfully."<addEventHandler( new osgViewer::StatsHandler ); + + } // run the viewers frame loop return viewer.run(); From c5b22f341a2aa2af27d88e8bc23244168ed66536 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 26 Apr 2017 09:48:08 +0100 Subject: [PATCH 3/5] Added ability to create windows for each view using -w command line hint. --- .../osgautotransform/osgautotransform.cpp | 57 ++++++++++++++----- 1 file changed, 43 insertions(+), 14 deletions(-) diff --git a/examples/osgautotransform/osgautotransform.cpp b/examples/osgautotransform/osgautotransform.cpp index 118dd6130..8668abf12 100644 --- a/examples/osgautotransform/osgautotransform.cpp +++ b/examples/osgautotransform/osgautotransform.cpp @@ -199,6 +199,29 @@ osgViewer::View* createView(osg::ref_ptr scenegraph, osg::ref_ptr traits = new osg::GraphicsContext::Traits; + traits->x = x; + traits->y = y; + traits->width = width; + traits->height = height; + traits->windowDecoration = true; + traits->doubleBuffer = true; + traits->sharedContext = 0; + + gc = osg::GraphicsContext::createGraphicsContext(traits.get()); + if (!gc) + { + osg::notify(osg::NOTICE)<<" GraphicsWindow has not been created successfully."<getCamera()->setGraphicsContext(gc); view->getCamera()->setViewport(new osg::Viewport(x, y, width, height)); @@ -222,6 +245,9 @@ int main(int argc, char** argv) unsigned int numViews = 1; while (arguments.read("-n",numViews)) {} + bool windows = false; + while (arguments.read("-w")) { windows = true; } + if (numViews<=1) { osgViewer::View* view = new osgViewer::View; @@ -246,21 +272,24 @@ int main(int argc, char** argv) unsigned int x=0, y=0; while(arguments.read("--window", x, y, width, height)) {} - osg::ref_ptr traits = new osg::GraphicsContext::Traits; - traits->x = x; - traits->y = y; - traits->width = width; - traits->height = height; - traits->windowDecoration = true; - traits->doubleBuffer = true; - traits->sharedContext = 0; - - - osg::ref_ptr gc = osg::GraphicsContext::createGraphicsContext(traits.get()); - if (!gc) + osg::ref_ptr gc; + if (!windows) { - osg::notify(osg::NOTICE)<<" GraphicsWindow has not been created successfully."< traits = new osg::GraphicsContext::Traits; + traits->x = x; + traits->y = y; + traits->width = width; + traits->height = height; + traits->windowDecoration = true; + traits->doubleBuffer = true; + traits->sharedContext = 0; + + gc = osg::GraphicsContext::createGraphicsContext(traits.get()); + if (!gc) + { + osg::notify(osg::NOTICE)<<" GraphicsWindow has not been created successfully."< Date: Wed, 26 Apr 2017 11:50:35 +0100 Subject: [PATCH 4/5] Refactored AutoTransform so that it dynamically computes the rotation, scale and matrices during the cull traversal to enable usage in multi-view, multi-threaded applications --- include/osg/AutoTransform | 21 +- include/osg/CullStack | 48 ++--- src/osg/AutoTransform.cpp | 402 +++++++++++++++----------------------- 3 files changed, 191 insertions(+), 280 deletions(-) diff --git a/include/osg/AutoTransform b/include/osg/AutoTransform index efa0f65e5..7867b0ff9 100644 --- a/include/osg/AutoTransform +++ b/include/osg/AutoTransform @@ -37,16 +37,14 @@ class OSG_EXPORT AutoTransform : public Transform virtual const char* className() const { return "AutoTransform"; } virtual const char* libraryName() const { return "osg"; } - virtual void accept(NodeVisitor& nv); - virtual AutoTransform* asAutoTransform() { return this; } virtual const AutoTransform* asAutoTransform() const { return this; } - inline void setPosition(const Vec3d& pos) { _position = pos; _matrixDirty=true; dirtyBound(); } + inline void setPosition(const Vec3d& pos) { _position = pos; dirtyBound(); } inline const Vec3d& getPosition() const { return _position; } - inline void setRotation(const Quat& quat) { _rotation = quat; _matrixDirty=true; dirtyBound(); } + inline void setRotation(const Quat& quat) { _rotation = quat; dirtyBound(); } inline const Quat& getRotation() const { return _rotation; } inline void setScale(double scale) { setScale(osg::Vec3(scale,scale,scale)); } @@ -60,7 +58,7 @@ class OSG_EXPORT AutoTransform : public Transform void setMaximumScale(double maximumScale) { _maximumScale = maximumScale; } double getMaximumScale() const { return _maximumScale; } - inline void setPivotPoint(const Vec3d& pivot) { _pivotPoint = pivot; _matrixDirty=true; dirtyBound(); } + inline void setPivotPoint(const Vec3d& pivot) { _pivotPoint = pivot; dirtyBound(); } inline const Vec3d& getPivotPoint() const { return _pivotPoint; } @@ -91,7 +89,7 @@ class OSG_EXPORT AutoTransform : public Transform /** Get the front face direction normal. */ inline const Vec3& getNormal() const { return _normal; } - void setAutoScaleToScreen(bool autoScaleToScreen) { _autoScaleToScreen = autoScaleToScreen; _matrixDirty=true; } + void setAutoScaleToScreen(bool autoScaleToScreen) { _autoScaleToScreen = autoScaleToScreen; } bool getAutoScaleToScreen() const { return _autoScaleToScreen; } @@ -120,21 +118,14 @@ class OSG_EXPORT AutoTransform : public Transform mutable Quat _rotation; mutable Vec3d _scale; - mutable bool _firstTimeToInitEyePoint; - mutable osg::Vec3 _previousEyePoint; - mutable osg::Vec3 _previousLocalUp; - mutable Viewport::value_type _previousWidth; - mutable Viewport::value_type _previousHeight; - mutable osg::Matrixd _previousProjection; - mutable osg::Vec3d _previousPosition; double _minimumScale; double _maximumScale; double _autoScaleTransitionWidthRatio; - void computeMatrix() const; + osg::Matrixd computeMatrix(const osg::NodeVisitor* nv) const; - mutable bool _matrixDirty; + mutable bool _matrixInitalized; mutable osg::Matrixd _cachedMatrix; enum AxisAligned diff --git a/include/osg/CullStack b/include/osg/CullStack index 61eb8b2f2..21398a1be 100644 --- a/include/osg/CullStack +++ b/include/osg/CullStack @@ -143,8 +143,14 @@ class OSG_EXPORT CullStack : public osg::CullSettings inline const CullingSet& getCurrentCullingSet() const { return *_back_modelviewCullingStack; } inline osg::Viewport* getViewport(); + inline const osg::Viewport* getViewport() const; + inline osg::RefMatrix* getModelViewMatrix(); + inline const osg::RefMatrix* getModelViewMatrix() const; + inline osg::RefMatrix* getProjectionMatrix(); + inline const osg::RefMatrix* getProjectionMatrix() const; + inline osg::Matrix getWindowMatrix() const; inline const osg::RefMatrix* getMVPW(); @@ -224,38 +230,32 @@ class OSG_EXPORT CullStack : public osg::CullSettings inline osg::Viewport* CullStack::getViewport() { - if (!_viewportStack.empty()) - { - return _viewportStack.back().get(); - } - else - { - return 0L; - } + return _viewportStack.empty() ? 0 : _viewportStack.back().get(); +} + +inline const osg::Viewport* CullStack::getViewport() const +{ + return _viewportStack.empty() ? 0 : _viewportStack.back().get(); } inline osg::RefMatrix* CullStack::getModelViewMatrix() { - if (!_modelviewStack.empty()) - { - return _modelviewStack.back().get(); - } - else - { - return _identity.get(); - } + return _modelviewStack.empty() ? _identity.get() : _modelviewStack.back().get(); +} + +inline const osg::RefMatrix* CullStack::getModelViewMatrix() const +{ + return _modelviewStack.empty() ? _identity.get() : _modelviewStack.back().get(); } inline osg::RefMatrix* CullStack::getProjectionMatrix() { - if (!_projectionStack.empty()) - { - return _projectionStack.back().get(); - } - else - { - return _identity.get(); - } + return _projectionStack.empty() ? _identity.get() : _projectionStack.back().get(); +} + +inline const osg::RefMatrix* CullStack::getProjectionMatrix() const +{ + return _projectionStack.empty() ? _identity.get() : _projectionStack.back().get(); } inline osg::Matrix CullStack::getWindowMatrix() const diff --git a/src/osg/AutoTransform.cpp b/src/osg/AutoTransform.cpp index e39c1cb62..c387131b6 100644 --- a/src/osg/AutoTransform.cpp +++ b/src/osg/AutoTransform.cpp @@ -22,13 +22,10 @@ AutoTransform::AutoTransform(): _autoRotateMode(NO_ROTATION), _autoScaleToScreen(false), _scale(1.0,1.0,1.0), - _firstTimeToInitEyePoint(true), - _previousWidth(0), - _previousHeight(0), _minimumScale(0.0), _maximumScale(DBL_MAX), _autoScaleTransitionWidthRatio(0.25), - _matrixDirty(true), + _matrixInitalized(false), _axis(0.0f,0.0f,1.0f), _normal(0.0f,-1.0f,0.0f), _cachedMode(NO_ROTATION), @@ -46,13 +43,10 @@ AutoTransform::AutoTransform(const AutoTransform& pat,const CopyOp& copyop): _autoScaleToScreen(pat._autoScaleToScreen), _rotation(pat._rotation), _scale(pat._scale), - _firstTimeToInitEyePoint(true), - _previousWidth(0), - _previousHeight(0), _minimumScale(pat._minimumScale), _maximumScale(pat._maximumScale), _autoScaleTransitionWidthRatio(pat._autoScaleTransitionWidthRatio), - _matrixDirty(true), + _matrixInitalized(false), _axis(pat._axis), _normal(pat._normal), _cachedMode(pat._cachedMode), @@ -64,7 +58,6 @@ AutoTransform::AutoTransform(const AutoTransform& pat,const CopyOp& copyop): void AutoTransform::setAutoRotateMode(AutoRotateMode mode) { _autoRotateMode = mode; - _firstTimeToInitEyePoint = true; _cachedMode = CACHE_DIRTY; updateCache(); } @@ -109,284 +102,211 @@ void AutoTransform::setScale(const Vec3d& scale) if (_scale.y()>_maximumScale) _scale.y() = _maximumScale; if (_scale.z()>_maximumScale) _scale.z() = _maximumScale; - _matrixDirty=true; dirtyBound(); } -bool AutoTransform::computeLocalToWorldMatrix(Matrix& matrix,NodeVisitor*) const +bool AutoTransform::computeLocalToWorldMatrix(Matrix& matrix,NodeVisitor* nv) const { - if (_matrixDirty) computeMatrix(); - if (_referenceFrame==RELATIVE_RF) { - matrix.preMult(_cachedMatrix); + matrix.preMult(computeMatrix(nv)); } else // absolute { - matrix = _cachedMatrix; + matrix = computeMatrix(nv); } return true; } -bool AutoTransform::computeWorldToLocalMatrix(Matrix& matrix,NodeVisitor*) const +bool AutoTransform::computeWorldToLocalMatrix(Matrix& matrix,NodeVisitor* nv) const { - if (_scale.x() == 0.0 || _scale.y() == 0.0 || _scale.z() == 0.0) - return false; - if (_referenceFrame==RELATIVE_RF) { - matrix.postMultTranslate(-_position); - matrix.postMultRotate(_rotation.inverse()); - matrix.postMultScale(Vec3d(1.0/_scale.x(), 1.0/_scale.y(), 1.0/_scale.z())); - matrix.postMultTranslate(_pivotPoint); + matrix.postMult(osg::Matrix::inverse(computeMatrix(nv))); } else // absolute { - matrix.makeRotate(_rotation.inverse()); - matrix.preMultTranslate(-_position); - matrix.postMultScale(Vec3d(1.0/_scale.x(), 1.0/_scale.y(), 1.0/_scale.z())); - matrix.postMultTranslate(_pivotPoint); + matrix = osg::Matrix::inverse(computeMatrix(nv)); } return true; } -void AutoTransform::computeMatrix() const +osg::Matrixd AutoTransform::computeMatrix(const osg::NodeVisitor* nv) const { - if (!_matrixDirty) return; + _matrixInitalized = true; - _cachedMatrix.makeRotate(_rotation); - _cachedMatrix.postMultTranslate(_position); - _cachedMatrix.preMultScale(_scale); - _cachedMatrix.preMultTranslate(-_pivotPoint); + Quat rotation = _rotation; + osg::Vec3d scale = _scale; - _matrixDirty = false; -} - -void AutoTransform::accept(NodeVisitor& nv) -{ - if (nv.validNodeMask(*this)) + const CullStack* cs = dynamic_cast(nv); + if (cs) { - // if app traversal update the frame count. - if (nv.getVisitorType()==NodeVisitor::UPDATE_VISITOR) - { - } - else - if (nv.getVisitorType()==NodeVisitor::CULL_VISITOR) - { + osg::Vec3d eyePoint = cs->getEyeLocal(); + osg::Vec3d localUp = cs->getUpLocal(); - CullStack* cs = dynamic_cast(&nv); - if (cs) + if (getAutoScaleToScreen()) + { + double size = 1.0/cs->pixelSize(getPosition(),0.48f); + + //if (_autoScaleTransitionWidthRatio>0.0) { - - Viewport::value_type width = _previousWidth; - Viewport::value_type height = _previousHeight; - - osg::Viewport* viewport = cs->getViewport(); - if (viewport) + if (_minimumScale>0.0) { - width = viewport->width(); - height = viewport->height(); + double j = _minimumScale; + double i = (_maximumScalegetEyeLocal(); - osg::Vec3d localUp = cs->getUpLocal(); - osg::Vec3d position = getPosition(); - - const osg::Matrix& projection = *(cs->getProjectionMatrix()); - - bool doUpdate = _firstTimeToInitEyePoint; - if (!_firstTimeToInitEyePoint) + if (_maximumScalegetAutoUpdateEyeMovementTolerance()*(eyePoint-getPosition()).length2()) - { - doUpdate = true; - } - osg::Vec3d dupv = _previousLocalUp-localUp; - // rotating the camera only affects ROTATE_TO_* - if (_autoRotateMode && - dupv.length2()>getAutoUpdateEyeMovementTolerance()) - { - doUpdate = true; - } - else if (width!=_previousWidth || height!=_previousHeight) - { - doUpdate = true; - } - else if (projection != _previousProjection) - { - doUpdate = true; - } - else if (position != _previousPosition) - { - doUpdate = true; - } + double n = _maximumScale; + double m = (_minimumScale>0.0) ? + _maximumScale+(_minimumScale-_maximumScale)*_autoScaleTransitionWidthRatio : + _maximumScale*(1.0-_autoScaleTransitionWidthRatio); + double c = 1.0 / (4.0*(m-n)); + double b = 1.0 - 2.0*c*m; + double a = n + b*b/(4.0*c); + double p = -b / (2.0*c); + + if (size>p) size = _maximumScale; + else if (size>m) size = a + b*size + c*(size*size); } - _firstTimeToInitEyePoint = false; - - if (doUpdate) - { - - if (getAutoScaleToScreen()) - { - double size = 1.0/cs->pixelSize(getPosition(),0.48f); - - if (_autoScaleTransitionWidthRatio>0.0) - { - if (_minimumScale>0.0) - { - double j = _minimumScale; - double i = (_maximumScale0.0) ? - _maximumScale+(_minimumScale-_maximumScale)*_autoScaleTransitionWidthRatio : - _maximumScale*(1.0-_autoScaleTransitionWidthRatio); - double c = 1.0 / (4.0*(m-n)); - double b = 1.0 - 2.0*c*m; - double a = n + b*b/(4.0*c); - double p = -b / (2.0*c); - - if (size>p) size = _maximumScale; - else if (size>m) size = a + b*size + c*(size*size); - } - } - - setScale(size); - } - - if (_autoRotateMode==ROTATE_TO_SCREEN) - { - osg::Vec3d translation; - osg::Quat rotation; - osg::Vec3d scale; - osg::Quat so; - - cs->getModelViewMatrix()->decompose( translation, rotation, scale, so ); - - setRotation(rotation.inverse()); - } - else if (_autoRotateMode==ROTATE_TO_CAMERA) - { - osg::Vec3d PosToEye = _position - eyePoint; - osg::Matrix lookto = osg::Matrix::lookAt( - osg::Vec3d(0,0,0), PosToEye, localUp); - Quat q; - q.set(osg::Matrix::inverse(lookto)); - setRotation(q); - } - else if (_autoRotateMode==ROTATE_TO_AXIS) - { - Matrix matrix; - Vec3 ev(eyePoint - _position); - - switch(_cachedMode) - { - case(AXIAL_ROT_Z_AXIS): - { - ev.z() = 0.0f; - float ev_length = ev.length(); - if (ev_length>0.0f) - { - //float rotation_zrotation_z = atan2f(ev.x(),ev.y()); - //mat.makeRotate(inRadians(rotation_z),0.0f,0.0f,1.0f); - float inv = 1.0f/ev_length; - float s = ev.x()*inv; - float c = -ev.y()*inv; - matrix(0,0) = c; - matrix(1,0) = -s; - matrix(0,1) = s; - matrix(1,1) = c; - } - break; - } - case(AXIAL_ROT_Y_AXIS): - { - ev.y() = 0.0f; - float ev_length = ev.length(); - if (ev_length>0.0f) - { - //float rotation_zrotation_z = atan2f(ev.x(),ev.y()); - //mat.makeRotate(inRadians(rotation_z),0.0f,0.0f,1.0f); - float inv = 1.0f/ev_length; - float s = -ev.z()*inv; - float c = ev.x()*inv; - matrix(0,0) = c; - matrix(2,0) = s; - matrix(0,2) = -s; - matrix(2,2) = c; - } - break; - } - case(AXIAL_ROT_X_AXIS): - { - ev.x() = 0.0f; - float ev_length = ev.length(); - if (ev_length>0.0f) - { - //float rotation_zrotation_z = atan2f(ev.x(),ev.y()); - //mat.makeRotate(inRadians(rotation_z),0.0f,0.0f,1.0f); - float inv = 1.0f/ev_length; - float s = -ev.z()*inv; - float c = -ev.y()*inv; - matrix(1,1) = c; - matrix(2,1) = -s; - matrix(1,2) = s; - matrix(2,2) = c; - } - break; - } - case(ROTATE_TO_AXIS): // need to implement - { - float ev_side = ev*_side; - float ev_normal = ev*_normal; - float rotation = atan2f(ev_side,ev_normal); - matrix.makeRotate(rotation,_axis); - break; - } - } - Quat q; - q.set(matrix); - setRotation(q); - } - - _previousEyePoint = eyePoint; - _previousLocalUp = localUp; - _previousWidth = width; - _previousHeight = height; - _previousProjection = projection; - _previousPosition = position; - - _matrixDirty = true; - } - } + + // TODO setScale(size); + scale.set(size, size, size); } - // now do the proper accept - Transform::accept(nv); + if (_autoRotateMode==ROTATE_TO_SCREEN) + { + osg::Vec3d mv_translation; + osg::Vec3d mv_scale; + osg::Quat mv_rotation; + osg::Quat mv_so; + + cs->getModelViewMatrix()->decompose( mv_translation, mv_rotation, mv_scale, mv_so ); + + // TODO setRotation(rotation.inverse()); + rotation = mv_rotation.inverse(); + } + else if (_autoRotateMode==ROTATE_TO_CAMERA) + { + osg::Vec3d PosToEye = _position - eyePoint; + osg::Matrix lookto = osg::Matrix::lookAt( + osg::Vec3d(0,0,0), PosToEye, localUp); + Quat q; + q.set(osg::Matrix::inverse(lookto)); + // TODO setRotation(q); + rotation = q; + } + else if (_autoRotateMode==ROTATE_TO_AXIS) + { + Matrix matrix; + Vec3 ev(eyePoint - _position); + + switch(_cachedMode) + { + case(AXIAL_ROT_Z_AXIS): + { + ev.z() = 0.0f; + float ev_length = ev.length(); + if (ev_length>0.0f) + { + //float rotation_zrotation_z = atan2f(ev.x(),ev.y()); + //mat.makeRotate(inRadians(rotation_z),0.0f,0.0f,1.0f); + float inv = 1.0f/ev_length; + float s = ev.x()*inv; + float c = -ev.y()*inv; + matrix(0,0) = c; + matrix(1,0) = -s; + matrix(0,1) = s; + matrix(1,1) = c; + } + break; + } + case(AXIAL_ROT_Y_AXIS): + { + ev.y() = 0.0f; + float ev_length = ev.length(); + if (ev_length>0.0f) + { + //float rotation_zrotation_z = atan2f(ev.x(),ev.y()); + //mat.makeRotate(inRadians(rotation_z),0.0f,0.0f,1.0f); + float inv = 1.0f/ev_length; + float s = -ev.z()*inv; + float c = ev.x()*inv; + matrix(0,0) = c; + matrix(2,0) = s; + matrix(0,2) = -s; + matrix(2,2) = c; + } + break; + } + case(AXIAL_ROT_X_AXIS): + { + ev.x() = 0.0f; + float ev_length = ev.length(); + if (ev_length>0.0f) + { + //float rotation_zrotation_z = atan2f(ev.x(),ev.y()); + //mat.makeRotate(inRadians(rotation_z),0.0f,0.0f,1.0f); + float inv = 1.0f/ev_length; + float s = -ev.z()*inv; + float c = -ev.y()*inv; + matrix(1,1) = c; + matrix(2,1) = -s; + matrix(1,2) = s; + matrix(2,2) = c; + } + break; + } + case(ROTATE_TO_AXIS): // need to implement + { + float ev_side = ev*_side; + float ev_normal = ev*_normal; + float angle = atan2f(ev_side,ev_normal); + matrix.makeRotate(angle,_axis); + break; + } + } + Quat q; + q.set(matrix); + // TODO setRotation(q); + rotation = q; + } } + + _rotation = rotation; + _scale = scale; + // setRotation(rotation); + // setScale(scale); + + osg::Matrixd matrix; + matrix.makeRotate(rotation); + matrix.postMultTranslate(_position); + matrix.preMultScale(scale); + matrix.preMultTranslate(-_pivotPoint); + + _cachedMatrix = matrix; + + return matrix; } BoundingSphere AutoTransform::computeBound() const { BoundingSphere bsphere; - if ( getAutoScaleToScreen() && _firstTimeToInitEyePoint ) + if ( getAutoScaleToScreen() && !_matrixInitalized ) return bsphere; bsphere = Transform::computeBound(); From a95d66a587580a92500c2a1237eeae8ac533a2e3 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 26 Apr 2017 17:10:58 +0100 Subject: [PATCH 5/5] Replaced dynamoc_cast with asCullStack() to improve performance of AutoTransform, screen size based LOD and PagedLOD. --- include/osg/NodeVisitor | 8 ++++++++ include/osgUtil/CullVisitor | 9 +++++++++ src/osg/AutoTransform.cpp | 2 +- src/osg/LOD.cpp | 2 +- src/osg/PagedLOD.cpp | 2 +- 5 files changed, 20 insertions(+), 3 deletions(-) diff --git a/include/osg/NodeVisitor b/include/osg/NodeVisitor index bf77ec975..dc6975636 100644 --- a/include/osg/NodeVisitor +++ b/include/osg/NodeVisitor @@ -52,6 +52,7 @@ class Camera; class CameraView; class Drawable; class Geometry; +class CullStack; @@ -149,6 +150,13 @@ class OSG_EXPORT NodeVisitor : public virtual Object * Equivalent to dynamic_cast(this).*/ virtual const osgUtil::IntersectionVisitor* asIntersectionVisitor() const { return 0; } + /** Convert 'this' into a osg::CullStack pointer if Object is a osg::CullStack, otherwise return 0. + * Equivalent to dynamic_cast(this).*/ + virtual osg::CullStack* asCullStack() { return 0; } + + /** convert 'const this' into a const osg::CullStack pointer if Object is a osg::CullStack, otherwise return 0. + * Equivalent to dynamic_cast(this).*/ + virtual const osg::CullStack* asCullStack() const { return 0; } diff --git a/include/osgUtil/CullVisitor b/include/osgUtil/CullVisitor index 3fab4f367..2e36bc2e2 100644 --- a/include/osgUtil/CullVisitor +++ b/include/osgUtil/CullVisitor @@ -67,6 +67,15 @@ class OSGUTIL_EXPORT CullVisitor : public osg::NodeVisitor, public osg::CullStac * Equivalent to dynamic_cast(this).*/ virtual const osgUtil::CullVisitor* asCullVisitor() const { return this; } + /** Convert 'this' into a osg::CullStack pointer if Object is a osg::CullStack, otherwise return 0. + * Equivalent to dynamic_cast(this).*/ + virtual osg::CullStack* asCullStack() { return static_cast(this); } + + /** convert 'const this' into a const osg::CullStack pointer if Object is a osg::CullStack, otherwise return 0. + * Equivalent to dynamic_cast(this).*/ + virtual const osg::CullStack* asCullStack() const { return static_cast(this); } + + using osg::NodeVisitor::clone; /** Create a shallow copy of the CullVisitor, used by CullVisitor::create() to clone the prototype. */ diff --git a/src/osg/AutoTransform.cpp b/src/osg/AutoTransform.cpp index c387131b6..5612db316 100644 --- a/src/osg/AutoTransform.cpp +++ b/src/osg/AutoTransform.cpp @@ -140,7 +140,7 @@ osg::Matrixd AutoTransform::computeMatrix(const osg::NodeVisitor* nv) const Quat rotation = _rotation; osg::Vec3d scale = _scale; - const CullStack* cs = dynamic_cast(nv); + const CullStack* cs = nv ? nv->asCullStack() : 0; if (cs) { osg::Vec3d eyePoint = cs->getEyeLocal(); diff --git a/src/osg/LOD.cpp b/src/osg/LOD.cpp index 679164b78..1ad24cfd6 100644 --- a/src/osg/LOD.cpp +++ b/src/osg/LOD.cpp @@ -51,7 +51,7 @@ void LOD::traverse(NodeVisitor& nv) } else { - osg::CullStack* cullStack = dynamic_cast(&nv); + osg::CullStack* cullStack = nv.asCullStack(); if (cullStack && cullStack->getLODScale()) { required_range = cullStack->clampedPixelSize(getBound()) / cullStack->getLODScale(); diff --git a/src/osg/PagedLOD.cpp b/src/osg/PagedLOD.cpp index 46ea5570c..e2680b2bd 100644 --- a/src/osg/PagedLOD.cpp +++ b/src/osg/PagedLOD.cpp @@ -150,7 +150,7 @@ void PagedLOD::traverse(NodeVisitor& nv) } else { - osg::CullStack* cullStack = dynamic_cast(&nv); + osg::CullStack* cullStack = nv.asCullStack(); if (cullStack && cullStack->getLODScale()>0.0f) { required_range = cullStack->clampedPixelSize(getBound()) / cullStack->getLODScale();