#include #include #include #include #include #include #include #include #include static void createScene(pfChannel *chan,int argc,char **argv); static void loadObjects(int argc,char **argv,pfGroup *parent); static int navigate(pfTraverser *trav,void *data); /* main() - this is identical to the skeleton main of outline.c++ */ int main(int argc,char **argv) { pfInit(); pfCAVEConfig(&argc,argv,NULL); pfConfig(); pfCAVEInitChannels(); if (CAVEConfig->Simulator) pfCAVEMasterChan()->getFStats()->setClass( PFSTATS_ALL^PFSTATSHW_ENGFXPIPE_FILL, PFSTATS_ON); else pfCAVEMasterChan()->getFStats()->setClass(PFSTATS_ALL, PFSTATS_OFF); createScene(pfCAVEMasterChan(),argc,argv); while (!CAVEgetbutton(CAVE_ESCKEY)) { pfSync(); pfCAVEPreFrame(); pfFrame(); pfCAVEPostFrame(); } pfCAVEHalt(); pfExit(); return 0; } /* createScene() - creates the scene. A geostate is assigned to the scene, in order to control global rendering options such as lighting, texturing, and backface culling. A light source is added; the light has its class's default settings (white, pointed straight down, etc.). A DCS is added for navigation; the CAVE navigation transformation will be applied to the DCS, so any scene nodes which are under the DCS will be drawn in world coordinates. A traversal function is used to update the DCS once per frame, in the APP process. loadObjects() is then called to load any objects given on the command line and place them under the DCS. */ static void createScene(pfChannel *chan,int argc,char **argv) { pfScene *scene; pfGeoState *gstate; pfDCS *dcs; pfLightSource *light; scene = new pfScene; gstate = new pfGeoState; /* Set up a base geostate for the scene */ gstate->setMode(PFSTATE_ENLIGHTING, PF_ON); gstate->setMode(PFSTATE_CULLFACE, PFCF_OFF); scene->setGState(gstate); scene->addChild(new pfLightSource); /* Add a default light */ light = new pfLightSource; light->setPos(1.0, -1.0, 0.5, 0.0); scene->addChild(light); dcs = new pfDCS; /* Create a DCS for navigation */ scene->addChild(dcs); dcs->setTravFuncs(PFTRAV_APP,navigate,NULL); loadObjects(argc,argv,dcs); chan->setScene(scene); /* Assign the scene to the channels */ } /* loadObjects() - loads objects specified on the command line (argc/argv). pfdLoadFile() will load an object in any supported format; the file format is determined based on the extension (.iv, .obj, .pfb, etc.) If it succeeds, it returns a pointer to the root of the subgraph containing the object, which is then added to the scene under the given parent. If it fails, pfdLoadFile() returns NULL. */ static void loadObjects(int argc,char **argv,pfGroup *parent) { int i; pfNode *obj; for (i=1; iaddChild(obj); else pfExit(); } } /* navigate() - traversal callback for the navigation DCS. This is called once each frame during the APP traversal of the scene graph. It performs CAVE navigation operations, and then loads the CAVE nav transformation into the DCS for Performer to use. */ static int navigate(pfTraverser *trav,void *) { #define SPEED 2.0f pfDCS *navDcs = (pfDCS *) trav->getNode(); /* Get a pointer to the DCS node itself */ float jx=CAVE_JOYSTICK_X,jy=CAVE_JOYSTICK_Y; if (fabs(jx) > 0.125) /* Rotate if the joystick is pushed left or right */ CAVENavRot(-1.0f*jx,'z'); if (fabs(jy) > 0.125) /* Translate if the joystick is pushed forward or back */ { float w[3]; CAVEGetVector(CAVE_WAND_FRONT,w); CAVENavTranslate(w[0]*jy*SPEED,w[1]*jy*SPEED,w[2]*jy*SPEED); } if ((CAVEBUTTON1) && (CAVEBUTTON3)) /* Reset navigation on secret handshake */ CAVENavLoadIdentity(); pfCAVEDCSNavTransform(navDcs); /* Load the DCS with the latest navigation matrix */ return PFTRAV_CONT; /* Tell Performer to continue traversing */ }