void DesktopDeviceNavigationTool::display(GLContextData& contextData) const { if(factory->showScreenCenter&&isActive()) { Color bgColor=getBackgroundColor(); Color fgColor; for(int i=0;i<3;++i) fgColor[i]=1.0f-bgColor[i]; fgColor[3]=bgColor[3]; ONTransform screenT=getMainScreen()->getScreenTransformation(); Point screenCenter=screenT.transform(Point(getMainScreen()->getWidth()*Scalar(0.5),getMainScreen()->getHeight()*Scalar(0.5),Scalar(0))); Vector x=screenT.transform(Vector(getMainScreen()->getWidth()*Scalar(0.5),Scalar(0),Scalar(0))); Vector y=screenT.transform(Vector(Scalar(0),getMainScreen()->getHeight()*Scalar(0.5),Scalar(0))); glPushAttrib(GL_DEPTH_BUFFER_BIT|GL_ENABLE_BIT|GL_LINE_BIT); glDisable(GL_LIGHTING); glDepthFunc(GL_LEQUAL); glLineWidth(3.0f); glColor(bgColor); glBegin(GL_LINES); glVertex(screenCenter-x); glVertex(screenCenter+x); glVertex(screenCenter-y); glVertex(screenCenter+y); glEnd(); glLineWidth(1.0f); glColor(fgColor); glBegin(GL_LINES); glVertex(screenCenter-x); glVertex(screenCenter+x); glVertex(screenCenter-y); glVertex(screenCenter+y); glEnd(); glPopAttrib(); } }
Point FPSNavigationTool::calcMousePosition(void) const { if(mouseAdapter!=0) { /* Return the mouse position directly: */ return Point(mouseAdapter->getMousePosition()[0],mouseAdapter->getMousePosition()[1],Scalar(0)); } else { /* Get pointer to input device: */ InputDevice* device=input.getDevice(0); /* Calculate ray equation: */ Ray ray(device->getPosition(),device->getRayDirection()); /* Intersect the ray with the main screen: */ ONTransform screenT=getMainScreen()->getScreenTransformation(); Vector screenNormal=screenT.getDirection(2); Scalar screenOffset=screenT.getOrigin()*screenNormal; Scalar lambda=(screenOffset-ray.getOrigin()*screenNormal)/(ray.getDirection()*screenNormal); /* Return the intersection point in screen coordinates: */ return screenT.inverseTransform(ray(lambda)); } }
Point MouseNavigationTool::calcScreenPos(void) const { /* Get pointer to input device: */ InputDevice* device=input.getDevice(0); /* Calculate ray equation: */ Point start=device->getPosition(); Vector direction=device->getRayDirection(); /* Find the screen currently containing the input device: */ const VRScreen* screen; if(mouseAdapter!=0&&mouseAdapter->getWindow()!=0) screen=mouseAdapter->getWindow()->getVRScreen(); else screen=getMainScreen(); /* Intersect ray with the screen: */ ONTransform screenT=screen->getScreenTransformation(); Vector normal=screenT.getDirection(2); Scalar d=normal*screenT.getOrigin(); Scalar divisor=normal*direction; if(divisor==Scalar(0)) return Point::origin; Scalar lambda=(d-start*normal)/divisor; if(lambda<Scalar(0)) return Point::origin; return start+direction*lambda; }
Point MouseDialogNavigationTool::calcScreenPos(void) { /* Calculate the ray equation: */ Ray ray=getDeviceRay(0); /* Find the screen currently containing the input device: */ const VRScreen* screen; if(mouseAdapter!=0&&mouseAdapter->getWindow()!=0) screen=mouseAdapter->getWindow()->getVRScreen(); else screen=getMainScreen(); /* Intersect ray with the screen: */ ONTransform screenT=screen->getScreenTransformation(); Vector normal=screenT.getDirection(2); Scalar d=normal*screenT.getOrigin(); Scalar divisor=normal*ray.getDirection(); if(divisor==Scalar(0)) return Point::origin; Scalar lambda=(d-ray.getOrigin()*normal)/divisor; if(lambda<Scalar(0)) return Point::origin; return ray(lambda); }
void FPSNavigationTool::initialize(void) { /* Get a pointer to the input device's controlling adapter: */ mouseAdapter=dynamic_cast<InputDeviceAdapterMouse*>(getInputDeviceManager()->findInputDeviceAdapter(input.getDevice(0))); /* Initialize the navigation frame and current position/orientation: */ ONTransform st=getMainScreen()->getScreenTransformation(); navFrame=st.getRotation(); }
Point MouseNavigationTool::calcScreenCenter(void) const { /* Determine the screen containing the input device and the screen's center: */ const VRScreen* screen; Point centerPos; if(mouseAdapter!=0&&mouseAdapter->getWindow()!=0) { screen=mouseAdapter->getWindow()->getVRScreen(); mouseAdapter->getWindow()->getWindowCenterPos(centerPos.getComponents()); } else { screen=getMainScreen(); centerPos[0]=getMainScreen()->getWidth()*Scalar(0.5); centerPos[1]=getMainScreen()->getHeight()*Scalar(0.5); } centerPos[2]=Scalar(0); /* Calculate the center position in physical coordinates: */ return screen->getScreenTransformation().transform(centerPos); }
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(); }
ONTransform getMouseScreenTransform(InputDeviceAdapterMouse* mouseAdapter,Scalar viewport[4]) { /* Check if the mouse adapter is valid: */ VRScreen* screen=0; if(mouseAdapter!=0&&mouseAdapter->getWindow()!=0) { /* Use the window associated with the mouse adapter: */ VRWindow* window=mouseAdapter->getWindow(); screen=window->getVRScreen(); window->getScreenViewport(viewport); } else { /* Use the main screen: */ screen=getMainScreen(); screen->getViewport(viewport); } /* Return the screen's transformation: */ return screen->getScreenTransformation(); }
DesktopDeviceNavigationToolFactory::DesktopDeviceNavigationToolFactory(ToolManager& toolManager) :ToolFactory("DesktopDeviceNavigationTool",toolManager), numButtons(0),buttonToggleFlags(0),buttonAxisShiftMasks(0), numRotationAxes(0),rotationAxes(0), rotateFactor(Scalar(1)), numTranslationAxes(0),translationAxes(0), translateFactor(getInchFactor()), invertNavigation(false), numZoomAxes(0),zoomAxes(0), zoomFactor(Scalar(1)), homeButtonIndex(-1), showScreenCenter(false) { /* Load class settings: */ typedef std::vector<int> IndexList; typedef std::vector<AxisDescriptor> AxisDescriptorList; Misc::ConfigurationFileSection cfs=toolManager.getToolClassSection(getClassName()); /* Read number of buttons on raw device: */ numButtons=cfs.retrieveValue<int>("./numButtons"); buttonToggleFlags=new bool[numButtons]; buttonAxisShiftMasks=new int[numButtons]; for(int i=0;i<numButtons;++i) { buttonToggleFlags[i]=false; buttonAxisShiftMasks[i]=0x0; } /* Read list of toggle button indices: */ IndexList toggleButtonIndices=cfs.retrieveValue<IndexList>("./toggleButtonIndices",IndexList()); for(IndexList::const_iterator tbiIt=toggleButtonIndices.begin();tbiIt!=toggleButtonIndices.end();++tbiIt) { if(*tbiIt>=0&&*tbiIt<numButtons) buttonToggleFlags[*tbiIt]=true; else Misc::throwStdErr("DesktopDeviceNavigationTool: Toggle button index out of valid range"); } /* Read list of axis shift button indices: */ IndexList axisShiftButtonIndices=cfs.retrieveValue<IndexList>("./axisShiftButtonIndices",IndexList()); int nextButtonMask=0x1; for(IndexList::const_iterator asbiIt=axisShiftButtonIndices.begin();asbiIt!=axisShiftButtonIndices.end();++asbiIt) { if(*asbiIt>=0&&*asbiIt<numButtons) { buttonAxisShiftMasks[*asbiIt]=nextButtonMask; nextButtonMask<<=1; } else Misc::throwStdErr("DesktopDeviceNavigationTool: Axis shift button index out of valid range"); } /* Read number of valuators on raw device: */ numValuators=cfs.retrieveValue<int>("./numValuators"); /* Read list of rotational axis descriptors: */ AxisDescriptorList rotationalAxisDescriptors=cfs.retrieveValue<AxisDescriptorList>("./rotationalAxes"); numRotationAxes=rotationalAxisDescriptors.size(); rotationAxes=new AxisDescriptor[numRotationAxes]; for(int i=0;i<numRotationAxes;++i) rotationAxes[i]=rotationalAxisDescriptors[i]; rotateFactor=cfs.retrieveValue<Scalar>("./rotateFactor",rotateFactor); /* Read list of translational axis descriptors: */ AxisDescriptorList translationalAxisDescriptors=cfs.retrieveValue<AxisDescriptorList>("./translationalAxes"); numTranslationAxes=translationalAxisDescriptors.size(); translationAxes=new AxisDescriptor[numTranslationAxes]; for(int i=0;i<numTranslationAxes;++i) translationAxes[i]=translationalAxisDescriptors[i]; translateFactor=cfs.retrieveValue<Scalar>("./translateFactor",translateFactor); /* Get navigation button index: */ navigationButtonIndex=cfs.retrieveValue<int>("./navigationButtonIndex",numButtons-1); /* Read navigation mode flag: */ invertNavigation=cfs.retrieveValue<bool>("./invertNavigation",invertNavigation); /* Read list of zoom axis descriptors: */ AxisDescriptorList zoomAxisDescriptors=cfs.retrieveValue<AxisDescriptorList>("./zoomAxes"); numZoomAxes=zoomAxisDescriptors.size(); zoomAxes=new AxisDescriptor[numZoomAxes]; for(int i=0;i<numZoomAxes;++i) zoomAxes[i]=zoomAxisDescriptors[i]; zoomFactor=cfs.retrieveValue<Scalar>("./zoomFactor",zoomFactor); /* Read the navigation center: */ navigationCenter=getMainScreen()->getScreenTransformation().transform(Point(getMainScreen()->getWidth()*Scalar(0.5),getMainScreen()->getHeight()*Scalar(0.5),Scalar(0))); navigationCenter=cfs.retrieveValue<Point>("./navigationCenter",navigationCenter); /* Get home button index: */ homeButtonIndex=cfs.retrieveValue<int>("./homeButtonIndex",homeButtonIndex); /* Configure device glyph for virtual DesktopDevice device: */ deviceGlyph.configure(cfs,"./deviceGlyphType","./deviceGlyphMaterial"); showScreenCenter=cfs.retrieveValue<bool>("./showScreenCenter",showScreenCenter); /* Initialize tool layout: */ layout.setNumDevices(1); layout.setNumButtons(0,numButtons); layout.setNumValuators(0,numValuators); /* Insert class into class hierarchy: */ ToolFactory* toolFactory=toolManager.loadClass("NavigationTool"); toolFactory->addChildClass(this); addParentClass(toolFactory); /* Set tool class' factory pointer: */ DesktopDeviceNavigationTool::factory=this; }
void MouseNavigationTool::display(GLContextData& contextData) const { bool gotoScreenCoords=factory->showMouseCursor||(factory->showScreenCenter&&navigationMode!=IDLE&&navigationMode!=WIDGETING); const VRScreen* screen=0; ONTransform screenT; if(gotoScreenCoords) { /* Get a pointer to the screen the mouse is on: */ if(mouseAdapter!=0&&mouseAdapter->getWindow()!=0) screen=mouseAdapter->getWindow()->getVRScreen(); else screen=getMainScreen(); screenT=screen->getScreenTransformation(); /* Save and set up OpenGL state: */ glPushAttrib(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_ENABLE_BIT|GL_LINE_BIT|GL_TEXTURE_BIT); glDisable(GL_LIGHTING); /* Go to screen coordinates: */ glPushMatrix(); glMultMatrix(screenT); } if(factory->showScreenCenter&&navigationMode!=IDLE&&navigationMode!=WIDGETING) { /* Determine the screen containing the input device and find its center: */ Scalar centerPos[2]; if(mouseAdapter!=0) mouseAdapter->getWindow()->getWindowCenterPos(centerPos); else { centerPos[0]=getMainScreen()->getWidth()*Scalar(0.5); centerPos[1]=getMainScreen()->getHeight()*Scalar(0.5); } /* Calculate the endpoints of the screen's crosshair lines in screen coordinates: */ Point l=Point(Scalar(0),centerPos[1],Scalar(0)); Point r=Point(screen->getWidth(),centerPos[1],Scalar(0)); Point b=Point(centerPos[0],Scalar(0),Scalar(0)); Point t=Point(centerPos[0],screen->getHeight(),Scalar(0)); /* Determine the crosshair colors: */ Color bgColor=getBackgroundColor(); Color fgColor; for(int i=0; i<3; ++i) fgColor[i]=1.0f-bgColor[i]; fgColor[3]=bgColor[3]; /* Draw the screen crosshairs: */ glDepthFunc(GL_LEQUAL); glLineWidth(3.0f); glColor(bgColor); glBegin(GL_LINES); glVertex(l); glVertex(r); glVertex(b); glVertex(t); glEnd(); glLineWidth(1.0f); glColor(fgColor); glBegin(GL_LINES); glVertex(l); glVertex(r); glVertex(b); glVertex(t); glEnd(); } if(factory->showMouseCursor) { /* Get the data item: */ DataItem* dataItem=contextData.retrieveDataItem<DataItem>(this); /* Calculate the mouse position: */ Point mousePos=screenT.inverseTransform(currentPos); for(int i=0; i<2; ++i) mousePos[i]-=factory->mouseCursorHotspot[i]*factory->mouseCursorSize[i]; /* Draw the mouse cursor: */ glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,dataItem->textureObjectId); glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GEQUAL,0.5f); glBegin(GL_QUADS); glTexCoord(mouseCursorTexCoordBox.getVertex(0)); glVertex(mousePos[0],mousePos[1]); glTexCoord(mouseCursorTexCoordBox.getVertex(1)); glVertex(mousePos[0]+factory->mouseCursorSize[0],mousePos[1]); glTexCoord(mouseCursorTexCoordBox.getVertex(3)); glVertex(mousePos[0]+factory->mouseCursorSize[0],mousePos[1]+factory->mouseCursorSize[1]); glTexCoord(mouseCursorTexCoordBox.getVertex(2)); glVertex(mousePos[0],mousePos[1]+factory->mouseCursorSize[1]); glEnd(); glBindTexture(GL_TEXTURE_2D,0); } if(gotoScreenCoords) { /* Go back to physical coordinates: */ glPopMatrix(); /* Restore OpenGL state: */ glPopAttrib(); } }
void MouseNavigationTool::frame(void) { /* Update the current mouse position: */ currentPos=calcScreenPos(); /* Act depending on this tool's current state: */ switch(navigationMode) { case IDLE: /* Do nothing */ break; case WIDGETING: { /* Deliver the event: */ GLMotif::Event event(true); event.setWorldLocation(calcSelectionRay()); getWidgetManager()->pointerMotion(event); if(draggedWidget!=0) { /* Update the dragged widget's transformation: */ NavTrackerState current=NavTrackerState::translateFromOriginTo(calcScreenPos()); current*=preScale; getWidgetManager()->setPrimaryWidgetTransformation(draggedWidget,GLMotif::WidgetManager::Transformation(current)); } break; } case ROTATING: { /* Calculate the rotation position: */ Vector offset=(lastRotationPos-screenCenter)+rotateOffset; /* Calculate mouse displacement vector: */ Point rotationPos=currentPos; Vector delta=rotationPos-lastRotationPos; lastRotationPos=rotationPos; /* Calculate incremental rotation: */ Vector axis=Geometry::cross(offset,delta); Scalar angle=Geometry::mag(delta)/factory->rotateFactor; if(angle!=Scalar(0)) rotation.leftMultiply(NavTrackerState::rotate(NavTrackerState::Rotation::rotateAxis(axis,angle))); NavTrackerState t=preScale; t*=rotation; t*=postScale; setNavigationTransformation(t); break; } case SPINNING: { /* Calculate incremental rotation: */ rotation.leftMultiply(NavTrackerState::rotate(NavTrackerState::Rotation::rotateScaledAxis(spinAngularVelocity*getCurrentFrameTime()))); NavTrackerState t=preScale; t*=rotation; t*=postScale; setNavigationTransformation(t); break; } case PANNING: { /* Update the navigation transformation: */ NavTrackerState t=NavTrackerState::translate(currentPos-motionStart); t*=preScale; setNavigationTransformation(t); break; } case DOLLYING: { /* Calculate the current dollying direction: */ Vector dollyingDirection; if(mouseAdapter!=0) dollyingDirection=mouseAdapter->getWindow()->getVRScreen()->getScreenTransformation().transform(factory->screenDollyingDirection); else dollyingDirection=getMainScreen()->getScreenTransformation().transform(factory->screenDollyingDirection); /* Update the navigation transformation: */ Scalar dollyDist=((currentPos-motionStart)*dollyingDirection)/factory->dollyFactor; NavTrackerState t=NavTrackerState::translate(dollyDirection*dollyDist); t*=preScale; setNavigationTransformation(t); break; } case SCALING: { /* Calculate the current scaling direction: */ Vector scalingDirection; if(mouseAdapter!=0) scalingDirection=mouseAdapter->getWindow()->getVRScreen()->getScreenTransformation().transform(factory->screenScalingDirection); else scalingDirection=getMainScreen()->getScreenTransformation().transform(factory->screenScalingDirection); /* Update the navigation transformation: */ Scalar scale=((currentPos-motionStart)*scalingDirection)/factory->scaleFactor; NavTrackerState t=preScale; t*=NavTrackerState::scale(Math::exp(scale)); t*=postScale; setNavigationTransformation(t); break; } case DOLLYING_WHEEL: { /* Update the navigation transformation: */ Scalar scale=currentValue; currentWheelScale+=factory->wheelDollyFactor*scale; NavTrackerState t=NavTrackerState::translate(dollyDirection*currentWheelScale); t*=preScale; setNavigationTransformation(t); break; } case SCALING_WHEEL: { /* Update the navigation transformation: */ Scalar scale=currentValue; currentWheelScale*=Math::pow(factory->wheelScaleFactor,scale); NavTrackerState t=preScale; t*=NavTrackerState::scale(currentWheelScale); t*=postScale; setNavigationTransformation(t); break; } } }
void MouseDialogNavigationTool::display(GLContextData& contextData) const { if(showScreenCenter) { /* Save and set up OpenGL state: */ glPushAttrib(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_ENABLE_BIT|GL_LINE_BIT|GL_TEXTURE_BIT); glDisable(GL_LIGHTING); /* Get a pointer to the screen the mouse is on: */ const VRScreen* screen; if(mouseAdapter!=0&&mouseAdapter->getWindow()!=0) screen=mouseAdapter->getWindow()->getVRScreen(); else screen=getMainScreen(); ONTransform screenT=screen->getScreenTransformation(); /* Go to screen coordinates: */ glPushMatrix(); glMultMatrix(screenT); /* Determine the screen containing the input device and find its center: */ Scalar centerPos[2]; if(mouseAdapter!=0) mouseAdapter->getWindow()->getWindowCenterPos(centerPos); else { centerPos[0]=getMainScreen()->getWidth()*Scalar(0.5); centerPos[1]=getMainScreen()->getHeight()*Scalar(0.5); } /* Calculate the endpoints of the screen's crosshair lines in screen coordinates: */ Point l=Point(Scalar(0),centerPos[1],Scalar(0)); Point r=Point(screen->getWidth(),centerPos[1],Scalar(0)); Point b=Point(centerPos[0],Scalar(0),Scalar(0)); Point t=Point(centerPos[0],screen->getHeight(),Scalar(0)); /* Determine the crosshair colors: */ Color bgColor=getBackgroundColor(); Color fgColor; for(int i=0;i<3;++i) fgColor[i]=1.0f-bgColor[i]; fgColor[3]=bgColor[3]; /* Draw the screen crosshairs: */ glDepthFunc(GL_LEQUAL); glLineWidth(3.0f); glColor(bgColor); glBegin(GL_LINES); glVertex(l); glVertex(r); glVertex(b); glVertex(t); glEnd(); glLineWidth(1.0f); glColor(fgColor); glBegin(GL_LINES); glVertex(l); glVertex(r); glVertex(b); glVertex(t); glEnd(); /* Go back to physical coordinates: */ glPopMatrix(); /* Restore OpenGL state: */ glPopAttrib(); } }
void MouseDialogNavigationTool::frame(void) { /* Update the current mouse position: */ currentPos=calcScreenPos(); /* Act depending on this tool's current state: */ if(isActive()) { if(spinning) { /* Calculate incremental rotation: */ rotation.leftMultiply(NavTrackerState::rotate(NavTrackerState::Rotation::rotateScaledAxis(spinAngularVelocity*getFrameTime()))); NavTrackerState t=preScale; t*=rotation; t*=postScale; setNavigationTransformation(t); } else { switch(navigationMode) { case ROTATING: { /* Calculate the rotation position: */ Vector offset=(lastRotationPos-screenCenter)+rotateOffset; /* Calculate mouse displacement vector: */ Point rotationPos=currentPos; Vector delta=rotationPos-lastRotationPos; lastRotationPos=rotationPos; /* Calculate incremental rotation: */ Vector axis=Geometry::cross(offset,delta); Scalar angle=Geometry::mag(delta)/factory->rotateFactor; if(angle!=Scalar(0)) rotation.leftMultiply(NavTrackerState::rotate(NavTrackerState::Rotation::rotateAxis(axis,angle))); NavTrackerState t=preScale; t*=rotation; t*=postScale; setNavigationTransformation(t); break; } case PANNING: { /* Update the navigation transformation: */ NavTrackerState t=NavTrackerState::translate(currentPos-motionStart); t*=preScale; setNavigationTransformation(t); break; } case DOLLYING: { /* Calculate the current dollying direction: */ Vector dollyingDirection; if(mouseAdapter!=0) dollyingDirection=mouseAdapter->getWindow()->getVRScreen()->getScreenTransformation().transform(factory->screenDollyingDirection); else dollyingDirection=getMainScreen()->getScreenTransformation().transform(factory->screenDollyingDirection); /* Update the navigation transformation: */ Scalar dollyDist=((currentPos-motionStart)*dollyingDirection)/factory->dollyFactor; NavTrackerState t=NavTrackerState::translate(dollyDirection*dollyDist); t*=preScale; setNavigationTransformation(t); break; } case SCALING: { /* Calculate the current scaling direction: */ Vector scalingDirection; if(mouseAdapter!=0) scalingDirection=mouseAdapter->getWindow()->getVRScreen()->getScreenTransformation().transform(factory->screenScalingDirection); else scalingDirection=getMainScreen()->getScreenTransformation().transform(factory->screenScalingDirection); /* Update the navigation transformation: */ Scalar scale=((currentPos-motionStart)*scalingDirection)/factory->scaleFactor; NavTrackerState t=preScale; t*=NavTrackerState::scale(Math::exp(scale)); t*=postScale; setNavigationTransformation(t); break; } } } } }