File: overunder.c

/*
  overunder.c

  A basic example of how to simulate overlays and underlays 
  using a texture and glDrawPixels.
*/

/****************************************************/
/*  Basic Win32 Template                            */
/****************************************************/

#define CPWDLL_EXTERN
#include <cpw.h>

static int texWidth  = 64;
static int texHeight = 64;
static int pixel     = 4;
static bool blending = false;

static char* texture;

/* handy window characteristics holder */

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

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

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

float rot = 0;

void drawWindowOne( pCpw cpw ) 
{
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    set2DMatrix();

    glPushMatrix();

    glRasterPos2d( 100, 100 );

    glPixelZoom( 2.0, 1.0 );

    glDrawPixels( texWidth, texHeight, GL_RGBA, GL_UNSIGNED_BYTE, texture );

    glPopMatrix();

    glPushMatrix();
    glBegin( GL_LINES );
    glVertex3d( 0, 0, 0 ); 
    glVertex3d( windowInfo.width, windowInfo.height, 0 ); 
    glEnd();
    glPopMatrix();

    set3DMatrix();

    glTranslated( 0.0, 0.0, -10.0 );

    glPushMatrix();
      glRotated( rot, 0.0, 1.0, 0.0 );
      glColor3d( 0.4, 0.4, 1.0 );
      cpwSetPrimitiveOpt( cpw, CPW_PRIMOPT_BASERADIUS,  0.5 );
      cpwSetPrimitiveOpt( cpw, CPW_PRIMOPT_TOPRADIUS,  2.0 );
      cpwSetPrimitiveOpt( cpw, CPW_PRIMOPT_HEIGHT, 10.0 );
      cpwSetPrimitiveOpt( cpw, CPW_PRIMOPT_SLICES, 20.0 );
      cpwSetPrimitiveOpt( cpw, CPW_PRIMOPT_STACKS, 20.0 );
      cpwDrawPrimitive( cpw, CPW_PRIM_3D_WIRECONE );    
    glPopMatrix();

    set2DMatrix();

    glPushMatrix();

    glRasterPos2d( 1, 1 );

    glPixelZoom( 3.0, 2.0 );

    glDrawPixels( texWidth, texHeight, GL_RGBA, GL_UNSIGNED_BYTE, texture );

    glPopMatrix();

}

/****************************************************/
/*  Window Draw Event callback                      */
/****************************************************/

void draw( pCpw cpw, uint_32 winid )
{
    drawWindowOne( cpw );
    cpwSwapWindowBuffers( cpw, winid );
}

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

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

    if ( flag == true ) {

        glShadeModel( GL_SMOOTH );
        glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
        glEnable( GL_LINE_SMOOTH );
        glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
        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 );
}

void createTexture( void )
{
    int y;
    int x;
    int offset = 0;
    uint_8 fill = 0x00;

    texture = (char*)malloc( texWidth*texHeight*pixel );

    for (y=0; y < texHeight; y++ ) {
    fill = fill + ( rand() * 2 );
    for (x=0; x < texWidth; x++ ) {
        *(texture + offset) = fill; fill = fill + 2; offset = offset + 1;
        *(texture + offset) = fill; fill = fill + 2; offset = offset + 1;
        *(texture + offset) = fill; fill = fill + 2; offset = offset + 1;
        *(texture + offset) = fill; fill = fill + 2; offset = offset + 1;
    } }
    offset = 0;
}

/****************************************************/
/*  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;

    if ( key == 'b' || key == 'B' ) blending = !blending;

    if ( blending == true ) glEnable( GL_BLEND );
    if ( blending == false ) glDisable( GL_BLEND );

    cpwPostRedisplay( cpw );
}

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

void timer( pCpw cpw, uint_32 id )
{
    rot = rot + (float)2;
    cpwPostRedisplay( cpw );
}

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

#ifdef _WINDOWS
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
#elif  _CONSOLE
int main(int argc, char* argv[])
#endif
{
    pCpw cpw = null;

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

    cpwInitContext( &cpw );

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

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

    cpwCreateCallback( cpw, window );
    cpwDisplayCallback( cpw, draw );
    cpwReshapeCallback( cpw, reshape );
    cpwKeyboardCallback( cpw, keyboard );
    cpwTimerCallback( cpw, 50, 1, true, timer );

    /****************************************************/
    /*  Texturing                                       */
    /****************************************************/

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

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

    cpwMainLoop( cpw );

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

    cpwFreeContext( &cpw );

    return 0;
}