//----------------------------------------------------------------------------- // file: TheForce.cpp // desc: sample shows setting up OpenGL, modelview transform, // basic real-time audio // // author: Music 256 | Fall 2008 // CCRMA, Stanford University //----------------------------------------------------------------------------- #include #include #include #include #include #include "RtAudio.h" #include #include #include using namespace std; // define sample #define SAMPLE double #define MY_PIE 3.14159265358979 #define MY_SRATE 44100 SAMPLE g_freq = 880; SAMPLE g_phase = 0; SAMPLE g_inc = g_freq / MY_SRATE; // struct to hold each laser struct Laser { GLfloat x; GLfloat y; GLfloat color[3]; Laser( GLfloat _x, GLfloat _y ) : x(_x), y(_y) {} }; // vector of lasers vector g_lasers; GLfloat g_fire = 0.0; // audio call back int callme( void * out, void * in, unsigned int numFrames, double streamTime, RtAudioStreamStatus status, void * userData ) { // warn in case of over/underflow if ( status ) std::cout << "Stream over/underflow detected." << std::endl; // fprintf( stderr, "." ); SAMPLE * buffy = (SAMPLE *)out; for( int i = 0; i < numFrames; i++ ) { buffy[2*i] = buffy[2*i+1] = g_fire * sin( 2 * MY_PIE * g_phase ); g_phase += g_inc; if( g_phase > 1.0f ) g_phase -= 1.0f; } // quick hack for sound, use as envelope g_fire *= .95; return 0; } //----------------------------------------------------------------------------- // function prototypes //----------------------------------------------------------------------------- void idleFunc( ); void displayFunc( ); void reshapeFunc( GLsizei width, GLsizei height ); void keyboardFunc( unsigned char, int, int ); void mouseFunc( int button, int state, int x, int y ); void initialize( ); void cleanUp( ); //----------------------------------------------------------------------------- // global variables and #defines //----------------------------------------------------------------------------- #define __PI 3.1415926 // width and height of the window GLsizei g_width = 800; GLsizei g_height = 600; // light 0 position GLfloat g_light0_pos[4] = { 2.0f, 8.2f, 4.0f, 1.0f }; // light 1 parameters GLfloat g_light1_ambient[] = { .2f, .2f, .2f, 1.0f }; GLfloat g_light1_diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f }; GLfloat g_light1_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f }; GLfloat g_light1_pos[4] = { -2.0f, 0.0f, -4.0f, 1.0f }; // RtAudio object RtAudio g_audio; //----------------------------------------------------------------------------- // Name: main( ) // Desc: starting point //----------------------------------------------------------------------------- int main( int argc, char ** argv ) { // initialize GLUT glutInit( &argc, argv ); // double buffer, use rgb color, enable depth buffer glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH ); // initialize the window size glutInitWindowSize( g_width, g_height ); // set the window postion glutInitWindowPosition( 100, 100 ); // create the window glutCreateWindow( "TheForce" ); // set the idle function - called when idle glutIdleFunc( idleFunc ); // set the display function - called when redrawing glutDisplayFunc( displayFunc ); // set the reshape function - called when client area changes glutReshapeFunc( reshapeFunc ); // set the keyboard function - called on keyboard events glutKeyboardFunc( keyboardFunc ); // set the mouse function - called on mouse stuff glutMouseFunc( mouseFunc ); // do our own initialization initialize(); // let GLUT handle the current thread from here glutMainLoop(); return 0; } //----------------------------------------------------------------------------- // Name: initialize( ) // Desc: sets initial OpenGL states // also initializes any application data //----------------------------------------------------------------------------- void initialize() { // set the GL clear color - use when the color buffer is cleared glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); // set the shading model to 'smooth' glShadeModel( GL_SMOOTH ); // enable depth glEnable( GL_DEPTH_TEST ); // set the front faces of polygons glFrontFace( GL_CCW ); // set fill mode glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); // enable lighting glEnable( GL_LIGHTING ); // enable lighting for front glLightModeli( GL_FRONT_AND_BACK, GL_TRUE ); // material have diffuse and ambient lighting glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE ); // enable color glEnable( GL_COLOR_MATERIAL ); // enable light 0 glEnable( GL_LIGHT0 ); // setup and enable light 1 glLightfv( GL_LIGHT1, GL_AMBIENT, g_light1_ambient ); glLightfv( GL_LIGHT1, GL_DIFFUSE, g_light1_diffuse ); glLightfv( GL_LIGHT1, GL_SPECULAR, g_light1_specular ); // glEnable( GL_LIGHT1 ); // set the position of the lights glLightfv( GL_LIGHT0, GL_POSITION, g_light0_pos ); // glLightfv( GL_LIGHT1, GL_POSITION, g_light1_pos ); // seed random number generator srand( time(NULL) ); // test for number of devices if( g_audio.getDeviceCount() < 1 ) { cerr << "no audio device found!\n" << endl; exit( 1 ); } // parameters unsigned int bufferFrames = 512; RtAudio::StreamParameters iParams, oParams; iParams.deviceId = g_audio.getDefaultInputDevice(); iParams.nChannels = 2; // stereo oParams.deviceId = g_audio.getDefaultOutputDevice(); oParams.nChannels = 2; // open the RtAudio try { g_audio.openStream( &oParams, &iParams, RTAUDIO_FLOAT64, 44100, &bufferFrames, &callme, NULL ); } catch( RtError & err ) { err.printMessage(); exit(1); } // start the stream try { // start g_audio.startStream(); } catch( RtError & err ) { // do stuff err.printMessage(); } } //----------------------------------------------------------------------------- // Name: cleanUp( ) // Desc: cleans up dynamic memory for vArray //----------------------------------------------------------------------------- void cleanUp( ) { // TODO: !!! } //----------------------------------------------------------------------------- // Name: reshapeFunc( ) // Desc: called when window size changes //----------------------------------------------------------------------------- void reshapeFunc( GLsizei w, GLsizei h ) { // save the new window size g_width = w; g_height = h; // map the view port to the client area glViewport( 0, 0, w, h ); // set the matrix mode to project glMatrixMode( GL_PROJECTION ); // load the identity matrix glLoadIdentity( ); // create the viewing frustum gluPerspective( 45.0, (GLfloat) w / (GLfloat) h, 1.0, 300.0 ); // set the matrix mode to modelview glMatrixMode( GL_MODELVIEW ); // load the identity matrix glLoadIdentity( ); // position the view point gluLookAt( 0.0f, 0.0f, 10.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f ); } //----------------------------------------------------------------------------- // name: rand2f() // desc: generate a random float //----------------------------------------------------------------------------- GLfloat rand2f( float a, float b ) { return a + (b-a)*(rand() / (GLfloat)RAND_MAX); } //----------------------------------------------------------------------------- // Name: keyboardFunc( ) // Desc: key event //----------------------------------------------------------------------------- void keyboardFunc( unsigned char key, int x, int y ) { switch( key ) { case 'Q': case 'q': exit(1); break; case 'f': // instantiate (local copy) Laser laser( 1.5, 0 ); laser.color[0] = rand2f(0,1); laser.color[1] = rand2f(0,1); laser.color[2] = rand2f(0,1); // copy it in g_lasers.push_back( laser ); // reset hack envelope g_fire = 1.0f; break; } glutPostRedisplay( ); } //----------------------------------------------------------------------------- // Name: mouseFunc( ) // Desc: handles mouse stuff //----------------------------------------------------------------------------- void mouseFunc( int button, int state, int x, int y ) { if( button == GLUT_LEFT_BUTTON ) { // when left mouse button is down, move left if( state == GLUT_DOWN ) { } else { } } else if ( button == GLUT_RIGHT_BUTTON ) { // when right mouse button down, move right if( state == GLUT_DOWN ) { } else { } } else { } glutPostRedisplay( ); } //----------------------------------------------------------------------------- // Name: idleFunc( ) // Desc: callback from GLUT //----------------------------------------------------------------------------- void idleFunc( ) { // render the scene glutPostRedisplay( ); } //----------------------------------------------------------------------------- // Name: displayFunc( ) // Desc: callback function invoked to draw the client area //----------------------------------------------------------------------------- void displayFunc( ) { // static variable static GLfloat rot = 0.0f, drot = 0.0f, arot = 0.0f, mrot = 0.0f; // clear the color and depth buffers glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); // save the current transformation glPushMatrix(); // color it glColor3f( .6, .6, .6 ); // rotate it glRotatef( rot, 0, 1, 0 ); rot += .05; // draw lasers | TODO: missing cleanup!!! for( int i = 0; i < g_lasers.size(); i++ ) { glPushMatrix(); // position it glTranslatef( g_lasers[i].x, 0, 0 ); // use color glColor3f( g_lasers[i].color[0], g_lasers[i].color[1], g_lasers[i].color[2] ); // draw sphere glutSolidSphere( .25, 5, 5 ); // move it g_lasers[i].x -= .02; glPopMatrix(); } // save glPushMatrix(); // move left glTranslatef( 2, 0, 0 ); // rotate it glRotatef( drot, 1, 0, 0 ); drot += .08; // draw deathstar glColor3f( .6, .6, .6 ); glutSolidSphere( .5, 15, 15 ); glTranslatef( -.501, 0, 0 ); glRotatef( 90, 0, 1, 0 ); // draw ultimate weapon in the universe glutSolidCone( .2, .01, 20, 20 ); // restore glPopMatrix(); // save glPushMatrix(); // move left glTranslatef( -3, 0, 0 ); glPushMatrix(); // rotate it glRotatef( mrot, 1, 0, 0 ); mrot += .04; // move the mooon glTranslatef( 0, 2, 0 ); // color the moon glColor3f( .25, .8, .25 ); // draw alderaan glutSolidSphere( .25, 15, 15 ); glPopMatrix(); // color the planet glColor3f( .25, .25, .8 ); // rotate it glRotatef( drot, 0, 0, 1 ); drot += .04; // draw alderaan glutSolidSphere( 1.5, 15, 15 ); // restore glPopMatrix(); // restore state glPopMatrix(); // flush! glFlush( ); // swap the double buffer glutSwapBuffers( ); } // TODO: draw cone // glutSolidCone( .3, .1, 20, 20 );