示例#1
0
Point WalkNavigationTool::projectToFloor(const Point& p)
{
    /* Project the given point onto the floor plane along the up direction: */
    const Vector& normal=getFloorPlane().getNormal();
    Scalar lambda=(getFloorPlane().getOffset()-p*normal)/(getUpDirection()*normal);
    return p+getUpDirection()*lambda;
}
示例#2
0
GLMotif::WidgetArranger::Transformation UIManagerSpherical::calcTopLevelTransformInternal(GLMotif::Widget* topLevelWidget,const Point& hotSpot) const
	{
	/* Project the given hot spot onto the sphere: */
	Vector d=hotSpot-sphere.getCenter();
	Scalar dLen=d.mag();
	if(dLen==Scalar(0))
		{
		d=getForwardDirection();
		dLen=d.mag();
		}
	Scalar r=sphere.getRadius();
	if(alignSecant)
		{
		/* Adjust the projection radius such that the widget is halfway in and out of the sphere: */
		const GLMotif::Box& exterior=topLevelWidget->getExterior();
		Scalar widgetSize=Scalar(Math::sqr(exterior.size[0])+Math::sqr(exterior.size[1]));
		r=Math::sqrt(Math::sqr(r)-widgetSize*Scalar(0.25));
		}
	Point sphereHotSpot=sphere.getCenter()+d*(r/dLen);
	
	/* Calculate the widget transformation: */
	Vector x=d^getUpDirection();
	if(x.mag()==Scalar(0))
		x=getForwardDirection()^getUpDirection();
	Vector y=x^d;
	Transformation result(sphereHotSpot-Point::origin,Rotation::fromBaseVectors(x,y),Scalar(1));
	
	/* Align the widget's hot spot with the given hot spot: */
	GLMotif::Vector widgetHotSpot=topLevelWidget->calcHotSpot();
	result*=Transformation::translate(-Transformation::Vector(widgetHotSpot.getXyzw()));
	
	result.renormalize();
	return result;
	}
TrackerState SixAxisTransformToolFactory::Configuration::getHomePosition(void) const
{
    if(homePosition.isSpecified())
    {
        /* Return the configured home position: */
        return homePosition.getValue();
    }
    else
    {
        /* Calculate the home position from current display center and environment orientation: */
        Vector x=getForwardDirection()^getUpDirection();
        Vector y=getUpDirection()^x;
        return TrackerState(getDisplayCenter()-Point::origin,Rotation::fromBaseVectors(x,y));
    }
}
void LookAtTransformationElement::calcMatrix(Matrix &result) const
{
    MatrixLookAt(result, 
                 getEyePosition(), 
                 getLookAtPosition(), 
                 getUpDirection()   );
}
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;
    }
}
示例#6
0
void UIManagerSpherical::projectDevice(InputDevice* device) const
	{
	/* Get the device's ray: */
	Ray ray=device->getRay();
	
	/* Check if the line defined by the device's ray intersects the sphere: */
	Scalar d2=Geometry::sqr(ray.getDirection());
	Vector oc=ray.getOrigin()-sphere.getCenter();
	Scalar ph=(oc*ray.getDirection());
	Scalar det=Math::sqr(ph)-(Geometry::sqr(oc)-Math::sqr(sphere.getRadius()))*d2;
	Scalar lambda(0);
	Point devicePos;
	Vector y;
	if(det>=Scalar(0))
		{
		/* Calculate the point where the line exits the sphere: */
		det=Math::sqrt(det);
		lambda=(-ph+det)/d2; // Second intersection
		devicePos=ray(lambda);
		y=devicePos-sphere.getCenter();
		}
	else
		{
		/* Project the device's position onto the sphere: */
		y=device->getPosition()-sphere.getCenter();
		Scalar yLen=y.mag();
		if(yLen==Scalar(0))
			{
			y=getForwardDirection();
			yLen=y.mag();
			}
		devicePos=sphere.getCenter()+y*(sphere.getRadius()/yLen);
		}
	
	/* Calculate a device orientation such that the y axis is normal to the sphere and points outwards: */
	Vector x=y^getUpDirection();
	if(x.mag()==Scalar(0))
		x=getForwardDirection()^getUpDirection();
	
	/* Set the device transformation: */
	device->setTransformation(TrackerState(devicePos-Point::origin,Rotation::fromBaseVectors(x,y)));
	
	/* Update the device's ray: */
	device->setDeviceRay(device->getTransformation().inverseTransform(ray.getDirection()),-lambda);
	}
示例#7
0
void PhysicalPlayer::applyTurning(double amount) {
    if(!onGround) return;
    
    rigidBody->activate();
    
    double constant = GET_SETTING("physics.constant.turn", 1.0);
    double centripetalConstant
        = GET_SETTING("physics.constant.centripetal", 1.0);
    //double leanConstant = GET_SETTING("physics.constant.lean", 1.0);
    
    Math::Matrix matrix = getTransformation();
    Math::Point forwardAxis = matrix * Math::Point(0.0, 0.0, 1.0, 0.0);
    Math::Point centripetalAxis = matrix * Math::Point(-1.0, 0.0, 0.0, 0.0);
    
    forwardAxis.normalize();
    centripetalAxis.normalize();
    
    double speed = getLinearVelocity().length();

	#if 0
    // turn in the opposite direction when travelling backwards
    if (getLinearVelocity().dotProduct(forwardAxis) < 0) {
        speed = -speed;
    }
	#endif

	double speedFactor = GET_SETTING("physics.turning.speedfactor", 0.5);
	double speedThreshhold = GET_SETTING("physics.turning.speedthreshhold", 15.0);
	double falloffFactor = GET_SETTING("physics.turning.fallofffactor", 0.25);

	double turning_factor = GET_SETTING("physics.turning.constant", 1.0);

	if (speed <= speedThreshhold) {
		turning_factor += sqrt(speed/speedThreshhold)*(speed*speedFactor);
	}
	else {
		turning_factor += (speedThreshhold*speedFactor)*(1.0/(1.0+(speed-speedThreshhold)*falloffFactor));
	}
	
	 // turn in the opposite direction when travelling backwards
    if (getLinearVelocity().dotProduct(forwardAxis) < 0) {
        turning_factor = -turning_factor;
    }
    
    if(getSliding()) {
        centripetalConstant *= GET_SETTING("physics.slipstate.centripetalfactor", 1.0);
        constant *= GET_SETTING("physics.slipstate.turnfactor", 1.0);
    }
    
    applyForce(centripetalAxis * centripetalConstant * turning_factor * amount);
    applyTorque(-getUpDirection() * constant * turning_factor * amount);
    
    // twist the car in response to a sharp turn
    //applyTorque(getFrontDirection() * leanConstant * turning_factor * amount);

	updatePhysicalInfo();
}
示例#8
0
ONTransform UIManagerSpherical::calcUITransform(const Point& point) const
	{
	/* Project the given point onto the sphere: */
	Vector d=point-sphere.getCenter();
	Scalar dLen=d.mag();
	if(dLen==Scalar(0))
		{
		d=getForwardDirection();
		dLen=d.mag();
		}
	Point spherePoint=sphere.getCenter()+d*(sphere.getRadius()/dLen);
	
	/* Calculate the UI transformation: */
	Vector x=d^getUpDirection();
	if(x.mag()==Scalar(0))
		x=getForwardDirection()^getUpDirection();
	Vector y=x^d;
	return ONTransform(spherePoint-Point::origin,Rotation::fromBaseVectors(x,y));
	}
示例#9
0
void gpp::CameraComponent::move(const gep::vec3& delta)
{
    gep::vec3 pos =m_transform.getWorldPosition();

    pos += getUpDirection() * delta.z;
    pos += getRightDirection() * delta.x;
    pos += getViewDirection() * delta.y;

    m_pCamera->setPosition(pos);
    m_transform.setPosition(pos);
}
示例#10
0
WalkNavigationToolFactory::WalkNavigationToolFactory(ToolManager& toolManager)
    :ToolFactory("WalkNavigationTool",toolManager),
     centerOnActivation(false),
     centerPoint(getDisplayCenter()),
     moveSpeed(getDisplaySize()),
     innerRadius(getDisplaySize()*Scalar(0.5)),outerRadius(getDisplaySize()*Scalar(0.75)),
     centerViewDirection(getForwardDirection()),
     rotateSpeed(Math::rad(Scalar(120))),
     innerAngle(Math::rad(Scalar(30))),outerAngle(Math::rad(Scalar(120))),
     drawMovementCircles(true),
     movementCircleColor(0.0f,1.0f,0.0f)
{
    /* Initialize tool layout: */
    layout.setNumButtons(1);

    /* Insert class into class hierarchy: */
    ToolFactory* navigationToolFactory=toolManager.loadClass("NavigationTool");
    navigationToolFactory->addChildClass(this);
    addParentClass(navigationToolFactory);

    /* Load class settings: */
    Misc::ConfigurationFileSection cfs=toolManager.getToolClassSection(getClassName());
    centerOnActivation=cfs.retrieveValue<bool>("./centerOnActivation",centerOnActivation);
    centerPoint=cfs.retrieveValue<Point>("./centerPoint",centerPoint);
    centerPoint=getFloorPlane().project(centerPoint);
    moveSpeed=cfs.retrieveValue<Scalar>("./moveSpeed",moveSpeed);
    innerRadius=cfs.retrieveValue<Scalar>("./innerRadius",innerRadius);
    outerRadius=cfs.retrieveValue<Scalar>("./outerRadius",outerRadius);
    centerViewDirection=cfs.retrieveValue<Vector>("./centerViewDirection",centerViewDirection);
    centerViewDirection-=getUpDirection()*((centerViewDirection*getUpDirection())/Geometry::sqr(getUpDirection()));
    centerViewDirection.normalize();
    rotateSpeed=Math::rad(cfs.retrieveValue<Scalar>("./rotateSpeed",Math::deg(rotateSpeed)));
    innerAngle=Math::rad(cfs.retrieveValue<Scalar>("./innerAngle",Math::deg(innerAngle)));
    outerAngle=Math::rad(cfs.retrieveValue<Scalar>("./outerAngle",Math::deg(outerAngle)));
    drawMovementCircles=cfs.retrieveValue<bool>("./drawMovementCircles",drawMovementCircles);
    movementCircleColor=cfs.retrieveValue<Color>("./movementCircleColor",movementCircleColor);

    /* Set tool class' factory pointer: */
    WalkNavigationTool::factory=this;
}
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);
					}
				}
			}
		}
	}
示例#12
0
void SceneGraphViewer::display(GLContextData& contextData) const
	{
	/* Save OpenGL state: */
	glPushAttrib(GL_ENABLE_BIT|GL_LIGHTING_BIT|GL_TEXTURE_BIT);
	
	/* Go to navigational coordinates: */
	glPushMatrix();
	glLoadIdentity();
	glMultMatrix(getDisplayState(contextData).modelviewNavigational);
	
	/* Create a render state to traverse the scene graph: */
	SceneGraph::GLRenderState renderState(contextData,getHeadPosition(),getNavigationTransformation().inverseTransform(getUpDirection()));
	
	/* Traverse the scene graph: */
	root->glRenderAction(renderState);
	
	/* Restore OpenGL state: */
	glPopMatrix();
	glPopAttrib();
	}
void ViewpointFileNavigationTool::buttonCallback(int,InputDevice::ButtonCallbackData* cbData)
	{
	if(cbData->newButtonState) // Activation button has just been pressed
		{
		#if 0
		/* Set the next saved viewpoint if the tool can be activated: */
		if(!viewpoints.empty()&&activate())
			{
			/* Compute the appropriate navigation transformation from the next viewpoint: */
			const Viewpoint& v=viewpoints[nextViewpointIndex];
			NavTransform nav=NavTransform::identity;
			nav*=NavTransform::translateFromOriginTo(getDisplayCenter());
			nav*=NavTransform::rotate(Rotation::fromBaseVectors(Geometry::cross(getForwardDirection(),getUpDirection()),getForwardDirection()));
			nav*=NavTransform::scale(getDisplaySize()/Math::exp(v.size)); // Scales are interpolated logarithmically
			nav*=NavTransform::rotate(Geometry::invert(Rotation::fromBaseVectors(Geometry::cross(v.forward,v.up),v.forward)));
			nav*=NavTransform::translateToOriginFrom(v.center);
			
			/* Set the viewpoint: */
			setNavigationTransformation(nav);
			
			/* Go to the next viewpoint: */
			++nextViewpointIndex;
			if(nextViewpointIndex==viewpoints.size())
				nextViewpointIndex=0U;
			
			/* Deactivate the tool: */
			deactivate();
			}
		#else
		/* Start animating the viewpoint if there are spline segments and the tool can be activated: */
		if(!splines.empty())
			{
			if(paused&&activate())
				{
				/* Unpause the animation: */
				paused=false;
				parameter-=Scalar(getFrameTime())*speed;
				}
			else if(isActive())
				{
				/* Pause the animation: */
				paused=true;
				deactivate();
				}
			else if(activate())
				{
				/* Animate from the beginning: */
				paused=false;
				parameter=splines.front().t[0]-Scalar(getFrameTime())*speed;
				if(positionSlider!=0)
					positionSlider->setValue(parameter);
				}
			}
		#endif
		}
	}
bool ViewpointFileNavigationTool::navigate(Scalar parameter)
	{
	/* Find the spline segment containing the given parameter: */
	int l=0;
	int r=splines.size();
	while(r-l>1)
		{
		int m=(l+r)>>1;
		if(parameter>=splines[m].t[0])
			l=m;
		else
			r=m;
		}
	const SplineSegment& s=splines[l];
	if(parameter>=s.t[0]&&parameter<=s.t[1])
		{
		/* Evaluate the spline segment at the current time: */
		Scalar t=(parameter-s.t[0])/(s.t[1]-s.t[0]);
		ControlPoint cp[6];
		for(int i=0;i<3;++i)
			interpolate(s.p[i],s.p[i+1],t,cp[i]);
		for(int i=0;i<2;++i)
			interpolate(cp[i],cp[i+1],t,cp[3+i]);
		interpolate(cp[3],cp[4],t,cp[5]);

		/* Compute the appropriate navigation transformation from the next viewpoint: */
		NavTransform nav=NavTransform::identity;
		nav*=NavTransform::translateFromOriginTo(getDisplayCenter());
		nav*=NavTransform::rotate(Rotation::fromBaseVectors(Geometry::cross(getForwardDirection(),getUpDirection()),getForwardDirection()));
		nav*=NavTransform::scale(getDisplaySize()/Math::exp(cp[5].size)); // Scales are interpolated logarithmically
		nav*=NavTransform::rotate(Geometry::invert(Rotation::fromBaseVectors(Geometry::cross(cp[5].forward,cp[5].up),cp[5].forward)));
		nav*=NavTransform::translateToOriginFrom(cp[5].center);
		
		if(isActive())
			{
			/* Set the viewpoint: */
			setNavigationTransformation(nav);
			}
		else if(activate())
			{
			/* Set the viewpoint: */
			setNavigationTransformation(nav);
			
			/* Deactivate again: */
			deactivate();
			}
		
		nextViewpointIndex=l+1;
		return true;
		}
	else
		{
		/* Stop animating; spline is over: */
		nextViewpointIndex=0;
		return false;
		}
	}
void ViewpointFileNavigationTool::readViewpointFile(const char* fileName)
	{
	try
		{
		/* Open the viewpoint file: */
		Misc::File viewpointFile(fileName,"rt");
		
		if(Misc::hasCaseExtension(fileName,".views"))
			{
			/* Load all viewpoint keyframes from the file: */
			Scalar time(0);
			while(true)
				{
				/* Read the next viewpoint: */
				Scalar timeInterval;
				ControlPoint v;
				if(fscanf(viewpointFile.getFilePtr(),"%lf (%lf, %lf, %lf) %lf (%lf, %lf, %lf) (%lf, %lf, %lf)\n",&timeInterval,&v.center[0],&v.center[1],&v.center[2],&v.size,&v.forward[0],&v.forward[1],&v.forward[2],&v.up[0],&v.up[1],&v.up[2])!=11)
					break;
				
				/* Store the viewpoint: */
				time+=timeInterval;
				times.push_back(time);
				v.size=Math::log(v.size); // Sizes are interpolated logarithmically
				viewpoints.push_back(v);
				}
			
			if(viewpoints.size()>1)
				{
				/* Create a big matrix to solve the C^2 spline problem: */
				unsigned int n=viewpoints.size()-1;
				Math::Matrix A(4*n,4*n,0.0);
				Math::Matrix b(4*n,10,0.0);
				
				A(0,0)=1.0;
				writeControlPoint(viewpoints[0],b,0);
				
				double dt1=double(times[1])-double(times[0]);
				#if 1
				/* Zero velocity at start: */
				A(1,0)=-3.0/dt1;
				A(1,1)=3.0/dt1;
				#else
				/* Zero acceleration at start: */
				A(1,0)=6.0/Math::sqr(dt1);
				A(1,1)=-12.0/Math::sqr(dt1);
				A(1,2)=6.0/Math::sqr(dt1);
				#endif
				
				for(unsigned int i=1;i<n;++i)
					{
					double dt0=double(times[i])-double(times[i-1]);
					double dt1=double(times[i+1])-double(times[i]);
					A(i*4-2,i*4-3)=6.0/Math::sqr(dt0);
					A(i*4-2,i*4-2)=-12.0/Math::sqr(dt0);
					A(i*4-2,i*4-1)=6.0/Math::sqr(dt0);
					A(i*4-2,i*4+0)=-6.0/Math::sqr(dt1);
					A(i*4-2,i*4+1)=12.0/Math::sqr(dt1);
					A(i*4-2,i*4+2)=-6.0/Math::sqr(dt1);
					
					A(i*4-1,i*4-2)=-3.0/dt0;
					A(i*4-1,i*4-1)=3.0/dt0;
					A(i*4-1,i*4+0)=3/dt1;
					A(i*4-1,i*4+1)=-3/dt1;
					
					A(i*4+0,i*4-1)=1.0;
					writeControlPoint(viewpoints[i],b,i*4+0);
					
					A(i*4+1,i*4+0)=1.0;
					writeControlPoint(viewpoints[i],b,i*4+1);
					}
				
				double dtn=double(times[n])-double(times[n-1]);
				#if 1
				/* Zero velocity at end: */
				A(n*4-2,n*4-2)=-3.0/dtn;
				A(n*4-2,n*4-1)=3.0/dtn;
				#else
				/* Zero acceleration at end: */
				A(n*4-2,n*4-3)=6.0/Math::sqr(dtn);
				A(n*4-2,n*4-2)=-12.0/Math::sqr(dtn);
				A(n*4-2,n*4-1)=6.0/Math::sqr(dtn);
				#endif
				
				A(n*4-1,n*4-1)=1.0;
				writeControlPoint(viewpoints[n],b,n*4-1);
				
				/* Solve the system of equations: */
				Math::Matrix x=b/A;
				
				/* Create the spline segment list: */
				for(unsigned int i=0;i<n;++i)
					{
					SplineSegment s;
					for(int j=0;j<2;++j)
						s.t[j]=times[i+j];
					for(int cp=0;cp<4;++cp)
						{
						for(int j=0;j<3;++j)
							s.p[cp].center[j]=x(i*4+cp,j);
						s.p[cp].size=x(i*4+cp,3);
						for(int j=0;j<3;++j)
							s.p[cp].forward[j]=x(i*4+cp,4+j);
						for(int j=0;j<3;++j)
							s.p[cp].up[j]=x(i*4+cp,7+j);
						}
					splines.push_back(s);
					}
				}
			}
		else if(Misc::hasCaseExtension(fileName,".curve"))
			{
			/* Load all spline segments from the file: */
			while(true)
				{
				SplineSegment s;
				if(splines.empty())
					{
					/* Read the first control point: */
					ControlPoint cp;
					if(fscanf(viewpointFile.getFilePtr(),"(%lf, %lf, %lf) %lf (%lf, %lf, %lf) (%lf, %lf, %lf)\n",&cp.center[0],&cp.center[1],&cp.center[2],&cp.size,&cp.forward[0],&cp.forward[1],&cp.forward[2],&cp.up[0],&cp.up[1],&cp.up[2])!=10)
						break;
					cp.size=Math::log(cp.size); // Sizes are interpolated logarithmically
					viewpoints.push_back(cp);
					times.push_back(Scalar(0));
					s.t[0]=Scalar(0);
					s.p[0]=cp;
					}
				else
					{
					/* Copy the last control point from the previous segment: */
					s.t[0]=splines.back().t[1];
					s.p[0]=splines.back().p[3];
					}
				
				/* Read the segment's parameter interval: */
				double pi;
				if(fscanf(viewpointFile.getFilePtr(),"%lf\n",&pi)!=1)
					break;
				s.t[1]=s.t[0]+Scalar(pi);
				
				/* Read the intermediate control points: */
				ControlPoint m0;
				if(fscanf(viewpointFile.getFilePtr(),"(%lf, %lf, %lf) %lf (%lf, %lf, %lf) (%lf, %lf, %lf)\n",&m0.center[0],&m0.center[1],&m0.center[2],&m0.size,&m0.forward[0],&m0.forward[1],&m0.forward[2],&m0.up[0],&m0.up[1],&m0.up[2])!=10)
					break;
				m0.size=Math::log(m0.size); // Sizes are interpolated logarithmically
				s.p[1]=m0;
				ControlPoint m1;
				if(fscanf(viewpointFile.getFilePtr(),"(%lf, %lf, %lf) %lf (%lf, %lf, %lf) (%lf, %lf, %lf)\n",&m1.center[0],&m1.center[1],&m1.center[2],&m1.size,&m1.forward[0],&m1.forward[1],&m1.forward[2],&m1.up[0],&m1.up[1],&m1.up[2])!=10)
					break;
				m1.size=Math::log(m1.size); // Sizes are interpolated logarithmically
				s.p[2]=m1;
				
				/* Read the last control point: */
				ControlPoint cp;
				if(fscanf(viewpointFile.getFilePtr(),"(%lf, %lf, %lf) %lf (%lf, %lf, %lf) (%lf, %lf, %lf)\n",&cp.center[0],&cp.center[1],&cp.center[2],&cp.size,&cp.forward[0],&cp.forward[1],&cp.forward[2],&cp.up[0],&cp.up[1],&cp.up[2])!=10)
					break;
				cp.size=Math::log(cp.size); // Sizes are interpolated logarithmically
				viewpoints.push_back(cp);
				times.push_back(s.t[1]);
				s.p[3]=cp;
				
				/* Save the spline segment: */
				splines.push_back(s);
				}
			}
		else
			{
			/* Display an error message: */
			std::string message="Curve file ";
			message.append(fileName);
			message.append(" has unrecognized extension \"");
			message.append(Misc::getExtension(fileName));
			message.push_back('"');
			showErrorMessage("Curve File Animation",message.c_str());
			}
		}
	catch(std::runtime_error err)
		{
		/* Display an error message: */
		std::string message="Could not read curve file ";
		message.append(fileName);
		message.append(" due to exception ");
		message.append(err.what());
		showErrorMessage("Curve File Animation",message.c_str());
		}
	
	if(!splines.empty())
		{
		/* Start animating from the beginning: */
		paused=false;
		parameter=splines.front().t[0];
		
		/* Create playback control dialog if requested: */
		if(showGui)
			createGui();
		
		/* Start animating if requested: */
		if(autostart)
			activate();
		}
	else if(!viewpoints.empty()&&activate())
		{
		/* Go to the first viewpoint: */
		const ControlPoint& v=viewpoints[0];
		NavTransform nav=NavTransform::identity;
		nav*=NavTransform::translateFromOriginTo(getDisplayCenter());
		nav*=NavTransform::rotate(Rotation::fromBaseVectors(Geometry::cross(getForwardDirection(),getUpDirection()),getForwardDirection()));
		nav*=NavTransform::scale(getDisplaySize()/Math::exp(v.size)); // Scales are interpolated logarithmically
		nav*=NavTransform::rotate(Geometry::invert(Rotation::fromBaseVectors(Geometry::cross(v.forward,v.up),v.forward)));
		nav*=NavTransform::translateToOriginFrom(v.center);
		setNavigationTransformation(nav);
		
		deactivate();
		}
	}
示例#16
0
void WalkNavigationTool::frame(void)
{
    /* Act depending on this tool's current state: */
    if(isActive())
    {
        /* Calculate azimuth angle change based on the current viewing direction: */
        Vector viewDir=getMainViewer()->getViewDirection();
        viewDir-=getUpDirection()*((viewDir*getUpDirection())/Geometry::sqr(getUpDirection()));
        Scalar viewDir2=Geometry::sqr(viewDir);
        if(viewDir2!=Scalar(0))
        {
            /* Calculate the rotation speed: */
            Scalar viewAngleCos=(viewDir*factory->centerViewDirection)/Math::sqrt(viewDir2);
            Scalar viewAngle;
            if(viewAngleCos>Scalar(1)-Math::Constants<Scalar>::epsilon)
                viewAngle=Scalar(0);
            else if(viewAngleCos<Scalar(-1)+Math::Constants<Scalar>::epsilon)
                viewAngle=Math::Constants<Scalar>::pi;
            else
                viewAngle=Math::acos(viewAngleCos);
            Scalar rotateSpeed=Scalar(0);
            if(viewAngle>=factory->outerAngle)
                rotateSpeed=factory->rotateSpeed;
            else if(viewAngle>factory->innerAngle)
                rotateSpeed=factory->rotateSpeed*(viewAngle-factory->innerAngle)/(factory->outerAngle-factory->innerAngle);
            Vector x=factory->centerViewDirection^getUpDirection();
            if(viewDir*x<Scalar(0))
                rotateSpeed=-rotateSpeed;

            /* Update the accumulated rotation angle: */
            azimuth+=rotateSpeed*getFrameTime();
            if(azimuth<-Math::Constants<Scalar>::pi)
                azimuth+=Scalar(2)*Math::Constants<Scalar>::pi;
            else if(azimuth>=Math::Constants<Scalar>::pi)
                azimuth-=Scalar(2)*Math::Constants<Scalar>::pi;
        }

        /* Calculate the movement direction and speed: */
        Point footPos=projectToFloor(getMainViewer()->getHeadPosition());
        Vector moveDir=centerPoint-footPos;
        Scalar moveDirLen=moveDir.mag();
        Scalar speed=Scalar(0);
        if(moveDirLen>=factory->outerRadius)
            speed=factory->moveSpeed;
        else if(moveDirLen>factory->innerRadius)
            speed=factory->moveSpeed*(moveDirLen-factory->innerRadius)/(factory->outerRadius-factory->innerRadius);
        moveDir*=speed/moveDirLen;

        /* Accumulate the transformation: */
        NavTransform::Rotation rot=NavTransform::Rotation::rotateAxis(getUpDirection(),azimuth);
        translation+=rot.inverseTransform(moveDir*getFrameTime());

        /* Set the navigation transformation: */
        NavTransform nav=NavTransform::identity;
        nav*=Vrui::NavTransform::translateFromOriginTo(centerPoint);
        nav*=Vrui::NavTransform::rotate(rot);
        nav*=Vrui::NavTransform::translateToOriginFrom(centerPoint);
        nav*=Vrui::NavTransform::translate(translation);
        nav*=preScale;
        setNavigationTransformation(nav);

        if(speed!=Scalar(0))
        {
            /* Request another frame: */
            scheduleUpdate(getApplicationTime()+1.0/125.0);
        }
    }
}