Esempio n. 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;
		}
	}
void TwoRayTransformTool::frame(void)
	{
	/* Check if the device is currently dragging a ray: */
	if(active)
		{
		/* Calculate the device's ray equation in navigational coordinates: */
		rays[numRays]=sourceDevice->getRay();
		rays[numRays].transform(getInverseNavigationTransformation());
		
		/* Check if there are two rays (one final and one intermediate): */
		if(numRays==1)
			{
			/* Calculate the "intersection" point between the two rays: */
			Geometry::Matrix<Scalar,3,3> a;
			Geometry::ComponentArray<Scalar,3> b;
			Vector bin=rays[0].getDirection()^rays[1].getDirection();
			for(int i=0;i<3;++i)
				{
				a(i,0)=rays[0].getDirection()[i];
				a(i,1)=-rays[1].getDirection()[i];
				a(i,2)=bin[i];
				b[i]=rays[1].getOrigin()[i]-rays[0].getOrigin()[i];
				}
			Geometry::ComponentArray<Scalar,3> x=b/a;
			intersection=Geometry::mid(rays[0](x[0]),rays[1](x[1]));
			}
		}
	if(numRays>=(active?1:2))
		{
		/* Set the transformed device's position and orientation: */
		transformedDevice->setDeviceRay(sourceDevice->getDeviceRayDirection(),Scalar(0));
		transformedDevice->setTransformation(ONTransform(getNavigationTransformation().transform(intersection)-Point::origin,sourceDevice->getTransformation().getRotation()));
		}
	}
void PlaneSnapInputDeviceTool::frame(void)
	{
	if(draggingPoint)
		{
		/* Set the position of the currently dragged point: */
		selectedPoints[numSelectedPoints-1]=getInverseNavigationTransformation().transform(getInteractionPosition());
		}
	}
void PlaneSnapInputDeviceTool::buttonCallback(int,InputDevice::ButtonCallbackData* cbData)
	{
	if(cbData->newButtonState) // Button has just been pressed
		{
		/* Try activating the tool: */
		if(interactionDevice->isRayDevice())
			{
			/* Pick a virtual input device using ray selection: */
			activate(calcInteractionRay());
			}
		else
			{
			/* Pick a virtual input device using point selection: */
			activate(getInteractionPosition());
			}
		
		/* Check if the tool was activated: */
		if(isActive())
			{
			/* Check if there are currently three selected points: */
			if(numSelectedPoints==3)
				{
				/* Snap the selected virtual input device to the plane defined by the three selected points: */
				Vector y=Geometry::cross(selectedPoints[1]-selectedPoints[0],selectedPoints[2]-selectedPoints[0]);
				Scalar offset=(selectedPoints[0]*y+selectedPoints[1]*y+selectedPoints[2]*y)/Scalar(3);
				Vector x=Geometry::normal(y);
				Point devicePos=getInverseNavigationTransformation().transform(getGrabbedDevice()->getPosition());
				Scalar lambda=(offset-devicePos*y)/Geometry::sqr(y);
				devicePos+=y*lambda;
				NavTransform dt=NavTransform(devicePos-Point::origin,NavTransform::Rotation::fromBaseVectors(x,y),Scalar(1));
				dt.leftMultiply(getNavigationTransformation());
				getGrabbedDevice()->setTransformation(TrackerState(dt.getTranslation(),dt.getRotation()));
				}
			
			/* Deactivate the tool again: */
			deactivate();
			}
		else
			{
			/* Start dragging another selection point: */
			if(numSelectedPoints==3)
				numSelectedPoints=0;
			draggingPoint=true;
			++numSelectedPoints;
			}
		}
	else // Button has just been released
		{
		/* Stop dragging a selection point: */
		draggingPoint=false;
		}
	}
Esempio n. 5
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 SixAxisSurfaceNavigationTool::initNavState(void)
	{
	/* Set up a physical navigation frame around the main viewer's current head position: */
	headPos=getMainViewer()->getHeadPosition();
	calcPhysicalFrame(headPos);
	
	/* Calculate the initial environment-aligned surface frame in navigation coordinates: */
	surfaceFrame=getInverseNavigationTransformation()*physicalFrame;
	NavTransform newSurfaceFrame=surfaceFrame;
	
	/* Align the initial frame with the application's surface: */
	AlignmentData ad(surfaceFrame,newSurfaceFrame,factory->probeSize,factory->maxClimb);
	align(ad,angles[0],angles[1],angles[2]);
	
	/* If flying is allowed and the initial surface frame was above the surface, lift it back up: */
	Scalar z=newSurfaceFrame.inverseTransform(surfaceFrame.getOrigin())[2];
	if(!factory->canFly||z<factory->probeSize)
		z=factory->probeSize;
	newSurfaceFrame*=NavTransform::translate(Vector(Scalar(0),Scalar(0),z));
	
	/* Apply the initial navigation state: */
	surfaceFrame=newSurfaceFrame;
	applyNavState();
	}
void ClipPlaneManager::clipRay(bool physical,Ray& ray,Scalar& lambdaMax) const
	{
	/* Calculate the ray interval inside all clipping planes: */
	Scalar lambda1=Scalar(0);
	Scalar lambda2=lambdaMax;
	for(const ClipPlaneListItem* cpPtr=firstClipPlane;cpPtr!=0;cpPtr=cpPtr->succ)
		if(cpPtr->isEnabled())
			{
			/* Get the clipping plane's plane equation in the same coordinate system as the ray's: */
			Plane plane=cpPtr->getPlane();
			if(physical&&!cpPtr->physical)
				{
				/* Transform the clipping plane to physical space: */
				plane.transform(getNavigationTransformation());
				}
			else if(!physical&&cpPtr->physical)
				{
				/* Transform the clipping plane to navigational space: */
				plane.transform(getInverseNavigationTransformation());
				}
			
			/* Intersect the plane and the ray: */
			Scalar divisor=plane.getNormal()*ray.getDirection();
			if(divisor!=Scalar(0))
				{
				Scalar lambda=(plane.getOffset()-plane.getNormal()*ray.getOrigin())/divisor;
				
				/* Check if the ray enters or exits the clipping plane's half-space: */
				if(divisor<Scalar(0))
					{
					/* Ray exits: */
					if(lambda2>lambda)
						lambda2=lambda;
					}
				else
					{
					/* Ray enters: */
					if(lambda1<lambda)
						lambda1=lambda;
					}
				}
			}
	
	/* Adjust the ray: */
	if(lambda1<lambda2)
		{
		if(lambda1>Scalar(0))
			{
			/* Adjust the ray's origin: */
			ray.setOrigin(ray(lambda1));
			lambda2-=lambda1;
			}
		
		/* Adjust the maximum ray intercept: */
		lambdaMax=lambda2;
		}
	else
		{
		/* Invalidate the ray: */
		lambdaMax=Scalar(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);
					}
				}
			}
		}
	}