[osg-users] [customizing manipulator] problem with delta mouse pos

Julien Valentin julienvalentin51 at gmail.com
Tue Apr 24 17:52:54 PDT 2018


Here's the code, 

Code:

class myFirstPersonManipulator : public osgGA::FirstPersonManipulator{
public:
    osg::ref_ptr<osgGA::GUIEventAdapter> myMouseEvent;
    myFirstPersonManipulator():osgGA::FirstPersonManipulator(){
        setAllowThrow(false);
        setVerticalAxisFixed(true);
        setAcceleration(0);
        this->setHomePosition(osg::Vec3(0,-0.2,0.5),osg::Vec3(0.0,0,0.0),osg::Vec3(1,0,0));
        flushMouseEventStack();
            myMouseEvent=new osgGA::GUIEventAdapter();
            myMouseEvent->setEventType(osgGA::GUIEventAdapter::MOVE);
            myMouseEvent->setButton(osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON);
            myMouseEvent->setTime(00);
            _ga_t1=myMouseEvent.get();
        //addMouseEvent( *new osgGA::GUIEventAdapter);
        //this->setPosition(osg::Vec3(0,0,0));
    }
protected:
    //bool performMovementLeftMouseButton( const double /*eventTimeDelta*/, const double dx, const double dy )
    //{   // world up vector
    //	osg::CoordinateFrame coordinateFrame = getCoordinateFrame( _eye );	osg::Vec3d localUp = getUpVector( coordinateFrame );
    //	rotateYawPitch( _rotation, dx*100, dy*100, localUp );//hack rotation x100
    //	return true;
    //}

    virtual bool handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us ){
        /*  switch(ea.getEventType())
        {*/
        //case(osgGA::GUIEventAdapter::KEYDOWN):
            switch( ea.getEventType() )
        {
            case  osgGA::GUIEventAdapter::MOVE:
            //mouse event
            //move the mouse away from window borders (100,100) may be good enoug
            //but viewport center is more accurate

            //addMouseEvent( ea );
                if(!_ga_t0.valid())   _ga_t0 = &ea;
                    myMouseEvent->setTime(_ga_t0->getTime());
                    myMouseEvent->setXmin(_ga_t0->getXmin());
                    myMouseEvent->setXmax(_ga_t0->getXmax());
                    myMouseEvent->setYmin(_ga_t0->getYmin());
                    myMouseEvent->setYmax(_ga_t0->getYmax());
  dynamic_cast<osgViewer::View*>(&us)->requestWarpPointer( 0.5*(_ga_t0->getXmax()-_ga_t0->getXmin()),0.5*(_ga_t0->getYmax()-_ga_t0->getYmin()));
             //   dynamic_cast<osgViewer::GraphicsWindow*>(us.asView()->getCamera()->getGraphicsContext())->requestWarpPointer( 0.5*(_ga_t0->getXmax()-_ga_t0->getXmin()),0.5*(_ga_t0->getYmax()-_ga_t0->getYmin()));
                 _ga_t1=myMouseEvent;
           // _ga_t1 = _ga_t0;
            _ga_t0 = &ea;

             if( performMovement() )
                us.requestRedraw();
             //dynamic_cast<osgViewer::GraphicsWindow*>(us.asView()->getCamera()->getGraphicsContext())->requestWarpPointer(100,100);

        default:
            //check 4 keyboard event
        switch(ea.getKey())
        {
        case osgGA::GUIEventAdapter::KEY_Up :

            moveForward(1);
            break;
        case osgGA::GUIEventAdapter::KEY_Down :

            moveForward(-1);
            break;
        case osgGA::GUIEventAdapter::KEY_Left :

            moveRight(-1);
            break;
        case osgGA::GUIEventAdapter::KEY_Right :

            moveRight(1);
            break;
        default:
            break;
        }

        /* default:
        }*/



        return true;
        //return osgGA::FirstPersonManipulator::handle(ea,us);
    }
    }
    virtual bool handleMousePush( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us )
    {


        if( performMovement() )
            us.requestRedraw();

      //  us.requestContinuousUpdate( false );
        _thrown = false;

        return true;
    }

    /// Handles GUIEventAdapter::RELEASE event.
    virtual bool handleMouseRelease( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us )
    {
        if( ea.getButtonMask() == 0 )
        {

            double timeSinceLastRecordEvent = _ga_t0.valid() ? (ea.getTime() - _ga_t0->getTime()) : DBL_MAX;
           /* if( timeSinceLastRecordEvent > 0.02 )
                flushMouseEventStack();*/

            if( isMouseMoving() )
            {

                if( performMovement() && _allowThrow )
                {
                    us.requestRedraw();
                    us.requestContinuousUpdate( true );
                    _thrown = true;
                }

                return true;
            }
        }
             //   dynamic_cast<osgViewer::View*>(&us)->requestWarpPointer(0,0);
        //flushMouseEventStack();
        //addMouseEvent( ea );
        if( performMovement() )
            us.requestRedraw();
       // us.requestContinuousUpdate( false );
        _thrown = false;

        return true;
    }


    /// Make movement step of manipulator. Returns true if any movement was made.
    bool performMovement()
    {
        // return if less then two events have been added
        if( _ga_t0.get() == NULL || _ga_t1.get() == NULL )
            return false;

        // get delta time
        double eventTimeDelta = _ga_t0->getTime() - _ga_t1->getTime();
        if( eventTimeDelta < 0. )
        {
            OSG_WARN << "Manipulator warning: eventTimeDelta = " << eventTimeDelta << std::endl;
            eventTimeDelta = 0.;
        }

        // get deltaX and deltaY_ga_t0
        float dx = _ga_t0->getXnormalized() ;//- _ga_t1->getXnormalized();
        float dy = _ga_t0->getYnormalized() ;//- _ga_t1->getYnormalized();

        // return if there is no movement.
        if( dx == 0. && dy == 0. )
            return false;


        // call appropriate methods
        unsigned int buttonMask = _ga_t1->getButtonMask();
        unsigned int modKeyMask = _ga_t1->getModKeyMask();
        if( buttonMask == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON )
        {
            return performMovementLeftMouseButton( eventTimeDelta, dx, dy );
        }
        else if( ( buttonMask == osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON ) ||
                 ( buttonMask == osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON && modKeyMask & osgGA::GUIEventAdapter::MODKEY_CTRL ) ||
                 ( buttonMask == (osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON | osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON) ) )
        {
            return performMovementMiddleMouseButton( eventTimeDelta, dx, dy );
        }
        else if( buttonMask == osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON )
        {
            return performMovementRightMouseButton( eventTimeDelta, dx, dy );
        }else{
            // world up vector
            CoordinateFrame coordinateFrame = getCoordinateFrame( _eye );
            Vec3d localUp = Vec3d(0,1,0);//getUpVector( coordinateFrame );
         RotateYawPitch( _rotation, dx, dy, localUp );

            return true;
         }
          //   return performMovementLeftMouseButton( eventTimeDelta, dx, dy );

        return false;
    }

    static void RotateYawPitch( Quat& rotation, const double yaw, const double pitch,
                                               const Vec3d& localUp )
    {
        bool verticalAxisFixed = (localUp != Vec3d( 0.,0.,0. ));

        // fix current rotation
        if( verticalAxisFixed )
            fixVerticalAxis( rotation, localUp, true );

        // rotations
        Quat rotateYaw( -yaw, verticalAxisFixed ? localUp : rotation * Vec3d( 0.,1.,0. ) );
        Quat rotatePitch;
        Quat newRotation;
        Vec3d cameraRight( rotation * Vec3d( 1.,0.,0. ) );

        double my_dy = pitch;
        int i = 0;

        do {

            // rotations
            rotatePitch.makeRotate( my_dy, cameraRight );
            newRotation = rotation * rotateYaw * rotatePitch;

            // update vertical axis
            if( verticalAxisFixed )
                fixVerticalAxis( newRotation, localUp, false );

            // check for viewer's up vector to be more than 90 degrees from "up" axis
            Vec3d newCameraUp = newRotation * Vec3d( 0.,1.,0. );
         //   if( newCameraUp * localUp > 0. )
            {

                // apply new rotation
                rotation = newRotation;
                return;

            }

            my_dy /= 2.;
            if( ++i == 20 )
            {
                rotation = rotation * rotateYaw;
                return;
            }

        } while( true );
    }
};



Hope it helps to diagnose the problem....
Thanks,


mp3butcher wrote:
> ok, i misinterpreted eventqueue::mouseWarped which in fact is not an event..
> so no there's nothin strange in how it's manage and my problem comes from somewhere elsewhere..
> 
> So I'll try to be concise
> -I derive my manip  from FirstPersonManipulator
> -i override handle and performMovement:
>    in handle I store only last evt time and warpmousepointer to window center
>    in performaction i remove from dx dy substraction of  lastevt.getXnormalized()  (as it's in theory 0,0 after warprequest) and pass dx,dy to FirstPersonManipulator::performMovementLeftMouseButton
> 
> It seams to work for small mouse moves but when I make larger mouse movement i get lost. It look like  the where numerical drift in the transformation from normalized screen to Euler Angle...or something..
> 
> I can post the code but if someone already experience the problem it would be welcome 
> Edit:
> Is the loop in StandardManipulator::rotateYawPitch refer to some exp mapping.I really dont understand
> Cheers
> 
> 
> robertosfield wrote:
> > Hi Julian,
> > 
> > On 23 April 2018 at 20:13, Julien Valentin <> wrote:
> > 
> > > I'm beginning the implementation of my own StandardManipulator
> > > and would like to make a classic fps controller.
> > > So mouse must stay centered all delta mouse pos be captured
> > > However I found out that requestWarpPointer posts a wrapMouse event both in Viewer and GraphicWindows implementations.
> > > it leads to duplication of the event (which is not so bad) but more dramatic, it prevent to recenter mouse without trigger an osgevent.
> > > Is it a desired behavior?
> > > 
> > 
> > Yes.  If the mouse moves you want objects that depend upon mouse
> > position to wake up to the fact that it's moved using an event.
> > 
> > I can't work out what the problem you are having.
> > 
> > Robert.
> > _______________________________________________
> > osg-users mailing list
> > 
> > http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
> > 
> >  ------------------
> > Post generated by Mail2Forum
> 


------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=73503#73503







More information about the osg-users mailing list