home *** CD-ROM | disk | FTP | other *** search
/ IRIX 6.2 Development Libraries / SGI IRIX 6.2 Development Libraries.iso / dist / gl_dev.idb / usr / share / src / OpenGL / teach / motif / multi-widget.c.z / multi-widget.c
Encoding:
C/C++ Source or Header  |  1996-03-15  |  8.7 KB  |  291 lines

  1. /*
  2.  * multi-widget.c - double buffered RGBA using two drawing area widgets
  3.  */
  4. /* compile: cc -o multi-widget multi-widget.c -lGLw -lGLU -lGL -lXm -lXt -lX11 */
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7. #include <Xm/Form.h>
  8. #include <Xm/Frame.h>
  9. #include <Xm/PushBG.h>
  10. #include <X11/GLw/GLwMDrawA.h>
  11. #include <X11/keysym.h>
  12. #include <X11/Xutil.h>
  13. #include <GL/glx.h>
  14. #include <GL/glu.h>
  15.  
  16. static int attribs[] = { GLX_RGBA, GLX_RED_SIZE, 1, GLX_DOUBLEBUFFER, None};
  17.  
  18. static String fallbackResources[] = {
  19.     "*sgiMode: True",
  20.     "*useSchemes: all",
  21.     "*glxwidget.width: 200", "*glxwidget.height: 200",
  22.     "*glxwidget2.width: 200", "*glxwidget2.height: 200",
  23.     "*frame.shadowType: SHADOW_IN",
  24.     NULL};
  25.  
  26. static struct state {            /* per widget UI variables - keep them together */
  27.     Widget w;
  28.     GLXContext cx;
  29.     short instance;
  30.     short mstate, omx, omy, mx, my;
  31.     short width, height;    /* viewport */
  32.     GLfloat trans[3];        /* current translation */
  33.     GLfloat rot[2];        /* current rotation */
  34. } state, state2;
  35.  
  36. static Boolean direct;
  37.  
  38. static void draw_scene(struct state *);
  39. static void update_view(struct state *);
  40. static void initialize(void);
  41.  
  42. static void
  43. input(Widget w, XtPointer client_data, XtPointer call) {
  44.     char buf[31];
  45.     KeySym keysym;
  46.     XEvent *event = ((GLwDrawingAreaCallbackStruct *) call)->event;
  47.     struct state *state = (struct state *)client_data;
  48.  
  49.     switch(event->type) {
  50.     case KeyRelease:
  51.     XLookupString(&event->xkey, buf, sizeof buf, &keysym, NULL);
  52.     switch(keysym) {
  53.     case XK_Escape:
  54.         exit(EXIT_SUCCESS);
  55.         break;
  56.     default: break;
  57.     }
  58.     break;
  59.     case ButtonPress:
  60.     if (event->xbutton.button == Button2) {
  61.         state->mstate |= 2;
  62.         state->mx = event->xbutton.x;
  63.         state->my = event->xbutton.y;
  64.     } else if (event->xbutton.button == Button1) {
  65.         state->mstate |= 1;
  66.         state->mx = event->xbutton.x;
  67.         state->my = event->xbutton.y;
  68.     }
  69.     break;
  70.     case ButtonRelease:
  71.     if (event->xbutton.button == Button2)
  72.         state->mstate &= ~2;
  73.     else if (event->xbutton.button == Button1)
  74.         state->mstate &= ~1;
  75.     break;
  76.     case MotionNotify:
  77.     if (state->mstate) {
  78.         state->omx = state->mx;
  79.         state->omy = state->my;
  80.         state->mx = event->xbutton.x;
  81.         state->my = event->xbutton.y;
  82.         update_view(state);
  83.     }
  84.     break;
  85.     }
  86. }
  87.  
  88. static void
  89. resize(Widget w, XtPointer client_data, XtPointer call) {
  90.     struct state *state = (struct state *)client_data;
  91.     GLwDrawingAreaCallbackStruct *call_data;
  92.     call_data = (GLwDrawingAreaCallbackStruct *) call;
  93.  
  94.     /* need to rebind context & reset viewport */
  95.     GLwDrawingAreaMakeCurrent(w, state->cx);
  96.     state->width = call_data->width;
  97.     state->height = call_data->height;
  98.     glViewport(0, 0, call_data->width, call_data->height);
  99. }
  100.  
  101. static void
  102. expose(Widget w, XtPointer client_data, XtPointer call) {
  103.     struct state *state = (struct state *)client_data;
  104.     GLwDrawingAreaCallbackStruct *call_data;
  105.     call_data = (GLwDrawingAreaCallbackStruct *) call;
  106.  
  107.     /* need to rebind context & reset viewport */
  108.     GLwDrawingAreaMakeCurrent(w, state->cx);
  109.     glViewport(0, 0, state->width, state->height);
  110.     draw_scene(state);
  111. }
  112.  
  113. static void
  114. quit(Widget w, XtPointer client_data, XtPointer call) {
  115.     exit(EXIT_SUCCESS);
  116. }
  117.  
  118. main(int argc, char *argv[]) {
  119.     Display        *dpy;
  120.     XVisualInfo    *visinfo;
  121.     Widget          toplevel, frame, form, button;
  122.     XtAppContext    appctx;
  123.     Arg            args[20];
  124.     int            n;
  125.  
  126.     toplevel = XtOpenApplication(&appctx, "multi-widget", NULL, 0, &argc, argv,
  127.         fallbackResources, applicationShellWidgetClass, NULL, 0);
  128.     dpy = XtDisplay(toplevel);
  129.  
  130.     form = XmCreateForm(toplevel, "form", NULL, 0);
  131.     XtManageChild(form);
  132.  
  133.     /* attach first drawing area at top of form so it grows in X, but
  134.      * doesn't grow in Y when the form resizes */
  135.     n = 0;
  136.     XtSetArg(args[n], XtNx, 10); n++;
  137.     XtSetArg(args[n], XtNy, 10); n++;
  138.     XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  139.     XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  140.     XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  141.     XtSetArg(args[n], XmNleftOffset, 10); n++;
  142.     XtSetArg(args[n], XmNtopOffset, 10); n++;
  143.     XtSetArg(args[n], XmNrightOffset, 10); n++;
  144.     frame = XmCreateFrame(form, "frame", args, n);
  145.     XtManageChild(frame);
  146.  
  147.     /* specify visual directly */
  148.     if (!(visinfo = glXChooseVisual(dpy, DefaultScreen(dpy), attribs)))
  149.     XtAppError(appctx, "no suitable RGB visual");
  150.  
  151.     state.w = XtVaCreateManagedWidget("glxwidget", glwMDrawingAreaWidgetClass,
  152.     frame, GLwNvisualInfo, visinfo, NULL);
  153.     XtAddCallback(state.w, GLwNexposeCallback, expose, &state);
  154.     XtAddCallback(state.w, GLwNresizeCallback, resize, &state);
  155.     XtAddCallback(state.w, GLwNinputCallback, input, &state);
  156.  
  157.     /* attach second widget at bottom so it grows in both X & Y with
  158.      * the rest of the form */
  159.     n = 0;
  160.     XtSetArg(args[n], XtNx, 10); n++;
  161.     XtSetArg(args[n], XtNy, 10); n++;
  162.     XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  163.     XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
  164.     XtSetArg(args[n], XmNtopWidget, frame); n++;
  165.     XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  166.     XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  167.     XtSetArg(args[n], XmNleftOffset, 10); n++;
  168.     XtSetArg(args[n], XmNtopOffset, 10); n++;
  169.     XtSetArg(args[n], XmNbottomOffset, 50); n++;
  170.     XtSetArg(args[n], XmNrightOffset, 10); n++;
  171.     frame = XmCreateFrame(form, "frame", args, n);
  172.     XtManageChild(frame);
  173.  
  174.     state2.w = XtVaCreateManagedWidget("glxwidget2", glwMDrawingAreaWidgetClass,
  175.         frame, GLwNvisualInfo, visinfo, NULL);
  176.     XtAddCallback(state2.w, GLwNexposeCallback, expose, &state2);
  177.     XtAddCallback(state2.w, GLwNresizeCallback, resize, &state2);
  178.     XtAddCallback(state2.w, GLwNinputCallback, input, &state2);
  179.  
  180.     /* attach Quit button at bottom left corner */
  181.     n = 0;
  182.     XtSetArg(args[n], XtNx, 10); n++;
  183.     XtSetArg(args[n], XtNy, 10); n++;
  184.     XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  185.     XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  186.     XtSetArg(args[n], XmNleftOffset, 10); n++;
  187.     XtSetArg(args[n], XmNbottomOffset, 10); n++;
  188.     XtSetArg(args[n], XmNtraversalOn, False); n++; /* no keyboard traversal */
  189.     button = XmCreatePushButtonGadget(form, "Quit", args, n);
  190.     XtAddCallback(button, XmNactivateCallback, quit, NULL);
  191.     XtManageChild(button);
  192.  
  193.     XtRealizeWidget(toplevel);
  194.  
  195.     /* retrieve initial viewports */
  196.     XtVaGetValues(state.w, XmNheight, &state.height,
  197.                    XmNwidth, &state.width, NULL);
  198.     XtVaGetValues(state2.w, XmNheight, &state2.height,
  199.                     XmNwidth, &state2.width, NULL);
  200.  
  201.     state.cx = state2.cx = glXCreateContext(dpy, visinfo, 0, GL_TRUE);
  202.     state.instance = 0; state2.instance = 1;
  203.     direct = glXIsDirect(dpy, state.cx);
  204.  
  205.     GLwDrawingAreaMakeCurrent(state.w, state.cx);
  206.     initialize();
  207.  
  208.     XtAppMainLoop(appctx);
  209. }
  210.  
  211. static void
  212. initialize(void) {    /* initialize context */
  213.     glShadeModel(GL_FLAT);
  214.     gluPerspective(40., 3.0/2.0, 0.001, 100000.0);
  215.     glTranslatef(0.0, 0.0, -3.0);
  216.     glClearColor(0.2,0.2,0.2,0.);
  217. }
  218.  
  219. static void
  220. side(void) { /* make a square translated 0.5 in the z direction */
  221.     glPushMatrix();
  222.     glTranslatef(0.0,0.0,0.5);
  223.     glRectf(-0.5,-0.5,0.5,0.5);
  224.     glPopMatrix();
  225. }
  226.  
  227. static void
  228. cube(void) { /* make a cube out of 4 squares */
  229.     glPushMatrix();
  230.     side();
  231.     glRotatef(90.,1.,0.,0.);
  232.     side();
  233.     glRotatef(90.,1.,0.,0.);
  234.     side();
  235.     glRotatef(90.,1.,0.,0.);
  236.     side();
  237.     glPopMatrix();
  238. }
  239.  
  240. static void
  241. draw_scene(struct state *state) {
  242.  
  243.     glClear(GL_COLOR_BUFFER_BIT);
  244.     glPushMatrix();
  245.     glTranslatef(state->trans[0], state->trans[1], state->trans[2]);
  246.     glRotatef(state->rot[0], 1.0, 0.0, 0.0);
  247.     glRotatef(state->rot[1], 0.0, 1.0, 0.0);
  248.     glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  249.     if (state->instance == 0)
  250.     glColor3f(.1, .1, .8);
  251.     else
  252.     glColor3f(.1, .8, .1);
  253.     cube();
  254.     glScalef(0.3,0.3,0.3);
  255.     glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  256.     if (state->instance == 0)
  257.     glColor3f(.8, .8, .1);
  258.     else
  259.     glColor3f(.8, .1, .1);
  260.     cube();
  261.     glPopMatrix();
  262.     GLwDrawingAreaSwapBuffers(state->w);
  263.     if (direct) glFinish();    /* hack to improve net interactivity */
  264. }
  265.  
  266. static void
  267. update_view(struct state *state) {
  268.     int dx = state->omx - state->mx;
  269.     int dy = state->my - state->omy;
  270.  
  271.     GLwDrawingAreaMakeCurrent(state->w, state->cx);
  272.     glViewport(0, 0, state->width, state->height);
  273.     switch(state->mstate) {
  274.     case 1:    /* pan */
  275.     state->trans[0] -= dx/100.;
  276.     state->trans[1] -= dy/100.;
  277.     break;
  278.     case 2:    /* rotate */
  279.     state->rot[0] += (dy * 180.0)/500.;
  280.     state->rot[1] -= (dx * 180.0)/500.;
  281. #define clamp(x) x = x > 360. ? x-360. : x < -360. ? x += 360. : x 
  282.     clamp(state->rot[0]);
  283.     clamp(state->rot[1]);
  284.     break;
  285.     case 3:    /* zoom */
  286.     state->trans[2] -= (dx+dy)/100.;
  287.     break;
  288.     }
  289.     draw_scene(state);
  290. }
  291.