void doSceneGraph( arMasterSlaveFramework &fw ) { static int loops = 0; static ar_timeval starttime = ar_time(); static ar_timeval lastdrawtime = ar_time(); ar_timeval now = ar_time(); long long curtime = ( now.sec * 1000000 ) + now.usec, lasttime = ( lastdrawtime.sec * 1000000 ) + lastdrawtime.usec; long long sleeptime = 2000 - ( curtime - lasttime ); ar_usleep( max( (int)sleeptime, 1 ) ); fw.loadNavMatrix(); glClearColor( 0, 0.749, 1, 0 ); primary.draw(); secondary.draw(); sg->drawSceneGraph(); if( menuOn ) drawMenu( menu, fw ); lastdrawtime = ar_time(); loops++; if( lastdrawtime.sec > starttime.sec ) { cout << "fps=" << loops << endl; starttime = lastdrawtime; loops = 0; } }
// draw callback // Purposes: // - Load the navigation matrix to reflect frame's navigation // - Use OpenGL to generate computer graphics. void draw(arMasterSlaveFramework& framework) { // Load the navigation matrix. framework.loadNavMatrix(); // Generate graphics. if(selectionMode == 2) { renderPrimitive(-2.5f); // draws square with quadrants drawObjects(-2.5f); // draw the mini versions } vector<arInteractable*>::iterator i; for(i=objects.begin(); i != objects.end(); ++i) { Object* oby = ((Object*)(*i)); oby->draw(); } // Draw the effectors. rightHand.draw(); leftHand.draw(); }
void drawHelp( arMasterSlaveFramework &fw ) { static arTexture tex; static bool init = false; if( !init ) { tex.readJPEG( "help.jpg" ); init = true; } static float size = 4; static GLfloat v[4][3] = { { -size / 2, -size / 2, 0.0001 }, { size / 2, -size / 2, 0.0001 }, { size / 2, size / 2, 0.0001 }, { -size / 2, size / 2, 0.0001 } }; glPushMatrix(); glMultMatrixf( ( ar_getNavMatrix() * fw.getMidEyeMatrix() * ar_TM( 0, 0, -5 ) ).v ); glClearColor( 1, 1, 1, 0 ); tex.activate(); glBegin( GL_QUADS ); glTexCoord2f( 0, 0 ); glVertex3fv( v[0] ); glTexCoord2f( 1, 0 ); glVertex3fv( v[1] ); glTexCoord2f( 1, 1 ); glVertex3fv( v[2] ); glTexCoord2f( 0, 1 ); glVertex3fv( v[3] ); glEnd(); tex.deactivate(); glPopMatrix(); }
// postExchange callback // Purposes: // - Update effectors based on input state transferred from master node. // - Synchronize slave nodes with master node based on transferred data. This is not necessary // for our system, but here's an example for cluster-based systems. void postExchange(arMasterSlaveFramework& framework) { // Presumably the master node already is up-to-date, so we ignore it. if(!framework.getMaster()) { // Update effectors. rightHand.updateState(framework.getInputState()); leftHand.updateState(framework.getInputState()); // Synchronize shared memory. vector<arInteractable*>::iterator i; for(i=objects.begin(); i != objects.end(); ++i) { Object* oby = ((Object*)(*i)); oby->setMatrix(oby->matrix.v); } } }
// windowEvent callback // Purposes: // - Process window events, such as resizing // Notes: // The values are defined in src/graphics/arGUIDefines.h. // arGUIWindowInfo is in arGUIInfo.h. // The window manager is in arGUIWindowManager.h. void windowEvent(arMasterSlaveFramework& framework, arGUIWindowInfo* windowInfo) { // Process window events. Here, we handle window resizing. if(windowInfo->getState() == AR_WINDOW_RESIZE) { const int windowID = windowInfo->getWindowID(); #ifdef UNUSED const int x = windowInfo->getPosX(); const int y = windowInfo->getPosY(); #endif const int width = windowInfo->getSizeX(); const int height = windowInfo->getSizeY(); framework.getWindowManager()->setWindowViewport(windowID, 0, 0, width, height); } }
// 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(); }
void onPreExchange( arMasterSlaveFramework &fw ) { fw.navUpdate(); // update the input state (placement matrix & button states) of our effector. primary.updateState( fw.getInputState() ); secondary.updateState( fw.getInputState() ); if( primary.getButton( WiiMote::HOME ) && secondary.getButton( WiiMote::HOME ) ) { helpOn = true; setMenuOff(); fw.setDrawCallback( drawHelp ); } if( helpOn ) { if( primary.getButton( WiiMote::A ) || secondary.getButton( WiiMote::A ) ) { helpOn = false; fw.setDrawCallback( doSceneGraph ); return; } } else { //used for scale the world (and possibly other scales later) WiiMote::updateTipDistance(primary, secondary); scaleWorld(); moveWorld( fw ); std::map<WiiMote::button_t, std::list<WiiMote*> > buttonMap; WiiMote::ButtonList buttons = secondary.getDownButtons(); for( WiiMote::ButtonList::iterator it = buttons.begin(); it != buttons.end(); ++it ) { // Process all butons just pressed on secondary if( buttonMap.find( *it ) == buttonMap.end() ) buttonMap.insert( std::make_pair( *it, std::list<WiiMote*>( 1, &secondary ) ) ); else buttonMap[*it].push_back( &secondary ); } buttons = primary.getDownButtons(); for( WiiMote::ButtonList::iterator it = buttons.begin(); it != buttons.end(); ++it ) { // Process all butons just pressed on primary if( buttonMap.find( *it ) == buttonMap.end() ) buttonMap.insert( std::make_pair( *it, std::list<WiiMote*>( 1, &primary ) ) ); else buttonMap[*it].push_back( &primary ); } buttons = primary.getUpButtons(); for( WiiMote::ButtonList::iterator it = buttons.begin(); it != buttons.end(); ++it ) { switch( *it ) { case WiiMote::A: case WiiMote::B: if( primary.getGrabbedObject() ) primary.requestUngrab( primary.getGrabbedObject() ); break; default: break; } } buttons = secondary.getUpButtons(); for( WiiMote::ButtonList::iterator it = buttons.begin(); it != buttons.end(); ++it ) { switch( *it ) { case WiiMote::A: case WiiMote::B: if( secondary.getGrabbedObject() ) secondary.requestUngrab( secondary.getGrabbedObject() ); break; default: break; } } for( std::map<WiiMote::button_t, std::list<WiiMote*> >::iterator it = buttonMap.begin(); it != buttonMap.end(); ++it ) { switch( it->first ) { case WiiMote::HOME: toggleMenu(); break; case WiiMote::DOWN: if( menuOn ) menu->pressedDown(); break; case WiiMote::RIGHT: if( menuOn ) menu->pressedRight(); break; case WiiMote::LEFT: if( menuOn ) menu->pressedLeft(); break; case WiiMote::UP: if( menuOn ) menu->pressedUp(); break; case WiiMote::MINUS: cout << "MINUS was pressed" << endl; if( !menuOn ) { iSelectMenuObj = 1; for( std::list<arInteractable*>::iterator it = SelectedObjects.begin(); it != SelectedObjects.end(); ++it ) if( Node *n = dynamic_cast<Node*>( *it ) ) n->setSelected( false ); SelectedObjects.clear(); } break; case WiiMote::PLUS: cout << "PLUS was pressed" << endl; if( !menuOn ) iSelectMenuObj = 2; break; case WiiMote::A: iSelectMenuObj = 0; if( menuOn ) { switch( menu->pressedA() ) { case REDRAW: setMenuOff(); setMenuOn(); break; case CLOSE: setMenuOff(); break; default: break; } } break; case WiiMote::ONE: for(std::list<WiiMote*>::iterator itt = it->second.begin(); itt != it->second.end(); ++itt) { (*itt)->toggleLightSaber(); } break; default: break; } } // do ray-casting after menu actions if ( !menuOn ) { rightClosest = primary.closestObject(interactableObjects); leftClosest = secondary.closestObject(interactableObjects); } if( rightClosest ) { rightClosest->touch( primary ); if( primary.getButton( WiiMote::A ) && primary.getButton( WiiMote::B ) ) { primary.requestScaleGrab( rightClosest ); } else if( primary.getButton( WiiMote::A ) ) { primary.requestPosGrab( rightClosest ); } else if( primary.getButton( WiiMote::B ) ) { primary.requestRotGrab( rightClosest ); } else if(((primary.getButton( WiiMote::PLUS )) || (primary.getButton( WiiMote::MINUS ))) && ((iSelectMenuObj == 1) || (iSelectMenuObj == 2))) { bool found = false; std::list<arInteractable*> tempSelectedObjects; while (!SelectedObjects.empty()) { if ( SelectedObjects.front() == rightClosest ) { cout << "Removing right hand object to selected list" << endl; rightClosest->setSelected( false ); SelectedObjects.pop_front(); found = true; iSelectMenuObj = 0; break; } else { tempSelectedObjects.push_back( SelectedObjects.front() ); SelectedObjects.pop_front(); } } while (!tempSelectedObjects.empty()) { SelectedObjects.push_back( tempSelectedObjects.front() ); if( Node *n = dynamic_cast<Node*>( tempSelectedObjects.front() ) ) n->setSelected( true ); tempSelectedObjects.pop_front(); } if (!found) { cout << "Adding right hand object to selected list" << endl; SelectedObjects.push_back( rightClosest ); rightClosest->setSelected( true ); iSelectMenuObj = 0; } } } if( leftClosest ) { leftClosest->touch( secondary ); if( secondary.getButton( WiiMote::A ) && secondary.getButton( WiiMote::B ) ) { secondary.requestScaleGrab( leftClosest ); } else if( secondary.getButton( WiiMote::A ) ) { secondary.requestPosGrab( leftClosest ); } else if( secondary.getButton( WiiMote::B ) ) { secondary.requestRotGrab( leftClosest ); } else if(((secondary.getButton( WiiMote::PLUS )) || (secondary.getButton( WiiMote::MINUS ))) && ((iSelectMenuObj == 1) || (iSelectMenuObj == 2))) { bool found = false; std::list<arInteractable*> tempSelectedObjects; while (!SelectedObjects.empty()) { if ( SelectedObjects.front() == leftClosest ) { cout << "Removing left hand object to selected list" << endl; leftClosest->setSelected( false ); SelectedObjects.pop_front(); found = true; iSelectMenuObj = 0; break; } else { tempSelectedObjects.push_back( SelectedObjects.front() ); SelectedObjects.pop_front(); } } while (!tempSelectedObjects.empty()) { SelectedObjects.push_back( tempSelectedObjects.front() ); if( Node *n = dynamic_cast<Node*>( tempSelectedObjects.front() ) ) n->setSelected( true ); tempSelectedObjects.pop_front(); } if (!found) { cout << "Adding left hand object to selected list" << endl; SelectedObjects.push_back( leftClosest ); leftClosest->setSelected( true ); iSelectMenuObj = 0; } } } } }