File: fullscreen.c

/*
  fullscreen.c

  A basic test of fullscreen rendering. Creates a fullscreen
  window and renders a tunnel. 
  
  Options:

  'esc' - exit
  'w'   - wrieframe 
  '?'   - toggle help screen on/off
  up/down arrow keys - speed up / slow down rotation

  Grats: I used Romka's tunnel demo as a basis for this. Thanks dude.
         http://romka.demonews.com/opengl/demos/

  fun: turn off all the lights, crank up the rotation and have a trash
  can ready.
*/

#define CPWDLL_EXTERN
#include <cpw.h>

/* handy window characteristics holder */

static CpwWindowInfo windowInfo = { 0,100,100,300,300 }; /* id,posx,posy,w,h */
static CpwFontFace font;

static char buf[1000];

/* some texture filenames and thier data holders */

static char * filename1 = "textures/tunneltexture.bmp";
static CpwImage image1;

static bool wireframe = false;
static bool fog = false;
static bool help = true;

#define pi 3.141592654f

typedef struct 
{
	float x,y,z;
} PCoord; /* Polygon Coordinates */

typedef struct
{
	float u,v;
} TCoord; /* Texture Coordinates */

static PCoord imgArray[36][36];
static TCoord texcord[36][36];

static float rot = 0, rotspeed = 1;

GLuint xloop,yloop;

GLfloat FogColour[4] = { 0.0f , 0.0f , 0.0f , 1.0f };

void init_fog()
{
	glFogi(GL_FOG_MODE, GL_LINEAR);
	glFogfv(GL_FOG_COLOR, FogColour);
	glFogf(GL_FOG_DENSITY, 0.25f);
	glHint(GL_FOG_HINT, GL_NICEST);
	glFogf(GL_FOG_START, 0);
	glFogf(GL_FOG_END, 30);
}

/****************************************************/
/*  OpenGL 2D Matrix Setup                          */
/****************************************************/

void set2DMatrix( void ) 
{
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    gluOrtho2D( 0, windowInfo.width, 0, windowInfo.height );
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
}

/****************************************************/
/*  OpenGL 3D Matrix Setup                          */
/****************************************************/

void set3DMatrix( void ) 
{
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    gluPerspective( 45, (float)windowInfo.width / (float)windowInfo.height, 1, 100 );
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
}

/****************************************************/
/*  Draw Help                                       */
/****************************************************/

void drawHelp( pCpw cpw )
{
    float ypos = (float)(windowInfo.height * .9);

    set2DMatrix();

    glPushMatrix();

    glDisable( GL_TEXTURE_2D );
    glEnable( GL_BLEND );
    
    glColor3d( 1.0, 0.6, 0.0 );

    sprintf( buf, "'esc' - exit" );
    glRasterPos2d( 10, ypos );
    cpwDrawFont( cpw, font, buf, 1 );

    sprintf( buf, "'w' - toggle wireframe / texturing" );
    ypos = ypos - 20;
    glRasterPos2d( 10, ypos );
    cpwDrawFont( cpw, font, buf, 1 );

    sprintf( buf, "'?' - toggle help screen" );
    ypos = ypos - 20;
    glRasterPos2d( 10, ypos );
    cpwDrawFont( cpw, font, buf, 1 );

    sprintf( buf, "'up/dn' - alter rotation speed" );
    ypos = ypos - 20;
    glRasterPos2d( 10, ypos );
    cpwDrawFont( cpw, font, buf, 1 );

    glDisable( GL_BLEND );

    glPopMatrix();
}

/****************************************************/
/*  Draw Window One                                 */
/****************************************************/

void drawSceneOne( pCpw cpw, uint_32 winid ) 
{
    int i,j;

    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    glColor3f( 1.0, 1.0, 1.0 );

    set3DMatrix();

    glPushMatrix();	

    glTranslated( 0.0, 0.0, -4.0 );

    for (i=0; i<33; i++)
    {
      for (j=0; j<33; j++)
      {
        texcord[i][j].u = (float) (i / 16.0 + cos( ( rot + 8.0 * j ) / 60 ) / 2 );
        texcord[i][j].v = (float) (j / 16.0 + ( (rot*2) + j ) / 120 );
      }
    }

    glEnable(GL_FOG); 

    if ( wireframe ) {
        glDisable( GL_TEXTURE_2D );
    } else {
        glEnable( GL_TEXTURE_2D );
    }

    for (xloop=0; xloop<32; xloop++)
    {
        if ( wireframe ) {
            glBegin(GL_LINES);
        } else {
            glBegin(GL_QUADS);
        }

        for (yloop=0; yloop<32; yloop++)
        {
          glTexCoord2f (texcord[xloop][yloop].u, texcord[xloop][yloop].v);
          glVertex3f (imgArray[xloop  ][yloop  ].x,imgArray[xloop  ][yloop  ].y,imgArray[xloop  ][yloop  ].z);
          glTexCoord2f (texcord[xloop+1][yloop  ].u, texcord[xloop+1][yloop  ].v);
          glVertex3f (imgArray[xloop+1][yloop  ].x,imgArray[xloop+1][yloop  ].y,imgArray[xloop  ][yloop  ].z);
          glTexCoord2f (texcord[xloop+1][yloop+1].u, texcord[xloop+1][yloop+1].v);
          glVertex3f (imgArray[xloop+1][yloop+1].x,imgArray[xloop+1][yloop+1].y,imgArray[xloop  ][yloop+1].z);
          glTexCoord2f (texcord[xloop  ][yloop+1].u, texcord[xloop  ][yloop+1].v);
          glVertex3f (imgArray[xloop  ][yloop+1].x,imgArray[xloop  ][yloop+1].y,imgArray[xloop  ][yloop+1].z);
        }
        glEnd();
    }

    glPopMatrix();

    if ( help ) 
        drawHelp( cpw );

    cpwSwapWindowBuffers( cpw, winid );
}

/****************************************************/
/*  Window Create / Destroy Event callback          */
/****************************************************/

void window( pCpw cpw, uint_32 winid, bool flag )
{
    int i, j;

    /* creation event */

    if ( flag == true ) {

        glEnable(GL_TEXTURE_2D);
        glShadeModel(GL_SMOOTH);
        glClearColor(0.0, 0.0, 0.0, 1.0);
        glClearDepth(1.0);
        glEnable(GL_DEPTH_TEST);
        glDepthFunc(GL_LEQUAL);
        glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
        glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );

        for (i=0; i<33; i++)
        {
          for (j=0; j<33; j++)
          {
            imgArray[i][j].x = (float) (3.0 - j/12.0)* (float) (cos(2.0*pi/32*i));
            imgArray[i][j].y = (float) (3.0 - j/12.0)* (float) (sin(2.0*pi/32*i));
            imgArray[i][j].z = (float) (-j);
          }
        }

        init_fog();

        return;
    }

    /* window close event */

    if ( flag == false ) {
        cpwDestroyWindow( cpw, winid );
        return;
    }
}

/****************************************************/
/*  Window Resize Event callback                    */
/****************************************************/

void reshape( pCpw cpw, uint_32 winid, uint_32 width, uint_32 height )
{
    if ( height == 0 ) { height = 1; }
    if ( width == 0 )  { width = 1; }

    windowInfo.width = width;
    windowInfo.height = height;

    glViewport( 0, 0, width, height );
}

/****************************************************/
/*  Timer Event Callback                            */
/****************************************************/

void timer( pCpw cpw, uint_32 id )
{
    rot = rot + (float)rotspeed;
    cpwPostWindowRedisplay( cpw, 1 );
}

/****************************************************/
/*  Key Event Callback                              */
/****************************************************/

void keyboard( pCpw cpw, uint_32 id, uint_32 key, uint_32 state, uint_32 x, uint_32 y )
{
    if ( state == CPW_KEYMOD_UP ) 
      return;

    switch( key ) {
        case 'w': /* wireframe */
          wireframe = !wireframe;
        break;
        case '?': /* help overlay */
          help = !help;
        break;
    };

    cpwPostWindowRedisplay( cpw, 1 );
}

void syskey( pCpw cpw, uint_32 id, uint_32 key, uint_32 state, uint_32 x, uint_32 y )
{
    if ( key == CPW_KEY_ESCAPE ) 
        cpwBreakMainLoop( cpw );

    if ( key == CPW_KEY_UP ) 
        rotspeed = rotspeed + (float).2;

    if ( key == CPW_KEY_DOWN ) 
        rotspeed = rotspeed - (float).2;
}

/****************************************************/
/*  Create Texture Object Helper                    */
/****************************************************/

void registerTexture( CpwImage * image, uint_32 textureId )
{
    GLenum format;

    if ( image->depth == 3 ) 
        format = GL_RGB;
    else if ( image->depth == 4 ) 
        format = GL_RGBA;
    else return;

    glBindTexture( GL_TEXTURE_2D, textureId );

    glTexImage2D( GL_TEXTURE_2D, 
                  0,            /* no mipmaps */
                  image->depth,
                  image->width, 
                  image->height, 
                  0,            /* no border */
                  format, 
                  GL_UNSIGNED_BYTE, 
                  image->data );

		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
		gluBuild2DMipmaps(GL_TEXTURE_2D, 3, image->width, image->height, GL_RGB, GL_UNSIGNED_BYTE, image->data );

    return;
}

/****************************************************/
/*  Main                                            */
/****************************************************/

int main(int argc, char* argv[])
{
    pCpw cpw = null;

    /****************************************************/
    /*  Init                                            */
    /****************************************************/

    cpwInitContext( &cpw );

    /****************************************************/
    /*  Creaing Windows                                 */
    /****************************************************/

    windowInfo.id = 
    cpwCreateFullscreenWindow( cpw );

    /*windowInfo.id = 
    cpwCreateWindowEx( cpw, "Images", windowInfo.x, windowInfo.y, 
                             windowInfo.width, windowInfo.height );*/

    /****************************************************/
    /*  Event Callbacks                                 */
    /****************************************************/

    cpwCreateCallback( cpw, window );
    cpwDisplayCallback( cpw, drawSceneOne );
    cpwReshapeCallback( cpw, reshape );
    cpwKeyboardCallback( cpw, keyboard );
    cpwSystemKeyboardCallback( cpw, syskey );
    cpwTimerCallback( cpw, 20, 1, true, timer );

    /****************************************************/
    /*  Image Loading                                   */
    /****************************************************/

    if ( !cpwLoadImage( cpw, &image1, CPW_IMAGEFORMAT_BMP, filename1, false ) ) {
        printf( "File not found: %s\n", filename1 );
        goto exithis;
    }

    /****************************************************/
    /*  Fonts                                           */
    /****************************************************/

    glPixelStorei( GL_UNPACK_LSB_FIRST, GL_FALSE );
    glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );

    cpwFontMode( cpw, CPW_FONTOPT_PIXELMAP, 0 );
    cpwFontMode( cpw, CPW_FONTOPT_ALIGNLEFT, 0 );
    cpwFontMode( cpw, CPW_FONTOPT_SIZE, 18 );
    cpwFontMode( cpw, CPW_FONTOPT_PIXELMAP_GLFORMAT, GL_RGBA );
    cpwFontMode( cpw, CPW_FONTOPT_LAYOUTDEBUG, 0 );

    font = cpwLoadFont( cpw, "arial.ttf", CPW_FONTLOC_HOST, "", "" );

    /****************************************************/
    /*  OpenGL Texture Object Creation                  */
    /****************************************************/

    registerTexture( &image1, 1 );

    /****************************************************/
    /*  MainLoop                                        */
    /****************************************************/

    cpwMainLoop( cpw );

    /****************************************************/
    /*  Exit and Free                                   */
    /****************************************************/

    cpwFreeImage( cpw, &image1 );

    exithis:

    cpwFreeContext( &cpw );

    return 0;
}