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 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 SixDofWithScaleNavigationTool::display(GLContextData& contextData) const { /* Get a pointer to the context entry: */ SixDofWithScaleNavigationToolFactory::DataItem* dataItem=contextData.retrieveDataItem<SixDofWithScaleNavigationToolFactory::DataItem>(factory); /* Translate coordinate system to scaling device's position and orientation: */ glPushMatrix(); glMultMatrix(getButtonDeviceTransformation(1)); /* Execute the tool model display list: */ glCallList(dataItem->modelListId); /* Go back to physical coordinate system: */ glPopMatrix(); }
void GridEditor::EditTool::glRenderActionTransparent(GLContextData& contextData) const { glPushAttrib(GL_ENABLE_BIT|GL_LINE_BIT|GL_POLYGON_BIT); /* Retrieve context entry: */ DataItem* dataItem=contextData.retrieveDataItem<DataItem>(application); /* Render the influence sphere: */ glDisable(GL_LIGHTING); glPushMatrix(); glMultMatrix(getButtonDeviceTransformation(0)); glScale(influenceRadius); glCallList(dataItem->influenceSphereDisplayListId); glPopMatrix(); glPopAttrib(); }
void GridEditor::EditTool::buttonCallback(int buttonSlotIndex,Vrui::InputDevice::ButtonCallbackData* cbData) { if(buttonSlotIndex==0) { /* Activate or deactivate the tool: */ active=cbData->newButtonState; if(active) { /* Initialize the tool's position and orientation in model coordinates: */ lastTrackerState=getButtonDeviceTransformation(0); lastTrackerState.leftMultiply(Vrui::getInverseNavigationTransformation()); } } else if(cbData->newButtonState) { /* Switch editing modes: */ switch(buttonSlotIndex) { case 1: editMode=ADD; break; case 2: editMode=SUBTRACT; break; case 3: editMode=SMOOTH; break; case 4: editMode=DRAG; break; } /* Update the tool mode dialog: */ editModeBox->setSelectedToggle(buttonSlotIndex-1); } }
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 FlyNavigationTool::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=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); /* Request another frame: */ scheduleUpdate(getNextAnimationTime()); } }
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 GridEditor::EditTool::frame(void) { /* Bail out if the tool is not active: */ if(!active) return; /* Update the tool's position and radius in model coordinates: */ Vrui::NavTrackerState newTrackerState=getButtonDeviceTransformation(0); newTrackerState.leftMultiply(Vrui::getInverseNavigationTransformation()); /* Update the brush position and size in model coordinates: */ modelCenter=Point(newTrackerState.getOrigin()); modelRadius=float(influenceRadius*newTrackerState.getScaling()); /* Determine the subdomain of the grid affected by the brush: */ EditableGrid::Index min,max; for(int i=0;i<3;++i) { min[i]=int(Math::floor((modelCenter[i]-modelRadius-fudgeSize)/grid->getCellSize(i))); if(min[i]<1) min[i]=1; max[i]=int(Math::ceil((modelCenter[i]+modelRadius+fudgeSize)/grid->getCellSize(i))); if(max[i]>grid->getNumVertices(i)-1) max[i]=grid->getNumVertices(i)-1; } /* Update the grid: */ float minr2=modelRadius>fudgeSize?Math::sqr(modelRadius-fudgeSize):0.0f; float maxr2=Math::sqr(modelRadius+fudgeSize); switch(editMode) { case ADD: { for(EditableGrid::Index v=min;v[0]<max[0];v.preInc(min,max)) { Point p; float dist=0.0f; for(int i=0;i<3;++i) { p[i]=float(v[i])*grid->getCellSize(i); dist+=Math::sqr(modelCenter[i]-p[i]); } if(dist<maxr2) { float val; if(dist<minr2) val=1.0f; else val=(modelRadius+fudgeSize-Math::sqrt(dist))/(2.0f*fudgeSize); float oldVal=grid->getValue(v); if(val>oldVal) grid->setValue(v,val); } } grid->invalidateVertices(min,max); break; } case SUBTRACT: { for(EditableGrid::Index v=min;v[0]<max[0];v.preInc(min,max)) { Point p; float dist=0.0f; for(int i=0;i<3;++i) { p[i]=float(v[i])*grid->getCellSize(i); dist+=Math::sqr(modelCenter[i]-p[i]); } if(dist<maxr2) { float val; if(dist<minr2) val=0.0f; else val=1.0f-(modelRadius+fudgeSize-Math::sqrt(dist))/(2.0f*fudgeSize); float oldVal=grid->getValue(v); if(val<oldVal) grid->setValue(v,val); } } grid->invalidateVertices(min,max); break; } case SMOOTH: { for(int i=0;i<3;++i) { if(min[i]==0) ++min[i]; if(max[i]==grid->getNumVertices(i)) --max[i]; } for(EditableGrid::Index v=min;v[0]<max[0];v.preInc(min,max)) { Point p; float dist=0.0f; for(int i=0;i<3;++i) { p[i]=float(v[i])*grid->getCellSize(i); dist+=Math::sqr(modelCenter[i]-p[i]); } if(dist<maxr2) { float avgVal=0.0f; EditableGrid::Index i; for(i[0]=v[0]-1;i[0]<=v[0]+1;++i[0]) for(i[1]=v[1]-1;i[1]<=v[1]+1;++i[1]) for(i[2]=v[2]-1;i[2]<=v[2]+1;++i[2]) avgVal+=grid->getValue(i); avgVal/=27.0f; if(dist<minr2) newValues(v)=avgVal; else { float w=(modelRadius+fudgeSize-Math::sqrt(dist))/(2.0f*fudgeSize); newValues(v)=avgVal*w+grid->getValue(v)*(1.0f-w); } } else newValues(v)=grid->getValue(v); } for(EditableGrid::Index v=min;v[0]<max[0];v.preInc(min,max)) grid->setValue(v,newValues(v)); grid->invalidateVertices(min,max); /* Request another frame to continue smoothing: */ Vrui::scheduleUpdate(Vrui::getApplicationTime()+1.0/125.0); break; } case DRAG: { /* Calculate the incremental tool transformation since the last frame: */ Vrui::NavTrackerState t=lastTrackerState; t*=Geometry::invert(newTrackerState); Geometry::OrthogonalTransformation<float,3> pt(t); float r2=Math::sqr(modelRadius); for(EditableGrid::Index v=min;v[0]<max[0];v.preInc(min,max)) { Point p; float dist=0.0f; for(int i=0;i<3;++i) { p[i]=float(v[i])*grid->getCellSize(i); dist+=Math::sqr(modelCenter[i]-p[i]); } if(dist<r2) { /* Compute the dragged position: */ Point dp=pt.transform(p); float w=Math::sqrt(dist)/modelRadius; dp=Geometry::affineCombination(dp,p,w); /* Look up the grid value at the dragged position: */ float dragVal=grid->getValue(dp); newValues(v)=dragVal; } else newValues(v)=grid->getValue(v); } for(EditableGrid::Index v=min;v[0]<max[0];v.preInc(min,max)) grid->setValue(v,newValues(v)); grid->invalidateVertices(min,max); break; } } lastTrackerState=newTrackerState; }
void ComeHitherNavigationTool::buttonCallback(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=getButtonDeviceTransformation(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); } } } } }