Point TrackballNavigationTool::calcTrackballPosition(void) const { /* Get device ray equation: */ Ray ray=getButtonDeviceRay(0); /* Intersect ray with trackball sphere: */ Vector d=getDisplayCenter()-ray.getOrigin(); Scalar dLen2=Geometry::sqr(d); Scalar ph=ray.getDirection()*d; Scalar radius=getDisplaySize(); Scalar det=Math::sqr(ph)+Math::sqr(radius)-dLen2; if(det>=Scalar(0)) { /* Find first intersection of ray with sphere (even if behind start point): */ det=Math::sqrt(det); Scalar lambda=ph-det; return ray(lambda); } else { /* Find closest point on sphere to ray: */ Vector ctop=ray.getDirection()*((d*ray.getDirection())/Geometry::sqr(ray.getDirection()))-d; ctop*=radius/Geometry::mag(ctop); return getDisplayCenter()+ctop; } }
void TrackballNavigationTool::frame(void) { /* Act depending on this tool's current state: */ if(isActive()) { /* Calculate new interaction position: */ Point dragPosition=calcTrackballPosition(); /* Calculate incremental transformation from old to new point: */ Vector v1=lastDragPosition-getDisplayCenter(); Vector v2=dragPosition-getDisplayCenter(); Vector axis=Geometry::cross(v1,v2); Scalar axisLen=Geometry::mag(axis); if(axisLen!=Scalar(0)) { /* Calculate rotation angle: */ axis/=axisLen; Scalar angle=Math::acos((v1*v2)/(Geometry::mag(v1)*Geometry::mag(v2)))*factory->rotateFactor; /* Compose new navigation transformation: */ NavTrackerState navigation=NavTrackerState::rotateAround(getDisplayCenter(),NavTrackerState::Rotation::rotateAxis(axis,angle)); navigation*=getNavigationTransformation(); /* Update Vrui's navigation transformation: */ setNavigationTransformation(navigation); } lastDragPosition=dragPosition; } }
void ScaleBar::pointerButtonDown(GLMotif::Event& event) { Scalar newScale=currentScale; /* Check if the event happened in the left or right corner: */ float relEventPos=(event.getWidgetPoint().getPoint()[0]-getInterior().origin[0])/getInterior().size[0]; if(relEventPos<=0.333f) { /* Calculate the next smaller quasi-binary scale factor: */ newScale=Scalar(getSmallerQuasiBinary(currentScale)); } else if(relEventPos>=0.667f) { /* Calculate the next bigger quasi-binary scale factor: */ newScale=Scalar(getBiggerQuasiBinary(currentScale)); } if(newScale!=currentScale&&activateNavigationTool(reinterpret_cast<const Tool*>(this))) { /* Adjust the navigation transformation: */ Scalar newNavScale; const Geometry::LinearUnit& unit=getCoordinateManager()->getUnit(); if(unit.isImperial()) { /* Calculate scale factor through imperial units: */ newNavScale=getInchFactor()*newScale/unit.getInchFactor(); } else { /* Calculate scale factor through metric units: */ newNavScale=getMeterFactor()*newScale/unit.getMeterFactor(); } /* Get the current navigation transformation and calculate the display center position in navigation coordinates: */ const NavTransform& nav=getNavigationTransformation(); Point center=nav.inverseTransform(getDisplayCenter()); /* Create the new navigation transformation: */ NavTransform newNav=NavTransform(nav.getTranslation(),nav.getRotation(),newNavScale); newNav.leftMultiply(NavTransform::translate(getDisplayCenter()-newNav.transform(center))); setNavigationTransformation(newNav); deactivateNavigationTool(reinterpret_cast<const Tool*>(this)); currentScale=newScale; /* Update the scale bar: */ calcSize(newNav); /* Resize the widget so that the clicked point stays in the same place: */ GLMotif::Vector newSize=calcNaturalSize(); GLfloat newInteriorWidth=newSize[0]-2.0f*getBorderWidth(); GLfloat newOrigin=event.getWidgetPoint().getPoint()[0]-newInteriorWidth*relEventPos-getBorderWidth(); resize(GLMotif::Box(GLMotif::Vector(newOrigin,0.0f,0.0f),newSize)); } }
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]&¶meter<=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::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 } }
MouseDialogNavigationTool::MouseDialogNavigationTool(const ToolFactory* factory,const ToolInputAssignment& inputAssignment) :NavigationTool(factory,inputAssignment), mouseAdapter(0), navigationDialogPopup(0), navigationMode(ROTATING), spinning(false), showScreenCenter(false) { /* Find the mouse input device adapter controlling the input device: */ mouseAdapter=dynamic_cast<InputDeviceAdapterMouse*>(getInputDeviceManager()->findInputDeviceAdapter(getDevice(0))); /* Create the tool's GUI: */ navigationDialogPopup=new GLMotif::PopupWindow("NavigationDialogPopup",getWidgetManager(),"Mouse Navigation Dialog"); GLMotif::RowColumn* navigationDialog=new GLMotif::RowColumn("NavigationDialog",navigationDialogPopup,false); GLMotif::RadioBox* navigationModes=new GLMotif::RadioBox("NavigationModes",navigationDialog,false); navigationModes->setOrientation(GLMotif::RowColumn::VERTICAL); navigationModes->setPacking(GLMotif::RowColumn::PACK_GRID); navigationModes->setSelectionMode(GLMotif::RadioBox::ALWAYS_ONE); navigationModes->addToggle("Rotate"); navigationModes->addToggle("Pan"); navigationModes->addToggle("Dolly"); navigationModes->addToggle("Scale"); switch(navigationMode) { case ROTATING: navigationModes->setSelectedToggle(0); break; case PANNING: navigationModes->setSelectedToggle(1); break; case DOLLYING: navigationModes->setSelectedToggle(2); break; case SCALING: navigationModes->setSelectedToggle(3); break; } navigationModes->getValueChangedCallbacks().add(this,&MouseDialogNavigationTool::navigationModesValueChangedCallback); navigationModes->manageChild(); GLMotif::ToggleButton* showScreenCenterToggle=new GLMotif::ToggleButton("ShowScreenCenterToggle",navigationDialog,"Show Screen Center"); showScreenCenterToggle->setToggle(showScreenCenter); showScreenCenterToggle->getValueChangedCallbacks().add(this,&MouseDialogNavigationTool::showScreenCenterToggleValueChangedCallback); navigationDialog->manageChild(); /* Pop up the navigation dialog: */ popupPrimaryWidget(navigationDialogPopup,getNavigationTransformation().transform(getDisplayCenter())); }
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)); } }
SixAxisTransformToolFactory::Configuration::Configuration(void) :translateFactor(getDisplaySize()/Scalar(3)), translations(Vector::zero), rotateFactor(Scalar(180)), rotations(Vector::zero), followDisplayCenter(true), homePosition(getDisplayCenter()), deviceGlyphType("Cone"), deviceGlyphMaterial(GLMaterial::Color(0.5f,0.5f,0.5f),GLMaterial::Color(1.0f,1.0f,1.0f),25.0f) { /* Initialize translation vectors and scaled rotation axes: */ for(int i=0;i<3;++i) translations[i][i]=Scalar(1); for(int i=0;i<3;++i) rotations[i][i]=Scalar(1); }
Point RayMenuTool::calcHotSpot(void) const { if(isUseEyeRay()||interactionDevice->isRayDevice()) { /* Find the intersection point of the interaction ray and a screen: */ std::pair<VRScreen*,Scalar> si=findScreen(GUIInteractor::getRay()); if(si.first!=0) return GUIInteractor::getRay()(si.second); else return getDisplayCenter(); } else { /* Return a position in front of the input device: */ return GUIInteractor::getRay()(factory->initialMenuOffset); } }
SixAxisNavigationToolFactory::Configuration::Configuration(void) :translateFactor(getDisplaySize()/Scalar(3)), translations(Vector::zero), rotateFactor(Scalar(180)), rotations(Vector::zero), zoomFactor(Scalar(1)), followDisplayCenter(false), navigationCenter(getDisplayCenter()), invertNavigation(false), showNavigationCenter(true) { /* Initialize translation vectors and scaled rotation axes: */ for(int i=0;i<3;++i) translations[i][i]=Scalar(1); for(int i=0;i<3;++i) rotations[i][i]=Scalar(1); }
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 SixAxisNavigationTool::display(GLContextData& contextData) const { if(config.showNavigationCenter&&isActive()) { /* Set up OpenGL state: */ glPushAttrib(GL_DEPTH_BUFFER_BIT|GL_ENABLE_BIT|GL_LINE_BIT); glDisable(GL_LIGHTING); glDepthFunc(GL_LEQUAL); /* Calculate colors to draw the crosshairs: */ Color bgColor=getBackgroundColor(); Color fgColor; for(int i=0;i<3;++i) fgColor[i]=1.0f-bgColor[i]; fgColor[3]=bgColor[3]; /* Go to crosshair space: */ glPushMatrix(); ONTransform trans=calcHUDTransform(config.followDisplayCenter?getDisplayCenter():config.navigationCenter); glMultMatrix(trans); glLineWidth(3.0f); glBegin(GL_LINES); glColor(bgColor); glVertex2d(-getDisplaySize(),0.0); glVertex2d(getDisplaySize(),0.0); glVertex2d(0.0,-getDisplaySize()); glVertex2d(0.0,getDisplaySize()); glEnd(); glLineWidth(1.0f); glBegin(GL_LINES); glColor(fgColor); glVertex2d(-getDisplaySize(),0.0); glVertex2d(getDisplaySize(),0.0); glVertex2d(0.0,-getDisplaySize()); glVertex2d(0.0,getDisplaySize()); glEnd(); glPopMatrix(); /* Restore OpenGL state: */ glPopAttrib(); } }
WalkNavigationToolFactory::WalkNavigationToolFactory(ToolManager& toolManager) :ToolFactory("WalkNavigationTool",toolManager), floorPlane(getFloorPlane()), 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.setNumDevices(1); layout.setNumButtons(0,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()); floorPlane=cfs.retrieveValue<Plane>("./floorPlane",floorPlane); floorPlane.normalize(); centerOnActivation=cfs.retrieveValue<bool>("./centerOnActivation",centerOnActivation); centerPoint=cfs.retrieveValue<Point>("./centerPoint",centerPoint); centerPoint=floorPlane.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=floorPlane.project(centerViewDirection); 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 SixAxisTransformTool::buttonCallback(int buttonSlotIndex,InputDevice::ButtonCallbackData* cbData) { if(buttonSlotIndex==0) { if(cbData->newButtonState) // Button has just been pressed { /* Reset the transformed device to the home position: */ transformedDevice->setTransformation(TrackerState::translateFromOriginTo(config.followDisplayCenter?getDisplayCenter():config.homePosition)); } } else { /* Let transform tool handle it: */ TransformTool::buttonCallback(buttonSlotIndex,cbData); } }
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(); } }
UIManagerSpherical::UIManagerSpherical(const Misc::ConfigurationFileSection& configFileSection) :UIManager(configFileSection), sphere(Point::origin,Scalar(1)), alignSecant(configFileSection.retrieveValue<bool>("./alignSecant",true)), constrainMovement(configFileSection.retrieveValue<bool>("./constrainMovement",true)) { /* Configure the UI sphere: */ sphere.setCenter(configFileSection.retrieveValue<Point>("./sphereCenter")); sphere.setRadius(configFileSection.retrieveValue<Scalar>("./sphereRadius",Geometry::dist(sphere.getCenter(),getDisplayCenter()))); }
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); } } } } }
void SixAxisTransformTool::initialize(void) { /* Let the base class do its thing: */ TransformTool::initialize(); /* Calculate derived configuration values: */ for(int i=0;i<3;++i) translations[i]=config.translations[i]*config.translateFactor; for(int i=0;i<3;++i) rotations[i]=config.rotations[i]*Math::rad(config.rotateFactor); /* Set the virtual input device's glyph: */ getInputGraphManager()->getInputDeviceGlyph(transformedDevice).setGlyphType(config.deviceGlyphType.c_str()); getInputGraphManager()->getInputDeviceGlyph(transformedDevice).setGlyphMaterial(config.deviceGlyphMaterial); /* Initialize the virtual input device's position: */ transformedDevice->setDeviceRay(Vector(0,1,0),-getInchFactor()); transformedDevice->setTransformation(TrackerState::translateFromOriginTo(config.followDisplayCenter?getDisplayCenter():config.homePosition)); }