/* caveinventor.c * * Author: Jason Leigh * * Compile: * CC -DREAD_ALL_GRAPHS -DCAVE -DOPENGL caveinventor.c -o caveinventor -I/usr/local/CAVE/include -L/usr/local/CAVE/lib -lcave_ogl -lgl_s -lm -lmalloc -lInventor -lInventorXt -lGLw -lGLU -lGL -lXirisw -lXm -lXt -lX11 * * Execute: caveinventor * * This program reads in an inventor object (object.iv) and displays it * in the CAVE. That's it. It is kept intentionally simple so that it can * easily be modified to suit other needs. * * * All comments that are not normally part of a CAVE program * are commented with ***YO!*** * * Implementation notes: * You must allocate one copy of the inventor scene graph for * each wall of the CAVE. Hence you should allocate the graph inside the * app_init_gl() call. You cannot allocate one scene graph in shared * memory and have all the walls share it. This is because during rendering * inventor will store temporary information in the scene graph. Hence * competing rendering calls will clobber what the other rendering function * has already done. */ /* ***YO!*** Include the inventor stuff you're going to use * in your program, like lighting, etc.. See individual man * pages for this info */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* CAVE prototypes */ void app_shared_init(), app_init_gl(), app_draw(), app_compute(), app_compute_init(); /* ***YO!*** Needed to get the X window size attributes*/ XWindowAttributes winAtts; /* ***YO!*** The scene contains 1 object, 1 light source and one main * root to hold it all together */ SoPointLight *pointLight; SoSeparator *scene; SoSeparator *mainRoot; void main(int argc,char **argv) { CAVEConfigure(&argc,argv,NULL); CAVEInit(); CAVEInitApplication(app_init_gl,0); CAVEDisplay(app_draw,0); app_compute_init(); while (!getbutton(ESCKEY)) { app_compute(); } CAVEExit(); } /* ***YO!*** Initialize Inventor */ void InitInventor() { /* ***YO!*** Initialize Inventor database */ SoDB::init(); } /* ***YO!*** Initialize OpenGL */ void InitOpenGL() { /* set the open gl clear color */ glClearColor(0.0, 0.0, 0.0, 0.0); /* set the depth clear */ glClearDepth(1.0); } /* ***YO!*** CAVE GL initialization */ void app_init_gl() { /* ***YO!*** Init GL and Inventor */ InitOpenGL(); InitInventor(); /* set the far clipping plane */ CAVEFar = 100000.0; /* ***YO!*** Load inventor file into a separator object */ SoSeparator * ReadInventorFile(const char *filename); printf("Loading Inventor object.\n"); scene = ReadInventorFile("object.iv"); printf("Done.\n"); if (scene == NULL) exit(1); scene->ref(); /* ***YO!*** Make a point light source */ pointLight = new SoPointLight(); pointLight->ref(); pointLight->intensity.setValue(1.0); pointLight->location.setValue(0.0,5.0,0.0); /* ***YO!*** Create one main root separator and add the light * and the inventor object to it */ mainRoot = new SoSeparator; mainRoot->ref(); mainRoot->addChild(pointLight); mainRoot->addChild(scene); } void app_draw() { /* save the OpenGL rendering attributes */ glPushAttrib(GL_ALL_ATTRIB_BITS); /* clear the screen and the depth buffer */ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); /* ***YO!*** Draw the mainRoot here */ /* ***YO!*** Use window geometry from winAtts to * set up the view port. I do this at every draw cycle * because the CAVE simulator file has a resizeable screen. * If you are joing to tailor this for the CAVE * it will be more efficient to do this in the GL init call once. */ /* In CAVE library */ extern Display *CAVEXdisplay; extern Window CAVEglxWindow; XGetWindowAttributes(CAVEXdisplay,CAVEglxWindow,&winAtts); SbViewportRegion myViewPort(winAtts.width, winAtts.height); /* ***YO!*** I have to create a SoGLRenderAction at every cycle * or else the lighting won't work. I don't know why. */ //SoGLRenderAction myRenderAction(myViewPort, FALSE); SoGLRenderAction myRenderAction(myViewPort); myRenderAction.apply(mainRoot); glPopMatrix(); /* restore the OpenGL attributes */ glPopAttrib(); } void app_compute_init() { } void app_compute() { sginap(1); } /* ***YO!*** Read an inventor object into a separator. * Code taken from the Inventor Mentor */ SoSeparator * ReadInventorFile(const char *filename) { // Open the input file SoInput mySceneInput; if (!mySceneInput.openFile(filename)) { fprintf(stderr, "Cannot open file %s\n", filename); return NULL; } // Read the whole file into the database SoSeparator *myGraph = SoDB::readAll(&mySceneInput); if (myGraph == NULL) { fprintf(stderr, "Problem reading file\n"); return NULL; } mySceneInput.closeFile(); return myGraph; }