#include #include #include /* Windows only!! */ /*#define GLUT_STATIC 1 */ #include #define NUM_COMPONENTS 4 /* Global variables */ /* pointer to the array of pixels, 4 bytes RGBA per pixel */ static unsigned char* Checkerboard = 0; static int CheckerWidth = 0, CheckerHeight = 0, CheckerStep = 0; /* current position of the bitmap */ static int CheckerPosX =0, CheckerPosY = 0; /* indicates whether we move the bitmap diagonally as a result of mouse clicks (1) or draw on the bitmap (0) */ static int CheckerMove = 1; unsigned char* MakeChecker( int width, int height, int step ) { unsigned char* bitmap; int i,j; bitmap = (unsigned char*)malloc( width*height*NUM_COMPONENTS); for( j = 0; j < height; j++) { for( i = 0; i < width; i++) { /* for each pixel choose a color; if the pixel is in a step X step square with vertical and horizontal number both even or odd, then we make it white, otherwise black */ if( (i % (2*step) < step) == (j % (2*step) < step) ) { /* each pixel has 4 bytes: RGB and A (alpha) which we do not use */ bitmap[(j*width+i)*NUM_COMPONENTS] = 255; bitmap[(j*width+i)*NUM_COMPONENTS+1] = 255; bitmap[(j*width+i)*NUM_COMPONENTS+2] = 255; bitmap[(j*width+i)*NUM_COMPONENTS+3] = 0; } else { bitmap[(j*width+i)*NUM_COMPONENTS] = 0; bitmap[(j*width+i)*NUM_COMPONENTS+1] = 0; bitmap[(j*width+i)*NUM_COMPONENTS+2] = 0; bitmap[(j*width+i)*NUM_COMPONENTS+3] = 0; } } } return bitmap; } /* magic function to setup the mapping between virtual space and screen; we will learn about this later */ void Reshape(int width, int height) { glViewport(0,0,width,height); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0,width, 0,height); } /* callback for button clicks; gets called each time amouse butten is pressed or released */ void Mouse( int button, int state, int x, int y) { if( button == GLUT_LEFT_BUTTON ) { if( state == GLUT_UP ) { if(CheckerMove) { /* shift the position up and right */ /* in a "real" program we should check that we stay within the bounds of the window */ CheckerPosX = CheckerPosX+1; CheckerPosY = CheckerPosY+1; /* puts a display event on the event queue to indicate that the window has to be redrawn because the bitmap postion has changed */ glutPostRedisplay(); } } else if (state == GLUT_DOWN) { } else { assert(0); } } else if( button == GLUT_MIDDLE_BUTTON ) { } else if( button == GLUT_RIGHT_BUTTON) { if( state == GLUT_UP ) { if(CheckerMove) { /* shift the position down and left */ /* in a "real" program we should check that we stay within the bounds of the window */ CheckerPosX = CheckerPosX-1; CheckerPosY = CheckerPosY-1; glutPostRedisplay(); } } else if (state == GLUT_DOWN) { } else { assert(0); } } else { assert(0); } } /* callback for keyboard keys*/ void Keyboard(unsigned char key, int x, int y ) { /* space bar toggles the current state of CheckerMove */ if( key == ' ') CheckerMove = !CheckerMove; } /* callback for motion of the mouse with a button pressed */ void Motion(int x, int y) { int pixnumX; int pixnumY; int pixnum; if( !CheckerMove ) { /* assign red = (255,0,0) to the pixel under the mouse */ /* using min and max we make sure that the pixel is within the checkerboard otherwise we may end p writing outside our array! */ pixnumX = min( CheckerWidth-1, max(0,x-CheckerPosX)); /* for Y,we also need to flip the direction: bitmap rows are counted from the top, but pixels in the window from the bottom */ pixnumY = min( CheckerHeight-1,max(0, (CheckerHeight-y)-CheckerPosY)); pixnum = pixnumY*CheckerWidth+pixnumX; Checkerboard[pixnum*NUM_COMPONENTS] = 255; Checkerboard[pixnum*NUM_COMPONENTS+1] = 0; Checkerboard[pixnum*NUM_COMPONENTS+2] = 0; Checkerboard[pixnum*NUM_COMPONENTS+3] = 0; glutPostRedisplay(); } } /* window redraw even callback; is called when the window is created, maximized, resized etc.; also called if glutPostRedisplay generates the necessary event */ void Draw() { /* in the double buffer mode all drawing happens in the invisible back buffer */ glClearColor( 1.0, 0.0,0.0,0.0); glClear(GL_COLOR_BUFFER_BIT); /* We can use pixel coordinates here because we have the right magic in Reshape */ glRasterPos2i(CheckerPosX,CheckerPosY); glDrawPixels(CheckerWidth, CheckerHeight, GL_RGBA, GL_UNSIGNED_BYTE, Checkerboard); glFlush(); /* once we are done drawing we swap the back and front buffers */ glutSwapBuffers(); } int main(int argc, char* argv[]) { /* initialize glut and parse command-line aguments that glut understands */ glutInit(&argc, argv); /* create the checkerboard */ CheckerWidth = 256; CheckerHeight = 256; CheckerStep = 16; Checkerboard = MakeChecker(CheckerWidth, CheckerHeight, CheckerStep); /* initialize dislay mode: 4 color components, double buffer */ glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE); glutInitWindowSize(256,256); glutCreateWindow("a simple window "); /* register all callbacks */ glutDisplayFunc(Draw); glutReshapeFunc(Reshape); glutMouseFunc(Mouse); glutKeyboardFunc(Keyboard); glutMotionFunc(Motion); /* this is an infinte loop get event - dispatch event which never returns */ glutMainLoop(); return 0; }