Example 28.2, “ Using a GLX Window ” creates a GLX window, makes Inventor and OpenGL calls, and then applies a GL render action. It uses OpenGL to render a checked “floor” and Inventor to render a red cube and a blue sphere, in the same window.
Example 28.2. Using a GLX Window
#include <stdio.h> #include <unistd.h> #include <Inventor/SoDB.h> #include <Inventor/SoSceneManager.h> #include <Inventor/devices/SoGLContext.h> #include <Inventor/nodes/SoCube.h> #include <Inventor/nodes/SoDirectionalLight.h> #include <Inventor/nodes/SoLightModel.h> #include <Inventor/nodes/SoMaterial.h> #include <Inventor/nodes/SoTransform.h> #include <Inventor/nodes/SoSeparator.h> #include <Inventor/nodes/SoSphere.h> // This is related to <GL/GL.h> and <GL/GLX.h> but // it is handled by GLEW #include <Inventor/sys/SoGL.h> #include <Inventor/sys/SoGLX.h> #define WINWIDTH 400 #define WINHEIGHT 400 float floorObj[81][3]; SoGLContext* oivContext = NULL; // Build an Inventor scene with two objects and some light void buildScene(SoGroup *root) { // Some light root->addChild(new SoLightModel); root->addChild(new SoDirectionalLight); // A red cube translated to the left and down SoTransform *myTrans = new SoTransform; myTrans->translation.setValue(-2.0, -2.0, 0.0); root->addChild(myTrans); SoMaterial *myMtl = new SoMaterial; myMtl->diffuseColor.setValue(1.0, 0.0, 0.0); root->addChild(myMtl); root->addChild(new SoCube); // A blue sphere translated right myTrans = new SoTransform; myTrans->translation.setValue(4.0, 0.0, 0.0); root->addChild(myTrans); myMtl = new SoMaterial; myMtl->diffuseColor.setValue(0.0, 0.0, 1.0); root->addChild(myMtl); root->addChild(new SoSphere); } // Build a floor that will be rendered using OpenGL. void buildFloor() { int a = 0; for (float i = -5.0; i <= 5.0; i += 1.25) { for (float j = -5.0; j <= 5.0; j += 1.25, a++) { floorObj[a][0] = j; floorObj[a][1] = 0.0; floorObj[a][2] = i; } } } // Callback used by GLX window static Bool waitForNotify(Display *, XEvent *e, char *arg) { return (e->type == MapNotify) && (e->xmap.window == (Window) arg); } // Create and initialize GLX window. void openWindow(Display *&display, Window &window) { XVisualInfo *vi; Colormap cmap; XSetWindowAttributes swa; GLXContext cx; XEvent event; static int attributeList[] = { GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_DEPTH_SIZE, 1, GLX_DOUBLEBUFFER, None, }; display = XOpenDisplay(0); vi = glXChooseVisual(display, DefaultScreen(display), attributeList); cx = glXCreateContext(display, vi, 0, GL_TRUE); cmap = XCreateColormap(display, RootWindow(display, vi->screen), vi->visual, AllocNone); swa.colormap = cmap; swa.border_pixel = 0; swa.event_mask = StructureNotifyMask; window = XCreateWindow(display, RootWindow(display, vi->screen), 100, 100, WINWIDTH, WINHEIGHT, 0, vi->depth, InputOutput, vi->visual, (CWBorderPixel | CWColormap | CWEventMask), &swa); XMapWindow(display, window); XIfEvent(display, &event, waitForNotify, (char *) window); // OIV needs an SoGLContext to perform OpenGL operations oivContext = new SoGLContext(display, vi, window, cx); } // Draw the lines that make up the floor, using OpenGL void drawFloor() { int i; glBegin(GL_LINES); for (i=0; i<4; i++) { glVertex3fv(floorObj[i*18]); glVertex3fv(floorObj[(i*18)+8]); glVertex3fv(floorObj[(i*18)+17]); glVertex3fv(floorObj[(i*18)+9]); } glVertex3fv(floorObj[i*18]); glVertex3fv(floorObj[(i*18)+8]); glEnd(); glBegin(GL_LINES); for (i=0; i<4; i++) { glVertex3fv(floorObj[i*2]); glVertex3fv(floorObj[(i*2)+72]); glVertex3fv(floorObj[(i*2)+73]); glVertex3fv(floorObj[(i*2)+1]); } glVertex3fv(floorObj[i*2]); glVertex3fv(floorObj[(i*2)+72]); glEnd(); } int main(int, char **) { // Initialize Inventor SoDB::init(); // Build a simple scene graph SoSeparator *root = new SoSeparator; root->ref(); buildScene(root); // It's better to use an SoSceneManager for some basic operations // - clear the buffers // - Handles the SoGLRenderAction // - Event handling (it is possible to provide the events to the // scene graph, useful for draggers...) SoSceneManager* sceneManager = new SoSceneManager(); sceneManager->setSceneGraph(root); sceneManager->setBackgroundColor(SbColor(0.8, 0.8, 0.8)); sceneManager->setWindowSize(SbVec2s(WINWIDTH, WINHEIGHT)); // Build the floor geometry buildFloor(); // Create and initialize window Display *display; Window window; openWindow(display, window); // We need a context here for rendering // OIV will bind the GL context. oivContext->bind(); // By default OIV does not enable the depth test. glEnable(GL_DEPTH_TEST); // Set up the camera using OpenGL. glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(90.0, 1.0, 2.0, 12.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.0, 0.0, -5.0); // Render the OIV scene. The render method will clear // the OpenGL buffers. sceneManager->render(); // Render the floor using OpenGL // - We push the attributes since OIV consider that // non-OIV code won't modify the OpenGL state. glPushAttrib(GL_ALL_ATTRIB_BITS); glPushMatrix(); glTranslatef(0.0, -3.0, 0.0); glColor3f(0.0, 0.7, 0.0); glLineWidth(2.0); glDisable(GL_LIGHTING); drawFloor(); glEnable(GL_LIGHTING); glPopMatrix(); glPopAttrib(); // Swap the buffers, the OIV context can handle this. oivContext->swapBuffers(); oivContext->unbind(); oivContext->unref(); sleep (10); root->unref(); delete sceneManager; return 0; }