File: imageloadsave.c

/*
  imageloadsave.c

  A basic test for the images extension loading and
  saving routines.

  Grats: I used some code from a NeHe tutorial for the cube. Thanks dude.
         http://nehe.gamedev.net/

*/

#define CPWDLL_EXTERN
#include <cpw.h>

/* handy window characteristics holder */

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

/* some texture filenames and thier data holders */

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

static char * filename2 = "textures/texture2.bmp";
static CpwImage image2;

static char * filename3 = "textures/texture3.bmp";
static CpwImage image3;

static char * filename4 = "textures/texture4.bmp";
static CpwImage image4;

static char * filename5 = "textures/texture5.tga"; /* cool alpha map tga texture */
static CpwImage image5;

static char * filename6 = "textures/wall2.bmp";
static CpwImage image6;

static CpwImage screenshot;

static float rot = 120;

static int screenshotcount = 1;
static bool takeashot = false;

/****************************************************/
/*  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( 60, (float)windowInfo.width / (float)windowInfo.height, 1, 100 );
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
}

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

static char filenamebuf[50];

void drawSceneOne( pCpw cpw, uint_32 winid ) 
{
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    glColor3f( 1.0, 1.0, 1.0 );

    set3DMatrix();

    glEnable( GL_TEXTURE_2D );

    glTranslatef( 0, 0, -5 ); 

    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );

    glRotated( rot, 0.5, 0.7, 0.3 );

    /* draw a cube using our textures */

    // Front Face
    glBindTexture(GL_TEXTURE_2D, 1 );
    glBegin(GL_QUADS);
    glTexCoord2d(0.0, 0.0); glVertex3d(-1.0, -1.0,  1.0);	// Bottom Left Of The Texture and Quad
    glTexCoord2d(1.0, 0.0); glVertex3d( 1.0, -1.0,  1.0);	// Bottom Right Of The Texture and Quad
    glTexCoord2d(1.0, 1.0); glVertex3d( 1.0,  1.0,  1.0);	// Top Right Of The Texture and Quad
    glTexCoord2d(0.0, 1.0); glVertex3d(-1.0,  1.0,  1.0);	// Top Left Of The Texture and Quad
    glEnd();
    // Back Face
    glBindTexture(GL_TEXTURE_2D, 2 );
    glBegin(GL_QUADS);
    glTexCoord2d(1.0, 0.0); glVertex3d(-1.0, -1.0, -1.0);	// Bottom Right Of The Texture and Quad
    glTexCoord2d(1.0, 1.0); glVertex3d(-1.0,  1.0, -1.0);	// Top Right Of The Texture and Quad
    glTexCoord2d(0.0, 1.0); glVertex3d( 1.0,  1.0, -1.0);	// Top Left Of The Texture and Quad
    glTexCoord2d(0.0, 0.0); glVertex3d( 1.0, -1.0, -1.0);	// Bottom Left Of The Texture and Quad
    glEnd();
    // Top Face
    glBindTexture(GL_TEXTURE_2D, 3 );
    glBegin(GL_QUADS);
    glTexCoord2d(0.0, 1.0); glVertex3d(-1.0,  1.0, -1.0);	// Top Left Of The Texture and Quad
    glTexCoord2d(0.0, 0.0); glVertex3d(-1.0,  1.0,  1.0);	// Bottom Left Of The Texture and Quad
    glTexCoord2d(1.0, 0.0); glVertex3d( 1.0,  1.0,  1.0);	// Bottom Right Of The Texture and Quad
    glTexCoord2d(1.0, 1.0); glVertex3d( 1.0,  1.0, -1.0);	// Top Right Of The Texture and Quad
    glEnd();
    // Bottom Face
    glBindTexture(GL_TEXTURE_2D, 4 );
    glBegin(GL_QUADS);
    glTexCoord2d(1.0, 1.0); glVertex3d(-1.0, -1.0, -1.0);	// Top Right Of The Texture and Quad
    glTexCoord2d(0.0, 1.0); glVertex3d( 1.0, -1.0, -1.0);	// Top Left Of The Texture and Quad
    glTexCoord2d(0.0, 0.0); glVertex3d( 1.0, -1.0,  1.0);	// Bottom Left Of The Texture and Quad
    glTexCoord2d(1.0, 0.0); glVertex3d(-1.0, -1.0,  1.0);	// Bottom Right Of The Texture and Quad
    glEnd();
    // Right face
    glBindTexture(GL_TEXTURE_2D, 5 );
    glBegin(GL_QUADS);
    glTexCoord2d(1.0, 0.0); glVertex3d( 1.0, -1.0, -1.0);	// Bottom Right Of The Texture and Quad
    glTexCoord2d(1.0, 1.0); glVertex3d( 1.0,  1.0, -1.0);	// Top Right Of The Texture and Quad
    glTexCoord2d(0.0, 1.0); glVertex3d( 1.0,  1.0,  1.0);	// Top Left Of The Texture and Quad
    glTexCoord2d(0.0, 0.0); glVertex3d( 1.0, -1.0,  1.0);	// Bottom Left Of The Texture and Quad
    glEnd();
    // Left Face
    glBindTexture(GL_TEXTURE_2D, 6 );
    glBegin(GL_QUADS);
    glTexCoord2d(0.0, 0.0); glVertex3d(-1.0, -1.0, -1.0);	// Bottom Left Of The Texture and Quad
    glTexCoord2d(1.0, 0.0); glVertex3d(-1.0, -1.0,  1.0);	// Bottom Right Of The Texture and Quad
    glTexCoord2d(1.0, 1.0); glVertex3d(-1.0,  1.0,  1.0);	// Top Right Of The Texture and Quad
    glTexCoord2d(0.0, 1.0); glVertex3d(-1.0,  1.0, -1.0);	// Top Left Of The Texture and Quad
    glEnd();

    if ( takeashot ) {

        glFinish();
        glFlush();

        cpwScreenShot( cpw, &screenshot );
        sprintf( filenamebuf, "screen%i.tga", screenshotcount );
        cpwSaveImage( cpw, &screenshot, filenamebuf );
        cpwFreeImage( cpw, &screenshot );      
        screenshotcount++;
        takeashot = false;
    }

    cpwSwapWindowBuffers( cpw, winid );
}

void drawSceneTwo( pCpw cpw, uint_32 winid ) 
{
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    set3DMatrix();

    glTranslatef( 0, 0, -5 ); 

    glRotated( rot, 1.0, 1.0, 1.0 );

    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );

    /* draw a cube using our textures */

    glColor3f( 0.0, (float)rand()/RAND_MAX, 0.0 );
    glBindTexture(GL_TEXTURE_2D, 5 );
    glBegin(GL_QUADS);
    // Front Face
    glTexCoord2d(0.0, 0.0); glVertex3d(-1.0, -1.0,  1.0);	// Bottom Left Of The Texture and Quad
    glTexCoord2d(1.0, 0.0); glVertex3d( 1.0, -1.0,  1.0);	// Bottom Right Of The Texture and Quad
    glTexCoord2d(1.0, 1.0); glVertex3d( 1.0,  1.0,  1.0);	// Top Right Of The Texture and Quad
    glTexCoord2d(0.0, 1.0); glVertex3d(-1.0,  1.0,  1.0);	// Top Left Of The Texture and Quad
    // Back Face
    glTexCoord2d(1.0, 0.0); glVertex3d(-1.0, -1.0, -1.0);	// Bottom Right Of The Texture and Quad
    glTexCoord2d(1.0, 1.0); glVertex3d(-1.0,  1.0, -1.0);	// Top Right Of The Texture and Quad
    glTexCoord2d(0.0, 1.0); glVertex3d( 1.0,  1.0, -1.0);	// Top Left Of The Texture and Quad
    glTexCoord2d(0.0, 0.0); glVertex3d( 1.0, -1.0, -1.0);	// Bottom Left Of The Texture and Quad
    // Top Face
    glTexCoord2d(0.0, 1.0); glVertex3d(-1.0,  1.0, -1.0);	// Top Left Of The Texture and Quad
    glTexCoord2d(0.0, 0.0); glVertex3d(-1.0,  1.0,  1.0);	// Bottom Left Of The Texture and Quad
    glTexCoord2d(1.0, 0.0); glVertex3d( 1.0,  1.0,  1.0);	// Bottom Right Of The Texture and Quad
    glTexCoord2d(1.0, 1.0); glVertex3d( 1.0,  1.0, -1.0);	// Top Right Of The Texture and Quad
    // Bottom Face
    glTexCoord2d(1.0, 1.0); glVertex3d(-1.0, -1.0, -1.0);	// Top Right Of The Texture and Quad
    glTexCoord2d(0.0, 1.0); glVertex3d( 1.0, -1.0, -1.0);	// Top Left Of The Texture and Quad
    glTexCoord2d(0.0, 0.0); glVertex3d( 1.0, -1.0,  1.0);	// Bottom Left Of The Texture and Quad
    glTexCoord2d(1.0, 0.0); glVertex3d(-1.0, -1.0,  1.0);	// Bottom Right Of The Texture and Quad
    // Right face
    glTexCoord2d(1.0, 0.0); glVertex3d( 1.0, -1.0, -1.0);	// Bottom Right Of The Texture and Quad
    glTexCoord2d(1.0, 1.0); glVertex3d( 1.0,  1.0, -1.0);	// Top Right Of The Texture and Quad
    glTexCoord2d(0.0, 1.0); glVertex3d( 1.0,  1.0,  1.0);	// Top Left Of The Texture and Quad
    glTexCoord2d(0.0, 0.0); glVertex3d( 1.0, -1.0,  1.0);	// Bottom Left Of The Texture and Quad
    // Left Face
    glTexCoord2d(0.0, 0.0); glVertex3d(-1.0, -1.0, -1.0);	// Bottom Left Of The Texture and Quad
    glTexCoord2d(1.0, 0.0); glVertex3d(-1.0, -1.0,  1.0);	// Bottom Right Of The Texture and Quad
    glTexCoord2d(1.0, 1.0); glVertex3d(-1.0,  1.0,  1.0);	// Top Right Of The Texture and Quad
    glTexCoord2d(0.0, 1.0); glVertex3d(-1.0,  1.0, -1.0);	// Top Left Of The Texture and Quad
    glEnd();
  
    if ( takeashot ) {

        glFinish();
        glFlush();

        cpwScreenShot( cpw, &screenshot );
        sprintf( filenamebuf, "screen%i.tga", screenshotcount );
        cpwSaveImage( cpw, &screenshot, filenamebuf );
        cpwFreeImage( cpw, &screenshot );      
        screenshotcount++;
        takeashot = false;
    }

    cpwSwapWindowBuffers( cpw, winid );
}

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

void window( pCpw cpw, uint_32 winid, bool flag )
{
    /* creation event */

    if ( flag == true ) {

        glDepthFunc( GL_LEQUAL );
        glClearDepth( 1.0 );
        glEnable( GL_DEPTH_TEST );
        glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST );
        glClearColor( 0.0, 0.0, 0.0, 1.0 );
        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)1.0;
    cpwPostWindowRedisplay( cpw, 1 );
}

/****************************************************/
/*  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_MIN_FILTER, GL_LINEAR );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

    return;
}

/****************************************************/
/*  Menu Select callback                            */
/****************************************************/

void menuselect( pCpw cpw, uint_32 winid, uint_32 menuid, uint_32 entryid )
{
    bool res = false;

    switch( entryid ) {

        case 1:
          takeashot = true;
        break;    

        case 2:
          cpwBreakMainLoop( cpw );
        break;

        case 3:
          cpwMaximizeWindow( cpw, winid );
        break;

        case 4:
          cpwIconifyWindow( cpw, winid );
        break;

        case 5:
          cpwRestoreWindow( cpw, winid );
        break;

        case 6:
          cpwFullscreenWindow( cpw, winid );
        break;

        case 7:
          cpwStandardWindow( cpw, winid );
        break;

        case 10:
        cpwDisplayCallback( cpw, drawSceneOne );
        cpwCheckMenuEntry( cpw, menuid, 10 );
        cpwUncheckMenuEntry( cpw, menuid, 11 );
        break;

        case 11:
        cpwDisplayCallback( cpw, drawSceneTwo );
        cpwCheckMenuEntry( cpw, menuid, 11 );
        cpwUncheckMenuEntry( cpw, menuid, 10 );
        break;

        case 20:
        if ( glIsEnabled( GL_BLEND ) ) {
            glDisable( GL_BLEND );
            cpwUncheckMenuEntry( cpw, menuid, 20 );
        } else {
            glEnable( GL_BLEND );
            cpwCheckMenuEntry( cpw, menuid, 20 );
        }
        break;

        case 21:
        if ( glIsEnabled( GL_POLYGON_SMOOTH ) ) {
            glDisable( GL_POLYGON_SMOOTH );
            cpwUncheckMenuEntry( cpw, menuid, 21 );
        } else {
            glEnable( GL_POLYGON_SMOOTH );
            cpwCheckMenuEntry( cpw, menuid, 21 );
        }
        break;

        case 22:
        {
          GLint flag[1];
          glGetIntegerv( GL_SHADE_MODEL, &flag[0] );
          if ( flag[0] == GL_SMOOTH ) {
              glShadeModel( GL_FLAT );
              cpwUncheckMenuEntry( cpw, menuid, 22 );
          } else {
              glShadeModel( GL_SMOOTH );
              cpwCheckMenuEntry( cpw, menuid, 22 );
          }
        }
        break;

    }    
}

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

int main(int argc, char* argv[])
{
    pCpw cpw = null;
    uint_32 topmenu, submenu1, submenu2, submenu3;

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

    cpwInitContext( &cpw );

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

    cpwInitWindowProperty( cpw, CPW_WINDOWPROP_EXPECTMENU, 1, 0 );    

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

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

    cpwCreateCallback( cpw, window );
    cpwDisplayCallback( cpw, drawSceneOne );
    cpwReshapeCallback( cpw, reshape );
    cpwTimerCallback( cpw, 10, 1, true, timer );

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

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

    cpwResizeImage( cpw, &image1, 64, 64 );

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

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

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

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

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

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

    registerTexture( &image1, 1 );
    registerTexture( &image2, 2 );
    registerTexture( &image3, 3 );
    registerTexture( &image4, 4 );
    registerTexture( &image5, 5 );
    registerTexture( &image6, 6 );

    /****************************************************/
    /*  Window Menus                                    */
    /****************************************************/

    topmenu = cpwCreateMenu( cpw, menuselect );

    submenu1 = cpwCreateSubMenu( cpw );
    submenu2 = cpwCreateSubMenu( cpw );
    submenu3 = cpwCreateSubMenu( cpw );

    /* sub menu 1 */

    cpwAddMenuEntry( cpw, submenu1, "Screenshot", 1, false );
    cpwAddMenuSeperator( cpw, submenu1, 0 );
    cpwAddMenuEntry( cpw, submenu1, "Maximize", 3, false );
    cpwAddMenuEntry( cpw, submenu1, "Minimize", 4, false );
    cpwAddMenuEntry( cpw, submenu1, "Restore", 5, false );
    cpwAddMenuSeperator( cpw, submenu1, 0 );
    cpwAddMenuEntry( cpw, submenu1, "Fullscreen", 6, false );
    cpwAddMenuEntry( cpw, submenu1, "Windowed", 7, false );
    cpwAddMenuSeperator( cpw, submenu1, 0 );
    cpwAddMenuEntry( cpw, submenu1, "Exit", 2, false );

    /* sub menu 2 */

    cpwAddMenuEntry( cpw, submenu2, "Scene 1", 10, true );
    cpwAddMenuEntry( cpw, submenu2, "Scene 2", 11, false );

    /* sub menu 3 */

    cpwAddMenuEntry( cpw, submenu3, "Blending", 20, true );
    cpwAddMenuEntry( cpw, submenu3, "Polygon Smooth", 21, false );
    cpwAddMenuEntry( cpw, submenu3, "Smooth Shading", 22, true );

    cpwAddSubMenu( cpw, topmenu, "Control", submenu1, 100 );
    cpwAddSubMenu( cpw, topmenu, "Scene", submenu2, 102 );
    cpwAddSubMenu( cpw, topmenu, "Options", submenu3, 103 );

    cpwAssignMenuToWindow( cpw, topmenu, windowInfo.id );

    glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
    glEnable( GL_BLEND );
    glShadeModel( GL_SMOOTH );

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

    cpwMainLoop( cpw );

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

    cpwFreeImage( cpw, &image1 );
    cpwFreeImage( cpw, &image2 );
    cpwFreeImage( cpw, &image3 );
    cpwFreeImage( cpw, &image4 );
    cpwFreeImage( cpw, &image5 );
    cpwFreeImage( cpw, &image6 );

    exithis:

    cpwFreeContext( &cpw );

    return 0;
}