Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

/home/landauf/painter/miniproject/framewk/framewk.cpp

Go to the documentation of this file.
00001 //
00002 //    Title: framewk.cc
00003 //  Created: Tue Oct 16 09:53:01 2001
00004 //   Author: Tim Weyrich <weyrich@inf.ethz.ch>
00005 //
00006 //  copyright (c) 2001--2003, Computer Graphics Laboratory, ETH Zuerich
00007 //
00008 
00009 #include <stdlib.h>
00010 #include <math.h>
00011 
00012 #include <imagergba.h>
00013 
00014 #include "framewk.h"
00015 
00016 
00018 
00022 typedef struct
00023 {
00024   int  width;
00025   int  height;
00026 
00027   int  bytesPerPixel;
00028 
00029   void  *data;
00030 } Image;
00031 
00032 static const Image  *displayImage = NULL;  /* let this pointer point to the
00033                                               image you want to display */
00034 static GLdouble      displayZoom = 1.0;    /* read only (is set by redrawCB);
00035                                               don't change it directly */
00036 static GLint  displayHotSpotX = 0;
00037 static GLint  displayHotSpotY = 0;
00038 
00039 static GLdouble  displayRasterX = 0;
00040 static GLdouble  displayRasterY = 0;
00041 
00042 static bool  displayChanged = true;
00043 
00044 static int  glutWindowId = -1;          /* for internal use */
00045 
00046 
00048 //  Static Function Prototypes                                               //
00050 
00052 static void  fwkPostRedisplayNoChange(void);
00053 
00055 static void  fwkWindowToImageCoordinates(int x, int y, float *ix, float *iy);
00056 
00058 static void  fwkSetDisplayHotSpot(int x, int y);
00059 
00061 //  Functions for Zoom Calculations                                          //
00063 
00064 #include <iostream.h>
00065 
00066 #define  HAVE_GLCOPYTEXSUBIMAGE2D
00067 
00068 static bool  fwkUpdateRasterPos(void)
00069   /* compute raster position */
00070 {
00071   GLdouble  oldRasterX = displayRasterX;
00072   GLdouble  oldRasterY = displayRasterY;
00073 
00074   {
00075     GLdouble  displayWidth = displayZoom * displayImage->width;
00076     GLdouble  displayHeight = displayZoom * displayImage->height;
00077     GLint     vp[4];
00078         
00079     glGetIntegerv(GL_VIEWPORT, vp);
00080         
00081     if (vp[2] >= displayWidth)
00082       displayRasterX = (vp[2] - displayWidth) / 2;
00083     else
00084       {
00085 #ifdef HAVE_GLCOPYTEXSUBIMAGE2D
00086         displayRasterX = displayHotSpotX - displayWidth * displayHotSpotX / (float)vp[2];
00087 #else
00088         displayRasterX = 0;  // as long as I'm using glDrawPixels, I'm not allowed to have a negative displayRasterX.
00089 #endif
00090       }
00091 
00092     if (vp[3] >= displayHeight)
00093       displayRasterY = (vp[3] - displayHeight) / 2;
00094     else
00095       {
00096 #ifdef HAVE_GLCOPYTEXSUBIMAGE2D
00097         displayRasterY = displayHotSpotY - displayHeight * displayHotSpotY / (float)vp[3];
00098 #else
00099         displayRasterY = 0;  // as long as I'm using glDrawPixels, I'm not allowed to have a negative displayRasterY.
00100 #endif
00101       }
00102   }
00103 
00104   return displayRasterX != oldRasterX || displayRasterY != oldRasterY;
00105 }
00106 
00107 void  fwkWindowToImageCoordinates(int x, int y, float *ix, float *iy)
00119 {
00120   *ix = (float)((x+0.5-displayRasterX) / displayZoom);
00121   *iy = (float)((y+0.5-displayRasterY) / displayZoom);
00122 }
00123 
00125 //  Callback Functions                                                       //
00127 
00128 #ifdef HAVE_GLCOPYTEXSUBIMAGE2D
00129 GLuint  imageTexID = 0;
00130 #endif
00131 static unsigned  nextPowerOfTwo(unsigned x)
00132 {
00133   int       n;
00134   unsigned  m = x;
00135   for (n=0; m; m>>=1, n++);
00136   if (x == (1u << (n-1)))
00137     return (1u << (n-1));
00138   else
00139     return (1u << n);
00140 }
00141 
00142 #ifdef HAVE_GLCOPYTEXSUBIMAGE2D
00143 unsigned  texWidth = 0;
00144 unsigned  texHeight = 0;
00145 GLenum    texId = 0;
00146 #endif
00147 
00148 static void  fwkRedrawCB(void)
00149   /* This callback function is called, whenever a redraw of the
00150    * current window is needed. For your work on the exercise, there
00151    * is no need to touch this function.
00152    *
00153    * Actually, this function displays the image pointed at by
00154    * displayImage.
00155    */
00156 {
00157   if (displayImage)
00158     { /* there is a valid image to display */
00159       GLint     vp[4];
00160         
00161       glGetIntegerv(GL_VIEWPORT, vp);
00162 
00163       fwkUpdateRasterPos();
00164 
00165       /* set up OpenGL projection matrix */
00166       glMatrixMode(GL_PROJECTION);
00167       glLoadIdentity();
00168       glOrtho(0, vp[2], vp[3], 0, -1, 1);
00169       glMatrixMode(GL_MODELVIEW);
00170       glLoadIdentity();
00171 
00172       /* set up memory alignment */
00173       glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
00174       glPixelStorei(GL_PACK_ALIGNMENT, 1);
00175 
00176       /* clear buffer and draw image */
00177       glClearColor(0.2f,0.2f,0.4f,1.0f);
00178       glClear(GL_COLOR_BUFFER_BIT);
00179 
00180 #ifdef HAVE_GLCOPYTEXSUBIMAGE2D
00181       {
00182         if (texId==0 || displayChanged)
00183           {
00184             unsigned  w2p = nextPowerOfTwo((unsigned)displayImage->width);
00185             unsigned  h2p = nextPowerOfTwo((unsigned)displayImage->width);
00186             if (texId > 0 && (w2p != texWidth || h2p != texHeight))
00187               {
00188                 glDeleteTextures(1, &texId);
00189                 texId = 0;
00190               }
00191             if (texId == 0)
00192               {
00193                 glGenTextures(1, &texId);
00194                 glBindTexture(GL_TEXTURE_2D, texId);
00195 
00196                 texWidth = w2p;
00197                 texHeight = h2p;
00198                 // Create Null Texture
00199                 glTexImage2D(GL_TEXTURE_2D, 0, 
00200                              displayImage->bytesPerPixel,
00201                              texWidth, texHeight, 0,
00202                              displayImage->bytesPerPixel == 4 ? GL_RGBA : GL_LUMINANCE,
00203                              GL_UNSIGNED_BYTE,
00204                              NULL);
00205               }
00206             else
00207               glBindTexture(GL_TEXTURE_2D, texId);
00208             
00209             glTexSubImage2D(GL_TEXTURE_2D, 0,
00210                             0, 0, displayImage->width, displayImage->height,
00211                             displayImage->bytesPerPixel == 4 ? GL_RGBA : GL_LUMINANCE,
00212                             GL_UNSIGNED_BYTE,
00213                             displayImage->data);
00214           }
00215         else
00216           glBindTexture(GL_TEXTURE_2D, texId);
00217         
00218         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
00219         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
00220         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00221         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00222             
00223         glEnable(GL_TEXTURE_2D);
00224         glDisable(GL_DEPTH_TEST);
00225         glDisable(GL_LIGHTING);
00226         glBegin(GL_QUADS);
00227         {
00228           GLfloat  displayWidth = displayZoom * displayImage->width;
00229           GLfloat  displayHeight = displayZoom * displayImage->height;
00230 
00231           GLfloat  maxS = (GLfloat)displayImage->width / texWidth;
00232           GLfloat  maxT = (GLfloat)displayImage->height / texHeight;
00233 
00234           glTexCoord2f(0, 0);
00235           glVertex2f(displayRasterX, displayRasterY);
00236           
00237           glTexCoord2f(maxS, 0);
00238           glVertex2f(displayRasterX+displayWidth, displayRasterY);
00239           
00240           glTexCoord2f(maxS, maxT);
00241           glVertex2f(displayRasterX+displayWidth, displayRasterY+displayHeight);
00242           
00243           glTexCoord2f(0, maxT);
00244           glVertex2f(displayRasterX, displayRasterY+displayHeight);
00245         }
00246         glEnd();
00247         glEnable(GL_DEPTH_TEST);
00248         glDisable(GL_TEXTURE_2D);
00249       }
00250 #else
00251       {
00252         glRasterPos2d(displayRasterX, displayRasterY);
00253         glPixelZoom(displayZoom, -displayZoom);
00254         if (displayImage->bytesPerPixel == 4)
00255           {
00256             glDrawPixels(displayImage->width, displayImage->height,
00257                          GL_RGBA,
00258                          GL_UNSIGNED_BYTE,
00259                          displayImage->data);
00260           }
00261         else
00262           {
00263             glDrawPixels(displayImage->width, displayImage->height,
00264                          GL_LUMINANCE,
00265                          GL_UNSIGNED_BYTE,
00266                          displayImage->data);
00267           }
00268       }
00269 #endif
00270     }
00271   else
00272     /* if no image is available, just clear buffer */
00273     glClear(GL_COLOR_BUFFER_BIT);
00274 
00275   /* transfer buffer to window */
00276   glutSwapBuffers();
00277 
00278   displayChanged = false;
00279 }
00280 
00281 static void  fwkKeyboardCB(unsigned char key, int x, int y)
00282 {
00283   float  imageX;
00284   float  imageY;
00285   
00286   fwkSetDisplayHotSpot(x, y);
00287   fwkWindowToImageCoordinates(x, y, &imageX, &imageY);
00288   
00289   keyboardCB(key, imageX, imageY);
00290 }
00291 
00292 static void  fwkSpecialCB(int key, int x, int y)
00293 {
00294   float  imageX;
00295   float  imageY;
00296   
00297   fwkSetDisplayHotSpot(x, y);
00298   fwkWindowToImageCoordinates(x, y, &imageX, &imageY);
00299   
00300   specialCB(key, imageX, imageY);
00301 }
00302 
00303 static void  fwkMouseCB(int button, int state, int x, int y)
00304 {
00305   float  imageX;
00306   float  imageY;
00307   
00308   fwkSetDisplayHotSpot(x, y);
00309   fwkWindowToImageCoordinates(x, y, &imageX, &imageY);
00310   
00311   mouseCB(button, state, imageX, imageY);
00312 }
00313 
00314 static void  fwkMotionCB(int x, int y)
00315 {
00316   float  imageX;
00317   float  imageY;
00318   
00319   fwkSetDisplayHotSpot(x, y);
00320   fwkWindowToImageCoordinates(x, y, &imageX, &imageY);
00321   
00322   motionCB(imageX, imageY);
00323 }
00324 
00325 static void  fwkPassiveMotionCB(int x, int y)
00334 {
00335   fwkSetDisplayHotSpot(x, y);
00336 }
00337 
00339 // Initializations                                                           //
00341 
00342 void  fwkInit(int *argc, const char *argv[])
00349 {
00350   /* Initialize Display */
00351   {
00352     if (argc && *argc >= 1 && argv)
00353       glutInit(argc, (char **)argv);
00354     else
00355       {
00356         int    fake_argc = 1;
00357         char  *fake_argv[] = {"painter"};
00358         glutInit(&fake_argc, fake_argv);
00359       }
00360   }
00361 
00362   /* Get double-buffered rgb display without depth-buffer. */
00363   glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
00364 
00365   /* Open Window */
00366   glutInitWindowSize(512, 512);
00367   glutWindowId = glutCreateWindow("Paint Application");
00368   
00369   /* Register Callbacks. */
00370   glutDisplayFunc(fwkRedrawCB);
00371   glutKeyboardFunc(fwkKeyboardCB);
00372   glutSpecialFunc(fwkSpecialCB);
00373   glutMouseFunc(fwkMouseCB);
00374   glutMotionFunc(fwkMotionCB);
00375   glutPassiveMotionFunc(fwkPassiveMotionCB);
00376   glutIdleFunc(idleCB);
00377 }
00378 
00379 void  fwkMainLoop(void)
00384 {
00385   glutMainLoop();
00386 }
00387 
00389 
00390 void  fwkSetDisplayImage(const void *img)
00397 {
00398   assert(((const Image *)img)->bytesPerPixel == 1 ||
00399          ((const Image *)img)->bytesPerPixel == 4);
00400   
00401   if (displayImage != img && glutWindowId >= 0)
00402     {
00403       displayImage = (const Image *)img;
00404       glutPostRedisplay();
00405     }
00406   else
00407     displayImage = (const Image *)img;
00408 }
00409 
00410 float  fwkGetDisplayZoom(void)
00411 {
00412   return (float)displayZoom;
00413 }
00414 
00415 void  fwkSetDisplayZoom(float zoom)
00416 {
00417   if (displayZoom != zoom)
00418     {
00419       displayZoom = zoom;
00420       fwkPostRedisplayNoChange();
00421     }
00422 }
00423 
00424 void  fwkSetDisplayHotSpot(int x, int y)
00428 {
00429   if (displayHotSpotX != x || displayHotSpotY != y)
00430     {
00431       GLint     vp[4];
00432         
00433       glGetIntegerv(GL_VIEWPORT, vp);
00434 
00435       if (x >= vp[0] && x-vp[0] < vp[2])
00436         displayHotSpotX = x;
00437           
00438       if(y >= vp[1] && y-vp[1] < vp[3])
00439         displayHotSpotY = y;
00440 
00441       if (fwkUpdateRasterPos())
00442         fwkPostRedisplayNoChange();
00443     }
00444 }
00445 
00446 void  fwkPostRedisplay(void)
00452 {
00453   displayChanged = true;
00454   glutPostRedisplay();
00455 }
00456 
00457 void  fwkPostRedisplayNoChange(void)
00464 {
00465   glutPostRedisplay();
00466 }
00467 

Generated on Mon Jan 30 09:13:02 2006 for Painter Framework by doxygen1.2.18