From Kristofer Tingdahl, reimplement of AntiSquish node to avoid the use of an update callback.
From Robert Osfield, small ammendments to clean up header.
This commit is contained in:
parent
6246cd5d85
commit
15399bbf35
@ -17,20 +17,15 @@
|
|||||||
|
|
||||||
#include <osgManipulator/Export>
|
#include <osgManipulator/Export>
|
||||||
|
|
||||||
#include <osg/Matrix>
|
#include <osg/Transform>
|
||||||
#include <osg/CopyOp>
|
#include <OpenThreads/Mutex>
|
||||||
#include <osg/NodeVisitor>
|
|
||||||
#include <osg/NodeCallback>
|
|
||||||
#include <osg/MatrixTransform>
|
|
||||||
#include <osg/Quat>
|
|
||||||
#include <osg/Vec3>
|
|
||||||
|
|
||||||
namespace osgManipulator {
|
namespace osgManipulator {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class that performs the Anti Squish by making the scaling uniform along all axes.
|
* 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 :
|
public :
|
||||||
AntiSquish();
|
AntiSquish();
|
||||||
@ -48,7 +43,7 @@ class OSGMANIPULATOR_EXPORT AntiSquish: public osg::MatrixTransform
|
|||||||
{
|
{
|
||||||
_pivot = pvt;
|
_pivot = pvt;
|
||||||
_usePivot = true;
|
_usePivot = true;
|
||||||
_dirty = true;
|
_cacheDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const osg::Vec3d& getPivot() const { return _pivot; }
|
const osg::Vec3d& getPivot() const { return _pivot; }
|
||||||
@ -57,18 +52,19 @@ class OSGMANIPULATOR_EXPORT AntiSquish: public osg::MatrixTransform
|
|||||||
{
|
{
|
||||||
_position = pos;
|
_position = pos;
|
||||||
_usePosition = true;
|
_usePosition = true;
|
||||||
_dirty = true;
|
_cacheDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const osg::Vec3d& getPosition() const { return _position; }
|
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:
|
protected:
|
||||||
|
|
||||||
virtual ~AntiSquish();
|
virtual ~AntiSquish();
|
||||||
|
|
||||||
osg::NodeCallback* _asqCallback;
|
bool computeUnSquishedMatrix(const osg::NodeVisitor*,osg::Matrix&) const;
|
||||||
|
|
||||||
osg::Vec3d _pivot;
|
osg::Vec3d _pivot;
|
||||||
bool _usePivot;
|
bool _usePivot;
|
||||||
@ -76,8 +72,10 @@ class OSGMANIPULATOR_EXPORT AntiSquish: public osg::MatrixTransform
|
|||||||
osg::Vec3d _position;
|
osg::Vec3d _position;
|
||||||
bool _usePosition;
|
bool _usePosition;
|
||||||
|
|
||||||
bool _dirty;
|
mutable OpenThreads::Mutex _cacheLock;
|
||||||
osg::Matrix _cachedLocalToWorld;
|
mutable bool _cacheDirty;
|
||||||
|
mutable osg::Matrix _cacheLocalToWorld;
|
||||||
|
mutable osg::Matrix _cache;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -12,71 +12,35 @@
|
|||||||
*/
|
*/
|
||||||
//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V.
|
//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V.
|
||||||
|
|
||||||
|
|
||||||
#include <osgManipulator/AntiSquish>
|
#include <osgManipulator/AntiSquish>
|
||||||
|
|
||||||
using namespace osgManipulator;
|
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(const osg::Vec3d& pivot) : _pivot(pivot), _usePivot(true), _usePosition(false), _cacheDirty( true )
|
||||||
AntiSquish* _antiSquish;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
AntiSquish::AntiSquish() : _usePivot(true), _usePosition(false)
|
|
||||||
{
|
{
|
||||||
_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)
|
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) :
|
AntiSquish::AntiSquish(const AntiSquish& pat,const osg::CopyOp& copyop) :
|
||||||
MatrixTransform(pat,copyop),
|
Transform(pat,copyop),
|
||||||
_asqCallback(pat._asqCallback),
|
|
||||||
_pivot(pat._pivot),
|
_pivot(pat._pivot),
|
||||||
_usePivot(pat._usePivot),
|
_usePivot(pat._usePivot),
|
||||||
_position(pat._position),
|
_position(pat._position),
|
||||||
_usePosition(pat._usePosition),
|
_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<OpenThreads::Mutex> 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::Vec3d t, s;
|
||||||
osg::Quat r, so;
|
osg::Quat r, so;
|
||||||
|
|
||||||
if (LTW == _cachedLocalToWorld && _dirty == false)
|
localToWorld.decompose(t, r, s, so);
|
||||||
{
|
|
||||||
flag = false;
|
|
||||||
return osg::Matrix::identity();
|
|
||||||
}
|
|
||||||
|
|
||||||
_cachedLocalToWorld = LTW;
|
|
||||||
|
|
||||||
LTW.decompose(t, r, s, so);
|
|
||||||
|
|
||||||
// Let's take an average of the scale.
|
// Let's take an average of the scale.
|
||||||
double av = (s[0] + s[1] + s[2])/3.0;
|
double av = (s[0] + s[1] + s[2])/3.0;
|
||||||
s[0] = av; s[1] = av; s[2]=av;
|
s[0] = av; s[1] = av; s[2]=av;
|
||||||
|
|
||||||
if (av == 0)
|
if (av == 0)
|
||||||
{
|
return false;
|
||||||
flag = false;
|
|
||||||
return osg::Matrix::identity();
|
|
||||||
}
|
|
||||||
|
|
||||||
osg::Matrix unsquished;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Final Matrix: [-Pivot][SO]^[S][SO][R][T][Pivot][LOCALTOWORLD]^[position]
|
// 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;
|
osg::Matrix tmps, invtmps;
|
||||||
so.get(tmps);
|
so.get(tmps);
|
||||||
if (!invtmps.invert(tmps))
|
if (!invtmps.invert(tmps))
|
||||||
{
|
return false;
|
||||||
flag = false;
|
|
||||||
return osg::Matrix::identity();
|
|
||||||
}
|
|
||||||
|
|
||||||
//SO^
|
//SO^
|
||||||
unsquished.postMult(invtmps);
|
unsquished.postMult(invtmps);
|
||||||
@ -139,11 +155,9 @@ osg::Matrix AntiSquish::computeUnSquishedMatrix(const osg::Matrix& LTW, bool& fl
|
|||||||
unsquished.postMultTranslate(t);
|
unsquished.postMultTranslate(t);
|
||||||
|
|
||||||
osg::Matrix invltw;
|
osg::Matrix invltw;
|
||||||
if (!invltw.invert(LTW))
|
if (!invltw.invert(localToWorld))
|
||||||
{
|
return false;
|
||||||
flag = false;
|
|
||||||
return osg::Matrix::identity();
|
|
||||||
}
|
|
||||||
// LTW^
|
// LTW^
|
||||||
unsquished.postMult( invltw );
|
unsquished.postMult( invltw );
|
||||||
|
|
||||||
@ -158,33 +172,31 @@ osg::Matrix AntiSquish::computeUnSquishedMatrix(const osg::Matrix& LTW, bool& fl
|
|||||||
osg::Matrix tmps, invtmps;
|
osg::Matrix tmps, invtmps;
|
||||||
so.get(tmps);
|
so.get(tmps);
|
||||||
if (!invtmps.invert(tmps))
|
if (!invtmps.invert(tmps))
|
||||||
{
|
return false;
|
||||||
flag = false;
|
|
||||||
return osg::Matrix::identity();
|
|
||||||
}
|
|
||||||
unsquished.postMult(invtmps);
|
unsquished.postMult(invtmps);
|
||||||
unsquished.postMultScale(s);
|
unsquished.postMultScale(s);
|
||||||
unsquished.postMult(tmps);
|
unsquished.postMult(tmps);
|
||||||
unsquished.postMultRotate(r);
|
unsquished.postMultRotate(r);
|
||||||
unsquished.postMultTranslate(t);
|
unsquished.postMultTranslate(t);
|
||||||
osg::Matrix invltw;
|
osg::Matrix invltw;
|
||||||
if (!invltw.invert(LTW))
|
if (!invltw.invert(localToWorld))
|
||||||
{
|
return false;
|
||||||
flag = false;
|
|
||||||
return osg::Matrix::identity();
|
|
||||||
}
|
|
||||||
unsquished.postMult( invltw );
|
unsquished.postMult( invltw );
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unsquished.isNaN())
|
if (unsquished.isNaN())
|
||||||
{
|
return false;
|
||||||
flag = false;
|
|
||||||
return osg::Matrix::identity();
|
|
||||||
}
|
|
||||||
|
|
||||||
flag = true;
|
_cache = unsquished;
|
||||||
_dirty = false;
|
_cacheLocalToWorld = localToWorld;
|
||||||
return unsquished;
|
_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<AntiSquish*>(this)->dirtyBound();
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user