19682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
29682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Simple program:  Create a blank window, wait for keypress, quit.
39682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
49682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall   Please see the SDL documentation for details on using the SDL API:
59682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall   /Developer/Documentation/SDL/docs.html
69682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
79682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
89682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <stdio.h>
99682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <stdlib.h>
109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <string.h>
119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <math.h>
129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "SDL.h"
149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallextern void Atlantis_Init ();
169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallextern void Atlantis_Reshape (int w, int h);
179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallextern void Atlantis_Animate ();
189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallextern void Atlantis_Display ();
199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic SDL_Surface *gScreen;
219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void initAttributes ()
239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    // Setup attributes we want for the OpenGL context
259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    int value;
279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    // Don't set color bit sizes (SDL_GL_RED_SIZE, etc)
299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    //    Mac OS X will always use 8-8-8-8 ARGB for 32-bit screens and
309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    //    5-5-5 RGB for 16-bit screens
319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    // Request a 16-bit depth buffer (without this, there is no depth buffer)
339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    value = 16;
349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, value);
359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    // Request double-buffered OpenGL
389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    //     The fact that windows are double-buffered on Mac OS X has no effect
399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    //     on OpenGL double buffering.
409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    value = 1;
419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, value);
429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void printAttributes ()
459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    // Print out attributes of the context we created
479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    int nAttr;
489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    int i;
499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    int  attr[] = { SDL_GL_RED_SIZE, SDL_GL_BLUE_SIZE, SDL_GL_GREEN_SIZE,
519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                    SDL_GL_ALPHA_SIZE, SDL_GL_BUFFER_SIZE, SDL_GL_DEPTH_SIZE };
529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    char *desc[] = { "Red size: %d bits\n", "Blue size: %d bits\n", "Green size: %d bits\n",
549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                     "Alpha size: %d bits\n", "Color buffer size: %d bits\n",
559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                     "Depth bufer size: %d bits\n" };
569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    nAttr = sizeof(attr) / sizeof(int);
589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    for (i = 0; i < nAttr; i++) {
609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        int value;
629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        SDL_GL_GetAttribute (attr[i], &value);
639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        printf (desc[i], value);
649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    }
659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void createSurface (int fullscreen)
689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    Uint32 flags = 0;
709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    flags = SDL_OPENGL;
729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (fullscreen)
739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        flags |= SDL_FULLSCREEN;
749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    // Create window
769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    gScreen = SDL_SetVideoMode (640, 480, 0, flags);
779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    if (gScreen == NULL) {
789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        fprintf (stderr, "Couldn't set 640x480 OpenGL video mode: %s\n",
809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                 SDL_GetError());
819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_Quit();
829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		exit(2);
839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void initGL ()
879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    Atlantis_Init ();
899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    Atlantis_Reshape (gScreen->w, gScreen->h);
909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void drawGL ()
939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    Atlantis_Animate ();
959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    Atlantis_Display ();
969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void mainLoop ()
999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
1009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL_Event event;
1019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    int done = 0;
1029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    int fps = 24;
1039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	int delay = 1000/fps;
1049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    int thenTicks = -1;
1059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    int nowTicks;
1069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    while ( !done ) {
1089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Check for events */
1109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		while ( SDL_PollEvent (&event) ) {
1119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			switch (event.type) {
1129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				case SDL_MOUSEMOTION:
1149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					break;
1159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				case SDL_MOUSEBUTTONDOWN:
1169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					break;
1179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				case SDL_KEYDOWN:
1189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					/* Any keypress quits the app... */
1199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				case SDL_QUIT:
1209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					done = 1;
1219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					break;
1229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				default:
1239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					break;
1249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			}
1259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
1269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        // Draw at 24 hz
1289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        //     This approach is not normally recommended - it is better to
1299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        //     use time-based animation and run as fast as possible
1309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        drawGL ();
1319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        SDL_GL_SwapBuffers ();
1329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        // Time how long each draw-swap-delay cycle takes
1349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        // and adjust delay to get closer to target framerate
1359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        if (thenTicks > 0) {
1369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            nowTicks = SDL_GetTicks ();
1379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            delay += (1000/fps - (nowTicks-thenTicks));
1389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            thenTicks = nowTicks;
1399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            if (delay < 0)
1409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                delay = 1000/fps;
1419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
1429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        else {
1439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall            thenTicks = SDL_GetTicks ();
1449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        }
1459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        SDL_Delay (delay);
1479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
1489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
1499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallint main(int argc, char *argv[])
1519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
1529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	// Init SDL video subsystem
1539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( SDL_Init (SDL_INIT_VIDEO) < 0 ) {
1549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        fprintf(stderr, "Couldn't initialize SDL: %s\n",
1569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			SDL_GetError());
1579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		exit(1);
1589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
1599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    // Set GL context attributes
1619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    initAttributes ();
1629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    // Create GL context
1649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    createSurface (0);
1659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    // Get GL context attributes
1679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    printAttributes ();
1689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    // Init GL state
1709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    initGL ();
1719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    // Draw, get events...
1739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    mainLoop ();
1749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    // Cleanup
1769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	SDL_Quit();
1779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    return 0;
1799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
180