Hi Robert,

I don't necessarily agree that a way to check if the transforms along a
nodepath using integers is not worthwhile, as you replace hundreds of
double-operations with a few integer ones, and the comparison becomes the
comparison of two ints. That seems useful, especially as there is hardly
any overhead (a few bytes per transform).

I'll leave that discussion and submit a new update of the AntiSquish. It
now inherits Transform rather than MatrixTransform, so there are no changes
to the object while traversing (apart from one cache). This solves most of
your objections as we rely on the standardness of the Transform. One
question is however what to do when there is no node-path available, such
as the Transform::computeBound(). In those cases I rely on the cache (if
available). But if I do that, I should really dirty the bound when I
re-compute my cache. This is implemented now in the version I'm sending,
but I'm not sure it is necessary. It will create an overload of
computeBound calls.

I opted to lock the cache as this is the only way to protect from corrupt
cache if there are multiple traversals going on at the same time. We don't
do that, but I thought it's safer.

Best regards,


Kristofer Tingdahl

Attachment: AntiSquish
Description: Binary data

/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * OpenSceneGraph Public License for more details.
*/
//osgManipulator - Copyright (C) 2007 Fugro-Jason B.V.


#include <osgManipulator/AntiSquish>

using namespace osgManipulator;


AntiSquish::AntiSquish() : _usePivot(true), _usePosition(false), _cacheDirty( true )
{
}

AntiSquish::AntiSquish(const osg::Vec3d& pivot) : _pivot(pivot), _usePivot(true), _usePosition(false), _cacheDirty( true )
{
}

AntiSquish::AntiSquish(const osg::Vec3d& pivot, const osg::Vec3d& pos)
    : _pivot(pivot), _usePivot(true), _position(pos), _usePosition(true), _cacheDirty( true )
{
}


AntiSquish::AntiSquish(const AntiSquish& pat,const osg::CopyOp& copyop) :
    Transform(pat,copyop),
    _pivot(pat._pivot),
    _usePivot(pat._usePivot),
    _position(pat._position),
    _usePosition(pat._usePosition),
    _cacheDirty(pat._cacheDirty),
    _cacheLocalToWorld(pat._cacheLocalToWorld),
    _cache(pat._cache)
{
}

AntiSquish::~AntiSquish()
{
}


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::Quat r, 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)
        return false;

    //
    // Final Matrix: [-Pivot][SO]^[S][SO][R][T][Pivot][LOCALTOWORLD]^[position]
    // OR [SO]^[S][SO][R][T][LOCALTOWORLD]^
    //
    if (_usePivot)
    {
        unsquished.postMultTranslate(-_pivot);

        osg::Matrix tmps, invtmps;
        so.get(tmps);
        if (!invtmps.invert(tmps))
            return false;

        //SO^
        unsquished.postMult(invtmps);
        //S
        unsquished.postMultScale(s);
        //SO
        unsquished.postMult(tmps);
        //R
        unsquished.postMultRotate(r);
        //T
        unsquished.postMultTranslate(t);

        osg::Matrix invltw;
        if (!invltw.invert(localToWorld))
            return false;

        // LTW^
        unsquished.postMult( invltw );

        // Position
        if (_usePosition)
            unsquished.postMultTranslate(_position);
        else
            unsquished.postMultTranslate(_pivot);
    }
    else
    {
        osg::Matrix tmps, invtmps;
        so.get(tmps);
        if (!invtmps.invert(tmps))
            return false;

        unsquished.postMult(invtmps);
        unsquished.postMultScale(s);
        unsquished.postMult(tmps);
        unsquished.postMultRotate(r);
        unsquished.postMultTranslate(t);
        osg::Matrix invltw;
        if (!invltw.invert(localToWorld))
            return false;
        unsquished.postMult( invltw );
    }

    if (unsquished.isNaN())
        return false;

    _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<AntiSquish*>(this)->dirtyBound();

    return true;
}



_______________________________________________
osg-submissions mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org

Reply via email to