android/testproject/jni/lesson05.c
author Paul Hunkin <paul@bieh.net>
Tue, 27 Jul 2010 21:21:24 +0200
changeset 4722 faa228f7ce5b
parent 4719 d59792d2c3ae
child 4723 74da47b2f5b7
permissions -rw-r--r--
- Cleaned up a bunch of code
- Added 'feature' enable/disable so we're not running accel/sound/whatever in Java when we don't need to be
- More work on the sound system. But it still crashes pretty horribly, not sure why yet.
     1 /*
     2  * This code was created by Jeff Molofee '99 
     3  * (ported to Linux/SDL by Ti Leggett '01)
     4  *
     5  * If you've found this code useful, please let me know.
     6  *
     7  * Visit Jeff at http://nehe.gamedev.net/
     8  * 
     9  * or for port-specific comments, questions, bugreports etc. 
    10  * email to leggett@eecs.tulane.edu
    11  */
    12  
    13 #include <stdio.h>
    14 #include <stdlib.h>
    15 #include <math.h>
    16 
    17 #include <signal.h>
    18 
    19 #include <android/log.h>
    20 
    21 
    22 #ifdef ANDROID
    23 #include <GLES/gl.h>
    24 #else
    25 #include <GL/gl.h>
    26 #include <GL/glu.h>
    27 #endif
    28 #include "SDL.h"
    29 
    30 /* screen width, height, and bit depth */
    31 #define SCREEN_WIDTH  320
    32 #define SCREEN_HEIGHT 430
    33 #define SCREEN_BPP     16
    34 
    35 /* Define our booleans */
    36 #define TRUE  1
    37 #define FALSE 0
    38 
    39 /* This is our SDL surface */
    40 SDL_Surface *surface;
    41 
    42 int rotation = 0;
    43 
    44 
    45 /**************************************
    46 	gluperspective implementation
    47 **************************************/
    48 void gluPerspective(double fovy, double aspect, double zNear, double zFar){
    49 	glMatrixMode(GL_PROJECTION);
    50 	glLoadIdentity();
    51 	double xmin, xmax, ymin, ymax;
    52 	ymax = zNear * tan(fovy * M_PI / 360.0);
    53 	ymin = -ymax;
    54 	xmin = ymin * aspect;
    55 	xmax = ymax * aspect;
    56 	glFrustumf(xmin, xmax, ymin, ymax, zNear, zFar);
    57 }
    58 
    59 
    60 /**************************************
    61 	  glulookat implementation
    62 **************************************/
    63 void gluLookAt(GLfloat eyex, GLfloat eyey, GLfloat eyez,
    64           GLfloat centerx, GLfloat centery, GLfloat centerz,
    65           GLfloat upx, GLfloat upy, GLfloat upz)
    66 {
    67     GLfloat m[16];
    68     GLfloat x[3], y[3], z[3];
    69     GLfloat mag;
    70     
    71     /* Make rotation matrix */
    72     
    73     /* Z vector */
    74     z[0] = eyex - centerx;
    75     z[1] = eyey - centery;
    76     z[2] = eyez - centerz;
    77     mag = sqrt(z[0] * z[0] + z[1] * z[1] + z[2] * z[2]);
    78     if (mag) {          /* mpichler, 19950515 */
    79         z[0] /= mag;
    80         z[1] /= mag;
    81         z[2] /= mag;
    82     }
    83     
    84     /* Y vector */
    85     y[0] = upx;
    86     y[1] = upy;
    87     y[2] = upz;
    88     
    89     /* X vector = Y cross Z */
    90     x[0] = y[1] * z[2] - y[2] * z[1];
    91     x[1] = -y[0] * z[2] + y[2] * z[0];
    92     x[2] = y[0] * z[1] - y[1] * z[0];
    93     
    94     /* Recompute Y = Z cross X */
    95     y[0] = z[1] * x[2] - z[2] * x[1];
    96     y[1] = -z[0] * x[2] + z[2] * x[0];
    97     y[2] = z[0] * x[1] - z[1] * x[0];
    98     
    99     /* mpichler, 19950515 */
   100     /* cross product gives area of parallelogram, which is < 1.0 for
   101      * non-perpendicular unit-length vectors; so normalize x, y here
   102      */
   103     
   104     mag = sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]);
   105     if (mag) {
   106         x[0] /= mag;
   107         x[1] /= mag;
   108         x[2] /= mag;
   109     }
   110     
   111     mag = sqrt(y[0] * y[0] + y[1] * y[1] + y[2] * y[2]);
   112     if (mag) {
   113         y[0] /= mag;
   114         y[1] /= mag;
   115         y[2] /= mag;
   116     }
   117     
   118 #define M(row,col)  m[col*4+row]
   119     M(0, 0) = x[0];
   120     M(0, 1) = x[1];
   121     M(0, 2) = x[2];
   122     M(0, 3) = 0.0;
   123     M(1, 0) = y[0];
   124     M(1, 1) = y[1];
   125     M(1, 2) = y[2];
   126     M(1, 3) = 0.0;
   127     M(2, 0) = z[0];
   128     M(2, 1) = z[1];
   129     M(2, 2) = z[2];
   130     M(2, 3) = 0.0;
   131     M(3, 0) = 0.0;
   132     M(3, 1) = 0.0;
   133     M(3, 2) = 0.0;
   134     M(3, 3) = 1.0;
   135 #undef M
   136     glMultMatrixf(m);
   137     
   138     /* Translate Eye to Origin */
   139     glTranslatef(-eyex, -eyey, -eyez);
   140     
   141 }
   142 
   143 
   144 
   145 
   146 
   147 /* function to release/destroy our resources and restoring the old desktop */
   148 void Quit( int returnCode )
   149 {
   150     /* clean up the window */
   151     SDL_Quit( );
   152 
   153     /* and exit appropriately */
   154     exit( returnCode );
   155 }
   156 
   157 /* function to reset our viewport after a window resize */
   158 int resizeWindow( int width, int height )
   159 {
   160     /* Height / width ration */
   161     GLfloat ratio;
   162  
   163     /* Protect against a divide by zero */
   164    if ( height == 0 )
   165 	height = 1;
   166 
   167     ratio = ( GLfloat )width / ( GLfloat )height;
   168 
   169     /* Setup our viewport. */
   170     glViewport( 0, 0, ( GLsizei )width, ( GLsizei )height );
   171 
   172     /* change to the projection matrix and set our viewing volume. */
   173     glMatrixMode( GL_PROJECTION );
   174     glLoadIdentity( );
   175 
   176     /* Set our perspective */
   177     gluPerspective( 45.0f, ratio, 0.1f, 100.0f );
   178 
   179     /* Make sure we're chaning the model view and not the projection */
   180     glMatrixMode( GL_MODELVIEW );
   181 
   182     /* Reset The View */
   183     glLoadIdentity( );
   184 
   185     return( TRUE );
   186 }
   187 
   188 /* function to handle key press events */
   189 void handleKeyPress( SDL_keysym *keysym )
   190 {
   191     switch ( keysym->sym )
   192 	{
   193 	case SDLK_ESCAPE:
   194 	    /* ESC key was pressed */
   195 	    Quit( 0 );
   196 	    break;
   197 	case SDLK_F1:
   198 	    /* F1 key was pressed
   199 	     * this toggles fullscreen mode
   200 	     */
   201 	    SDL_WM_ToggleFullScreen( surface );
   202 	    break;
   203     case SDLK_LEFT:
   204         rotation -= 30;
   205         break;
   206 
   207     case SDLK_RIGHT:
   208         rotation += 30;
   209         break;
   210         
   211 	default:
   212 	    break;
   213 	}
   214 
   215     __android_log_print(ANDROID_LOG_INFO, "SDL","Keycode: %d, %d, %d\n", keysym->sym, SDLK_LEFT, SDLK_RIGHT);
   216 
   217     return;
   218 }
   219 
   220 /* general OpenGL initialization function */
   221 int initGL( GLvoid )
   222 {
   223 
   224     /* Enable smooth shading */
   225     glShadeModel( GL_SMOOTH );
   226 
   227     /* Set the background black */
   228     glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
   229 
   230     /* Depth buffer setup */
   231     //glClearDepth( 1.0f );
   232 
   233     /* Enables Depth Testing */
   234     glEnable( GL_DEPTH_TEST );
   235 
   236     /* The Type Of Depth Test To Do */
   237     glDepthFunc( GL_LEQUAL );
   238 
   239     /* Really Nice Perspective Calculations */
   240     glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
   241 
   242     return( TRUE );
   243 }
   244 
   245 /* Here goes our drawing code */
   246 int drawGLScene( GLvoid )
   247 {
   248       
   249 	static int Frames = 0;
   250 	static int T0 = 0;
   251 	
   252     glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
   253 
   254     glClearColorx(0,0,0,255);
   255     glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
   256 
   257     glMatrixMode(GL_PROJECTION);
   258     glLoadIdentity();
   259     gluPerspective(45, (float)SCREEN_WIDTH / SCREEN_HEIGHT, 0.5f, 150);
   260 
   261     glMatrixMode(GL_MODELVIEW);
   262 
   263     glLoadIdentity();
   264 
   265 	//Camera
   266 	gluLookAt(0,0,5, 0,0,0, 0,1,0);
   267 			
   268 	//Draw a triangle
   269 	//glRotatef(iRot, 0, 1, 0);
   270 
   271 	glRotatef( rotation, 0.0f, 1.0f, 0.0f );
   272 
   273 
   274 	glEnableClientState (GL_VERTEX_ARRAY);
   275 	glEnableClientState (GL_COLOR_ARRAY);
   276 	
   277 	/* Rotate The Triangle On The Y axis ( NEW ) */
   278     //glRotatef( Frames % 360, 0.0f, 1.0f, 0.0f );
   279 
   280     /* GLES variant of drawing a triangle */
   281     const GLfloat triVertices[][9] = {
   282       {     /* Front Triangle */
   283 	 0.0f,  1.0f,  0.0f,               /* Top Of Triangle               */
   284 	-1.0f, -1.0f,  1.0f,               /* Left Of Triangle              */
   285 	 1.0f, -1.0f,  1.0f                /* Right Of Triangle             */
   286       }, {  /* Right Triangle */
   287 	 0.0f,  1.0f,  0.0f,               /* Top Of Triangle               */
   288 	 1.0f, -1.0f,  1.0f,               /* Left Of Triangle              */
   289 	 1.0f, -1.0f, -1.0f                /* Right Of Triangle             */
   290       }, {  /* Back Triangle */
   291 	 0.0f,  1.0f,  0.0f,               /* Top Of Triangle               */
   292 	 1.0f, -1.0f, -1.0f,               /* Left Of Triangle              */
   293 	-1.0f, -1.0f, -1.0f                /* Right Of Triangle             */
   294       }, {  /* Left Triangle */
   295 	 0.0f,  1.0f,  0.0f,               /* Top Of Triangle               */
   296 	-1.0f, -1.0f, -1.0f,               /* Left Of Triangle              */
   297 	-1.0f, -1.0f,  1.0f                /* Right Of Triangle             */
   298       }
   299     };
   300 
   301     /* unlike GL, GLES does not support RGB. We have to use RGBA instead */
   302     const GLfloat triColors[][12] = {
   303       {     /* Front triangle */
   304         1.0f, 0.0f, 0.0f, 1.0f,            /* Red                           */
   305 	0.0f, 1.0f, 0.0f, 1.0f,            /* Green                         */
   306 	0.0f, 0.0f, 1.0f, 1.0f             /* Blue                          */
   307       }, {  /* Right triangle */
   308         1.0f, 0.0f, 0.0f, 1.0f,            /* Red                           */
   309 	0.0f, 0.0f, 1.0f, 1.0f,            /* Blue                          */
   310 	0.0f, 1.0f, 0.0f, 1.0f             /* Green                         */
   311       }, {  /* Back triangle */
   312         1.0f, 0.0f, 0.0f, 1.0f,            /* Red                           */
   313 	0.0f, 1.0f, 0.0f, 1.0f,            /* Green                         */
   314 	0.0f, 0.0f, 1.0f, 1.0f             /* Blue                          */
   315       }, {  /* Left triangle */
   316         1.0f, 0.0f, 0.0f, 1.0f,            /* Red                           */
   317 	0.0f, 0.0f, 1.0f, 1.0f,            /* Blue                          */
   318 	0.0f, 1.0f, 0.0f, 1.0f             /* Green                         */
   319       }
   320     };
   321 
   322     glEnableClientState(GL_COLOR_ARRAY);
   323 
   324     int tri=0;
   325 
   326     /* Loop through all Triangles */
   327     for(tri=0;tri<sizeof(triVertices)/(9*sizeof(GLfloat));tri++) 
   328     {
   329       glVertexPointer(3, GL_FLOAT, 0, triVertices[tri]);
   330       glColorPointer(4, GL_FLOAT, 0, triColors[tri]);
   331       
   332       glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
   333     }
   334 		
   335     //__android_log_print(ANDROID_LOG_INFO, "SDL", "render %d", Frames++);
   336 
   337     /* Draw it to the screen */
   338     SDL_GL_SwapBuffers( );
   339 
   340     /* Gather our frames per second */
   341     Frames++;
   342     {
   343 	GLint t = SDL_GetTicks();
   344 	if (t - T0 >= 5000) {
   345 	    GLfloat seconds = (t - T0) / 1000.0;
   346 	    GLfloat fps = Frames / seconds;
   347 	    __android_log_print(ANDROID_LOG_INFO, "SDL","%d frames in %g seconds = %g FPS\n", Frames, seconds, fps);
   348 	    T0 = t;
   349 	    Frames = 0;
   350 	}
   351     }
   352 
   353     rotation++;
   354 
   355     return( TRUE );
   356 }
   357 
   358 
   359 struct
   360 {
   361     SDL_AudioSpec spec;
   362     Uint8 *sound;               /* Pointer to wave data */
   363     Uint32 soundlen;            /* Length of wave data */
   364     int soundpos;               /* Current play position */
   365 } wave;
   366 
   367 void SDLCALL
   368 fillerup(void *unused, Uint8 * stream, int len)
   369 {
   370     __android_log_print(ANDROID_LOG_INFO, "SDL","FILLERUP\n");
   371     
   372     Uint8 *waveptr;
   373     int waveleft;
   374 
   375     /* Set up the pointers */
   376     waveptr = wave.sound + wave.soundpos;
   377     waveleft = wave.soundlen - wave.soundpos;
   378 
   379     /* Go! */
   380     while (waveleft <= len) {
   381         SDL_memcpy(stream, waveptr, waveleft);
   382         stream += waveleft;
   383         len -= waveleft;
   384         waveptr = wave.sound;
   385         waveleft = wave.soundlen;
   386         wave.soundpos = 0;
   387     }
   388     SDL_memcpy(stream, waveptr, len);
   389     wave.soundpos += len;
   390 }
   391 
   392 void testAudio(){
   393 
   394     const char *file = "/sdcard/sample.wav";
   395 
   396     /* Load the SDL library */
   397     if (SDL_Init(SDL_INIT_AUDIO) < 0) {
   398         __android_log_print(ANDROID_LOG_INFO, "SDL","Couldn't initialize SDL Audio: %s\n", SDL_GetError());
   399         return;
   400     }else{
   401         __android_log_print(ANDROID_LOG_INFO, "SDL","Init audio ok\n");
   402     }
   403 
   404     /* Load the wave file into memory */
   405     if (SDL_LoadWAV(file, &wave.spec, &wave.sound, &wave.soundlen) == NULL) {
   406         __android_log_print(ANDROID_LOG_INFO, "SDL", "Couldn't load %s: %s\n", file, SDL_GetError());
   407         return;
   408     }
   409 
   410     wave.spec.callback = fillerup;
   411 
   412     __android_log_print(ANDROID_LOG_INFO, "SDL","Loaded: %d\n", wave.soundlen);
   413 
   414 
   415     /* Initialize fillerup() variables */
   416     if (SDL_OpenAudio(&wave.spec, NULL) < 0) {
   417         __android_log_print(ANDROID_LOG_INFO, "SDL", "Couldn't open audio: %s\n", SDL_GetError());
   418         SDL_FreeWAV(wave.sound);
   419         return;
   420     }
   421 
   422      __android_log_print(ANDROID_LOG_INFO, "SDL","Using audio driver: %s\n", SDL_GetCurrentAudioDriver());
   423 
   424     /* Let the audio run */
   425     SDL_PauseAudio(0);
   426 
   427      __android_log_print(ANDROID_LOG_INFO, "SDL","Playing\n");
   428     
   429     while (SDL_GetAudioStatus() == SDL_AUDIO_PLAYING){
   430          //__android_log_print(ANDROID_LOG_INFO, "SDL","Still playing\n");
   431         //SDL_Delay(100);
   432     }
   433 
   434      __android_log_print(ANDROID_LOG_INFO, "SDL","Closing down\n");
   435 
   436     /* Clean up on signal */
   437     SDL_CloseAudio();
   438     SDL_FreeWAV(wave.sound);
   439 }
   440 
   441 int SDL_main( int argc, char **argv )
   442 {
   443 
   444 	__android_log_print(ANDROID_LOG_INFO, "SDL","entry\n");
   445 
   446     /* Flags to pass to SDL_SetVideoMode */
   447     int videoFlags;
   448     /* main loop variable */
   449     int done = FALSE;
   450     /* used to collect events */
   451     SDL_Event event;
   452     /* this holds some info about our display */
   453     const SDL_VideoInfo *videoInfo;
   454     /* whether or not the window is active */
   455     int isActive = TRUE;
   456 
   457     /* initialize SDL */
   458     if ( SDL_Init( SDL_INIT_VIDEO ) < 0 )
   459 	{
   460 	    __android_log_print(ANDROID_LOG_INFO, "SDL", "Video initialization failed: %s\n",
   461 		     SDL_GetError( ) );
   462 	    Quit( 1 );
   463 	}
   464 
   465     /* Fetch the video info */
   466     videoInfo = SDL_GetVideoInfo( );
   467 
   468     if ( !videoInfo )
   469 	{
   470 	    __android_log_print(ANDROID_LOG_INFO, "SDL", "Video query failed: %s\n",
   471 		     SDL_GetError( ) );
   472 	    Quit( 1 );
   473 	}
   474 
   475     /* the flags to pass to SDL_SetVideoMode */
   476     videoFlags  = SDL_OPENGL;          /* Enable OpenGL in SDL */
   477     videoFlags |= SDL_GL_DOUBLEBUFFER; /* Enable double buffering */
   478     videoFlags |= SDL_HWPALETTE;       /* Store the palette in hardware */
   479     videoFlags |= SDL_RESIZABLE;       /* Enable window resizing */
   480 
   481     /* This checks to see if surfaces can be stored in memory */
   482     if ( videoInfo->hw_available )
   483 	videoFlags |= SDL_HWSURFACE;
   484     else
   485 	videoFlags |= SDL_SWSURFACE;
   486 
   487     /* This checks if hardware blits can be done */
   488     if ( videoInfo->blit_hw )
   489 	videoFlags |= SDL_HWACCEL;
   490 
   491     /* Sets up OpenGL double buffering */
   492     SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
   493 
   494     /* get a SDL surface */
   495     surface = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,
   496 				videoFlags );
   497 
   498     /* Verify there is a surface */
   499     if ( !surface )
   500 	{
   501 	    __android_log_print(ANDROID_LOG_INFO, "SDL",  "Video mode set failed: %s\n", SDL_GetError( ) );
   502 	    Quit( 1 );
   503 	}
   504 
   505 	__android_log_print(ANDROID_LOG_INFO, "SDL","Made a video mode!\n");
   506 
   507     /* initialize OpenGL */
   508     initGL( );
   509 
   510     /* resize the initial window */
   511     resizeWindow( SCREEN_WIDTH, SCREEN_HEIGHT );
   512 
   513 
   514     testAudio();
   515 
   516 
   517     /* wait for events */ 
   518     while ( !done )
   519 	{
   520 	    /* handle the events in the queue */
   521 
   522 	    while ( SDL_PollEvent( &event ) )
   523 		{
   524 		    switch( event.type )
   525 			{
   526 			case SDL_ACTIVEEVENT:
   527 			    /* Something's happend with our focus
   528 			     * If we lost focus or we are iconified, we
   529 			     * shouldn't draw the screen
   530 			     */
   531 			    if ( event.active.gain == 0 )
   532 				isActive = FALSE;
   533 			    else
   534 				isActive = TRUE;
   535 			    break;			    
   536 			case SDL_VIDEORESIZE:
   537 			    /* handle resize event */
   538 			    surface = SDL_SetVideoMode( event.resize.w,
   539 							event.resize.h,
   540 							16, videoFlags );
   541 			    if ( !surface )
   542 				{
   543 				    __android_log_print(ANDROID_LOG_INFO, "SDL","Could not get a surface after resize: %s\n", SDL_GetError( ) );
   544 				    Quit( 1 );
   545 				}
   546 			    resizeWindow( event.resize.w, event.resize.h );
   547 			    break;
   548 			case SDL_KEYDOWN:
   549 			    /* handle key presses */
   550 			    handleKeyPress( &event.key.keysym );
   551 			    break;
   552 			case SDL_QUIT:
   553 			    /* handle quit requests */
   554 			    done = TRUE;
   555 			    __android_log_print(ANDROID_LOG_INFO, "SDL","App is shutting down\n");
   556 			    break;
   557 			default:
   558 			    break;
   559 			}
   560 		}
   561 
   562 	    /* draw the scene */
   563 	    if ( isActive )
   564 		drawGLScene( );
   565 	}
   566 
   567     /* clean ourselves up and exit */
   568     Quit( 0 );
   569 
   570     /* Should never get here */
   571     return( 0 );
   572 }
   573 
   574