// Left hand effector's extend function for a single object. // Purpose: // - Extends effector until it touches the object or reaches the maximum length. void LeftVirtualHand::extend(arEffector& self, arInteractable* object, float maxLength) { // Return if grabbing an object. if(getGrabbedObject() != 0) return; // Reset tip to 0.0 ft. length. _currentLength = 0.0; setTipOffset(arVector3(0, 0, -_currentLength)); // Check if the maximum length has been reached or an object has been touched. while(_currentLength < maxLength && !ar_pollingInteraction(self, object)) { // If not, increase tip length by interaction distance. _currentLength += _interactionDistance; setTipOffset(arVector3(0, 0, -_currentLength)); } }
// start callback // Purposes: // - Register shared memory by adding transfer fields. This is to syncronize cluster-based // systems, hence we don't need to do this. But there's a few examples anyway. // - Set up navigation through the framework by specifying translation conditions, rotation // conditions, translation speed, and rotation speed. We provide a couple examples here. // - Initialize any global variables specific to your application. // Notes: // DO NOT initialize OpenGL here. The start callback is called before window creation. // Instead initialize OpenGL in the windowStartGL callback. bool start(arMasterSlaveFramework& framework, arSZGClient& client ) { theMrCreepyBook7.setMatrix(ar_translationMatrix(-3,4,-7)); objects.push_back(&theMrCreepyBook7); theMrBookshelf6.setMatrix(ar_translationMatrix(-3,3,-7)); objects.push_back(&theMrBookshelf6); theMrDungeonRoom5.setMatrix(ar_translationMatrix(0,4,-5)); objects.push_back(&theMrDungeonRoom5); // Register shared memory. Not needed for non-cluster-based systems. // framework.addTransferField(char* name, void* address, arDataType type, int numElements); vector<arInteractable*>::iterator i; for(i=objects.begin(); i != objects.end(); ++i) { Object* obj = ((Object*)(*i)); obj->loadedOBJ.normalizeModelSize(); ostringstream ostr; ostr << "objMatrix" << &i; arMatrix4 obM = obj->matrix; framework.addTransferField(ostr.str(), &obM, AR_FLOAT, 16); } // Set up navigation. // A traditional pointing technique using the joystick with left and right rotating the scene. // Translate along Z-axis (forwards/backwards) if joystick is pressed more than 20% along axis 1. framework.setNavTransCondition('z', AR_EVENT_AXIS, 1, 0.2); // Rotate around Y-axis (vertical) if joystick is pressed more than 20% along axis 0. //framework.setNavRotCondition('y', AR_EVENT_AXIS, 0, 0.2); //FOR ROTATE framework.setNavTransCondition('x', AR_EVENT_AXIS, 0, 0.2); //FOR STRAFING // Set translation speed to 5 feet/second. framework.setNavTransSpeed(5.0); // Set rotation speed to 30 degrees/second. framework.setNavRotSpeed(30.0); // Initialize application variables here. // Move object's to initial positions. // Create sound transform. soundTransformID = dsTransform("world", framework.getNavNodeName(), ar_scaleMatrix(1.0)); // Parameters are: // name - string name for sound // transformName - string name for dsTransform // loopType - 1 for continuous, -1 for one-time, 0 to stop // loudness - float from 0.0 (quiet) to 1.0 (max) // positionVector - vector position of sound origin // Create loop for click sound. clickSound = dsLoop("click", "world", "click.mp3", 0, 1.0, arVector3(0, 0, 0)); musicNotey.readOBJ("MusicNote.obj","data/obj"); // Return true if everything is initialized correctly. return true; }
// preExchange callback // Purposes: // - Handle navigation updates. // - Process user input. // - Set random variables. // - Update shared memory. // Notes: // This is only called on the master node of the cluster and before shared memory is // transferred to the slave nodes. void preExchange(arMasterSlaveFramework& framework) { // Handle navigation update. The resulting navigation matrix is automatically transferred // to the slave nodes. framework.navUpdate(); currentTimeGlobal = framework.getTime(); double currentTime = framework.getTime(); // Process user input. // Update shared memory. // Transfer data about objects to slave nodes. // Detect right hand collisions. rightHand.detectCollisions(rightHand, objects); // Extend left ray to collision point. leftHand.extend(leftHand, objects); // Update input state (placement matrix & button states) of our effectors. rightHand.updateState(framework.getInputState()); leftHand.updateState(framework.getInputState()); // Handle any interaction with the objects (see interaction/arInteractionUtilities.h). list<arInteractable*> objectlist; std::copy(objects.begin (), objects.end (), std::back_inserter(objectlist)); ar_pollingInteraction(rightHand, objectlist); ar_pollingInteraction(leftHand, objectlist); // Play click sound if right hand has grabbed an object. if(rightHand.getGrabbedObject() != 0) { dsLoop(clickSound, "click.mp3", -1, 1.0, arVector3(0, 0, 0)); } // Or reset the trigger else { dsLoop(clickSound, "click.mp3", 0, 1.0, arVector3(0, 0, 0)); } // Update shared memory. // Transfer data about objects to slave nodes. vector<arInteractable*>::iterator i; for(i=objects.begin(); i != objects.end(); ++i) { Object* oby = ((Object*)(*i)); oby->matrix = oby->getMatrix(); } arMatrix4 navMatrix = ar_getNavMatrix(); }
// Left hand effector's extend function for multiple objects. // Purpose: // - Extends effector until it touches an object or reaches the maximum length. void LeftVirtualHand::extend(arEffector& self, vector<arInteractable*>& objects, float maxLength) { // Return if grabbing an object. if(getGrabbedObject() != 0) return; // Reset tip to 0.0 ft. length. _currentLength = 0.0; setTipOffset(arVector3(0, 0, -_currentLength)); list<arInteractable*> objectlist; std::copy(objects.begin (), objects.end (), std::back_inserter(objectlist)); // Check if the maximum length has been reached or an object has been touched. while(_currentLength < maxLength && !ar_pollingInteraction(self, objectlist)) { // If not, increase tip length by interaction distance. _currentLength += _interactionDistance; setTipOffset(arVector3(0, 0, -_currentLength)); } if(selectionMode == 3 && ar_pollingInteraction(self, objectlist)) //if it interacted { //cout << "hit an object" << '\n'; //find out which object it interacted with vector<arInteractable*>::iterator i; for(i=objects.begin(); i != objects.end(); ++i) { if(ar_pollingInteraction(self, *i)) { Object *oby = ((Object*)(*i)); oby->_selected = !oby->_selected; selectionMode = 0; } } selectionMode = 0; } else if(selectionMode==3) { selectionMode = 0; } else if(selectionMode == 1) { leftSelectedObjects.clear(); upSelectedObjects.clear(); rightSelectedObjects.clear(); downSelectedObjects.clear(); int numObjects = 0; vector<arInteractable*>::iterator i; for(i=objects.begin(); i != objects.end(); ++i) { // get object location Object* oby = ((Object*)(*i)); arMatrix4 objLoc = oby->getMatrix(); // if object is in cone, then add to selected list float x[] = {objLoc[12], objLoc[13], objLoc[14]}; float height = getLength(); float radius = height/2.f; arMatrix4 tp = getBaseMatrix(); arMatrix4 bm = getMatrix(); float t[] = {tp[12],tp[13],tp[14]}; float b[] = {bm[12],bm[13],bm[14]}; if(isLyingInCone(x, t, b, radius, height)) { if((numObjects) % 4 == 0) { leftSelectedObjects.push_back(oby); } else if(numObjects % 4 == 1) { upSelectedObjects.push_back(oby); } else if(numObjects % 4 == 2) { rightSelectedObjects.push_back(oby); } else if(numObjects % 4 == 3) { downSelectedObjects.push_back(oby); } ++numObjects; } } if(numObjects == 0) { selectionMode = 0; } else if(numObjects == 1) { //if only one object, select it selectionMode = 0; Object* oby = leftSelectedObjects.front(); //set the one object to selected oby->_selected = !oby->_selected; } else { //else selectionMode = 2, selected lists have all the items selectionMode = 2; } } }