Why can't I call computeLocalToWorldMatrix&computeWorldToLocalMatrix virtual function overwritten by osg::MatrixTransform?

37 views
Skip to first unread message

mirr...@gmail.com

unread,
Oct 12, 2021, 4:08:46 AM10/12/21
to OpenSceneGraph Users
evn is win10&gtx1660ti&osg3.6.4
I want to implement drag and drop zooming with the screen when I rewrite module osgManipulator.


#ifndef Dragger_H
#define Dragger_H

#include "Export.h"

#include <osg/BoundingSphere>
#include <osg/MatrixTransform>
#include <osgUtil/SceneView>
#include <osgGA/GUIEventAdapter>
#include <osgGA/GUIActionAdapter>

#include "Constraint.h"
#include "Command.h"

namespace osgManipulatorEx
{

class CompositeDragger;
class MotionCommand;
class TranslateInLineCommand;
class TranslateInPlaneCommand;
class Scale1DCommand;
class Scale2DCommand;
class ScaleUniformCommand;
class Rotate3DCommand;

/**
 * Base class for draggers. Concrete draggers implement the pick event handler
 * and generate motion commands (translate, rotate, ...) and sends these
 * command to all the DraggerCallbacks & Transforms that are connected to the Dragger that generates the
 * commands.
 */
class OSGMANIPULATOREX_API Dragger : public osg::MatrixTransform
{
    public:
        META_Node(osgManipulatorEx,Dragger);

        /**
         * Set/Get parent dragger. For simple draggers parent points to itself.
         * For composite draggers parent points to the parent dragger that uses
         * this dragger.
         */
        virtual void setParentDragger(Dragger* parent) { _parentDragger = parent; }

        Dragger* getParentDragger() { return _parentDragger; }
        const Dragger* getParentDragger() const { return _parentDragger; }

        /** Returns 0 if this Dragger is not a CompositeDragger. */
        virtual const CompositeDragger* getComposite() const { return 0; }

        /** Returns 0 if this Dragger is not a CompositeDragger. */
        virtual CompositeDragger* getComposite() { return 0; }


        void setHandleEvents(bool flag);
        bool getHandleEvents() const { return _handleEvents; }

        void setActivationModKeyMask(unsigned int mask) { _activationModKeyMask = mask; }
        unsigned int getActivationModKeyMask() const { return _activationModKeyMask; }

        void setActivationMouseButtonMask(unsigned int mask) { _activationMouseButtonMask = mask; }
        unsigned int getActivationMouseButtonMask() const { return _activationMouseButtonMask; }

        void setActivationKeyEvent(int key) { _activationKeyEvent = key; }
        int getActivationKeyEvent() const { return _activationKeyEvent; }


        virtual void traverse(osg::NodeVisitor& nv);

        virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa);
        virtual bool handle(const PointerInfo&, const osgGA::GUIEventAdapter&, osgGA::GUIActionAdapter&) { return false; }


        typedef std::vector< osg::ref_ptr<Constraint> > Constraints;

        void addConstraint(Constraint* constraint);
        template<class T> void addConstraint(const osg::ref_ptr<T>& c) { addConstraint(c.get()); }

        void removeConstraint(Constraint* constraint);
        template<class T> void removeConstraint(const osg::ref_ptr<T>& c) { removeConstraint(c.get()); }

        Constraints& getConstraints() { return _constraints; }
        const Constraints& getConstraints() const { return _constraints; }


        typedef std::vector< osg::ref_ptr<DraggerCallback> > DraggerCallbacks;

        void addDraggerCallback(DraggerCallback* dc);
        template<class T> void addDraggerCallback(const osg::ref_ptr<T>& dc) { addDraggerCallback(dc.get()); }

        void removeDraggerCallback(DraggerCallback* dc);
        template<class T> void removeDraggerCallback(const osg::ref_ptr<T>& dc) { removeDraggerCallback(dc.get()); }

        DraggerCallbacks& getDraggerCallbacks() { return _draggerCallbacks; }
        const DraggerCallbacks& getDraggerCallbacks() const { return _draggerCallbacks; }

        void addTransformUpdating(MatrixTransform* transform, int handleCommandMask = DraggerTransformCallback::HANDLE_ALL);
        void removeTransformUpdating(MatrixTransform* transform);

        /** Setup default geometry for dragger. */
        virtual void setupDefaultGeometry() {}

        virtual bool receive(const MotionCommand& command);
        virtual void dispatch(MotionCommand& command);

        void setDraggerActive(bool active) { _draggerActive = active; }
        bool getDraggerActive() const { return _draggerActive; }

        /**
         * Set/Get the traversal mask used by this dragger when looking for intersections during event handling.
         * This is useful to "hide" some geometry during event handling.
         */
        virtual void setIntersectionMask(osg::Node::NodeMask intersectionMask) { _intersectionMask = intersectionMask; }
        osg::Node::NodeMask getIntersectionMask() const { return _intersectionMask; }

        /** Return true if the axis of the Locator are inverted requiring the faces of any cubes used from rendering to be flipped to ensure the correct front/back face is used.*/
        bool inverted() const;

        /** apply the appropriate FrontFace setting to provided StateSet to ensure that the rendering of hull of the volume is the correct orientation.*/
        void applyAppropriateFrontFace(osg::StateSet* ss) const;

virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix, osg::NodeVisitor* nv) const;
virtual bool computeWorldToLocalMatrix(osg::Matrix& matrix, osg::NodeVisitor* nv) const;
protected:
osg::Matrixd Dragger::computeMatrix(const osg::NodeVisitor* nv) const;
protected:

        Dragger();
        Dragger(const Dragger& rhs, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);

        virtual ~Dragger();


        bool                            _handleEvents;
        bool                            _draggerActive;

        unsigned int                    _activationModKeyMask;
        unsigned int                    _activationMouseButtonMask;
        int                             _activationKeyEvent;
        bool                            _activationPermittedByModKeyMask;
        bool                            _activationPermittedByMouseButtonMask;
        bool                            _activationPermittedByKeyEvent;

        osgManipulatorEx::PointerInfo     _pointer;

        Dragger*                        _parentDragger;

        osg::ref_ptr<DraggerCallback>   _selfUpdater;
        Constraints                     _constraints;
        DraggerCallbacks                _draggerCallbacks;
        osg::Node::NodeMask             _intersectionMask;

};

#endif
---------------------------------------------------------------------------------------------
#include <osg/Material>
#include <osg/FrontFace>
#include <osgGA/EventVisitor>
#include <osgViewer/View>
#include <osg/io_utils>

#include "Dragger.h"
#include "Command.h"
using namespace osgManipulatorEx;

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Dragger
//
Dragger::Dragger() :
    _handleEvents(false),
    _draggerActive(false),
    _activationModKeyMask(0),
    _activationMouseButtonMask(0),
    _activationKeyEvent(0),
    _activationPermittedByModKeyMask(false),
    _activationPermittedByMouseButtonMask(false),
    _activationPermittedByKeyEvent(false),
    _parentDragger(0),
    _intersectionMask(0xffffffff)
{
    _parentDragger = this;
    getOrCreateStateSet()->setDataVariance(osg::Object::DYNAMIC);

    _selfUpdater = new DraggerTransformCallback(this);
//
setCullingActive(false);
}

Dragger::Dragger(const Dragger& rhs, const osg::CopyOp& copyop):
    osg::MatrixTransform(rhs, copyop),
    _handleEvents(rhs._handleEvents),
    _draggerActive(false),
    _activationModKeyMask(rhs._activationModKeyMask),
    _activationMouseButtonMask(rhs._activationMouseButtonMask),
    _activationKeyEvent(rhs._activationKeyEvent),
    _activationPermittedByModKeyMask(false),
    _activationPermittedByMouseButtonMask(false),
    _activationPermittedByKeyEvent(false),
    _parentDragger(0),
    _intersectionMask(0xffffffff)
{
}

Dragger::~Dragger()
{
}

bool Dragger::inverted() const
{
    osg::Vec3d xAxis(_matrix(0,0), _matrix(1,0), _matrix(2,0));
    osg::Vec3d yAxis(_matrix(0,1), _matrix(1,1), _matrix(2,1));
    osg::Vec3d zAxis(_matrix(0,2), _matrix(1,2), _matrix(2,2));
    double volume = (xAxis^yAxis)*zAxis;
    return volume<0.0;
}

void Dragger::applyAppropriateFrontFace(osg::StateSet* ss) const
{
    osg::StateAttribute* sa = ss->getAttribute(osg::StateAttribute::FRONTFACE);
    osg::FrontFace* ff = dynamic_cast<osg::FrontFace*>(sa);
    if (!ff)
    {
        ff = new osg::FrontFace;
        ss->setAttribute(ff);
    }
    ff->setMode( inverted() ? osg::FrontFace::CLOCKWISE : osg::FrontFace::COUNTER_CLOCKWISE);
}

void Dragger::setHandleEvents(bool flag)
{
    if (_handleEvents == flag) return;

    _handleEvents = flag;

    // update the number of children that require an event traversal to make sure this dragger receives events.
    if (_handleEvents) setNumChildrenRequiringEventTraversal(getNumChildrenRequiringEventTraversal()+1);
    else if (getNumChildrenRequiringEventTraversal()>=1) setNumChildrenRequiringEventTraversal(getNumChildrenRequiringEventTraversal()-1);
}

void Dragger::addConstraint(Constraint* constraint)
{
    // check to make sure constaint hasn't already been attached.
    for(Constraints::iterator itr = _constraints.begin();
        itr != _constraints.end();
        ++itr)
    {
        if (*itr == constraint) return;
    }

    _constraints.push_back(constraint);
}

void Dragger::removeConstraint(Constraint* constraint)
{
    for(Constraints::iterator itr = _constraints.begin();
        itr != _constraints.end();
        )
    {
        if (*itr == constraint)
        {
            _constraints.erase(itr);
            return;
        } else
        {
            ++itr;
        }
    }
}

void Dragger::addTransformUpdating(osg::MatrixTransform* transform, int handleCommandMask)
{
    addDraggerCallback(new DraggerTransformCallback(transform, handleCommandMask));
}

void Dragger::removeTransformUpdating(osg::MatrixTransform* transform)
{
    for(Dragger::DraggerCallbacks::iterator itr = _draggerCallbacks.begin();
        itr != _draggerCallbacks.end();
        )
    {
        DraggerCallback* dc = itr->get();
        DraggerTransformCallback* dtc = dynamic_cast<DraggerTransformCallback*>(dc);
        if (dtc && dtc->getTransform()==transform)
        {
            itr = _draggerCallbacks.erase(itr);
        }
        else
        {
            ++itr;
        }
    }

}

void Dragger::addDraggerCallback(DraggerCallback* dc)
{
    for(DraggerCallbacks::iterator itr = _draggerCallbacks.begin();
        itr != _draggerCallbacks.end();
        ++itr)
    {
        if (*itr == dc) return;
    }

    _draggerCallbacks.push_back(dc);
}

void Dragger::removeDraggerCallback(DraggerCallback* dc)
{
    for(Dragger::DraggerCallbacks::iterator itr = _draggerCallbacks.begin();
        itr != _draggerCallbacks.end();
        )
    {
        if (dc==itr->get())
        {
            itr = _draggerCallbacks.erase(itr);
        }
        else
        {
            ++itr;
        }
    }
}


void Dragger::traverse(osg::NodeVisitor& nv)
{
    if (_handleEvents && nv.getVisitorType()==osg::NodeVisitor::EVENT_VISITOR)
    {
        osgGA::EventVisitor* ev = nv.asEventVisitor();
        if (ev)
        {
            for(osgGA::EventQueue::Events::iterator itr = ev->getEvents().begin();
                itr != ev->getEvents().end();
                ++itr)
            {
                osgGA::GUIEventAdapter* ea = (*itr)->asGUIEventAdapter();
                if (ea && handle(*ea, *(ev->getActionAdapter()))) ea->setHandled(true);
            }
        }
        return;
    }

    MatrixTransform::traverse(nv);
}

bool Dragger::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
{
    if (ea.getHandled()) return false;

    osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa);
    if (!view) return false;

    bool handled = false;

    bool activationPermitted = true;
    if (_activationModKeyMask!=0 || _activationMouseButtonMask!=0 || _activationKeyEvent!=0)
    {
        _activationPermittedByModKeyMask = (_activationModKeyMask!=0) ?
            ((ea.getModKeyMask() & _activationModKeyMask)!=0) :
            false;

        _activationPermittedByMouseButtonMask = (_activationMouseButtonMask!=0) ?
            ((ea.getButtonMask() & _activationMouseButtonMask)!=0) :
            false;

        if (_activationKeyEvent!=0)
        {
            switch (ea.getEventType())
            {
                case osgGA::GUIEventAdapter::KEYDOWN:
                {
                    if (ea.getKey()==_activationKeyEvent) _activationPermittedByKeyEvent = true;
                    break;
                }
                case osgGA::GUIEventAdapter::KEYUP:
                {
                    if (ea.getKey()==_activationKeyEvent) _activationPermittedByKeyEvent = false;
                    break;
                }
                default:
                    break;
            }
        }

        activationPermitted =  _activationPermittedByModKeyMask || _activationPermittedByMouseButtonMask || _activationPermittedByKeyEvent;

    }

    if (activationPermitted || _draggerActive)
    {
        switch (ea.getEventType())
        {
            case osgGA::GUIEventAdapter::PUSH:
            {
                osgUtil::LineSegmentIntersector::Intersections intersections;

                _pointer.reset();

double mx = ea.getXnormalized();
double my = ea.getYnormalized();
// half width, height.
double w = 0.005;
double h = 0.005;
osg::ref_ptr<osgUtil::PolytopeIntersector> picker = new osgUtil::PolytopeIntersector(osgUtil::Intersector::PROJECTION, mx - w, my - h, mx + w, my + h);
picker->setPrecisionHint(osgUtil::Intersector::USE_DOUBLE_CALCULATIONS);
picker->setPrimitiveMask(osgUtil::PolytopeIntersector::LINE_PRIMITIVES);
picker->setIntersectionLimit(osgUtil::Intersector::NO_LIMIT);
//
osgUtil::IntersectionVisitor iv(picker.get());
view->getCamera()->accept(iv);
if (picker->containsIntersections())
{
bool isGet = false;
osgUtil::PolytopeIntersector::Intersections intersections = picker->getIntersections();
osgUtil::PolytopeIntersector::Intersections::iterator intersection = intersections.begin();
for (intersection; intersection != intersections.end(); intersection++)
{
osg::NodePath nodePath = intersection->nodePath;
for (int i = 0; i < nodePath.size(); i++)
{
osgManipulatorEx::Dragger* dragger = dynamic_cast<osgManipulatorEx::Dragger*>(nodePath[i]);
if (dragger)
{
_pointer.addIntersection(intersection->nodePath, intersection->localIntersectionPoint);
isGet = true;
break;
}
}
if (isGet)
{
break;
}
}
if (!_pointer._hitList.size())
break;
                    for (osg::NodePath::iterator itr = _pointer._hitList.front().first.begin();
                            itr != _pointer._hitList.front().first.end();
                            ++itr)
                    {
                        osgManipulatorEx::Dragger* dragger = dynamic_cast<osgManipulatorEx::Dragger*>(*itr);
                        if (dragger)
                        {
                            if (dragger==this)
                            {
                                osg::Camera *rootCamera = view->getCamera();
                                osg::NodePath nodePath = _pointer._hitList.front().first;
                                osg::NodePath::iterator ritr;
                                for(ritr = nodePath.begin();
                                    ritr != nodePath.end();
                                    ++ritr)
                                {
                                    osg::Camera* camera = (*ritr)->asCamera();
                                    if (camera && (camera->getReferenceFrame()!=osg::Transform::RELATIVE_RF || camera->getParents().empty()))
                                    {
                                         rootCamera = camera;
                                         break;
                                    }
                                }

                                _pointer.setCamera(rootCamera);
                                _pointer.setMousePosition(ea.getX(), ea.getY());

                                if(dragger->handle(_pointer, ea, aa))
                                {
                                    dragger->setDraggerActive(true);
                                    handled = true;
                                }
                            }
                        }
                    }
                }
                break;
            }
            case osgGA::GUIEventAdapter::DRAG:
            case osgGA::GUIEventAdapter::RELEASE:
            {
                if (_draggerActive)
                {
                    _pointer._hitIter = _pointer._hitList.begin();
//                    _pointer.setCamera(view->getCamera());
                    _pointer.setMousePosition(ea.getX(), ea.getY());

                    if(handle(_pointer, ea, aa))
                    {
                        handled = true;
                    }
                }
                break;
            }
            default:
                break;
        }

        if (_draggerActive && ea.getEventType() == osgGA::GUIEventAdapter::RELEASE)
        {
            setDraggerActive(false);
            _pointer.reset();
        }
    }

    return handled;
}

bool Dragger::receive(const MotionCommand& command)
{
    if (_selfUpdater.valid()) return _selfUpdater->receive(command);
    else return false;
}

void Dragger::dispatch(MotionCommand& command)
{
    // apply any constraints
    for(Constraints::iterator itr = _constraints.begin();
        itr != _constraints.end();
        ++itr)
    {
        command.accept(*(*itr));
    }

    // apply any constraints of parent dragger.
    if (getParentDragger()!=this)
    {
        for(Constraints::iterator itr = getParentDragger()->getConstraints().begin();
            itr != getParentDragger()->getConstraints().end();
            ++itr)
        {
            command.accept(*(*itr));
        }
    }

    // move self
    getParentDragger()->receive(command);

    // pass on movement to any dragger callbacks
    for(DraggerCallbacks::iterator itr = getParentDragger()->getDraggerCallbacks().begin();
        itr != getParentDragger()->getDraggerCallbacks().end();
        ++itr)
    {
        command.accept(*(*itr));
    }
}

bool Dragger::computeLocalToWorldMatrix(osg::Matrix& matrix, osg::NodeVisitor* nv) const
{
if (_referenceFrame == RELATIVE_RF)
{
matrix.preMult(computeMatrix(nv));
}
else // absolute
{
matrix = computeMatrix(nv);
}
return true;
}


bool Dragger::computeWorldToLocalMatrix(osg::Matrix& matrix, osg::NodeVisitor* nv) const
{
if (_referenceFrame == RELATIVE_RF)
{
matrix.postMult(osg::Matrix::inverse(computeMatrix(nv)));
}
else // absolute
{
matrix = osg::Matrix::inverse(computeMatrix(nv));
}
return true;
}

osg::Matrixd Dragger::computeMatrix(const osg::NodeVisitor* nv) const
{
osg::Matrixd mt = getMatrix();
//
osg::Vec3d pos,scale;
osg::Quat  q;
osg::Quat  quat;
mt.decompose(pos, quat, scale, q);
//
const osg::CullStack* cs = nv ? nv->asCullStack() : 0;
if (cs)
{
osg::Vec3d eyePoint = cs->getEyeLocal();
osg::Vec3d localUp = cs->getUpLocal();

double size = 1.0 / cs->pixelSize(pos, 0.48f);
//
{
double j = 0.0;
double i = 0.0*(1.0 + 0.25);

double c = 1.0 / (4.0*(i - j));
double b = 1.0 - 2.0*c*i;
double a = j + b*b / (4.0*c);
double k = -b / (2.0*c);

if (size < k) size = 0.0;
else if (size < i) size = a + b*size + c*(size*size);
}
// TODO setScale(size);
scale.set(size, size, size);
}
//
osg::Matrixd matrix;
matrix.makeRotate(quat);
matrix.postMultTranslate(pos);
matrix.preMultScale(scale);
matrix.preMultTranslate(-osg::Vec3d(0,0,0));

return matrix;
}

Robert Osfield

unread,
Oct 13, 2021, 8:15:34 AM10/13/21
to OpenSceneGraph Users
This simply isn't the way to ask questions in a way that others can support.  You can just put in a cryptic subject that possibly encodes part of the problem, then just a massive code dump with practically no explanation.

Please, think carefully about conveying what you want to achieve at a high level so others understand what you are trying to do, then add more details about how you are going about achieving that goal and then what problems you have hit up against.  It may be that code drops/building examples might be needed, but one doesn't lead with this without any of the required introduction.

mirr...@gmail.com

unread,
Oct 16, 2021, 3:42:49 AM10/16/21
to OpenSceneGraph Users

ok!
Reply all
Reply to author
Forward
0 new messages