void SixAxisTransformTool::frame(void) { /* 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+=config.rotations[i]*Scalar(getValuatorState(3+i)); rotation*=getCurrentFrameTime(); /* Calculate an incremental transformation for the virtual input device: */ ONTransform deltaT=ONTransform::translate(translation); Point pos=transformedDevice->getPosition(); deltaT*=ONTransform::translateFromOriginTo(pos); deltaT*=ONTransform::rotate(ONTransform::Rotation::rotateScaledAxis(rotation)); deltaT*=ONTransform::translateToOriginFrom(pos); /* Update the virtual input device's transformation: */ deltaT*=transformedDevice->getTransformation(); deltaT.renormalize(); transformedDevice->setTransformation(deltaT); /* Request another frame if the input device has moved: */ if(translation!=Vector::zero||rotation!=Vector::zero) { /* Request another frame: */ scheduleUpdate(getApplicationTime()+1.0/125.0); } }
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 Time::show () { getLog()->trace ( "CurrentTime: {}, LastTime: {}, DeltaTime: {}" , getCurrentFrameTime(), getLastFrameTime(), getFrameTimeDelta() ); }
void FPSNavigationTool::frame(void) { /* Act depending on this tool's current state: */ if(isActive()) { /* Calculate the change in mouse position: */ Point mousePos=calcMousePosition(); if(mousePos[0]!=lastMousePos[0]||mousePos[1]!=lastMousePos[1]||moveVelocity[0]!=Scalar(0)||moveVelocity[2]!=Scalar(0)) { angles[0]+=(mousePos[0]-lastMousePos[0])/factory->rotateFactor; angles[0]=Math::wrapRad(angles[0]); angles[1]+=(mousePos[1]-lastMousePos[1])/factory->rotateFactor; if(angles[1]<Math::rad(Scalar(-90))) angles[1]=Math::rad(Scalar(-90)); else if(angles[1]>Math::rad(Scalar(90))) angles[1]=Math::rad(Scalar(90)); /* Calculate the new orientation and move by the current velocity: */ ONTransform::Rotation yawT=ONTransform::Rotation::rotateY(angles[0]); ONTransform::Rotation rot=navFrame; rot*=ONTransform::Rotation::rotateX(angles[1]); rot*=yawT; pos+=yawT.inverseTransform(moveVelocity*getCurrentFrameTime()); /* Set the new navigation transformation: */ NavTransform nav=NavTransform::translateFromOriginTo(getMainViewer()->getHeadPosition()); nav*=NavTransform::rotate(rot); nav*=NavTransform::translateToOriginFrom(getMainViewer()->getHeadPosition()); nav*=NavTransform::translateFromOriginTo(pos); nav*=preScale; setNavigationTransformation(nav); if(mousePos[0]!=lastMousePos[0]||mousePos[1]!=lastMousePos[1]) { if(mouseAdapter!=0) { /* Warp the cursor back to the center of the window: */ mouseAdapter->getWindow()->setCursorPos(lastMousePos.getComponents()); } else lastMousePos=mousePos; } } } }
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=input.getDevice(0)->getTransformation(); /* Calculate the current flying velocity: */ Vector v=ts.transform(factory->flyDirection); v*=currentValue*factory->flyFactor*getCurrentFrameTime(); /* Compose the new navigation transformation: */ NavTransform t=NavTransform::translate(v); t*=getNavigationTransformation(); /* Update Vrui's navigation transformation: */ setNavigationTransformation(t); } }
void SixAxisSurfaceNavigationTool::frame(void) { /* Act depending on this tool's current state: */ if(isActive()) { /* Use the average frame time as simulation time: */ Scalar dt=getCurrentFrameTime(); /* Update rotation angles based on current rotation valuator states: */ for(int i=0;i<3;++i) angles[i]=wrapAngle(angles[i]+getValuatorState(i+3)*factory->rotateFactors[i]*dt); if(angles[1]<Math::rad(Scalar(-90))) angles[1]=Math::rad(Scalar(-90)); else if(angles[1]>Math::rad(Scalar(90))) angles[1]=Math::rad(Scalar(90)); if(!factory->canRoll||factory->bankTurns) { Scalar targetRoll=factory->bankTurns?getValuatorState(3)*factory->rotateFactors[2]:Scalar(0); Scalar t=Math::exp(-factory->levelSpeed*dt); angles[2]=angles[2]*t+targetRoll*(Scalar(1)-t); if(Math::abs(angles[2]-targetRoll)<Scalar(1.0e-3)) angles[2]=targetRoll; } /* Calculate the new head position: */ Point newHeadPos=getMainViewer()->getHeadPosition(); /* Create a physical navigation frame around the new foot position: */ calcPhysicalFrame(newHeadPos); /* Calculate movement from head position change: */ Vector move=newHeadPos-headPos; headPos=newHeadPos; /* Add movement velocity based on the current translation valuator states: */ for(int i=0;i<3;++i) move[i]+=getValuatorState(i)*factory->translateFactors[i]*dt; /* Transform the movement vector from physical space to the physical navigation frame: */ move=physicalFrame.inverseTransform(move); /* Rotate by the current azimuth and elevation angles: */ move=Rotation::rotateX(-angles[1]).transform(move); move=Rotation::rotateZ(-angles[0]).transform(move); /* Move the surface frame: */ NavTransform newSurfaceFrame=surfaceFrame; newSurfaceFrame*=NavTransform::translate(move); /* Re-align the surface frame with the surface: */ Point initialOrigin=newSurfaceFrame.getOrigin(); Rotation initialOrientation=newSurfaceFrame.getRotation(); AlignmentData ad(surfaceFrame,newSurfaceFrame,factory->probeSize,factory->maxClimb); align(ad); if(!factory->fixAzimuth) { /* Have the azimuth angle track changes in the surface frame's rotation: */ Rotation rot=Geometry::invert(initialOrientation)*newSurfaceFrame.getRotation(); rot.leftMultiply(Rotation::rotateFromTo(rot.getDirection(2),Vector(0,0,1))); Vector x=rot.getDirection(0); angles[0]=wrapAngle(angles[0]+Math::atan2(x[1],x[0])); } /* If flying is allowed and the initial surface frame was above the surface, lift it back up: */ Scalar z=newSurfaceFrame.inverseTransform(initialOrigin)[2]; if(!factory->canFly||z<factory->probeSize) z=factory->probeSize; newSurfaceFrame*=NavTransform::translate(Vector(Scalar(0),Scalar(0),z)); /* Apply the newly aligned surface frame: */ surfaceFrame=newSurfaceFrame; applyNavState(); /* Deactivate the tool if it is done: */ if(numActiveAxes==0&&Math::abs(angles[2])<Math::Constants<Scalar>::epsilon) deactivate(); else { /* Request another frame: */ scheduleUpdate(getApplicationTime()+1.0/125.0); } } }
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 MouseNavigationTool::buttonCallback(int,int buttonIndex,InputDevice::ButtonCallbackData* cbData) { /* Process based on which button was pressed: */ switch(buttonIndex) { case 0: if(cbData->newButtonState) // Button has just been pressed { /* Act depending on this tool's current state: */ switch(navigationMode) { case IDLE: case SPINNING: if(factory->interactWithWidgets) { /* Check if the mouse pointer is over a GLMotif widget: */ GLMotif::Event event(false); event.setWorldLocation(calcSelectionRay()); if(getWidgetManager()->pointerButtonDown(event)) { if(navigationMode==SPINNING) { /* Deactivate this tool: */ deactivate(); } /* Go to widget interaction mode: */ navigationMode=WIDGETING; /* Drag the entire root widget if the event's target widget is a title bar: */ if(dynamic_cast<GLMotif::TitleBar*>(event.getTargetWidget())!=0) { /* Start dragging: */ draggedWidget=event.getTargetWidget(); /* Calculate the dragging transformation: */ NavTrackerState initialTracker=NavTrackerState::translateFromOriginTo(calcScreenPos()); preScale=Geometry::invert(initialTracker); GLMotif::WidgetManager::Transformation initialWidget=getWidgetManager()->calcWidgetTransformation(draggedWidget); preScale*=NavTrackerState(initialWidget); } else draggedWidget=0; } else { /* Try activating this tool: */ if(navigationMode==SPINNING||activate()) startRotating(); } } else { /* Try activating this tool: */ if(navigationMode==SPINNING||activate()) startRotating(); } break; case PANNING: if(dolly) startDollying(); else startScaling(); 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 WIDGETING: { /* Deliver the event: */ GLMotif::Event event(true); event.setWorldLocation(calcSelectionRay()); getWidgetManager()->pointerButtonUp(event); /* Deactivate this tool: */ navigationMode=IDLE; draggedWidget=0; break; } case ROTATING: { /* Check if the input device is still moving: */ Point currentPos=calcScreenPos(); Vector delta=currentPos-lastRotationPos; if(Geometry::mag(delta)>factory->spinThreshold) { /* Calculate spinning angular velocity: */ Vector offset=(lastRotationPos-screenCenter)+rotateOffset; Vector axis=Geometry::cross(offset,delta); Scalar angularVelocity=Geometry::mag(delta)/(factory->rotateFactor*getCurrentFrameTime()); spinAngularVelocity=axis*(Scalar(0.5)*angularVelocity/axis.mag()); /* Go to spinning mode: */ navigationMode=SPINNING; } else { /* Deactivate this tool: */ deactivate(); /* Go to idle mode: */ navigationMode=IDLE; } break; } case DOLLYING: case SCALING: startPanning(); 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: case SPINNING: /* Try activating this tool: */ if(navigationMode==SPINNING||activate()) startPanning(); break; case ROTATING: if(dolly) startDollying(); else startScaling(); 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 PANNING: /* Deactivate this tool: */ deactivate(); /* Go to idle mode: */ navigationMode=IDLE; break; case DOLLYING: case SCALING: startRotating(); break; default: /* This shouldn't happen; just ignore the event */ break; } } break; case 2: /* Set the dolly flag: */ dolly=cbData->newButtonState; if(factory->invertDolly) dolly=!dolly; if(dolly) // Dollying has just been enabled { /* Act depending on this tool's current state: */ switch(navigationMode) { case SCALING: startDollying(); break; default: /* Nothing to do */ break; } } else { /* Act depending on this tool's current state: */ switch(navigationMode) { case DOLLYING: startScaling(); break; default: /* Nothing to do */ break; } } break; } }