/* ////////////////////////////////////////////////////////////////////// */ /* */ /* intersect.c - Intersection testing sample */ /* */ /* Requires IRIS Performer 1.2 */ /* */ /* To compile: */ /* cc -o intersect intersect.c -O2 -fullwarn -I/usr/include/Performer */ /* -L/usr/src/Performer/lib -lpfsgi -lpfdwb -lpfflt -lpfutil */ /* -lpf -lpr -lmpc -limage -lfm_s -lgl_s -lm -lfpe -lC */ /* */ /* If using Performer 1.0/1.1, see "intersect1-0.c", also */ /* available via anonymous ftp on sgi.sgi.com in the directory */ /* ~ftp/support/Pipeline */ /* */ /* To toggle the Statistics display, press the F1 or G keys. */ /* To exit, press ESC. */ /* */ /* ////////////////////////////////////////////////////////////////////// */ #include #include #include #include #include #include typedef struct SharedData { int exitFlag; int showStats; float yval; float zval; } SharedData; static void DrawChannel (pfChannel *chan, void *data); static void OpenPipeline (pfPipe *p); SharedData *shared; static pfVec3 scoords[] ={ { -1.0f, -1.0f, 1.0f }, { 1.0f, -1.0f, 1.0f }, { 1.0f, 1.0f, 1.0f }, { -1.0f, 1.0f, 1.0f }, { -2.0f, -2.0f, 0.0f }, { 2.0f, -2.0f, 0.0f }, { 2.0f, 2.0f, 0.0f }, { -2.0f, 2.0f, 0.0f }}; static ushort svindex[] ={ 0, 1, 2, 3, 0, 3, 7, 4, 4, 7, 6, 5, 1, 5, 6, 2, 3, 2, 6, 7, 0, 4, 5, 1}; static pfVec4 scolors[] ={ {1.0f, 0.0f, 0.0f, 0.5f}, {0.0f, 1.0f, 0.0f, 0.5f}, {0.0f, 0.0f, 1.0f, 0.5f}, {1.0f, 1.0f, 1.0f, 0.5f}}; static ushort scindex[] ={ 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3}; /* ////////////////////////////////////////////////////////////////////// */ void main() { pfPipe *pipe; pfChannel *chan; pfScene *scene; pfEarthSky *eSky; pfGroup *root; pfGeoSet *gset; pfSCS *scs[10]; pfGeode *geode; pfMatrix mat; pfCoord view; pfSegSet segset; int loop; /* Initialize Performer */ pfInit(); /* Use default multiprocessing mode based on number of processors. */ pfMultiprocess (PFMP_DEFAULT); /* Malloc storage in shared memory region for shared data */ shared = (SharedData *) pfMalloc(sizeof(SharedData),pfGetSharedArena()); /* Configure multiprocessing mode and start parallel processes */ pfConfig(); shared->exitFlag = 0; shared->showStats = 0; /* ////////////////////////////////////////////////////////////// */ /* Configure and open GL window */ pipe = pfGetPipe(0); pfInitPipe (pipe, OpenPipeline); pfFrameRate(30.0f); /* Create & configure channel */ chan = pfNewChan(pipe); pfChanDrawFunc (chan, DrawChannel); pfChanNearFar (chan, 0.1f, 10000.0f); pfChanFOV (chan, 45.0f, -1.0f); /* Add an earth/sky effect */ eSky = pfNewESky(); pfESkyMode(eSky, PFES_BUFFER_CLEAR, PFES_SKY_GRND); pfESkyAttr(eSky, PFES_GRND_HT, 0.0f); pfESkyColor(eSky, PFES_SKY_TOP, 1.0f, 1.0f, 1.0f, 1.0f); pfESkyColor(eSky, PFES_SKY_BOT, 0.0f, 0.0f, 0.0f, 1.0f); pfESkyColor(eSky, PFES_HORIZ, 0.0f, 0.0f, 0.0f, 1.0f); pfESkyColor(eSky, PFES_GRND_FAR, 0.3f, 0.1f, 0.0f, 1.0f); pfESkyColor(eSky, PFES_GRND_NEAR, 0.5f, 0.3f, 0.1f, 1.0f); pfChanESky(chan, eSky); /* ////////////////////////////////////////////////////////////// */ /* Create pfScene node, attach it to channel */ scene = pfNewScene(); pfChanScene (chan, scene); /* Create group node to hold SCS's; attach it to scene */ root = pfNewGroup(); pfAddChild (scene, root); /* Create 10 SCS nodes, spaced equally apart. Make each one a child of 'root', and make 'geode' a child of each SCS */ geode = pfNewGeode(); for (loop=0; loop < 10; loop++) { pfMakeTransMat (mat, 0.0f, (float) loop * 10.0f + 10.0f, 0.0f); scs[loop] = pfNewSCS (mat); pfAddChild (scs[loop], geode); pfAddChild (root, scs[loop]); /* set up SCS's (and their children) for intersections */ pfNodeTravMask (scs[loop], PFTRAV_ISECT, 1, PFTRAV_SELF, PF_SET); } /* Create a GeoSet to hold the ramp geometry */ gset = pfNewGSet (pfGetSharedArena()); pfGSetAttr (gset, PFGS_COORD3, PFGS_PER_VERTEX, scoords, svindex); pfGSetAttr (gset, PFGS_COLOR4, PFGS_PER_VERTEX, scolors,scindex); pfGSetPrimType (gset, PFGS_QUADS); pfGSetNumPrims (gset, 6); /* attach it to the parent geode */ pfAddGSet (geode, gset); /* ////////////////////////////////////////////////////////////// */ /* set initial view position */ shared->yval=0.0f; shared->zval=0.5f; /* set up intersection segment, pointing down for "terrain" following */ segset.activeMask = 1; segset.isectMask = 0xFFFF; segset.mode = PFTRAV_IS_PRIM|PFTRAV_IS_NORM|PFTRAV_IS_CULL_BACK; pfSetVec3(segset.segs[0].dir, 0.0f, 0.0f, -1.0f); segset.segs[0].length = 50000.0f; /* ////////////////////////////////////////////////////////////// */ /* main loop */ while (!shared->exitFlag) { pfHit **hits[100]; long isect; pfSetVec3(view.xyz, 0.0f, shared->yval, shared->zval); pfSetVec3(view.hpr, 0.0f, -5.0f, 0.0f); pfChanView (chan, view.xyz, view.hpr); pfFrame(); /* increment view position; if too far, reset */ shared->yval += 0.1f; if (shared->yval > 110.0f) shared->yval = 0.0f; /* update location of intersection segment */ pfSetVec3(segset.segs[0].pos, 0.0f, shared->yval,shared->zval); /* do an intersection test against the scene graph */ isect = pfSegsIsectNode(root, &segset, hits); /* if successful, set our height to that of the point of contact, plus a small offset */ if (isect) { pfVec3 pnt; pfQueryHit (*hits[0], PFQHIT_POINT, &pnt); shared->zval = pnt[PF_Z] + 0.5; } } pfExit(); } /* ////////////////////////////////////////////////////////////////////// */ /* Pipe Initialization Callback to open and configure * GL window, and set up GL event handling */ static void OpenPipeline (pfPipe *p) { foreground(); winopen ("Terrain"); pfInitGfx(p); qdevice (ESCKEY); qdevice (F1KEY); qdevice (GKEY); } /* /////////////////////////////////////////////////////////////////////// */ /* Draw Process Callback to draw the channel and handle GL events */ static void DrawChannel (pfChannel *chan, void *data) { short dev,val; /* clear and draw the channel */ pfClearChan (chan); pfDraw(); if (shared->showStats) pfDrawChanStats(chan); while (qtest()) { dev = qread(&val); if (val) switch (dev) { case ESCKEY: shared->exitFlag=1; break; case F1KEY: case GKEY: shared->showStats = !shared->showStats; break; } } } /* /////////////////////////////////////////////////////////////////////// */