home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / tutorials / OGLT / Examples / ImageProcessing / src.shakib / roam.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-11-11  |  16.3 KB  |  530 lines

  1.  /**************************************************************************
  2.   *                                                                        *
  3.   *               Copyright (C) 1996, Silicon Graphics, Inc.               *      *                          All Rights Reserved.                          *
  4.   *                                                                        *
  5.   *  The files in this subtree  contain  UNPUBLISHED  PROPRIETARY  SOURCE  *
  6.   *  CODE of Silicon Graphics, Inc.;  the  contents  of  these  files may  *
  7.   *  not be disclosed to third  parties,  copied  or  duplicated  in  any  *
  8.   *  form, in whole or in part,  without  the  prior  written  permission  *
  9.   *  of  Silicon Graphics, Inc.                                            *
  10.   *                                                                        *
  11.   *  RESTRICTED RIGHTS LEGEND:                                             *
  12.   *  Use,  duplication  or  disclosure  by  the  Government is subject to  *
  13.   *  restrictions as set forth in subdivision (c)(1)(ii) of the Rights in  *
  14.   *  Technical Data and Computer Software clause at  DFARS  252.227-7013,  *
  15.   *  and/or in similar or successor  clauses in the FAR,  DOD or NASA FAR  *
  16.   *  Supplement.  Unpublished - rights reserved  under the Copyright Laws  *
  17.   *  of the United States.                                                 *
  18.   *                                                                        *
  19.   *  THIS SOFTWARE IS  PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,  *
  20.   *  EXPRESS,  IMPLIED OR  OTHERWISE,  INCLUDING  WITHOUT LIMITATION, ANY  *
  21.   *  WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.      *
  22.   *                                                                        *
  23.   *  IN  NO  EVENT  SHALL  SILICON  GRAPHICS  BE  LIABLE FOR ANY SPECIAL,  *
  24.   *  INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF  ANY  KIND,  OR ANY  *
  25.   *  DAMAGES WHATSOEVER RESULTING FROM LOSS  OF  USE,  DATA  OR  PROFITS,  *
  26.   *  WHETHER OR NOT ADVISED OF  THE  POSSIBILITY  OF  DAMAGE,  AND ON ANY  *
  27.   *  THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR  *
  28.   *  PERFORMANCE OF THIS SOFTWARE.                                         *
  29.   **************************************************************************/
  30.  
  31. /**************************************************************************
  32.  *  AUTHOR: Bob Shakib                                                    *
  33.  *  shakib@sgi.com                                                        *
  34.  *  (415) 933 6046                                                        *
  35.  **************************************************************************/
  36. /***************************************************************************
  37. * compile: cc -o roam roam.c -lGLw -lGL -lGLU -lXm -lXt -lX11 -limage -lm  *
  38. * To run the demo:                                                         *
  39. * ./Roam
  40. * roam with button1                                                        *
  41. * zoom with button2                                                        *
  42. * rotate with button3                                                      *
  43. * press "a" key for auto roam                                              *
  44. * press "r" key to reset view                                              *
  45. ****************************************************************************/
  46.  
  47. #include <stdlib.h>
  48. #include <stdio.h>
  49. #include <math.h>
  50. #include <Xm/Frame.h>
  51. #include <X11/GLw/GLwMDrawA.h>
  52. #include <X11/keysym.h>
  53. #include <X11/Xutil.h>
  54. #include <GL/glx.h>
  55. #include <GL/glu.h>
  56. #include <sys/fcntl.h>
  57. #include "/usr/include/gl/image.h"
  58. #include "/usr/include/device.h"
  59.  
  60. #define NUMTEX     16
  61. #define X_TEX 4
  62. #define Y_TEX 4
  63. #define WIDTH 4096
  64.  
  65. typedef struct {
  66.   GLuint compID;
  67.   GLuint rectBaseX;
  68.   GLuint rectBaseY;
  69. } tileStruct;
  70.  
  71. typedef struct {
  72.   GLuint  textureID;
  73.   tileStruct tile[2][2];
  74. } texStruct;
  75.  
  76. typedef struct {
  77.   texStruct tex[2][2];
  78. } listStruct;
  79.  
  80. /* define a struct to keep image and widget information */
  81. typedef struct {
  82.   Widget glxWidget;             /* widget where images will be drawn */
  83.   Widget frame;
  84.   XtAppContext app;             /* Xt application context */
  85.   XtWorkProcId wpid;            /* workproc id used for the rotate workproc */ 
  86.   GLfloat theta;                  /* the angle by which the image is rotated */
  87.   int direction;        /* direction of image rotation */
  88.   GLfloat incr;                   /* the increment to be added to the angle of rotation */
  89.   GLfloat zoomFact;    
  90.   GLfloat factor;
  91.   int winWidth;                /* width of displayed image */
  92.   int winHeight;        /* height of displayed image */
  93.   int mstate, omx, omy, mx, my; /* pointer locations and the button state */
  94.   GLfloat x, y;
  95.   listStruct list[3][3];
  96. } infoStruct;
  97.  
  98.  
  99.  
  100. static void update_view_info(infoStruct* info);
  101. static void render_tex(infoStruct *info);
  102. static void readimage( char *file, char *buf);
  103.  
  104. /* define the required atributes for the GLX drawable */
  105. static int      attribs[] = {GLX_RGBA, GLX_DOUBLEBUFFER, GLX_RED_SIZE, 4, None};
  106.  
  107. /* define the resources for the GL widget */
  108. static String   fallbackResources[] = {
  109.   "*useSchemes: all",
  110.   "*frame*shadowType: SHADOW_IN",
  111.   NULL};
  112.  
  113. static void readimage( char *file, char *buf)
  114. {
  115.   int i,j;
  116.   short rowbuf[4096];
  117.  
  118.   IMAGE *image;
  119.   image = iopen(file,"r");
  120.   
  121.   for (i=0; i<image->ysize; i++)
  122.     {
  123.       getrow( image, rowbuf, i, 0 );
  124.       for (j=0; j<image->xsize; j++)
  125.         {
  126.           *buf++ = (char) rowbuf[j];
  127.         }
  128.     }
  129.   iclose(image);
  130. }
  131.  
  132. /* workproc function that gets called repeatedly to increment the angle */
  133. /* and call the draw function */
  134. static Boolean
  135. roam_proc(XtPointer clientData) 
  136. {    
  137.   infoStruct *info = (infoStruct *)clientData;
  138.  
  139.   info->theta += .05;
  140.     info->theta = (info->theta < -360) ? info->theta=+360 : 
  141.       (info->theta > 360) ? info->theta=-360 : 
  142.     info->theta;
  143.   
  144.   if ((info->x < 6) &&  ((info->y == 1)||(info->y < 1)))
  145.     {
  146.       info->x += 0.002;
  147.       render_tex(info);
  148.       return False;
  149.     }
  150.   if ((info->y < 6) && (info->x > 6))
  151.     {
  152.       info->y += 0.002;
  153.       render_tex(info);
  154.       return False;
  155.     }
  156.   if ((info->x > 1) && (info->y > 6))
  157.     {
  158.       info->x -= 0.002;
  159.       render_tex(info);
  160.       return False;
  161.     }
  162.   if ((info->y > 1) && (info->x < 1))
  163.     {
  164.       info->y -= 0.002;
  165.       render_tex(info);
  166.       return False;
  167.     }
  168. }
  169.  
  170.  
  171. /* callback to handle keyboard input */
  172. static void
  173. inputCB(Widget w, XtPointer client_data, XtPointer call) 
  174. {
  175.   char buffer[31];
  176.   KeySym keysym;
  177.   XEvent *event = ((GLwDrawingAreaCallbackStruct *) call)->event;
  178.   /*  GLwDrawingAreaCallbackStruct *call_data; */
  179.   infoStruct *info = (infoStruct *) client_data;
  180.   
  181.   switch(event->type) 
  182.     {            
  183.     case KeyRelease:
  184.       XLookupString(&event->xkey, buffer, 30, &keysym, NULL);
  185.       switch(keysym) 
  186.     {
  187.       /* exit the program if escape is pressed */
  188.     case XK_Escape :
  189.       exit(EXIT_SUCCESS);
  190.       break;
  191.     case XK_a :
  192.       info->x = 1.0;
  193.       info->y = 1.0;
  194.       if (!info->wpid) 
  195.         {
  196.           info->wpid = XtAppAddWorkProc(info->app, roam_proc, info);
  197.         }
  198.       break;
  199.     case XK_s :
  200.       if (info->wpid) 
  201.         {
  202.           XtRemoveWorkProc(info->wpid);
  203.           info->wpid = 0;
  204.         }
  205.       break;
  206.     case XK_r :
  207.       if (info->wpid) 
  208.         {
  209.           XtRemoveWorkProc(info->wpid);
  210.           info->wpid = 0;
  211.         }
  212.       info->x = 4.0;
  213.       info->y = 4.0;
  214.       info->theta = 0.0;
  215.       info->zoomFact = 1.0;
  216.       render_tex(info);
  217.       break;
  218.     case XK_Up :
  219.       if (info->factor > 50)
  220.         info->factor -= 10;
  221.       break;
  222.     case XK_Down :
  223.       if (info->factor <1000)
  224.         info->factor += 10;
  225.       break;
  226.     default: break;
  227.     }
  228.       break;
  229.       
  230.     case ButtonPress:
  231.       if (info->wpid) 
  232.     {
  233.       XtRemoveWorkProc(info->wpid);
  234.       info->wpid = 0;
  235.     }
  236.       if (event->xbutton.button == Button1) 
  237.     {
  238.       info->mstate = 1; 
  239.       info->mx = event->xbutton.x;
  240.       info->my = event->xbutton.y;
  241.     } 
  242.       else if (event->xbutton.button == Button2) 
  243.     {
  244.       info->mstate = 2;
  245.       info->mx = event->xbutton.x;
  246.       info->my = event->xbutton.y;
  247.     }
  248.       else if (event->xbutton.button == Button3) 
  249.     {
  250.       info->mstate = 3;
  251.       info->mx = event->xbutton.x;
  252.       info->my = event->xbutton.y;
  253.     }
  254.       break;
  255.       
  256.     case ButtonRelease:
  257.       info->mstate = 0;
  258.       break;
  259.       
  260.     case MotionNotify:
  261.       if (info->mstate) 
  262.     {
  263.       info->omx = info->mx;
  264.       info->omy = info->my;
  265.       info->mx = event->xbutton.x;
  266.       info->my = event->xbutton.y;
  267.       update_view_info(info);
  268.     }
  269.       break;
  270.     }
  271. }
  272.  
  273. /* this callback gets called everytime the window gets an expose or resize event */
  274. static void
  275. exposeCB(Widget w, XtPointer client_data, XtPointer call) 
  276. {
  277.   GLwDrawingAreaCallbackStruct *call_data;
  278.   infoStruct *info;
  279.   
  280.   call_data = (GLwDrawingAreaCallbackStruct *) call;
  281.   info = (infoStruct *) client_data;
  282.   update_view_info(info);
  283. }
  284.  
  285. static void
  286. update_view_info(infoStruct *info) 
  287. {
  288.   int dx = info->omx - info->mx;
  289.   int dy = info->omy - info->my;
  290.   
  291.   
  292.   if (info->mstate == 1)  /*translate*/
  293.     {
  294.       info->x += (float)dx/info->factor;
  295.       info->x = (info->x < 1.0) ? 1.0 : (info->x > 6.9) ? 6.9 : info->x;
  296.       info->y -= (float)dy/info->factor;
  297.       info->y = (info->y < 1.0) ? 1.0 : (info->y > 6.9) ? 6.9 : info->y;
  298.     }
  299.   else if (info->mstate == 2)  /*zoom*/
  300.     {
  301.       info->zoomFact += (float)dy/150;
  302.       info->zoomFact = (info->zoomFact < 1.0) ? 1.0 : ((info->zoomFact > 5.0) ? 5.0 : info->zoomFact);
  303.     }
  304.   else if (info->mstate == 3)  /*rotate*/
  305.     {
  306.       info->theta += - (float)dy/5;
  307.     info->theta = (info->theta < -360) ? info->theta = -360 : 
  308.                 (info->theta > 360) ? info->theta= 360 : 
  309.              info->theta;
  310.     }
  311.   
  312.   render_tex(info);
  313. }
  314.  
  315.  
  316. static void
  317. render_tex(infoStruct *info) 
  318. {
  319.  
  320.   int  lx, ly, tx, ty, cx, cy, baseX, baseY;
  321.   /* Locate nearest four corners and call render textures on that corner */
  322.   lx = (int)floor(info->x / 2. + .5) - 1;
  323.   lx = (lx < 0) ? 0 : ((lx > (X_TEX - 1)) ? (X_TEX - 1) : lx); /* clamp [0, m - 1] */
  324.   ly = (int)floor(info->y / 2. + .5) - 1;
  325.   ly = (ly < 0) ? 0 : ((ly > (Y_TEX - 1)) ? (Y_TEX - 1) : ly); /* clamp [0, n - 1] */
  326.  
  327.   glPushMatrix(); /* Make sure that you're always in MODELVIEW here */
  328.   glScalef(info->zoomFact, info->zoomFact, 1.0);
  329.   glRotatef(-info->theta, 0., 0., 1.);
  330.   glTranslatef(-info->x, -info->y, 0);
  331.  
  332.   for (tx=0; tx<2; tx++)
  333.     for (ty=0; ty<2; ty++)
  334.       {
  335.     glBindTextureEXT(GL_TEXTURE_2D, info->list[lx][ly].tex[tx][ty].textureID); 
  336.     for (cx=0; cx<2; cx++)
  337.       for (cy=0; cy<2; cy++)
  338.         {
  339.           glTexParameteri(GL_TEXTURE_2D, GL_QUAD_TEXTURE_SELECT_SGIS, 
  340.                   info->list[lx][ly].tex[tx][ty].tile[cx][cy].compID);  
  341.           /* map the texture one component at a time */
  342.           /* texture coordinates go from 1/1024 to 511/512 */
  343.           baseX = info->list[lx][ly].tex[tx][ty].tile[cx][cy].rectBaseX;
  344.           baseY = info->list[lx][ly].tex[tx][ty].tile[cx][cy].rectBaseY;
  345.           glBegin(GL_QUADS);
  346.           glTexCoord2f(0.0009765625, 0.0009765625); 
  347.           glVertex2f(baseX, baseY);
  348.           glTexCoord2f(0.99804688, 0.0009765625);
  349.           glVertex2i(baseX + 1, baseY);
  350.           glTexCoord2f(0.99804688, 0.99804688); 
  351.           glVertex2i(baseX + 1, baseY + 1);
  352.           glTexCoord2f(0.0009765625, 0.99804688);
  353.           glVertex2i(baseX, baseY + 1);
  354.           glEnd();
  355.         }
  356.       }
  357.   glPopMatrix();  
  358.   glXSwapBuffers(XtDisplay(info->glxWidget), XtWindow(info->glxWidget));
  359. }
  360.  
  361. main(int argc, char *argv[]) 
  362. {
  363.   
  364.   infoStruct     *info;
  365.   Display        *dpy;
  366.   XVisualInfo    *visinfo;
  367.   Widget          toplevel;
  368.   GLXContext      glxcontext;
  369.   XtAppContext    app;           
  370.   GLubyte        *srcImg;
  371.   GLubyte        *base1, *base2, *base3, *base4;
  372.   GLubyte        *dst, *dstPtr;
  373.   GLubyte        *src1, *src2, *src3, *src4;
  374.   GLint           i, j, k, m, n, p, tx, ty, cx, cy, lx, ly;
  375.   GLuint          texCount, xsize, ysize;
  376.   GLuint          textures[4][4];
  377.   GLuint         *texNames;
  378.   GLuint          rectBaseX;
  379.   GLuint          rectBaseY;  
  380.   IMAGE          *image;
  381.  
  382.   
  383.   /* Allocate the infoStruct space */
  384.   info  = (infoStruct*) calloc(1, sizeof(infoStruct));
  385.   
  386.   /* set the angle of rotation to zero since the image is still until user */
  387.   /* starts the rotation */
  388.   info->theta = 0.0; 
  389.   /* set the initial increment to a low value to get a smooth rotation */
  390.   info->incr = 0.2;
  391.   /* creat ea top level shell for the application */
  392.   info->x = 4.0;
  393.   info->y = 4.0;
  394.   info->zoomFact = 1.0;
  395.   info->factor = 400;
  396.  
  397.   toplevel = XtOpenApplication(&info->app, "rotate", NULL, 0, &argc, argv,
  398.                    fallbackResources, applicationShellWidgetClass,
  399.                    NULL, 0);
  400.  
  401.   /* get a display going */
  402.   dpy = XtDisplay(toplevel);
  403.   /* create a frame widget to put the gl widget in */
  404.   info->frame = XmCreateFrame(toplevel, "frame", NULL, 0);
  405.   XtManageChild(info->frame);
  406.   
  407.   /* specify visual directly */
  408.   if (!(visinfo = glXChooseVisual(dpy, DefaultScreen(dpy), attribs)))
  409.     XtAppError(info->app, "no suitable RGB visual");
  410.   /* create the gl widget for drawing */
  411.   info->glxWidget = XtVaCreateManagedWidget("glxwidget", glwMDrawingAreaWidgetClass,
  412.                          info->frame, GLwNvisualInfo, visinfo, NULL);
  413.   /* set the initial width and height of the GL widget to be the width and height */
  414.   /* of the loaded image */ 
  415.   XtVaSetValues(info->glxWidget, XmNwidth, 950, NULL);
  416.   XtVaSetValues(info->glxWidget, XmNheight, 950, NULL);
  417.  
  418.   /* add the input handling and expose callbacks */
  419.   XtAddCallback(info->glxWidget, GLwNexposeCallback, exposeCB, info);
  420.   XtAddCallback(info->glxWidget, GLwNinputCallback, inputCB, info);
  421.   
  422.   XtRealizeWidget(toplevel);  
  423.   
  424.   /* create a context */
  425.   glxcontext = glXCreateContext(dpy, visinfo, 0, GL_TRUE);
  426.   /* make the context current with the gl widget */
  427.   GLwDrawingAreaMakeCurrent(info->glxWidget, glxcontext);
  428.  
  429.  
  430.   glClearColor(0.0, 0.0, 0.0, 1.0);
  431.   glClear(GL_COLOR_BUFFER_BIT);
  432.   glXSwapBuffers(XtDisplay(info->glxWidget), XtWindow(info->glxWidget)); 
  433.  
  434.   srcImg = (unsigned char *)calloc(1, 4096*4096);
  435.  
  436.   readimage( "./data/berlin.bw", srcImg); 
  437.  
  438.  
  439.   glViewport(0, 0, 950, 950);
  440.   glMatrixMode(GL_PROJECTION);
  441.   glLoadIdentity();
  442.   glOrtho(-0.70710678, 0.70710678, -0.70710678, 0.70710678, -1.0, 1.0);
  443.   glMatrixMode(GL_MODELVIEW);
  444.   glLoadIdentity();
  445.   
  446.   glEnable(GL_TEXTURE_2D); 
  447.   
  448.   /* set up the texture parameters and load the texture */
  449.   glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  450.   
  451.   /* split up the image data into XSIZE*YSIZE texture tiles which are 
  452.      grouped in 4 and interleaved */
  453.   dst = (GLubyte*)calloc(1, 1024*1024);
  454.   texCount = 0;
  455.   texNames = malloc(NUMTEX*sizeof(GLuint));
  456.   glGenTexturesEXT(NUMTEX, texNames);
  457.   
  458.   for (p=0, base1=srcImg; p<2; p++, base1+=WIDTH*2044)
  459.     for (n=0, base2=base1; n<2; n++, base2+=2044)
  460.       for (m=0, base3=base2; m<2; m++, base3+=WIDTH*1022)
  461.     for (k=0, base4=base3; k<2; k++,base4+=1022)
  462.       {
  463.         /* reposition the src and destination pointers */
  464.         src1=base4;
  465.         src2=src1+511;
  466.         src3=base4+(511*WIDTH);
  467.         src4=src3+511;
  468.         dstPtr=(GLubyte*)dst;
  469.         
  470.         for (j=0;j<512;j++)
  471.           {
  472.         for (i=0;i<512;i++)
  473.           {
  474.             *dstPtr++ = *src1++; 
  475.             *dstPtr++ = *src2++;
  476.             *dstPtr++ = *src3++;
  477.             *dstPtr++ = *src4++; 
  478.           }
  479.         src1 += 4096 - 512;
  480.         src2 += 4096 - 512;
  481.         src3 += 4096 - 512;
  482.         src4 += 4096 - 512;
  483.           }
  484.         glBindTextureEXT(GL_TEXTURE_2D, texNames[texCount++]);
  485.           glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  486.           glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  487.          glTexImage2D(GL_TEXTURE_2D, 0, GL_QUAD_LUMINANCE8_SGIS, 512, 512, 0,
  488.              GL_RGBA, GL_UNSIGNED_BYTE, dst);  
  489.       }
  490.   free(dst);
  491.  
  492.   /* Fill in textures array with jittered texture names */
  493.   textures[0][0] = 1;
  494.   textures[0][1] = 3;
  495.   textures[0][2] = 9;
  496.   textures[0][3] = 11;
  497.   textures[1][0] = 2;
  498.   textures[1][1] = 4;
  499.   textures[1][2] = 10;
  500.   textures[1][3] = 12;
  501.   textures[2][0] = 5;
  502.   textures[2][1] = 7;
  503.   textures[2][2] = 13;
  504.   textures[2][3] = 15;
  505.   textures[3][0] = 6;
  506.   textures[3][1] = 8;
  507.   textures[3][2] = 14;
  508.   textures[3][3] = 16;
  509.   
  510.   /* initialize the central cross-sections with surrounding 4 textures and subtiles */
  511.   for (j = 0; j < X_TEX - 1; j++) 
  512.     for (i = 0; i < Y_TEX - 1; i++) 
  513.       for (tx = 0; tx < 2; tx++) 
  514.     for (ty = 0; ty < 2; ty++) 
  515.         {
  516.           info->list[j][i].tex[tx][ty].textureID = textures[j + ty][i + tx];
  517.           for (cx = 0; cx < 2; cx++) 
  518.         for (cy = 0; cy < 2; cy++) 
  519.           {
  520.             info->list[j][i].tex[tx][ty].tile[cx][cy].compID = 2 * cx + cy;
  521.             info->list[j][i].tex[tx][ty].tile[cx][cy].rectBaseX = 2 * (j + ty) + cy;
  522.             info->list[j][i].tex[tx][ty].tile[cx][cy].rectBaseY = 2 * (i + tx) + cx; 
  523.           }
  524.         }
  525.  
  526.   /* start the Xt main loop */
  527.   XtAppMainLoop(info->app);
  528. }
  529.  
  530.