From 15399bbf35a5e457d52fc015bd10c650e2dc4d46 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 20 Jan 2014 11:00:09 +0000 Subject: [PATCH] From Kristofer Tingdahl, reimplement of AntiSquish node to avoid the use of an update callback. From Robert Osfield, small ammendments to clean up header. --- include/osgManipulator/AntiSquish | 26 ++--- src/osgManipulator/AntiSquish.cpp | 184 ++++++++++++++++-------------- 2 files changed, 110 insertions(+), 100 deletions(-) diff --git a/include/osgManipulator/AntiSquish b/include/osgManipulator/AntiSquish index e48c7a42f..fe72103db 100644 --- a/include/osgManipulator/AntiSquish +++ b/include/osgManipulator/AntiSquish @@ -17,20 +17,15 @@ #include -#include -#include -#include -#include -#include -#include -#include +#include +#include namespace osgManipulator { /** * Class that performs the Anti Squish by making the scaling uniform along all axes. */ -class OSGMANIPULATOR_EXPORT AntiSquish: public osg::MatrixTransform +class OSGMANIPULATOR_EXPORT AntiSquish: public osg::Transform { public : AntiSquish(); @@ -48,7 +43,7 @@ class OSGMANIPULATOR_EXPORT AntiSquish: public osg::MatrixTransform { _pivot = pvt; _usePivot = true; - _dirty = true; + _cacheDirty = true; } const osg::Vec3d& getPivot() const { return _pivot; } @@ -57,18 +52,19 @@ class OSGMANIPULATOR_EXPORT AntiSquish: public osg::MatrixTransform { _position = pos; _usePosition = true; - _dirty = true; + _cacheDirty = true; } const osg::Vec3d& getPosition() const { return _position; } - osg::Matrix computeUnSquishedMatrix(const osg::Matrix&, bool& flag); + bool computeLocalToWorldMatrix(osg::Matrix& matrix,osg::NodeVisitor*) const; + bool computeWorldToLocalMatrix(osg::Matrix& matrix,osg::NodeVisitor*) const; protected: virtual ~AntiSquish(); - osg::NodeCallback* _asqCallback; + bool computeUnSquishedMatrix(const osg::NodeVisitor*,osg::Matrix&) const; osg::Vec3d _pivot; bool _usePivot; @@ -76,8 +72,10 @@ class OSGMANIPULATOR_EXPORT AntiSquish: public osg::MatrixTransform osg::Vec3d _position; bool _usePosition; - bool _dirty; - osg::Matrix _cachedLocalToWorld; + mutable OpenThreads::Mutex _cacheLock; + mutable bool _cacheDirty; + mutable osg::Matrix _cacheLocalToWorld; + mutable osg::Matrix _cache; }; } diff --git a/src/osgManipulator/AntiSquish.cpp b/src/osgManipulator/AntiSquish.cpp index 4eab06e68..47e676336 100644 --- a/src/osgManipulator/AntiSquish.cpp +++ b/src/osgManipulator/AntiSquish.cpp @@ -12,71 +12,35 @@ */ //osgManipulator - Copyright (C) 2007 Fugro-Jason B.V. + #include using namespace osgManipulator; -namespace + +AntiSquish::AntiSquish() : _usePivot(true), _usePosition(false), _cacheDirty( true ) { - class AntiSquishCallback: public osg::NodeCallback - { - public: - AntiSquishCallback(AntiSquish* asq) : osg::NodeCallback(), _antiSquish(asq) {} - virtual ~AntiSquishCallback() {}; - - virtual void operator() (osg::Node* node, osg::NodeVisitor* nv) - { - // Get the node path. - osg::NodePath np = nv->getNodePath(); - - // Remove the last node which is the anti squish node itself. - np.pop_back(); - - // Get the accumulated modeling matrix. - osg::Matrix localToWorld = osg::computeLocalToWorld(np); - - // compute the unsquished matrix. - bool flag = false; - osg::Matrix _unsquishedMatrix = _antiSquish->computeUnSquishedMatrix(localToWorld, flag); - if (flag) - _antiSquish->setMatrix(_unsquishedMatrix); - traverse(node,nv); - } - - protected: - AntiSquish* _antiSquish; - }; - } -AntiSquish::AntiSquish() : _usePivot(true), _usePosition(false) +AntiSquish::AntiSquish(const osg::Vec3d& pivot) : _pivot(pivot), _usePivot(true), _usePosition(false), _cacheDirty( true ) { - _asqCallback = new AntiSquishCallback(this); - setUpdateCallback(_asqCallback); -} - -AntiSquish::AntiSquish(const osg::Vec3d& pivot) : _pivot(pivot), _usePivot(true), _usePosition(false) -{ - _asqCallback = new AntiSquishCallback(this); - setUpdateCallback(_asqCallback); } AntiSquish::AntiSquish(const osg::Vec3d& pivot, const osg::Vec3d& pos) - : _pivot(pivot), _usePivot(true), _position(pos), _usePosition(true) + : _pivot(pivot), _usePivot(true), _position(pos), _usePosition(true), _cacheDirty( true ) { - _asqCallback = new AntiSquishCallback(this); - setUpdateCallback(_asqCallback); } AntiSquish::AntiSquish(const AntiSquish& pat,const osg::CopyOp& copyop) : - MatrixTransform(pat,copyop), - _asqCallback(pat._asqCallback), + Transform(pat,copyop), _pivot(pat._pivot), _usePivot(pat._usePivot), _position(pat._position), _usePosition(pat._usePosition), - _cachedLocalToWorld(pat._cachedLocalToWorld) + _cacheDirty(pat._cacheDirty), + _cacheLocalToWorld(pat._cacheLocalToWorld), + _cache(pat._cache) { } @@ -84,32 +48,87 @@ AntiSquish::~AntiSquish() { } -osg::Matrix AntiSquish::computeUnSquishedMatrix(const osg::Matrix& LTW, bool& flag) + +bool AntiSquish::computeLocalToWorldMatrix(osg::Matrix& matrix,osg::NodeVisitor* nv) const { + osg::Matrix unsquishedMatrix; + if ( !computeUnSquishedMatrix( nv, unsquishedMatrix ) ) + return Transform::computeLocalToWorldMatrix( matrix, nv ); + + if (_referenceFrame==RELATIVE_RF) + { + matrix.preMult(unsquishedMatrix); + } + else // absolute + { + matrix = unsquishedMatrix; + } + + return true; +} + + +bool AntiSquish::computeWorldToLocalMatrix(osg::Matrix& matrix,osg::NodeVisitor* nv) const +{ + osg::Matrix unsquishedMatrix; + if ( !computeUnSquishedMatrix( nv, unsquishedMatrix ) ) + return Transform::computeWorldToLocalMatrix( matrix, nv ); + + osg::Matrixd inverse; + inverse.invert( unsquishedMatrix ); + + if (_referenceFrame==RELATIVE_RF) + { + matrix.postMult(inverse); + } + else // absolute + { + matrix = inverse; + } + return true; +} + + +bool AntiSquish::computeUnSquishedMatrix(const osg::NodeVisitor* nv, osg::Matrix& unsquished) const +{ + OpenThreads::ScopedLock lock( _cacheLock ); + + if ( !nv ) + { + if ( !_cacheDirty ) + { + unsquished = _cache; + return true; + } + + return false; + } + + osg::NodePath np = nv->getNodePath(); + + // Remove the last node which is the anti squish node itself. + np.pop_back(); + + // Get the accumulated modeling matrix. + const osg::Matrix localToWorld = osg::computeLocalToWorld(np); + + if ( !_cacheDirty && _cacheLocalToWorld==localToWorld ) + { + unsquished = _cache; + return true; + } + osg::Vec3d t, s; osg::Quat r, so; - if (LTW == _cachedLocalToWorld && _dirty == false) - { - flag = false; - return osg::Matrix::identity(); - } - - _cachedLocalToWorld = LTW; - - LTW.decompose(t, r, s, so); + localToWorld.decompose(t, r, s, so); // Let's take an average of the scale. double av = (s[0] + s[1] + s[2])/3.0; s[0] = av; s[1] = av; s[2]=av; if (av == 0) - { - flag = false; - return osg::Matrix::identity(); - } - - osg::Matrix unsquished; + return false; // // Final Matrix: [-Pivot][SO]^[S][SO][R][T][Pivot][LOCALTOWORLD]^[position] @@ -122,10 +141,7 @@ osg::Matrix AntiSquish::computeUnSquishedMatrix(const osg::Matrix& LTW, bool& fl osg::Matrix tmps, invtmps; so.get(tmps); if (!invtmps.invert(tmps)) - { - flag = false; - return osg::Matrix::identity(); - } + return false; //SO^ unsquished.postMult(invtmps); @@ -139,11 +155,9 @@ osg::Matrix AntiSquish::computeUnSquishedMatrix(const osg::Matrix& LTW, bool& fl unsquished.postMultTranslate(t); osg::Matrix invltw; - if (!invltw.invert(LTW)) - { - flag = false; - return osg::Matrix::identity(); - } + if (!invltw.invert(localToWorld)) + return false; + // LTW^ unsquished.postMult( invltw ); @@ -158,33 +172,31 @@ osg::Matrix AntiSquish::computeUnSquishedMatrix(const osg::Matrix& LTW, bool& fl osg::Matrix tmps, invtmps; so.get(tmps); if (!invtmps.invert(tmps)) - { - flag = false; - return osg::Matrix::identity(); - } + return false; + unsquished.postMult(invtmps); unsquished.postMultScale(s); unsquished.postMult(tmps); unsquished.postMultRotate(r); unsquished.postMultTranslate(t); osg::Matrix invltw; - if (!invltw.invert(LTW)) - { - flag = false; - return osg::Matrix::identity(); - } + if (!invltw.invert(localToWorld)) + return false; unsquished.postMult( invltw ); } if (unsquished.isNaN()) - { - flag = false; - return osg::Matrix::identity(); - } + return false; - flag = true; - _dirty = false; - return unsquished; + _cache = unsquished; + _cacheLocalToWorld = localToWorld; + _cacheDirty = false; + + //As Transform::computeBounde calls us without a node-path it relies on + //The cache. Hence a new _cache affects the bound. + const_cast(this)->dirtyBound(); + + return true; }