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 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 SixAxisNavigationTool::valuatorCallback(int valuatorSlotIndex,InputDevice::ValuatorCallbackData* cbData) { /* Check if the valuator became active or inactive: */ if(cbData->oldValuatorValue==0.0&&cbData->newValuatorValue!=0.0) { /* Activate the axis: */ ++numActiveAxes; /* Try activating navigation if it is not already active: */ if(!isActive()&&activate()) { /* Initialize transient navigation state: */ navTransform=getNavigationTransformation(); } } if(cbData->oldValuatorValue!=0.0&&cbData->newValuatorValue==0.0) { /* Deactivate the axis: */ --numActiveAxes; if(numActiveAxes==0) { /* Deactivate navigation: */ deactivate(); } } }
void ValuatorFlyTurnNavigationTool::frame(void) { /* Act depending on this tool's current state: */ if(isActive()) { /* Get the current state of the input device: */ const TrackerState& ts=getDeviceTransformation(0); /* Check whether to change the super acceleration factor: */ if(Math::abs(currentValues[0])==Scalar(1)) superAcceleration*=Math::pow(factory->superAccelerationFactor,getFrameTime()); /* Calculate the current flying velocity: */ Vector v=factory->flyDirectionDeviceCoordinates?ts.transform(factory->flyDirection):factory->flyDirection; v*=-currentValues[0]*factory->flyFactor*superAcceleration*getFrameTime(); /* Calculate the current angular velocity: */ Vector w=factory->rotationAxisDeviceCoordinates?ts.transform(factory->rotationAxis):factory->rotationAxis; w*=currentValues[1]*factory->rotationFactor*getFrameTime(); /* Compose the new navigation transformation: */ Point p=factory->rotationCenterDeviceCoordinates?ts.transform(factory->rotationCenter):factory->rotationCenter; NavTransform t=NavTransform::translate(v); t*=NavTransform::translateFromOriginTo(p); t*=NavTransform::rotate(NavTransform::Rotation::rotateScaledAxis(w)); t*=NavTransform::translateToOriginFrom(p); t*=getNavigationTransformation(); /* Update Vrui's navigation transformation: */ setNavigationTransformation(t); } }
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 MouseDialogNavigationTool::startPanning(void) { /* Calculate initial motion position: */ motionStart=calcScreenPos(); preScale=getNavigationTransformation(); }
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())); }
void MouseNavigationTool::startPanning(void) { /* Calculate initial motion position: */ motionStart=calcScreenPos(); preScale=getNavigationTransformation(); /* Go to panning mode: */ navigationMode=PANNING; }
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)); } }
void MouseDialogNavigationTool::startScaling(void) { /* Calculate the scaling center: */ screenCenter=calcScreenCenter(); /* Calculate initial motion position: */ motionStart=calcScreenPos(); preScale=NavTrackerState::translateFromOriginTo(screenCenter); postScale=NavTrackerState::translateToOriginFrom(screenCenter); postScale*=getNavigationTransformation(); }
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; } }
void MouseDialogNavigationTool::startDollying(void) { /* Calculate the dollying direction: */ if(mouseAdapter!=0&&mouseAdapter->getWindow()!=0) dollyDirection=mouseAdapter->getWindow()->getViewer()->getHeadPosition()-calcScreenCenter(); else dollyDirection=getMainViewer()->getHeadPosition()-calcScreenCenter(); dollyDirection.normalize(); /* Calculate initial motion position: */ motionStart=calcScreenPos(); preScale=getNavigationTransformation(); }
ScaleBar::ScaleBar(const char* sName,GLMotif::WidgetManager* sManager) :GLMotif::Widget(sName,0,false),manager(sManager), targetLength(getDisplaySize()*Scalar(0.2)), currentMantissa(1),currentExponent(0),currentNavLength(1),currentScale(1), lengthLabel(0),scaleLabel(0), currentPhysLength(0) { /* Set widget parameters: */ setBorderWidth(0.0f); setBorderType(GLMotif::Widget::PLAIN); /* Set default background and foreground colors: */ Color bgColor=Vrui::getBackgroundColor(); bgColor[3]=0.0f; Color fgColor; for(int i=0;i<3;++i) fgColor[i]=1.0f-bgColor[i]; fgColor[3]=1.0f; setBorderColor(bgColor); setBackgroundColor(bgColor); setForegroundColor(fgColor); /* Create the initial scale bar length label: */ if(getCoordinateManager()->getUnit().unit!=Geometry::LinearUnit::UNKNOWN) { char labelText[10]; snprintf(labelText,sizeof(labelText),"1 %s",getCoordinateManager()->getUnit().getAbbreviation()); lengthLabel=new GLLabel(labelText,*getUiFont()); } else lengthLabel=new GLLabel("1",*getUiFont()); lengthLabel->setBackground(bgColor); lengthLabel->setForeground(fgColor); scaleLabel=new GLLabel("1:1",*getUiFont()); scaleLabel->setBackground(bgColor); scaleLabel->setForeground(fgColor); /* Calculate the initial navigation-space scale bar length: */ calcSize(getNavigationTransformation()); /* Resize the widget: */ GLMotif::Vector newSize=calcNaturalSize(); GLMotif::Vector newOrigin=GLMotif::Vector(0.0f,0.0f,0.0f); newOrigin[0]=-newSize[0]*0.5f; resize(GLMotif::Box(newOrigin,newSize)); /* Register a navigation change callback with the Vrui kernel: */ getNavigationTransformationChangedCallbacks().add(this,&ScaleBar::navigationChangedCallback); }
void MouseDialogNavigationTool::startRotating(void) { /* Calculate the rotation center: */ screenCenter=calcScreenCenter(); /* Calculate initial rotation position: */ lastRotationPos=calcScreenPos(); /* Calculate the rotation offset vector: */ rotateOffset=getMainScreen()->getScreenTransformation().transform(Vector(0,0,factory->rotatePlaneOffset)); preScale=NavTrackerState::translateFromOriginTo(screenCenter); rotation=NavTrackerState::identity; postScale=NavTrackerState::translateToOriginFrom(screenCenter); postScale*=getNavigationTransformation(); }
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; } }
void SixDofNavigationTool::buttonCallback(int,int,InputDevice::ButtonCallbackData* cbData) { if(cbData->newButtonState) // Button has just been pressed { /* Try activating this tool: */ if(activate()) { /* Initialize the navigation transformations: */ preScale=Geometry::invert(getDeviceTransformation(0)); preScale*=getNavigationTransformation(); } } else // Button has just been released { /* Deactivate this tool: */ deactivate(); } }
void DesktopDeviceNavigationTool::setButtonState(int buttonIndex,bool newButtonState) { if(buttonIndex==factory->homeButtonIndex) { if(newButtonState) { /* Reset the virtual input device to its home position: */ virtualDevice->setTransformation(homePosition); } } else if(buttonIndex==factory->navigationButtonIndex) { /* Set navigation state: */ if(newButtonState) { /* Try activating this tool: */ if(activate()) { /* Initialize the navigation transformation: */ postScale=getNavigationTransformation(); } } else { /* Deactivate this tool: */ deactivate(); } } else if(factory->buttonAxisShiftMasks[buttonIndex]!=0x0) { /* Update the current axis shift mask: */ if(newButtonState) axisIndexBase|=factory->buttonAxisShiftMasks[buttonIndex]; else axisIndexBase&=~factory->buttonAxisShiftMasks[buttonIndex]; } else { /* Pass the button event through to the virtual input device: */ virtualDevice->setButtonState(buttonIndex,newButtonState); } }
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 FlyNavigationTool::frame(void) { /* Act depending on this tool's current state: */ if(isActive()) { /* Get the current state of the input device: */ const TrackerState& ts=getDeviceTransformation(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); } }
void MouseDialogNavigationTool::startRotating(void) { /* Calculate the rotation center: */ screenCenter=calcScreenCenter(); /* Calculate initial rotation position: */ lastRotationPos=calcScreenPos(); /* Get the transformation of the screen currently containing the input device: */ Scalar viewport[4]; ONTransform screenT=getMouseScreenTransform(mouseAdapter,viewport); /* Calculate the rotation offset vector: */ rotateOffset=screenT.transform(Vector(0,0,factory->rotatePlaneOffset)); preScale=NavTrackerState::translateFromOriginTo(screenCenter); rotation=NavTrackerState::identity; postScale=NavTrackerState::translateToOriginFrom(screenCenter); postScale*=getNavigationTransformation(); }
void ValuatorScalingNavigationTool::valuatorCallback(int,int,InputDevice::ValuatorCallbackData* cbData) { currentValue=Scalar(cbData->newValuatorValue); if(Math::abs(currentValue)>factory->valuatorThreshold) { /* Try activating this tool: */ if(!isActive()&&activate()) { /* Initialize the navigation transformations: */ scalingCenter=getDevicePosition(0); preScale=NavTrackerState::translateFromOriginTo(scalingCenter); postScale=NavTrackerState::translateToOriginFrom(scalingCenter); postScale*=getNavigationTransformation(); currentScale=Scalar(1); } } else { /* Deactivate this tool: */ deactivate(); } }
void TwoRayTransformTool::display(GLContextData& contextData) const { if(numRays>0) { /* Draw the selection rays: */ glPushAttrib(GL_ENABLE_BIT|GL_LINE_BIT); glDisable(GL_LIGHTING); glColor3f(1.0f,0.0f,0.0f); glLineWidth(3.0f); glBegin(GL_LINES); for(int i=0;i<(active?numRays+1:numRays);++i) { Ray tr=rays[i]; tr.transform(getNavigationTransformation()); glVertex(tr.getOrigin()); glVertex(tr(getDisplaySize()*Scalar(5))); } glEnd(); glPopAttrib(); } }
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 ViewpointFileNavigationTool::display(GLContextData& contextData) const { if(!viewpoints.empty()&&showKeyframes) { /* Display the next keyframe viewpoint in navigational coordinates: */ glPushAttrib(GL_ENABLE_BIT|GL_LINE_BIT); glDisable(GL_LIGHTING); glLineWidth(3.0f); glPushMatrix(); glMultMatrix(getNavigationTransformation()); glBegin(GL_LINES); glColor3f(1.0f,0.0f,0.0f); glVertex(viewpoints[nextViewpointIndex].center); glVertex(viewpoints[nextViewpointIndex].center+viewpoints[nextViewpointIndex].forward*Math::exp(viewpoints[nextViewpointIndex].size)*Scalar(0.25)); glColor3f(0.0f,1.0f,0.0f); glVertex(viewpoints[nextViewpointIndex].center); glVertex(viewpoints[nextViewpointIndex].center+viewpoints[nextViewpointIndex].up*Math::exp(viewpoints[nextViewpointIndex].size)*Scalar(0.25)); glEnd(); glPopMatrix(); glPopAttrib(); } }
void FPSNavigationTool::startNavigating(void) { /* Initialize the navigation state: */ if(mouseAdapter!=0) { /* Get the current cursor position in the controlling window: */ for(int i=0;i<2;++i) oldMousePos[i]=mouseAdapter->getMousePosition()[i]; /* Enable mouse warping on the controlling window: */ mouseAdapter->getWindow()->hideCursor(); mouseAdapter->getWindow()->getWindowCenterPos(lastMousePos.getComponents()); lastMousePos[2]=Scalar(0); mouseAdapter->getWindow()->setCursorPosWithAdjust(lastMousePos.getComponents()); mouseAdapter->setMousePosition(mouseAdapter->getWindow(),lastMousePos.getComponents()); /* Update the navigation frame on the off chance that the controlling window changed: */ ONTransform st=mouseAdapter->getWindow()->getVRScreen()->getScreenTransformation(); navFrame=st.getRotation(); pos=mouseAdapter->getWindow()->getViewer()->getHeadPosition(); } else { pos=getMainViewer()->getHeadPosition(); lastMousePos=calcMousePosition(); } angles[0]=angles[1]=Scalar(0); moveVelocity=Vector::zero; /* Calculate the prescale transformation: */ preScale=NavTransform::translateToOriginFrom(pos); preScale*=NavTransform::translateFromOriginTo(pos); preScale*=NavTransform::rotate(Geometry::invert(navFrame)); preScale*=NavTransform::translateToOriginFrom(pos); preScale*=getNavigationTransformation(); }
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 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 MouseNavigationTool::valuatorCallback(int,InputDevice::ValuatorCallbackData* cbData) { currentValue=Scalar(cbData->newValuatorValue); if(currentValue!=Scalar(0)) { /* Act depending on this tool's current state: */ switch(navigationMode) { case IDLE: case SPINNING: /* Try activating this tool: */ if(navigationMode==SPINNING||activate()) { if(dolly) { /* Calculate the dollying direction: */ if(mouseAdapter!=0) dollyDirection=mouseAdapter->getWindow()->getViewer()->getHeadPosition()-calcScreenCenter(); else dollyDirection=getMainViewer()->getHeadPosition()-calcScreenCenter(); dollyDirection.normalize(); /* Initialize the wheel dollying factor: */ currentWheelScale=Scalar(1); preScale=getNavigationTransformation(); /* Go to wheel dollying mode: */ navigationMode=DOLLYING_WHEEL; } else { /* Calculate the scaling center: */ screenCenter=calcScreenCenter(); /* Initialize the wheel scaling factor: */ currentWheelScale=Scalar(1); preScale=NavTrackerState::translateFromOriginTo(screenCenter); postScale=NavTrackerState::translateToOriginFrom(screenCenter); postScale*=getNavigationTransformation(); /* Go to wheel scaling mode: */ navigationMode=SCALING_WHEEL; } } break; default: /* This can definitely happen; just ignore the event */ break; } } else { /* Act depending on this tool's current state: */ switch(navigationMode) { case DOLLYING_WHEEL: case SCALING_WHEEL: /* Deactivate this tool: */ deactivate(); /* Go to idle mode: */ navigationMode=IDLE; break; default: /* This can definitely happen; just ignore the event */ break; } } }
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; } }