VISH  0.2
InteractivePoint.cpp

Specifying a point in 3D using the mouse Preliminiary object to specify a 3D point within a given bounding box via mouse movement. The object makes use of the VInteractionEvent type that is provided by a MetaViewer object. This interaction event is grabbed from a Camera object.

Example Vish Script:

Examples/LocatableGear LGear
Create/InteractivePoint ControlPoint

LGear.center=>ControlPoint
#include <ocean/plankton/VCreator.hpp>
#include <ocean/plankton/VInputCreator.hpp>

#include <ocean/shrimp/VInteractionEvent.hpp>
#include <ocean/shrimp/PhysicalSpace.hpp>
#include <ocean/shrimp/VObjectStatus.hpp>
#include <ocean/shrimp/VEnum.hpp>
#include <ocean/shrimp/VCamera.hpp>

#include <ocean/GLvish/BoundingBox.hpp>


using namespace Wizt;
using namespace Eagle;

namespace
{

class   BoundedPoint : public VObject, public StatusIndicator
{
public:
        typedef Eagle::PhysicalSpace::point point;

        TypedSlot<VEnum>                GrabMouse;

        TypedSlot<VInteractionEvent>    Interaction;

        TypedSlot<VCamera>              MyCamera;

        VOutput<point>                  thePoint;
        
        BoundedPoint(const string&name, int p, const RefPtr<VCreationPreferences>&VP)
        : VObject(name, p, VP)
        , StatusIndicator(this, "No point")

        , GrabMouse(this, "mouse", VEnum( "ignore", "grab") )
        , Interaction(this, "interaction", VInteractionEvent( NullPtr() ), 10 )
        , MyCamera( this,  "camera", VCamera( point(5,0,0) ),5 )
        , thePoint( self(), "point", point(0,0,0) )
        {
                attachUniqueObject(MyCamera);
        }

        override bool update(VRequest&R, double precision);

static string createChildname(const string&parent_name)
        {
                return parent_name + "_Point";
        }
};


bool BoundedPoint::update(VRequest&Context, double precision)
{
VEnum   GrabTheMouse; 
        GrabMouse << Context >> GrabTheMouse; 

        if (RefPtr<VObject> theCamera = MyCamera->getSource() )
        {
        RefPtr<VSlot> CameraInteractionInput = theCamera->getUniqueInputSlot( typeid(VInteractionEvent) ); 

                if (CameraInteractionInput && CameraInteractionInput->getParameter() )
                {
//                      puts("**********if (!attachParameter(CameraInteractionInput->getParameter(),***********");
                        if (!attachParameter(CameraInteractionInput->getParameter(),
                                             Interaction, "" ) )
                        {
                                puts("Hm??? could not grab camera mouse input?");
                        } 
                        assert( CameraInteractionInput->getParameter() == Interaction->getParameter() );
                }
        }

VCamera theCamera;
        MyCamera << Context >> theCamera;

using namespace Eagle::PhysicalSpace;

        // Get the value of the mouse parameter 
VInteractionEvent mp;
        Interaction << Context >> mp; 

        if (GrabTheMouse("ignore") )
        {
                mp.ungrab( self() );
                return ConnectionsHaveChanged( Context );
        }
        if (!mp.mayuse(self() ) )
        {
                return false;
        }
        mp.grab( self() );
        if ((mp.state & VInteractionEvent::LeftButton)==0 )
        {
                return false;
        }

double  x = mp.PosX,
        y = mp.PosY; 

        {
        point   P; 
                thePoint << Context >> P; 

        tvector Pdir = theCamera.Observer - P;
        double  Pdist= norm(Pdir); 
        tvector CUp = (*(theCamera.Up)).unit(); 
        tvector Up = Pdist * CUp; 
        tvector Right = *(Pdir ^ CUp); 

        point   ViewCenter =  theCamera.Observer + Pdist*theCamera.viewdir().unit(); 


        point   Pshift = ViewCenter - (x-0.5)*Right - (y-0.5)*Up; 
        point   newP =  theCamera.Observer + Pdist*(Pshift - theCamera.Observer).unit(); 

/*
                cout << " ViewCenter=" << ViewCenter
                     << " Up = " << Up
                     << " Right = " << Right 
                     << " P = " << P << endl; 

                cout << "Distance: " << Pdist << " --> " << norm(theCamera.Observer - P ) << endl;
*/ 

                if (norm2(newP-P)>1E-8)
                {
                        puts("bool BoundedPoint::update(VRequest&Context, double precision) NEW POINT");
                        thePoint << Context << newP;
                        return setStatusInfo( Context, "Point: " + String(P) ); 
//                      return true;
                }
        } 
        puts("bool BoundedPoint::update(VRequest&Context, double precision) OLD POINT");
        return true;
}

static  Ref<VInputCreator<Eagle::PhysicalSpace::point, VCreator<BoundedPoint, AcceptList<VBoundingBox > > >  >  
        myCreator_t("Create/InteractivePoint", ObjectQuality::BETA);

}