/* * $Id: picksquare.c 604 2008-02-22 02:27:50Z tapted $ * $URL: svn+ssh://pc-g33-9.it.usyd.edu.au/var/svn/pub/picksquare/picksquare.c $ */ /** * picksquare.c * Use of multiple names and picking are demonstrated. * A RxC grid of squares is drawn. When the left mouse * button is pressed, all squares under the cursor position * have the blue component of their color changed. */ #include #include #include "SDL.h" #include "SDL_opengl.h" enum { R = 300, /* number of rows of squares */ C = 400, /* number of columns of squares */ Z = 100, /* granularity of blue component */ RANGE=5, /* range of pick matrix in each direction (screen pixels) */ STEPS = 3, /* number of steps to cycle blue component */ SZ=2 /* size of each square in "world" coordinates */ }; static const GLfloat RM = 1.0/R; static const GLfloat CM = 1.0/C; static const GLfloat ZM = 1.0/Z; enum { WINWIDTH = SZ*C, /* initial window width (screen pixels) */ WINHEIGHT = SZ*R, /* initial window height (screen pixels) */ WINBPP = 32, /* bits per pixel to request */ WINXPOS = 100, /* requested window x-position (often ignored) */ WINYPOS = 100, /* requested window y-position */ INCR = Z/STEPS*3/2 /* The integer increment of the blue component */ /* each time a square is selected */ }; static int board[R][C]; /* amount of blue color for each square */ static int videoFlags; /* Flags to pass to SDL_SetVideoMode */ static SDL_Surface *surf = 0; /* The SDL surface (window handle) */ /* Clear color value for every square on the board */ static void init_cols(void) { int i, j; for (i = 0; i < R; i++) for (j = 0; j < C; j ++) board[i][j] = 0; glClearColor (1.0, 0.0, 0.0, 0.0); } /* The nine squares are drawn. In selection mode, each * square is given two names: one for the row and the * other for the column on the grid. The color of each * square is determined by its position on the grid, and * the value in the board[][] array. */ static void drawSquares(GLenum mode) { Uint32 start = SDL_GetTicks(); GLuint i, j; for (i = 0; i < R; i++) { if (mode == GL_SELECT) glLoadName (i); for (j = 0; j < C; j ++) { if (mode == GL_SELECT) glPushName (j); glColor3f ((GLfloat) i*RM, (GLfloat) j*CM, (GLfloat) board[i][j]*ZM); glRecti (j, i, j+1, i+1); if (mode == GL_SELECT) glPopName (); } } fprintf(stderr, "%d squares %s in %dms\n", R*C, mode == GL_SELECT ? "select" : "render", SDL_GetTicks() - start); } /* processHits prints out the contents of the * selection array. */ static void processHits (GLint hits, GLuint buffer[]) { unsigned int i, j; GLuint ii, jj, names, *ptr; /* printf ("hits = %d\n", hits); */ ptr = (GLuint *) buffer; for (i = 0; i < (unsigned)hits; i++) { /* for each hit */ names = *ptr; /* printf (" number of names for this hit = %d\n", names); */ ptr++; /* printf(" z1 is %g;", (float) *ptr/0x7fffffff); */ ptr++; /* printf(" z2 is %g\n", (float) *ptr/0x7fffffff); */ ptr++; /* printf (" names are "); */ for (j = 0; j < names; j++) { /* for each name */ /* printf ("%d ", *ptr); */ if (j == 0) /* set row and column */ ii = *ptr; else if (j == 1) jj = *ptr; ptr++; } /* printf ("\n"); */ if (ii >= R || jj >= C) { fprintf(stderr, "ERROR: name out of range: (%u, %u)\n", (unsigned)ii, (unsigned)jj); } else { board[ii][jj] = (board[ii][jj] + INCR) % Z; } } } /* pickSquares() sets up selection mode, name stack, * and projection matrix for picking. Then the * objects are drawn. */ #define BUFSIZE 512 static void pickSquares(int button, int state, int x, int y) { GLuint selectBuf[BUFSIZE]; GLint hits; GLint viewport[4]; /* just interpret all mouse clicks */ (void)button; (void)state; glGetIntegerv (GL_VIEWPORT, viewport); glSelectBuffer (BUFSIZE, selectBuf); (void) glRenderMode (GL_SELECT); glInitNames(); glPushName(0); glMatrixMode (GL_PROJECTION); glPushMatrix (); glLoadIdentity (); /* create RANGExRANGE pixel picking region near cursor location */ gluPickMatrix ((GLdouble) x, (GLdouble) (viewport[3] - y), RANGE, RANGE, viewport); gluOrtho2D (0.0, C, 0.0, R); drawSquares (GL_SELECT); glMatrixMode (GL_PROJECTION); glPopMatrix (); glFlush (); hits = glRenderMode (GL_RENDER); processHits (hits, selectBuf); } static void display(void) { glClear(GL_COLOR_BUFFER_BIT); drawSquares (GL_RENDER); SDL_GL_SwapBuffers(); glFlush(); } static int reshape(int w, int h) { if (w < C) w = C; if (h < R) h = R; fprintf(stderr, "Reshaping to %d x %d\n", w, h); /* get a SDL surface */ fprintf(stderr, "[N] Calling SDL_SetVideoMode(%u, %u, %u, 0x%x)\n", w, h, WINBPP, videoFlags); surf = SDL_SetVideoMode(w, h, WINBPP, videoFlags ); if (!surf) { fprintf(stderr, "[!CRITICAL!] Video mode set failed: %s\n", SDL_GetError( )); fprintf(stderr, "\tVideo flags:\n" "\t\t%s SDL_OPENGL\n" "\t\t%s SDL_HWPALETTE\n" "\t\t%s SDL_RESIZABLE\n" "\t\t%s SDL_FULLSCREEN\n" "\t\t%s SDL_HWSURFACE\n" "\t\t%s SDL_SWSURFACE\n" "\t\t%s SDL_HWACCEL\n" "\t\t%s SDL_GL_DOUBLEBUFFER\n", videoFlags & SDL_OPENGL ? "yes" : "NO ", videoFlags & SDL_HWPALETTE ? "yes" : "NO ", videoFlags & SDL_RESIZABLE ? "yes" : "NO ", videoFlags & SDL_FULLSCREEN ? "yes" : "NO ", videoFlags & SDL_HWSURFACE ? "yes" : "NO ", videoFlags & SDL_SWSURFACE ? "yes" : "NO ", videoFlags & SDL_HWACCEL ? "yes" : "NO ", videoFlags & SDL_GL_DOUBLEBUFFER ? "yes" : "NO "); return 1; } glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D (0.0, C, 0.0, R); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); return 0; } static void makeSurface() { /* this holds some info about our display */ const SDL_VideoInfo *videoInfo; /* initialize SDL */ if ( SDL_Init( SDL_INIT_VIDEO ) < 0 ) { fprintf( stderr, "[N] Video initialization failed: %s", SDL_GetError( ) ); return; } if (!(videoInfo = SDL_GetVideoInfo( ))) { fprintf( stderr, "[N] Video query failed: %s", SDL_GetError( ) ); return; } /* the flags to pass to SDL_SetVideoMode */ videoFlags = SDL_OPENGL; /* Enable OpenGL in SDL */ videoFlags |= SDL_HWPALETTE; /* Store the palette in hardware */ videoFlags |= SDL_RESIZABLE; /* Enable window resizing */ /* This checks to see if surfaces can be stored in memory */ videoFlags |= videoInfo->hw_available ? SDL_HWSURFACE : SDL_SWSURFACE; /* This checks if hardware blits can be done */ if (videoInfo->blit_hw) videoFlags |= SDL_HWACCEL; videoFlags |= SDL_GL_DOUBLEBUFFER; /* Enable double buffering */ /* Sets up OpenGL double buffering */ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); if (videoFlags & SDL_HWSURFACE) { fprintf(stderr, "[N] Using hardware accelleration\n"); } } static int mainloop() { SDL_Event event; reshape(WINWIDTH, WINHEIGHT); display(); while (SDL_WaitEvent(&event)) { switch(event.type) { case SDL_USEREVENT: break; case SDL_MOUSEMOTION: /* handleMotion(event.motion) */ continue; case SDL_MOUSEBUTTONDOWN: pickSquares(event.button.button, event.button.state, event.button.x, event.button.y); break; case SDL_MOUSEBUTTONUP: continue; case SDL_KEYUP: case SDL_KEYDOWN: if (event.key.keysym.sym == SDLK_ESCAPE) return 0; break; case SDL_VIDEOEXPOSE: break; case SDL_QUIT: return 0; case SDL_ACTIVEEVENT: case SDL_SYSWMEVENT: /* fprintf(stderr, "[E] Ignoring WM Events\n"); */ break; case SDL_VIDEORESIZE: reshape(event.resize.w, event.resize.h); /* fprintf(stderr, "[E] Resize not supported!\n"); */ break; case SDL_JOYAXISMOTION: case SDL_JOYBALLMOTION: case SDL_JOYHATMOTION: case SDL_JOYBUTTONDOWN: case SDL_JOYBUTTONUP: fprintf(stderr, "[E] Ignoring Joystick Events\n"); break; default: fprintf(stderr, "[E] Ignoring unknown SDL Event type\n"); } display(); } return 1; } /* Main Loop */ int main(int argc, char** argv) { (void)argc; (void)argv; makeSurface(); init_cols(); return mainloop(); } /* * Copyright (c) 1993-1997, Silicon Graphics, Inc. * ALL RIGHTS RESERVED * Permission to use, copy, modify, and distribute this software for * any purpose and without fee is hereby granted, provided that the above * copyright notice appear in all copies and that both the copyright notice * and this permission notice appear in supporting documentation, and that * the name of Silicon Graphics, Inc. not be used in advertising * or publicity pertaining to distribution of the software without specific, * written prior permission. * * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. * * US Government Users Restricted Rights * Use, duplication, or disclosure by the Government is subject to * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph * (c)(1)(ii) of the Rights in Technical Data and Computer Software * clause at DFARS 252.227-7013 and/or in similar or successor * clauses in the FAR or the DOD or NASA FAR Supplement. * Unpublished-- rights reserved under the copyright laws of the * United States. Contractor/manufacturer is Silicon Graphics, * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311. * * OpenGL(R) is a registered trademark of Silicon Graphics, Inc. */