void SixDofWithScaleNavigationTool::buttonCallback(int buttonSlotIndex,InputDevice::ButtonCallbackData* cbData)
	{
	switch(buttonSlotIndex)
		{
		case 0:
			if(cbData->newButtonState) // Button has just been pressed
				{
				if(navigationMode==IDLE&&activate())
					{
					/* Decide whether to go to moving or scaling mode: */
					if(Geometry::sqrDist(getButtonDevicePosition(0),getButtonDevicePosition(1))<=factory->scaleDeviceDistance2) // Want to scale
						{
						/* Determine the scaling center and initial scale: */
						scalingCenter=getButtonDevicePosition(1);
						Vector scaleDirection=getButtonDeviceTransformation(1).transform(factory->deviceScaleDirection);
						initialScale=getButtonDevicePosition(0)*scaleDirection;
						
						/* Initialize the navigation transformations: */
						preScale=NavTrackerState::translateFromOriginTo(scalingCenter);
						postScale=NavTrackerState::translateToOriginFrom(scalingCenter);
						postScale*=getNavigationTransformation();
						
						/* Go from MOVING to SCALING mode: */
						navigationMode=SCALING;
						}
					else // Want to move
						{
						/* Initialize the navigation transformations: */
						preScale=Geometry::invert(getDeviceTransformation(0));
						preScale*=getNavigationTransformation();
						
						/* Go from IDLE to MOVING mode: */
						navigationMode=MOVING;
						}
					}
				}
			else // Button has just been released
				{
				/* Deactivate this tool: */
				deactivate();
				
				/* Go from MOVING or SCALING to IDLE mode: */
				navigationMode=IDLE;
				}
			
			break;
		
		case 1:
			/* Pass the button event to the virtual input device: */
			buttonDevice->setButtonState(0,cbData->newButtonState);
			
			break;
		}
	}
void SixDofWithScaleNavigationTool::frame(void)
	{
	/* Act depending on this tool's current state: */
	switch(navigationMode)
		{
		case IDLE:
			/* Do nothing */
			break;
		
		case MOVING:
			{
			/* Compose the new navigation transformation: */
			NavTrackerState navigation=getButtonDeviceTransformation(0);
			navigation*=preScale;
			
			/* Update Vrui's navigation transformation: */
			setNavigationTransformation(navigation);
			break;
			}
		
		case SCALING:
			{
			/* Compose the new navigation transformation: */
			NavTrackerState navigation=preScale;
			Vector scaleDirection=getButtonDeviceTransformation(1).transform(factory->deviceScaleDirection);
			Scalar currentScale=Math::exp((getButtonDevicePosition(0)*scaleDirection-initialScale)/factory->scaleFactor);
			navigation*=NavTrackerState::scale(currentScale);
			navigation*=postScale;
			
			/* Update Vrui's navigation transformation: */
			setNavigationTransformation(navigation);
			break;
			}
		}
	
	/* Update the virtual input device: */
	InputDevice* device=getButtonDevice(1);
	buttonDevice->setTransformation(device->getTransformation());
	buttonDevice->setDeviceRayDirection(device->getDeviceRayDirection());
	}
void SixDofWithScaleNavigationTool::display(GLContextData& contextData) const
	{
	/* Get a pointer to the context entry: */
	SixDofWithScaleNavigationToolFactory::DataItem* dataItem=contextData.retrieveDataItem<SixDofWithScaleNavigationToolFactory::DataItem>(factory);
	
	/* Translate coordinate system to scaling device's position and orientation: */
	glPushMatrix();
	glMultMatrix(getButtonDeviceTransformation(1));
	
	/* Execute the tool model display list: */
	glCallList(dataItem->modelListId);
	
	/* Go back to physical coordinate system: */
	glPopMatrix();
	}
示例#4
0
void GridEditor::EditTool::glRenderActionTransparent(GLContextData& contextData) const
	{
	glPushAttrib(GL_ENABLE_BIT|GL_LINE_BIT|GL_POLYGON_BIT);
	
	/* Retrieve context entry: */
	DataItem* dataItem=contextData.retrieveDataItem<DataItem>(application);
	
	/* Render the influence sphere: */
	glDisable(GL_LIGHTING);
	
	glPushMatrix();
	glMultMatrix(getButtonDeviceTransformation(0));
	glScale(influenceRadius);
	glCallList(dataItem->influenceSphereDisplayListId);
	glPopMatrix();
	
	glPopAttrib();
	}
示例#5
0
void GridEditor::EditTool::buttonCallback(int buttonSlotIndex,Vrui::InputDevice::ButtonCallbackData* cbData)
	{
	if(buttonSlotIndex==0)
		{
		/* Activate or deactivate the tool: */
		active=cbData->newButtonState;
		
		if(active)
			{
			/* Initialize the tool's position and orientation in model coordinates: */
			lastTrackerState=getButtonDeviceTransformation(0);
			lastTrackerState.leftMultiply(Vrui::getInverseNavigationTransformation());
			}
		}
	else if(cbData->newButtonState)
		{
		/* Switch editing modes: */
		switch(buttonSlotIndex)
			{
			case 1:
				editMode=ADD;
				break;
			
			case 2:
				editMode=SUBTRACT;
				break;
			
			case 3:
				editMode=SMOOTH;
				break;
			
			case 4:
				editMode=DRAG;
				break;
			}
		
		/* Update the tool mode dialog: */
		editModeBox->setSelectedToggle(buttonSlotIndex-1);
		}
	}
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);
		}
	}
示例#7
0
void FlyNavigationTool::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=ts.transform(factory->flyDirection);
		v*=-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(getNextAnimationTime());
		}
	}
void WandNavigationTool::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:
						/* Try activating this tool: */
						if(activate())
							{
							/* Initialize the navigation transformations: */
							preScale=Geometry::invert(getButtonDeviceTransformation(0));
							preScale*=getNavigationTransformation();
							
							/* Go from IDLE to MOVING mode: */
							navigationMode=MOVING;
							}
						break;
					
					case PASSTHROUGH:
						/* Remember that the main button is pressed: */
						navigationMode=PASSTHROUGH_MOVING;
						break;
					
					case SCALING_PAUSED:
						/* Determine the scaling center and direction: */
						scalingCenter=getButtonDevicePosition(0);
						scalingDirection=getButtonDeviceRayDirection(0);
						initialScale=scalingCenter*scalingDirection;
						
						/* Initialize the transformation parts: */
						preScale=NavTrackerState::translateFromOriginTo(scalingCenter);
						postScale=NavTrackerState::translateToOriginFrom(scalingCenter);
						postScale*=getNavigationTransformation();
						
						/* Go from SCALING_PAUSED to SCALING mode: */
						navigationMode=SCALING;
						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 PASSTHROUGH_MOVING:
						/* Remember that the main button is released: */
						navigationMode=PASSTHROUGH;
						break;
					
					case SCALING:
						/* Pause scaling until button is pressed again: */
						
						/* Go from SCALING to SCALING_PAUSED mode: */
						navigationMode=SCALING_PAUSED;
						break;
					
					case MOVING:
						/* Deactivate this tool: */
						deactivate();
						
						/* Go from MOVING to IDLE mode: */
						navigationMode=IDLE;
						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:
						/* Pass the button event to the virtual input device: */
						buttonDevice->setButtonState(0,true);
						
						/* Go to pass-through mode: */
						navigationMode=PASSTHROUGH;
						break;
					
					case MOVING:
						/* Determine the scaling center and direction: */
						scalingCenter=getButtonDevicePosition(0);
						scalingDirection=getButtonDeviceRayDirection(0);
						initialScale=scalingCenter*scalingDirection;
						
						/* Initialize the transformation parts: */
						preScale=NavTrackerState::translateFromOriginTo(scalingCenter);
						postScale=NavTrackerState::translateToOriginFrom(scalingCenter);
						postScale*=getNavigationTransformation();
						
						/* Go from MOVING to SCALING mode: */
						navigationMode=SCALING;
						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 PASSTHROUGH:
						/* Pass the button event to the virtual input device: */
						buttonDevice->setButtonState(0,false);
						
						/* Go to idle mode: */
						navigationMode=IDLE;
						break;
					
					case PASSTHROUGH_MOVING:
						/* Pass the button event to the virtual input device: */
						buttonDevice->setButtonState(0,false);
						
						/* Try activating this tool: */
						if(activate())
							{
							/* Initialize the navigation transformations: */
							preScale=Geometry::invert(getButtonDeviceTransformation(0));
							preScale*=getNavigationTransformation();
							
							/* Go to MOVING mode: */
							navigationMode=MOVING;
							}
						else
							{
							/* Go to idle mode: */
							navigationMode=IDLE;
							}
						break;
					
					case SCALING:
						/* Initialize the transformation parts: */
						preScale=Geometry::invert(getButtonDeviceTransformation(0));
						preScale*=getNavigationTransformation();
						
						/* Go from SCALING to MOVING mode: */
						navigationMode=MOVING;
						break;
					
					case SCALING_PAUSED:
						/* Deactivate this tool: */
						deactivate();
						
						/* Go from SCALING_PAUSED to IDLE mode: */
						navigationMode=IDLE;
						break;
					
					default:
						/* This shouldn't happen; just ignore the event */
						break;
					}
				}
			break;
		}
	}
示例#9
0
void GridEditor::EditTool::frame(void)
	{
	/* Bail out if the tool is not active: */
	if(!active)
		return;
	
	/* Update the tool's position and radius in model coordinates: */
	Vrui::NavTrackerState newTrackerState=getButtonDeviceTransformation(0);
	newTrackerState.leftMultiply(Vrui::getInverseNavigationTransformation());
	
	/* Update the brush position and size in model coordinates: */
	modelCenter=Point(newTrackerState.getOrigin());
	modelRadius=float(influenceRadius*newTrackerState.getScaling());
	
	/* Determine the subdomain of the grid affected by the brush: */
	EditableGrid::Index min,max;
	for(int i=0;i<3;++i)
		{
		min[i]=int(Math::floor((modelCenter[i]-modelRadius-fudgeSize)/grid->getCellSize(i)));
		if(min[i]<1)
			min[i]=1;
		max[i]=int(Math::ceil((modelCenter[i]+modelRadius+fudgeSize)/grid->getCellSize(i)));
		if(max[i]>grid->getNumVertices(i)-1)
			max[i]=grid->getNumVertices(i)-1;
		}
	
	/* Update the grid: */
	float minr2=modelRadius>fudgeSize?Math::sqr(modelRadius-fudgeSize):0.0f;
	float maxr2=Math::sqr(modelRadius+fudgeSize);
	switch(editMode)
		{
		case ADD:
			{
			for(EditableGrid::Index v=min;v[0]<max[0];v.preInc(min,max))
				{
				Point p;
				float dist=0.0f;
				for(int i=0;i<3;++i)
					{
					p[i]=float(v[i])*grid->getCellSize(i);
					dist+=Math::sqr(modelCenter[i]-p[i]);
					}
				if(dist<maxr2)
					{
					float val;
					if(dist<minr2)
						val=1.0f;
					else
						val=(modelRadius+fudgeSize-Math::sqrt(dist))/(2.0f*fudgeSize);
					float oldVal=grid->getValue(v);
					if(val>oldVal)
						grid->setValue(v,val);
					}
				}
			
			grid->invalidateVertices(min,max);
			break;
			}
		
		case SUBTRACT:
			{
			for(EditableGrid::Index v=min;v[0]<max[0];v.preInc(min,max))
				{
				Point p;
				float dist=0.0f;
				for(int i=0;i<3;++i)
					{
					p[i]=float(v[i])*grid->getCellSize(i);
					dist+=Math::sqr(modelCenter[i]-p[i]);
					}
				if(dist<maxr2)
					{
					float val;
					if(dist<minr2)
						val=0.0f;
					else
						val=1.0f-(modelRadius+fudgeSize-Math::sqrt(dist))/(2.0f*fudgeSize);
					float oldVal=grid->getValue(v);
					if(val<oldVal)
						grid->setValue(v,val);
					}
				}
			
			grid->invalidateVertices(min,max);
			break;
			}
		
		case SMOOTH:
			{
			for(int i=0;i<3;++i)
				{
				if(min[i]==0)
					++min[i];
				if(max[i]==grid->getNumVertices(i))
					--max[i];
				}
			for(EditableGrid::Index v=min;v[0]<max[0];v.preInc(min,max))
				{
				Point p;
				float dist=0.0f;
				for(int i=0;i<3;++i)
					{
					p[i]=float(v[i])*grid->getCellSize(i);
					dist+=Math::sqr(modelCenter[i]-p[i]);
					}
				if(dist<maxr2)
					{
					float avgVal=0.0f;
					EditableGrid::Index i;
					for(i[0]=v[0]-1;i[0]<=v[0]+1;++i[0])
						for(i[1]=v[1]-1;i[1]<=v[1]+1;++i[1])
							for(i[2]=v[2]-1;i[2]<=v[2]+1;++i[2])
								avgVal+=grid->getValue(i);
					avgVal/=27.0f;
					if(dist<minr2)
						newValues(v)=avgVal;
					else
						{
						float w=(modelRadius+fudgeSize-Math::sqrt(dist))/(2.0f*fudgeSize);
						newValues(v)=avgVal*w+grid->getValue(v)*(1.0f-w);
						}
					}
				else
					newValues(v)=grid->getValue(v);
				}
			
			for(EditableGrid::Index v=min;v[0]<max[0];v.preInc(min,max))
				grid->setValue(v,newValues(v));
			
			grid->invalidateVertices(min,max);
			
			/* Request another frame to continue smoothing: */
			Vrui::scheduleUpdate(Vrui::getApplicationTime()+1.0/125.0);
			break;
			}
		
		case DRAG:
			{
			/* Calculate the incremental tool transformation since the last frame: */
			Vrui::NavTrackerState t=lastTrackerState;
			t*=Geometry::invert(newTrackerState);
			Geometry::OrthogonalTransformation<float,3> pt(t);
			
			float r2=Math::sqr(modelRadius);
			for(EditableGrid::Index v=min;v[0]<max[0];v.preInc(min,max))
				{
				Point p;
				float dist=0.0f;
				for(int i=0;i<3;++i)
					{
					p[i]=float(v[i])*grid->getCellSize(i);
					dist+=Math::sqr(modelCenter[i]-p[i]);
					}
				if(dist<r2)
					{
					/* Compute the dragged position: */
					Point dp=pt.transform(p);
					float w=Math::sqrt(dist)/modelRadius;
					dp=Geometry::affineCombination(dp,p,w);
					
					/* Look up the grid value at the dragged position: */
					float dragVal=grid->getValue(dp);
					newValues(v)=dragVal;
					}
				else
					newValues(v)=grid->getValue(v);
				}
			
			for(EditableGrid::Index v=min;v[0]<max[0];v.preInc(min,max))
				grid->setValue(v,newValues(v));
			
			grid->invalidateVertices(min,max);
			break;
			}
		}
	
	lastTrackerState=newTrackerState;
	}
示例#10
0
void ComeHitherNavigationTool::buttonCallback(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=getButtonDeviceTransformation(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);
					}
				}
			}
		}
	}