示例#1
0
void SketchingTool::buttonCallback(int,InputDevice::ButtonCallbackData* cbData)
	{
	/* Check if the button has just been pressed: */
	if(cbData->newButtonState)
		{
		/* Activate the tool: */
		active=true;
		
		/* Start a new curve: */
		currentCurve=new Curve;
		currentCurve->lineWidth=newLineWidth;
		currentCurve->color=newColor;
		curves.push_back(currentCurve);
		
		/* Append the curve's first control point: */
		Curve::ControlPoint cp;
		const NavTransform& invNav=getInverseNavigationTransformation();
		cp.pos=lastPoint=invNav.transform(getButtonDevicePosition(0));
		cp.t=getApplicationTime();
		currentCurve->controlPoints.push_back(cp);
		}
	else
		{
		/* Append the final control point to the curve: */
		Curve::ControlPoint cp;
		cp.pos=currentPoint;
		cp.t=getApplicationTime();
		currentCurve->controlPoints.push_back(cp);
		
		/* Deactivate the tool: */
		active=false;
		currentCurve=0;
		}
	}
示例#2
0
void RevolverTool::display(GLContextData& contextData) const
	{
	if(getApplicationTime()<showNumbersTime)
		{
		/* Set up OpenGL state: */
		glPushAttrib(GL_ENABLE_BIT|GL_LINE_BIT);
		glDisable(GL_LIGHTING);
		glLineWidth(1.0f);
		glColor3f(0.0f,1.0f,0.0f);
		glPushMatrix();
		
		/* Draw the "revolver chambers:" */
		glMultMatrix(calcHUDTransform(sourceDevice->getPosition()));
		
		Scalar chamberAngle=Scalar(2)*Math::Constants<Scalar>::pi/Scalar(factory->numChambers);
		Scalar angleOffset=Scalar(0);
		double animTime=(getApplicationTime()-(showNumbersTime-1.0))*2.0;
		if(animTime<1.0)
			angleOffset=chamberAngle*Scalar(1.0-animTime);
		
		for(int i=0;i<factory->numChambers;++i)
			{
			Scalar angle=chamberAngle*Scalar(i)+angleOffset;
			GLNumberRenderer::Vector pos;
			pos[0]=Math::sin(angle)*Scalar(getUiSize()*4.0f);
			pos[1]=Math::cos(angle)*Scalar(getUiSize()*4.0f);
			pos[2]=0.0f;
			numberRenderer.drawNumber(pos,(currentChamber+i)%factory->numChambers+1,contextData,0,0);
			}
		
		glPopMatrix();
		glPopAttrib();
		}
	}
void ButtonInputDeviceTool::frame(void)
	{
	if(isActive()&&numPressedNavButtons>0)
		{
		/* Calculate the current frame time step: */
		double frameTime=getApplicationTime();
		double timeStep=frameTime-lastFrameTime;
		lastFrameTime=frameTime;
		
		/* Update the input device transformation: */
		TrackerState ts=getGrabbedDevice()->getTransformation();
		if(transformationMode==TRANSLATING)
			{
			for(int i=0;i<6;++i)
				if(navButtonStates[i])
					ts.leftMultiply(TrackerState::translate(factory->translations[i]*timeStep));
			}
		else
			{
			Point p=ts.getOrigin();
			ts.leftMultiply(TrackerState::translateToOriginFrom(p));
			for(int i=0;i<6;++i)
				if(navButtonStates[i])
					ts.leftMultiply(TrackerState::rotate(Rotation::rotateScaledAxis(factory->rotations[i]*timeStep)));
			ts.leftMultiply(TrackerState::translateFromOriginTo(p));
			}
		getGrabbedDevice()->setTransformation(ts);
		
		/* Request another frame: */
		scheduleUpdate(getApplicationTime()+1.0/125.0);
		}
	}
示例#4
0
void RevolverTool::display(GLContextData& contextData) const
	{
	if(getApplicationTime()<showNumbersTime)
		{
		/* Get the context data item: */
		DataItem* dataItem=contextData.retrieveDataItem<DataItem>(this);
		
		/* Set up OpenGL state: */
		glPushAttrib(GL_ENABLE_BIT|GL_LINE_BIT);
		glDisable(GL_LIGHTING);
		glLineWidth(1.0f);
		glColor3f(0.0f,1.0f,0.0f);
		glPushMatrix();
		
		/* Draw the "revolver chambers:" */
		glMultMatrix(getDeviceTransformation(0));
		
		Scalar chamberAngle=Scalar(2)*Math::Constants<Scalar>::pi/Scalar(factory->numButtons);
		Scalar angleOffset=Scalar(0);
		double animTime=(getApplicationTime()-(showNumbersTime-1.0))*2.0;
		if(animTime<1.0)
			angleOffset=chamberAngle*Scalar(1.0-animTime);
		
		for(int i=0;i<factory->numButtons;++i)
			{
			Scalar angle=chamberAngle*Scalar(i)+angleOffset;
			Point position(Math::sin(angle)*Scalar(getUiSize()*4.0f),Scalar(0),Math::cos(angle)*Scalar(getUiSize()*4.0f));
			dataItem->writeNumber(position,(mappedButtonIndex+i)%factory->numButtons+1);
			}
		
		glPopMatrix();
		glPopAttrib();
		}
	}
示例#5
0
void RevolverTool::frame(void)
	{
	/* Call the base class method: */
	TransformTool::frame();
	
	/* Request a rendering update while the animation is going: */
	if(getApplicationTime()<showNumbersTime)
		{
		/* Request another frame: */
		scheduleUpdate(getApplicationTime()+1.0/125.0);
		}
	}
void ComeHitherNavigationTool::frame(void)
	{
	/* Act depending on this tool's current state: */
	if(isActive())
		{
		/* Get the current application time: */
		double time=getApplicationTime();
		
		if(time>=endTime)
			{
			/* Set the final navigation transformation: */
			setNavigationTransformation(targetNav);
			
			/* Deactivate this tool: */
			deactivate();
			}
		else
			{
			/* Compute and set the intermediate navigation transformation: */
			double deltaTime=time-startTime;
			NavTransform delta=NavTransform(linearVelocity*deltaTime,Rotation::rotateScaledAxis(angularVelocity*deltaTime),Scalar(1));
			delta*=startNav;
			setNavigationTransformation(delta);
			}
		}
	}
void SixAxisTransformTool::frame(void)
{
    /* Assemble translation from translation vectors and current valuator values: */
    Vector translation=Vector::zero;
    for(int i=0; i<3; ++i)
        translation+=translations[i]*Scalar(getValuatorState(i));
    translation*=getCurrentFrameTime();

    /* Assemble rotation from scaled rotation axes and current valuator values: */
    Vector rotation=Vector::zero;
    for(int i=0; i<3; ++i)
        rotation+=config.rotations[i]*Scalar(getValuatorState(3+i));
    rotation*=getCurrentFrameTime();

    /* Calculate an incremental transformation for the virtual input device: */
    ONTransform deltaT=ONTransform::translate(translation);
    Point pos=transformedDevice->getPosition();
    deltaT*=ONTransform::translateFromOriginTo(pos);
    deltaT*=ONTransform::rotate(ONTransform::Rotation::rotateScaledAxis(rotation));
    deltaT*=ONTransform::translateToOriginFrom(pos);

    /* Update the virtual input device's transformation: */
    deltaT*=transformedDevice->getTransformation();
    deltaT.renormalize();
    transformedDevice->setTransformation(deltaT);

    /* Request another frame if the input device has moved: */
    if(translation!=Vector::zero||rotation!=Vector::zero)
    {
        /* Request another frame: */
        scheduleUpdate(getApplicationTime()+1.0/125.0);
    }
}
void ScrollTool::valuatorCallback(int,InputDevice::ValuatorCallbackData* cbData)
	{
	if(cbData->newValuatorValue!=0.0) // Valuator is pushed
		{
		/* Check if the GUI interactor accepts the event: */
		GUIInteractor::updateRay();
		GLMotif::TextControlEvent tce(cbData->newValuatorValue>0.0?GLMotif::TextControlEvent::CURSOR_UP:GLMotif::TextControlEvent::CURSOR_DOWN);
		int numEvents=int(Math::ceil(Math::abs(cbData->newValuatorValue)*10.0));
		sendingEvents=false;
		for(int i=0;i<numEvents;++i)
			sendingEvents=GUIInteractor::textControl(tce)||sendingEvents;
		if(sendingEvents)
			{
			/* Request another frame: */
			scheduleUpdate(getApplicationTime()+1.0/125.0);
			}
		else
			{
			/* Pass the valuator event to the virtual input device: */
			valuatorDevice->setValuator(0,cbData->newValuatorValue);
			}
		}
	else // Valuator has just been released
		{
		/* Check if the tool has been sending text control events: */
		if(!sendingEvents)
			{
			/* Pass the button event to the virtual input device: */
			valuatorDevice->setValuator(0,cbData->newValuatorValue);
			}
		sendingEvents=false;
		}
	}
示例#9
0
void RevolverTool::buttonCallback(int buttonSlotIndex,InputDevice::ButtonCallbackData* cbData)
	{
	if(buttonSlotIndex==0)
		{
		if(cbData->newButtonState)
			{
			/* Change the currently mapped button set: */
			currentChamber=(currentChamber+1)%factory->numChambers;
			
			/* Set the newly mapped chamber's state to the input device's buttons' and valuators' states: */
			for(int i=1;i<input.getNumButtonSlots();++i)
				transformedDevice->setButtonState((i-1)*factory->numChambers+currentChamber,getButtonState(i));
			for(int i=0;i<input.getNumValuatorSlots();++i)
				transformedDevice->setValuator(i*factory->numChambers+currentChamber,getValuatorState(i));
			
			/* Show the current button assignment for one second: */
			showNumbersTime=getApplicationTime()+1.0;
			}
		}
	else
		{
		/* Pass the button event through to the virtual input device: */
		transformedDevice->setButtonState((buttonSlotIndex-1)*factory->numChambers+currentChamber,cbData->newButtonState);
		}
	}
ButtonInputDeviceTool::ButtonInputDeviceTool(const ToolFactory* sFactory,const ToolInputAssignment& inputAssignment)
	:InputDeviceTool(sFactory,inputAssignment),
	 transformationMode(TRANSLATING),
	 numPressedNavButtons(0),
	 lastFrameTime(getApplicationTime())
	{
	for(int i=0;i<6;++i)
		navButtonStates[i]=false;
	}
示例#11
0
void RevolverTool::frame(void)
	{
	/* Call the base class method: */
	TransformTool::frame();
	
	/* Request a rendering update while the animation is going: */
	if(getApplicationTime()<showNumbersTime)
		requestUpdate();
	}
示例#12
0
 int App::run()
 {
     try{init(); m_running = GL_TRUE;}
     catch(std::exception &e){LOG_ERROR<<e.what();}
     double timeStamp = 0.0;
     
     // Main loop
     while( m_running )
     {            
         // update application time
         timeStamp = getApplicationTime();
         
         // poll io_service if no seperate worker-threads exist
         if(!m_main_queue.get_num_threads()) m_main_queue.io_service().poll();
         
         // poll input events
         pollEvents();
         
         // time elapsed since last frame
         double time_delta = timeStamp - m_lastTimeStamp;
         
         // call update callback
         update(time_delta);
         
         m_lastTimeStamp = timeStamp;
         
         if(needs_redraw())
         {
             // call draw callback
             draw_internal();
             
             // Swap front and back rendering buffers
             swapBuffers();
         }
         
         // perform fps-timing
         timing(timeStamp);
         
         // Check if ESC key was pressed or window was closed or whatever
         m_running = checkRunning();
         
         // fps managment
         float current_fps = 1.f / time_delta;
         
         if(current_fps > m_max_fps)
         {
             double sleep_secs = std::max(0.0, (1.0 / m_max_fps - time_delta));
             this_thread::sleep_for(duration_t(sleep_secs));
         }
     }
     
     // manage tearDown, save stuff etc.
     tearDown();
     
     return EXIT_SUCCESS;
 }
void InputDeviceAdapterTrackd::updateInputDevices(void)
	{
	for(int deviceIndex=0;deviceIndex<numInputDevices;++deviceIndex)
		{
		/* Get pointer to the input device: */
		InputDevice* device=inputDevices[deviceIndex];
		
		/* Don't update tracker-related state for devices that are not tracked: */
		if(trackerIndexMapping[deviceIndex]>=0)
			{
			/* Get device's tracker state from sensor shared memory segment: */
			SensorData& sd=*sensors[trackerIndexMapping[deviceIndex]];
			
			/*****************************************************************
			Construct device's transformation:
			*****************************************************************/
			
			/* Translation vector is straightforward: */
			Vector translation=Vector(Scalar(sd.position[0]),Scalar(sd.position[1]),Scalar(sd.position[2]));
			
			/* To assemble the orientation, we assume all angles are in degrees, and the order of rotations is as follows: */
			Rotation rotation=Rotation::rotateZ(Math::rad(Scalar(sd.angles[0])));
			rotation*=Rotation::rotateX(Math::rad(Scalar(sd.angles[1])));
			rotation*=Rotation::rotateY(Math::rad(Scalar(sd.angles[2])));
			
			/* Calibrate the device's position and orientation from the trackd daemon's space to Vrui's physical space: */
			OGTransform calibratedTransformation=calibrationTransformation;
			calibratedTransformation*=OGTransform(translation,rotation,Scalar(1));
			
			/* Calibrate and set the device's transformation: */
			device->setTransformation(TrackerState(calibratedTransformation.getTranslation(),calibratedTransformation.getRotation()));
			
			/* Set device's linear and angular velocities to zero because we don't know any better: */
			device->setLinearVelocity(Vector::zero);
			device->setAngularVelocity(Vector::zero);
			}
		
		/* Update button states: */
		for(int i=0;i<device->getNumButtons();++i)
			device->setButtonState(i,buttons[buttonIndexMapping[deviceIndex][i]]);
		
		/* Update valuator states: */
		for(int i=0;i<device->getNumValuators();++i)
			device->setValuator(i,valuators[valuatorIndexMapping[deviceIndex][i]]);
		}
	
	/* Schedule the next Vrui frame at the update interval if asked to do so: */
	if(updateInterval!=0.0)
		Vrui::scheduleUpdate(getApplicationTime()+updateInterval);
	}
void HelicopterNavigationTool::buttonCallback(int,int buttonIndex,InputDevice::ButtonCallbackData* cbData)
{
    /* Process based on which button was pressed: */
    if(buttonIndex==0)
    {
        if(cbData->newButtonState)
        {
            /* Act depending on this tool's current state: */
            if(isActive())
            {
                /* Go back to original transformation: */
                NavTransform nav=pre;
                nav*=NavTransform::translateToOriginFrom(currentPosition);
                nav*=post;
                setNavigationTransformation(nav);

                /* Deactivate this tool: */
                deactivate();
            }
            else
            {
                /* Try activating this tool: */
                if(activate())
                {
                    /* Initialize the navigation: */
                    Vector x=Geometry::cross(getForwardDirection(),getUpDirection());
                    Vector y=Geometry::cross(getUpDirection(),x);
                    pre=NavTransform::translateFromOriginTo(getMainViewer()->getHeadPosition());
                    pre*=NavTransform::rotate(Rotation::fromBaseVectors(x,y));

                    post=Geometry::invert(pre);
                    post*=getNavigationTransformation();

                    currentPosition=Point::origin;
                    currentOrientation=Rotation::identity;
                    currentVelocity=Vector::zero;
                    lastFrameTime=getApplicationTime();
                }
            }
        }
    }
    else
    {
        /* Store the new state of the button: */
        buttons[buttonIndex-1]=cbData->newButtonState;
    }
}
示例#15
0
void JediTool::buttonCallback(int,InputDevice::ButtonCallbackData* cbData)
	{
	if(cbData->newButtonState) // Activation button has just been pressed
		{
		if(!active)
			{
			/* Activate the light saber: */
			active=true;
			activationTime=getApplicationTime();
			}
		else
			{
			/* Deactivate the light saber: */
			active=false;
			}
		}
	}
void SixAxisNavigationTool::frame(void)
	{
	if(isActive())
		{
		/* Assemble translation from translation vectors and current valuator values: */
		Vector translation=Vector::zero;
		for(int i=0;i<3;++i)
			translation+=translations[i]*Scalar(getValuatorState(i));
		translation*=getCurrentFrameTime();
		
		/* Assemble rotation from scaled rotation axes and current valuator values: */
		Vector rotation=Vector::zero;
		for(int i=0;i<3;++i)
			rotation+=rotations[i]*Scalar(getValuatorState(3+i));
		rotation*=getCurrentFrameTime();
		
		/* Calculate incremental zoom factor: */
		Scalar zoom=config.zoomFactor*Scalar(getValuatorState(6))*getCurrentFrameTime();
		
		/* Apply proper navigation mode: */
		if(config.invertNavigation)
			{
			translation=-translation;
			rotation=-rotation;
			zoom=-zoom;
			}
		
		/* Calculate an incremental transformation based on the translation and rotation: */
		NavTrackerState deltaT=NavTrackerState::translateFromOriginTo(config.followDisplayCenter?getDisplayCenter():config.navigationCenter);
		deltaT*=NavTrackerState::translate(translation);
		deltaT*=NavTrackerState::rotate(NavTrackerState::Rotation::rotateScaledAxis(rotation));
		deltaT*=NavTrackerState::scale(Math::exp(-zoom));
		deltaT*=NavTrackerState::translateToOriginFrom(config.followDisplayCenter?getDisplayCenter():config.navigationCenter);
		
		/* Update the accumulated transformation: */
		navTransform.leftMultiply(deltaT);
		navTransform.renormalize();
		
		/* Update the navigation transformation: */
		setNavigationTransformation(navTransform);
		
		/* Request another frame: */
		scheduleUpdate(getApplicationTime()+1.0/125.0);
		}
	}
void HelicopterNavigationTool::frame(void)
{
    /* Act depending on this tool's current state: */
    if(isActive())
    {
        double newFrameTime=getApplicationTime();
        Scalar dt=Scalar(newFrameTime-lastFrameTime);

        /* Update the current orientation based on the pitch, roll, and yaw controls: */
        Vector rot=Vector(valuators[0]*factory->rotateFactors[0],valuators[1]*factory->rotateFactors[1],valuators[2]*factory->rotateFactors[2]);
        currentOrientation.leftMultiply(Rotation::rotateScaledAxis(rot*dt));
        currentOrientation.renormalize();

        /* Update the current velocity based on collective, throttle and brake: */
        Vector accel=Vector(0,0,-factory->g);
        accel+=currentOrientation.inverseTransform(Vector(0,0,(factory->collectiveMax-factory->collectiveMin)*(Scalar(1)-valuators[3])*Scalar(0.5)+factory->collectiveMin));
        if(buttons[0])
            accel+=currentOrientation.inverseTransform(Vector(0,factory->thrust,0));
        if(buttons[1])
            accel+=currentOrientation.inverseTransform(Vector(0,-factory->brake,0));

        /* Calculate drag: */
        Vector localVel=currentOrientation.transform(currentVelocity);
        Vector drag=Vector(localVel[0]*factory->dragCoefficients[0],localVel[1]*factory->dragCoefficients[1],localVel[2]*factory->dragCoefficients[2]);
        accel+=currentOrientation.inverseTransform(drag);

        currentVelocity+=accel*dt;

        /* Update the current position based on current velocity: */
        currentPosition+=currentVelocity*dt;

        /* Set the new navigation transformation: */
        NavTransform nav=pre;
        nav*=NavTransform::rotate(Rotation::rotateZ(valuators[4]*factory->viewAngleFactors[0]));
        nav*=NavTransform::rotate(Rotation::rotateX(valuators[5]*factory->viewAngleFactors[1]));
        nav*=NavTransform::rotate(currentOrientation);
        nav*=NavTransform::translateToOriginFrom(currentPosition);
        nav*=post;
        setNavigationTransformation(nav);

        /* Prepare for the next frame: */
        lastFrameTime=newFrameTime;
        Vrui::requestUpdate();
    }
}
示例#18
0
void RevolverTool::buttonCallback(int,int deviceButtonIndex,InputDevice::ButtonCallbackData* cbData)
	{
	if(deviceButtonIndex==0)
		{
		/* Pass the button event through to the virtual input device: */
		transformedDevice->setButtonState(mappedButtonIndex,cbData->newButtonState);
		}
	else if(cbData->newButtonState)
		{
		/* Change the currently mapped button: */
		mappedButtonIndex=(mappedButtonIndex+1)%factory->numButtons;
		
		/* Set the newly mapped button's state to the input device's button's state: */
		transformedDevice->setButtonState(mappedButtonIndex,getDeviceButtonState(0,0));
		
		/* Show the current button assignment: */
		showNumbersTime=getApplicationTime()+1.0;
		}
	}
示例#19
0
void JediTool::frame(void)
	{
	if(active)
		{
		/* Update the light saber billboard: */
		origin=getButtonDevicePosition(0);
		axis=getButtonDeviceRayDirection(0);
		
		/* Scale the lightsaber during activation: */
		length=factory->lightsaberLength;
		double activeTime=getApplicationTime()-activationTime;
		if(activeTime<1.5)
			{
			length*=activeTime/1.5;
			
			/* Request another frame: */
			scheduleUpdate(getNextAnimationTime());
			}
		}
	}
void ViewpointFileNavigationTool::frame(void)
	{
	/* Animate the navigation transformation if the tool is active: */
	if(isActive())
		{
		/* Get the next curve parameter: */
		Scalar newParameter=parameter+Scalar(getFrameTime())*speed;
		
		/* Check if a pause was scheduled between the last frame and this one: */
		bool passedPause=false;
		for(std::vector<Scalar>::const_iterator pIt=pauses.begin();pIt!=pauses.end();++pIt)
			if(parameter<*pIt&&*pIt<=newParameter)
				{
				passedPause=true;
				newParameter=*pIt;
				break;
				}
		
		/* Navigate to the new curve parameter: */
		if(!navigate(newParameter))
			{
			/* Stop animating, curve is over: */
			deactivate();
			}
		else if(passedPause)
			{
			paused=true;
			deactivate();
			}
		else
			{
			/* Request another frame: */
			scheduleUpdate(getApplicationTime()+1.0/125.0);
			}
		
		/* Update the curve parameter and the GUI: */
		parameter=newParameter;
		if(positionSlider!=0)
			positionSlider->setValue(parameter);
		}
	}
示例#21
0
void SketchingTool::frame(void)
	{
	if(active)
		{
		/* Get the current dragging point: */
		const NavTransform& invNav=getInverseNavigationTransformation();
		currentPoint=invNav.transform(getButtonDevicePosition(0));
		
		/* Check if the dragging point is far enough away from the most recent curve vertex: */
		if(Geometry::sqrDist(currentPoint,lastPoint)>=Math::sqr(factory->detailSize*invNav.getScaling()))
			{
			/* Append the current dragging point to the curve: */
			Curve::ControlPoint cp;
			cp.pos=currentPoint;
			cp.t=getApplicationTime();
			currentCurve->controlPoints.push_back(cp);
			
			/* Remember the last added point: */
			lastPoint=currentPoint;
			}
		}
	}
void ValuatorTurnNavigationTool::frame(void)
	{
	/* Act depending on this tool's current state: */
	if(isActive())
		{
		/* Get the current state of the input device: */
		const TrackerState& ts=getButtonDeviceTransformation(0);
		
		/* Calculate the current flying velocity: */
		Vector v=Vector::zero;
		if(buttonState)
			{
			v=ts.transform(factory->flyDirection);
			v*=-factory->flyFactor*getFrameTime();
			}
		
		/* Calculate the current angular velocities: */
		Vector w0=factory->rotationAxis0;
		w0*=currentValues[0]*factory->rotationFactor*getFrameTime();
		Vector w1=factory->rotationAxis1;
		w1*=currentValues[1]*factory->rotationFactor*getFrameTime();
		
		/* Compose the new navigation transformation: */
		Point p=ts.transform(factory->rotationCenter);
		NavTransform t=NavTransform::translate(v);
		t*=NavTransform::translateFromOriginTo(p);
		t*=NavTransform::rotate(NavTransform::Rotation::rotateScaledAxis(w0));
		t*=NavTransform::rotate(NavTransform::Rotation::rotateScaledAxis(w1));
		t*=NavTransform::translateToOriginFrom(p);
		t*=getNavigationTransformation();
		
		/* Update Vrui's navigation transformation: */
		setNavigationTransformation(t);
		
		/* Request another frame: */
		scheduleUpdate(getApplicationTime()+1.0/125.0);
		}
	}
void ValuatorFlyNavigationTool::frame(void)
	{
	/* Act depending on this tool's current state: */
	if(isActive())
		{
		/* Get the current state of the input device: */
		const TrackerState& ts=getValuatorDeviceTransformation(0);
		
		/* Calculate the current flying velocity: */
		Vector v=ts.transform(factory->flyDirection);
		v*=-currentValue*factory->flyFactor*getFrameTime();
		
		/* Compose the new navigation transformation: */
		NavTransform t=NavTransform::translate(v);
		t*=getNavigationTransformation();
		
		/* Update Vrui's navigation transformation: */
		setNavigationTransformation(t);
		
		/* Request another frame: */
		scheduleUpdate(getApplicationTime()+1.0/125.0);
		}
	}
void ButtonInputDeviceTool::buttonCallback(int buttonSlotIndex,InputDevice::ButtonCallbackData* cbData)
	{
	if(cbData->newButtonState) // Button has just been pressed
		{
		switch(buttonSlotIndex)
			{
			case 0: // Device switch button
				grabNextDevice();
				break;
			
			case 1: // Transformation mode toggle
				if(transformationMode==TRANSLATING)
					transformationMode=ROTATING;
				else
					transformationMode=TRANSLATING;
				break;
			
			case 2: // Navigation buttons
			case 3:
			case 4:
			case 5:
			case 6:
			case 7:
				if(!navButtonStates[buttonSlotIndex-2])
					{
					navButtonStates[buttonSlotIndex-2]=true;
					if(numPressedNavButtons==0)
						lastFrameTime=getApplicationTime();
					++numPressedNavButtons;
					}
				break;
			
			default: // Forwarded buttons
				/* Let input device tool handle it: */
				InputDeviceTool::buttonCallback(buttonSlotIndex,cbData);
			}
		}
	else // Button has just been released
		{
		switch(buttonSlotIndex)
			{
			case 0: // Device switch button
			case 1: // Transformation mode toggle
				break;
			
			case 2: // Navigation buttons
			case 3:
			case 4:
			case 5:
			case 6:
			case 7:
				if(navButtonStates[buttonSlotIndex-2])
					{
					navButtonStates[buttonSlotIndex-2]=false;
					--numPressedNavButtons;
					}
				break;
			
			default: // Forwarded buttons
				/* Let input device tool handle it: */
				InputDeviceTool::buttonCallback(buttonSlotIndex,cbData);
			}
		}
	}
void MouseDialogNavigationTool::buttonCallback(int,InputDevice::ButtonCallbackData* cbData)
	{
	if(cbData->newButtonState) // Button has just been pressed
		{
		bool takeEvent=true;
		if(factory->interactWithWidgets)
			{
			/* Check if the GUI interactor accepts the event: */
			GUIInteractor::updateRay();
			if(GUIInteractor::buttonDown(false))
				{
				/* Deactivate this tool if it is spinning: */
				if(spinning)
					deactivate();
				spinning=false;
				
				/* Disable navigation: */
				takeEvent=false;
				}
			}
		
		if(takeEvent)
			{
			/* Deactivate spinning: */
			spinning=false;
			
			/* Start navigating according to the current navigation mode: */
			switch(navigationMode)
				{
				case ROTATING:
					if(activate())
						startRotating();
					break;
				
				case PANNING:
					if(activate())
						startPanning();
					break;
				
				case DOLLYING:
					if(activate())
						startDollying();
					break;
				
				case SCALING:
					if(activate())
						startScaling();
					break;
				}
			}
		}
	else // Button has just been released
		{
		if(GUIInteractor::isActive())
			{
			/* Deliver the event: */
			GUIInteractor::buttonUp();
			}
		else
			{
			/* Check for spinning if currently in rotating mode: */
			if(navigationMode==ROTATING)
				{
				/* Check if the input device is still moving: */
				Point currentPos=calcScreenPos();
				Vector delta=currentPos-lastRotationPos;
				if(Geometry::mag(delta)>factory->spinThreshold)
					{
					/* Calculate spinning angular velocity: */
					Vector offset=(lastRotationPos-screenCenter)+rotateOffset;
					Vector axis=Geometry::cross(offset,delta);
					Scalar angularVelocity=Geometry::mag(delta)/(factory->rotateFactor*(getApplicationTime()-lastMoveTime));
					spinAngularVelocity=axis*(Scalar(0.5)*angularVelocity/axis.mag());
					
					/* Enable spinning: */
					spinning=true;
					}
				else
					{
					/* Deactivate the tool: */
					deactivate();
					}
				}
			else
				{
				/* Deactivate the tool: */
				deactivate();
				}
			}
		}
	}
void SixAxisSurfaceNavigationTool::frame(void)
	{
	/* Act depending on this tool's current state: */
	if(isActive())
		{
		/* Use the average frame time as simulation time: */
		Scalar dt=getCurrentFrameTime();
		
		/* Update rotation angles based on current rotation valuator states: */
		for(int i=0;i<3;++i)
			angles[i]=wrapAngle(angles[i]+getValuatorState(i+3)*factory->rotateFactors[i]*dt);
		if(angles[1]<Math::rad(Scalar(-90)))
			angles[1]=Math::rad(Scalar(-90));
		else if(angles[1]>Math::rad(Scalar(90)))
			angles[1]=Math::rad(Scalar(90));
		if(!factory->canRoll||factory->bankTurns)
			{
			Scalar targetRoll=factory->bankTurns?getValuatorState(3)*factory->rotateFactors[2]:Scalar(0);
			Scalar t=Math::exp(-factory->levelSpeed*dt);
			angles[2]=angles[2]*t+targetRoll*(Scalar(1)-t);
			if(Math::abs(angles[2]-targetRoll)<Scalar(1.0e-3))
				angles[2]=targetRoll;
			}
		
		/* Calculate the new head position: */
		Point newHeadPos=getMainViewer()->getHeadPosition();
		
		/* Create a physical navigation frame around the new foot position: */
		calcPhysicalFrame(newHeadPos);
		
		/* Calculate movement from head position change: */
		Vector move=newHeadPos-headPos;
		headPos=newHeadPos;
		
		/* Add movement velocity based on the current translation valuator states: */
		for(int i=0;i<3;++i)
			move[i]+=getValuatorState(i)*factory->translateFactors[i]*dt;
		
		/* Transform the movement vector from physical space to the physical navigation frame: */
		move=physicalFrame.inverseTransform(move);
		
		/* Rotate by the current azimuth and elevation angles: */
		move=Rotation::rotateX(-angles[1]).transform(move);
		move=Rotation::rotateZ(-angles[0]).transform(move);
		
		/* Move the surface frame: */
		NavTransform newSurfaceFrame=surfaceFrame;
		newSurfaceFrame*=NavTransform::translate(move);
		
		/* Re-align the surface frame with the surface: */
		Point initialOrigin=newSurfaceFrame.getOrigin();
		Rotation initialOrientation=newSurfaceFrame.getRotation();
		AlignmentData ad(surfaceFrame,newSurfaceFrame,factory->probeSize,factory->maxClimb);
		align(ad);
		
		if(!factory->fixAzimuth)
			{
			/* Have the azimuth angle track changes in the surface frame's rotation: */
			Rotation rot=Geometry::invert(initialOrientation)*newSurfaceFrame.getRotation();
			rot.leftMultiply(Rotation::rotateFromTo(rot.getDirection(2),Vector(0,0,1)));
			Vector x=rot.getDirection(0);
			angles[0]=wrapAngle(angles[0]+Math::atan2(x[1],x[0]));
			}
		
		/* If flying is allowed and the initial surface frame was above the surface, lift it back up: */
		Scalar z=newSurfaceFrame.inverseTransform(initialOrigin)[2];
		if(!factory->canFly||z<factory->probeSize)
			z=factory->probeSize;
		newSurfaceFrame*=NavTransform::translate(Vector(Scalar(0),Scalar(0),z));
		
		/* Apply the newly aligned surface frame: */
		surfaceFrame=newSurfaceFrame;
		applyNavState();
		
		/* Deactivate the tool if it is done: */
		if(numActiveAxes==0&&Math::abs(angles[2])<Math::Constants<Scalar>::epsilon)
			deactivate();
		else
			{
			/* Request another frame: */
			scheduleUpdate(getApplicationTime()+1.0/125.0);
			}
		}
	}
void ComeHitherNavigationTool::buttonCallback(int,int,InputDevice::ButtonCallbackData* cbData)
	{
	if(cbData->newButtonState) // Button has just been pressed
		{
		if(isActive()) // Tool is already active
			{
			/* Snap to the target transformation immediately: */
			setNavigationTransformation(targetNav);
			
			/* Deactivate this tool: */
			deactivate();
			}
		else // Tool is not yet active
			{
			/* Try activating this tool: */
			if(activate())
				{
				/* Get the start navigation transformation: */
				startNav=getNavigationTransformation();
				startTime=getApplicationTime();
				
				/* Get the target transformation: */
				NavTransform device=getDeviceTransformation(0);
				device.leftMultiply(getInverseNavigationTransformation());
				Point center=device.getOrigin();
				Vector forward=device.getDirection(1);
				Vector up=device.getDirection(2);
				
				/* Compute the navigation transformation for the target transformation: */
				targetNav=NavTransform::identity;
				targetNav*=NavTransform::translateFromOriginTo(getDisplayCenter());
				targetNav*=NavTransform::rotate(Rotation::fromBaseVectors(Geometry::cross(getForwardDirection(),getUpDirection()),getForwardDirection()));
				targetNav*=NavTransform::scale(startNav.getScaling());
				targetNav*=NavTransform::rotate(Geometry::invert(Rotation::fromBaseVectors(Geometry::cross(forward,up),forward)));
				targetNav*=NavTransform::translateToOriginFrom(center);
				
				/* Compute the linear and angular velocities for the movement: */
				NavTransform delta=startNav;
				delta.doInvert();
				delta.leftMultiply(targetNav);
				Vector linearDist=delta.getTranslation();
				double linearMag=Geometry::mag(linearDist);
				Vector angularDist=delta.getRotation().getScaledAxis();
				double angularMag=Geometry::mag(angularDist);
				if(linearMag<=factory->linearSnapThreshold&&angularMag<=factory->angularSnapThreshold)
					{
					/* Snap to the target transformation immediately: */
					setNavigationTransformation(targetNav);
					
					/* Deactivate this tool: */
					deactivate();
					}
				else
					{
					/* Compute the total transition time: */
					double transitionTime=linearMag/factory->maxLinearVelocity;
					if(transitionTime<angularMag/factory->maxAngularVelocity)
						transitionTime=angularMag/factory->maxAngularVelocity;
					endTime=startTime+transitionTime;
					
					/* Compute the effective linear and angular velocities: */
					linearVelocity=linearDist/Scalar(transitionTime);
					angularVelocity=angularDist/Scalar(transitionTime);
					}
				}
			}
		}
	}
示例#28
0
void MouseNavigationTool::buttonCallback(int buttonSlotIndex,InputDevice::ButtonCallbackData* cbData)
	{
	/* Process based on which button was pressed: */
	switch(buttonSlotIndex)
		{
		case 0:
			if(cbData->newButtonState) // Button has just been pressed
				{
				/* Act depending on this tool's current state: */
				switch(navigationMode)
					{
					case IDLE:
					case SPINNING:
						if(factory->interactWithWidgets)
							{
							/* Check if the GUI interactor accepts the event: */
							GUIInteractor::updateRay();
							if(GUIInteractor::buttonDown(false))
								{
								/* Deactivate this tool if it is spinning: */
								if(navigationMode==SPINNING)
									deactivate();
								
								/* Go to widget interaction mode: */
								navigationMode=WIDGETING;
								}
							else
								{
								/* Try activating this tool: */
								if(navigationMode==SPINNING||activate())
									startRotating();
								}
							}
						else
							{
							/* Try activating this tool: */
							if(navigationMode==SPINNING||activate())
								startRotating();
							}
						break;
					
					case PANNING:
						if(dolly)
							startDollying();
						else
							startScaling();
						break;
					
					default:
						/* This shouldn't happen; just ignore the event */
						break;
					}
				}
			else // Button has just been released
				{
				/* Act depending on this tool's current state: */
				switch(navigationMode)
					{
					case WIDGETING:
						{
						if(GUIInteractor::isActive())
							{
							/* Deliver the event: */
							GUIInteractor::buttonUp();
							}
						
						/* Deactivate this tool: */
						navigationMode=IDLE;
						break;
						}
					
					case ROTATING:
						{
						/* Check if the input device is still moving: */
						Point currentPos=calcScreenPos();
						Vector delta=currentPos-lastRotationPos;
						if(Geometry::mag(delta)>factory->spinThreshold)
							{
							/* Calculate spinning angular velocity: */
							Vector offset=(lastRotationPos-screenCenter)+rotateOffset;
							Vector axis=Geometry::cross(offset,delta);
							Scalar angularVelocity=Geometry::mag(delta)/(factory->rotateFactor*(getApplicationTime()-lastMoveTime));
							spinAngularVelocity=axis*(Scalar(0.5)*angularVelocity/axis.mag());
							
							/* Go to spinning mode: */
							navigationMode=SPINNING;
							}
						else
							{
							/* Deactivate this tool: */
							deactivate();
							
							/* Go to idle mode: */
							navigationMode=IDLE;
							}
						break;
						}
					
					case DOLLYING:
					case SCALING:
						startPanning();
						break;
					
					default:
						/* This shouldn't happen; just ignore the event */
						break;
					}
				}
			break;
		
		case 1:
			if(cbData->newButtonState) // Button has just been pressed
				{
				/* Act depending on this tool's current state: */
				switch(navigationMode)
					{
					case IDLE:
					case SPINNING:
						/* Try activating this tool: */
						if(navigationMode==SPINNING||activate())
							startPanning();
						break;
					
					case ROTATING:
						if(dolly)
							startDollying();
						else
							startScaling();
						break;
					
					default:
						/* This shouldn't happen; just ignore the event */
						break;
					}
				}
			else // Button has just been released
				{
				/* Act depending on this tool's current state: */
				switch(navigationMode)
					{
					case PANNING:
						/* Deactivate this tool: */
						deactivate();
						
						/* Go to idle mode: */
						navigationMode=IDLE;
						break;
					
					case DOLLYING:
					case SCALING:
						startRotating();
						break;
					
					default:
						/* This shouldn't happen; just ignore the event */
						break;
					}
				}
			break;
		
		case 2:
			/* Set the dolly flag: */
			dolly=cbData->newButtonState;
			if(factory->invertDolly)
				dolly=!dolly;
			if(dolly) // Dollying has just been enabled
				{
				/* Act depending on this tool's current state: */
				switch(navigationMode)
					{
					case SCALING:
						startDollying();
						break;
					
					default:
						/* Nothing to do */
						break;
					}
				}
			else
				{
				/* Act depending on this tool's current state: */
				switch(navigationMode)
					{
					case DOLLYING:
						startScaling();
						break;
					
					default:
						/* Nothing to do */
						break;
					}
				}
			break;
		}
	}
void ButtonInputDeviceTool::buttonCallback(int,int buttonIndex,InputDevice::ButtonCallbackData* cbData)
	{
	if(cbData->newButtonState) // Button has just been pressed
		{
		switch(buttonIndex)
			{
			case 0: // Device switch button
				grabNextDevice();
				break;
			
			case 1: // Transformation mode toggle
				if(transformationMode==TRANSLATING)
					transformationMode=ROTATING;
				else
					transformationMode=TRANSLATING;
				break;
			
			case 2: // Navigation buttons
			case 3:
			case 4:
			case 5:
			case 6:
			case 7:
				if(!navButtonStates[buttonIndex-2])
					{
					navButtonStates[buttonIndex-2]=true;
					if(numPressedNavButtons==0)
						lastFrameTime=getApplicationTime();
					++numPressedNavButtons;
					}
				break;
			
			default: // Device button buttons
				if(isActive()&&buttonIndex-8<getGrabbedDevice()->getNumButtons())
					getGrabbedDevice()->setButtonState(buttonIndex-8,true);
			}
		}
	else // Button has just been released
		{
		switch(buttonIndex)
			{
			case 0: // Device switch button
			case 1: // Transformation mode toggle
				break;
			
			case 2: // Navigation buttons
			case 3:
			case 4:
			case 5:
			case 6:
			case 7:
				if(navButtonStates[buttonIndex-2])
					{
					navButtonStates[buttonIndex-2]=false;
					--numPressedNavButtons;
					}
				break;
			
			default: // Device button buttons
				if(isActive()&&buttonIndex-8<getGrabbedDevice()->getNumButtons())
					getGrabbedDevice()->setButtonState(buttonIndex-8,false);
			}
		}
	}
示例#30
0
void MouseNavigationTool::frame(void)
	{
	/* Update the current mouse position: */
	Point newCurrentPos=calcScreenPos();
	if(currentPos!=newCurrentPos)
		{
		currentPos=calcScreenPos();
		lastMoveTime=getApplicationTime();
		}
	if(factory->interactWithWidgets)
		{
		/* Update the GUI interactor: */
		GUIInteractor::updateRay();
		GUIInteractor::move();
		}
	
	/* Act depending on this tool's current state: */
	switch(navigationMode)
		{
		case ROTATING:
			{
			/* Calculate the rotation position: */
			Vector offset=(lastRotationPos-screenCenter)+rotateOffset;
			
			/* Calculate mouse displacement vector: */
			Point rotationPos=currentPos;
			Vector delta=rotationPos-lastRotationPos;
			lastRotationPos=rotationPos;
			
			/* Calculate incremental rotation: */
			Vector axis=Geometry::cross(offset,delta);
			Scalar angle=Geometry::mag(delta)/factory->rotateFactor;
			if(angle!=Scalar(0))
				rotation.leftMultiply(NavTrackerState::rotate(NavTrackerState::Rotation::rotateAxis(axis,angle)));
			
			NavTrackerState t=preScale;
			t*=rotation;
			t*=postScale;
			setNavigationTransformation(t);
			break;
			}
		
		case SPINNING:
			{
			/* Calculate incremental rotation: */
			rotation.leftMultiply(NavTrackerState::rotate(NavTrackerState::Rotation::rotateScaledAxis(spinAngularVelocity*getFrameTime())));
			
			NavTrackerState t=preScale;
			t*=rotation;
			t*=postScale;
			setNavigationTransformation(t);
			
			scheduleUpdate(getApplicationTime()+1.0/125.0);
			
			break;
			}
		
		case PANNING:
			{
			/* Update the navigation transformation: */
			NavTrackerState t=NavTrackerState::translate(currentPos-motionStart);
			t*=preScale;
			setNavigationTransformation(t);
			break;
			}
		
		case DOLLYING:
			{
			/* Calculate the current dollying direction: */
			Scalar viewport[4];
			ONTransform screenT=getMouseScreenTransform(mouseAdapter,viewport);
			Vector dollyingDirection=screenT.transform(factory->screenDollyingDirection);
			
			/* Update the navigation transformation: */
			Scalar dollyDist=((currentPos-motionStart)*dollyingDirection)/factory->dollyFactor;
			NavTrackerState t=NavTrackerState::translate(dollyDirection*dollyDist);
			t*=preScale;
			setNavigationTransformation(t);
			break;
			}
		
		case SCALING:
			{
			/* Calculate the current scaling direction: */
			Scalar viewport[4];
			ONTransform screenT=getMouseScreenTransform(mouseAdapter,viewport);
			Vector scalingDirection=screenT.transform(factory->screenScalingDirection);
			
			/* Update the navigation transformation: */
			Scalar scale=((currentPos-motionStart)*scalingDirection)/factory->scaleFactor;
			NavTrackerState t=preScale;
			t*=NavTrackerState::scale(Math::exp(scale));
			t*=postScale;
			setNavigationTransformation(t);
			break;
			}
		
		case DOLLYING_WHEEL:
			{
			/* Update the navigation transformation: */
			Scalar scale=currentValue;
			currentWheelScale+=factory->wheelDollyFactor*scale;
			NavTrackerState t=NavTrackerState::translate(dollyDirection*currentWheelScale);
			t*=preScale;
			setNavigationTransformation(t);
			break;
			}
		
		case SCALING_WHEEL:
			{
			/* Update the navigation transformation: */
			Scalar scale=currentValue;
			currentWheelScale*=Math::pow(factory->wheelScaleFactor,scale);
			NavTrackerState t=preScale;
			t*=NavTrackerState::scale(currentWheelScale);
			t*=postScale;
			setNavigationTransformation(t);
			break;
			}
		
		default:
			;
		}
	}