File: heightmap.c

/****************************************************/
/* Height Mapping Demo using font buffers           */
/****************************************************/

/* 
  Cpw link options:

  #define CPW_EXTERN        - link to the static lib
  #define CPWDLL_EXTERN     - link to the release dll's stub
  #define CPWDLLDBG_EXTERN  - link to the debug dll's stub
  #define CPWEXTDLL_EXTERN  - link to the release dll with cpw addons 
*/

#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 CpwFontBuffer  fontbuf;
static char*          fontstring = "CPW";
static int_32         rot = 0; 

static float_32 colormod[256][3];

static GLenum mode = GL_POINTS;

static GLuint listid = 0;
static GLuint list   = 0;

/****************************************************/
/*  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, 1000 );
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
}

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

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

    glClear( GL_COLOR_BUFFER_BIT );

    set3DMatrix();

    glTranslatef( 0, 0, -210 );

    glPushMatrix();

    glRotatef( rot, 1, 1, 1 ); 

    /* draw the axis */

    glPushMatrix();
    glLineWidth( 1 );
    /* x axis */
    glColor3f( 0, 0, 1 );
    glBegin( GL_LINES );
    glVertex3f( -100, 0, 0 );
    glVertex3f( 100, 0, 0 );
    glEnd();

    /* y axis */
    glColor3f( 1, 0, 0 );
    glBegin( GL_LINES );
    glVertex3f( 0, -100, 0 );
    glVertex3f( 0, 100, 0 );
    glEnd();

    /* z axis */
    glColor3f( 1, 1, 0 );
    glBegin( GL_LINES );
    glVertex3f( 0, 0, 1 );
    glVertex3f( 0, 0, 100 );
    glEnd();
    glLineWidth( 1 );
    glPopMatrix();


    /* center the texture on the origin */

    glPushMatrix();

    glTranslatef( (fontbuf.w*2) * -.5, (fontbuf.h*2) * -.5, 0 ); 

    /* draw the hightmap */

    glCallList( list );

    glPopMatrix();

    glPopMatrix();

    /* blit the texture */

    //set2DMatrix();
    //glRasterPos2d( 1, 1 );
    //glDrawPixels( fontbuf.w, fontbuf.h, fontbuf.glformat, GL_UNSIGNED_BYTE, fontbuf.data );

    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 );
        glDepthFunc( GL_LEQUAL );
        glEnable( GL_DEPTH );
        glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST );
        //glEnable( GL_LINE_SMOOTH );
		    //glEnable(GL_BLEND);
		    //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
        //glEnable( GL_POINT_SMOOTH );
        //glEnable( GL_POLYGON_SMOOTH );
        glClearColor( 0.0, 0.0, 0.0, 1.0 );
        glPointSize( 1 );
        return;
    }

    /* window close event */

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

/****************************************************/
/*  Timer Event callback                            */
/****************************************************/

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

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

    set3DMatrix();

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

/****************************************************/
/*  Window 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 == 'p' || key == 'P' ) list = listid;
    if ( key == 'l' || key == 'L' ) list = listid+1;
    if ( key == 'q' || key == 'Q' ) list = listid+2;
    

    cpwPostRedisplay( cpw );
}

void createDisplayList( GLuint list, GLint mode ) 
{
    float_32 x, y, z;

    glNewList( list, GL_COMPILE );

    /* draw the hightmap */

    for ( y = 0; y < fontbuf.h-1; y++ )
    for ( x = 0; x < fontbuf.w-1; x++ ) /* iterate across the luminance buffer width */
    {
        glBegin( mode );

        /* draw a quad in counter clockwise order */

        /* origin */
        z = (float_32)( ( (unsigned char)        
        *( fontbuf.data + (int_32)((y * fontbuf.w) + x ) ) ) );
        glColor3f( colormod[(int_32)z][0], colormod[(int_32)z][1], colormod[(int_32)z][2] );
        glVertex3f( x*2, y*2, z*.2 );

        /* right */
        z = (float_32)( ( (unsigned char)        
        *( fontbuf.data + (int_32)((y * fontbuf.w) + (x+1) ) ) ) );
        glColor3f( colormod[(int_32)z][0], colormod[(int_32)z][1], colormod[(int_32)z][2] );
        glVertex3f( (x+1)*2, y*2, z*.2 );

        /* right top */
        z = (float_32)( ( (unsigned char)        
        *( fontbuf.data + (int_32)(((y+1) * fontbuf.w) + (x+1) ) ) ) );
        glColor3f( colormod[(int_32)z][0], colormod[(int_32)z][1], colormod[(int_32)z][2] );
        glVertex3f( (x+1)*2, (y+1)*2, z*.2 );

        /* top */
        z = (float_32)( ( (unsigned char)        
        *( fontbuf.data + (int_32)(((y+1) * fontbuf.w) + x ) ) ) );
        glColor3f( colormod[(int_32)z][0], colormod[(int_32)z][1], colormod[(int_32)z][2] );
        glVertex3f( x*2, (y+1)*2, z*.2 );

        glEnd();      

    }

    glEndList();

}


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

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

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

    cpwInitContext( &cpw );

    /****************************************************/
    /*  Creaing Windows                                 */
    /****************************************************/
    
    windowInfo.id = 
    cpwCreateWindowEx( cpw, "Press q, p, l", windowInfo.x, windowInfo.y, 
                             windowInfo.width, windowInfo.height );

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

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

    /****************************************************/
    /*  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, 40 );
    cpwFontMode( cpw, CPW_FONTOPT_PIXELMAP_GLFORMAT, GL_LUMINANCE );
    cpwFontMode( cpw, CPW_FONTOPT_LAYOUTDEBUG, 0 );
    cpwFontMode( cpw, CPW_FONTOPT_SPACING, 1 );

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

    /* pre-render our font string into a buffer */

    cpwDrawBufferedFont( cpw, font, fontstring, &fontbuf );

    {
      float_32 red = 0, green = 0, blue = 255;

      for ( i = 0; i < 256; i++ ){

          /* green: */
          if ( i > 200 ) green=green+2;
          if ( i > 240 ) green=green+4;
          /* red: */
          if ( i > 50 && i < 200 ) red=red+3;
          if ( i > 200 ) red=red-1;
          /* blue: */
          blue--;

          colormod[i][0] = red / 255; 
          colormod[i][1] = green / 255; 
          colormod[i][2] = blue / 255; 
      } 
    }

    listid = glGenLists( 3 );

    createDisplayList( listid, GL_POINTS );
    createDisplayList( listid+1, GL_LINES );
    createDisplayList( listid+2, GL_QUADS );

    list = listid;

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

    cpwMainLoop( cpw );

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

    cpwFreeBufferedFont( cpw, &fontbuf );
    cpwFreeContext( &cpw );

    return 0;
}