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 GrapheinClient::GrapheinTool::frame(void) { if(client==0) return; if(active) { /* Update the current dragging point: */ const Vrui::NavTransform& invNav=Vrui::getInverseNavigationTransformation(); currentPoint=invNav.transform(getButtonDevicePosition(0)); /* Check if the dragging point is far enough away from the most recent curve vertex: */ if(Geometry::sqrDist(currentPoint,lastPoint)>=Math::sqr(Vrui::getUiSize()*invNav.getScaling())) { CurveMap::Iterator cIt=client->localCurves.findEntry(currentCurveId); if(!cIt.isFinished()) { /* Add the dragging point to the curve: */ cIt->getDest()->vertices.push_back(currentPoint); /* Send a vertex appending message: */ { Threads::Mutex::Lock messageLock(client->messageMutex); writeMessage(APPEND_POINT,client->message); client->message.write<Card>(currentCurveId); write(currentPoint,client->message); } } /* Remember the last added point: */ lastPoint=currentPoint; } } }
void SketchingTool::buttonCallback(int,InputDevice::ButtonCallbackData* cbData) { /* Check if the button has just been pressed: */ if(cbData->newButtonState) { /* Activate the tool: */ active=true; /* Start a new curve: */ currentCurve=new Curve; currentCurve->lineWidth=newLineWidth; currentCurve->color=newColor; curves.push_back(currentCurve); /* Append the curve's first control point: */ Curve::ControlPoint cp; const NavTransform& invNav=getInverseNavigationTransformation(); cp.pos=lastPoint=invNav.transform(getButtonDevicePosition(0)); cp.t=getApplicationTime(); currentCurve->controlPoints.push_back(cp); } else { /* Append the final control point to the curve: */ Curve::ControlPoint cp; cp.pos=currentPoint; cp.t=getApplicationTime(); currentCurve->controlPoints.push_back(cp); /* Deactivate the tool: */ active=false; currentCurve=0; } }
void GrapheinClient::GrapheinTool::buttonCallback(int,Vrui::InputDevice::ButtonCallbackData* cbData) { if(client==0) return; /* Check if the button has just been pressed: */ if(cbData->newButtonState) { /* Activate the tool: */ active=true; /* Start a new curve: */ currentCurveId=client->nextLocalCurveId; ++client->nextLocalCurveId; Curve* newCurve=new Curve; newCurve->lineWidth=newLineWidth; newCurve->color=newColor; const Vrui::NavTransform& invNav=Vrui::getInverseNavigationTransformation(); lastPoint=invNav.transform(getButtonDevicePosition(0)); newCurve->vertices.push_back(lastPoint); client->localCurves.setEntry(CurveMap::Entry(currentCurveId,newCurve)); /* Send a curve creation message: */ { Threads::Mutex::Lock messageLock(client->messageMutex); writeMessage(ADD_CURVE,client->message); client->message.write<Card>(currentCurveId); newCurve->write(client->message); } } else { /* Retrieve the current curve: */ CurveMap::Iterator cIt=client->localCurves.findEntry(currentCurveId); if(!cIt.isFinished()) { if(currentPoint!=lastPoint) { /* Add the final dragging point to the curve: */ cIt->getDest()->vertices.push_back(currentPoint); /* Send a vertex appending message: */ { Threads::Mutex::Lock messageLock(client->messageMutex); writeMessage(APPEND_POINT,client->message); client->message.write<Card>(currentCurveId); write(currentPoint,client->message); } } } /* Deactivate the tool: */ active=false; } }
void JediTool::frame(void) { if(active) { /* Update the light saber billboard: */ origin=getButtonDevicePosition(0); axis=getButtonDeviceRayDirection(0); /* Scale the lightsaber during activation: */ length=factory->lightsaberLength; double activeTime=getApplicationTime()-activationTime; if(activeTime<1.5) { length*=activeTime/1.5; /* Request another frame: */ scheduleUpdate(getNextAnimationTime()); } } }
void SixDofWithScaleNavigationTool::frame(void) { /* Act depending on this tool's current state: */ switch(navigationMode) { case IDLE: /* Do nothing */ break; case MOVING: { /* Compose the new navigation transformation: */ NavTrackerState navigation=getButtonDeviceTransformation(0); navigation*=preScale; /* Update Vrui's navigation transformation: */ setNavigationTransformation(navigation); break; } case SCALING: { /* Compose the new navigation transformation: */ NavTrackerState navigation=preScale; Vector scaleDirection=getButtonDeviceTransformation(1).transform(factory->deviceScaleDirection); Scalar currentScale=Math::exp((getButtonDevicePosition(0)*scaleDirection-initialScale)/factory->scaleFactor); navigation*=NavTrackerState::scale(currentScale); navigation*=postScale; /* Update Vrui's navigation transformation: */ setNavigationTransformation(navigation); break; } } /* Update the virtual input device: */ InputDevice* device=getButtonDevice(1); buttonDevice->setTransformation(device->getTransformation()); buttonDevice->setDeviceRayDirection(device->getDeviceRayDirection()); }
void SketchingTool::frame(void) { if(active) { /* Get the current dragging point: */ const NavTransform& invNav=getInverseNavigationTransformation(); currentPoint=invNav.transform(getButtonDevicePosition(0)); /* Check if the dragging point is far enough away from the most recent curve vertex: */ if(Geometry::sqrDist(currentPoint,lastPoint)>=Math::sqr(factory->detailSize*invNav.getScaling())) { /* Append the current dragging point to the curve: */ Curve::ControlPoint cp; cp.pos=currentPoint; cp.t=getApplicationTime(); currentCurve->controlPoints.push_back(cp); /* Remember the last added point: */ lastPoint=currentPoint; } } }
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; } }
void MultiDeviceNavigationTool::frame(void) { /* Do nothing if the tool is inactive: */ if(isActive()) { /* Calculate the centroid of all devices whose buttons were pressed in the last frame: */ int numLastDevices=0; Point::AffineCombiner centroidC; for(int i=0;i<input.getNumButtonSlots();++i) if(lastDeviceButtonStates[i]) { ++numLastDevices; centroidC.addPoint(getButtonDevicePosition(i)); } if(numLastDevices>0) { Point currentCentroid=centroidC.getPoint(); /* Calculate the average rotation vector and scaling factor of all devices whose buttons were pressed in the last frame: */ Vector rotation=Vector::zero; Scalar scaling(1); int numActiveDevices=0; for(int i=0;i<input.getNumButtonSlots();++i) if(lastDeviceButtonStates[i]) { /* Calculate the previous vector to centroid: */ Vector lastDist=lastDevicePositions[i]-lastCentroid; Scalar lastLen=Geometry::mag(lastDist); /* Calculate the new vector to centroid: */ Vector currentDist=getButtonDevicePosition(i)-currentCentroid; Scalar currentLen=Geometry::mag(currentDist); if(lastLen>configuration.minRotationScalingDistance&¤tLen>configuration.minRotationScalingDistance) { /* Calculate the rotation axis and angle: */ Vector rot=lastDist^currentDist; Scalar rotLen=Geometry::mag(rot); if(rotLen>Scalar(0)) { Scalar angle=Math::asin(rotLen/(lastLen*currentLen)); rot*=angle/rotLen; /* Accumulate the rotation vector: */ rotation+=rot; } /* Calculate the scaling factor: */ Scalar scal=currentLen/lastLen; /* Accumulate the scaling factor: */ scaling*=scal; ++numActiveDevices; } } /* Navigate: */ NavTransform t=NavTransform::translate((currentCentroid-lastCentroid)*configuration.translationFactor); if(numActiveDevices>0) { /* Average and scale rotation and scaling: */ rotation*=configuration.rotationFactor/Scalar(numActiveDevices); scaling=Math::pow(scaling,configuration.scalingFactor/Scalar(numActiveDevices)); /* Apply rotation and scaling: */ t*=NavTransform::translateFromOriginTo(currentCentroid); t*=NavTransform::rotate(Rotation::rotateScaledAxis(rotation)); t*=NavTransform::scale(scaling); t*=NavTransform::translateToOriginFrom(currentCentroid); } concatenateNavigationTransformationLeft(t); } /* Update button states and device positions for next frame: */ Point::AffineCombiner newLastCentroidC; for(int i=0;i<input.getNumButtonSlots();++i) { lastDeviceButtonStates[i]=getButtonState(i); lastDevicePositions[i]=getButtonDevicePosition(i); if(lastDeviceButtonStates[i]) newLastCentroidC.addPoint(lastDevicePositions[i]); } lastCentroid=newLastCentroidC.getPoint(); } }