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();