Rob Jenkins (robj++at++barney.reading.sgi.com)
Fri, 26 May 1995 08:45:28 +0100
As is traditional - I forgot to attach the attachment :-)
Cheers
Rob
-- ________________________________________________________________ Rob Jenkins, Software Support Group, Silicon Graphics UK Ltd. 1530 Arlington Business Park, Theale, Reading, UK, RG7 4SB. tel 01734 257736, fax 01734 257553, email robj++at++reading.sgi.com,
/* * follow.c - loads terrain and model_files specified and * puts each model under an SCS, then follows terrain in * a spiral * * Copyright 1994, Silicon Graphics, Inc. * Worldwide Education R & D * Developer: David Marsland, mars++at++sgi.com */
#include <math.h> #include <stdlib.h> #include "pf.h" #include "pfsgi.h" #include "pfutil.h"
#define MAX_MODELS 100
/* function prototypes */ void initialize( int argc, char *argv[] ); static void openPipeline (pfPipe *p); pfGroup *buildScene( int argc, char *argv[] ); pfSCS *loadTerrain( int argc, char *argv[] ); void followTerrain( void ); void fogScene( void ); void printHelp( char *programName );
typedef struct SharedData { pfCoord view; float eyeRadius; pfChannel *chan; pfScene *scene; void *texList; int modelCount; } SharedData;
/* Global Variables */ SharedData *shared; pfSCS *terrainSCS; pfDCS *dcs[MAX_MODELS]; pfSegSet segset; pfMatrix terrainSCSmatrix;
int main(int argc, char *argv[]) { pfCoord view; float time; int i; float maxTime = 120.0;
initialize( argc, argv );
pfInitClock (0.0f); /* Simulate for maxTime seconds. */ /* main loop */ while (time < maxTime) { float s, c; float angle;
/* Go to sleep until next frame time. */ pfSync();
/* Compute new view position. */ time = pfGetTime(); angle = 200.0f + 6.0f*time; pfSinCos(angle, &s, &c);
#define SPIRAL #ifdef SPIRAL /* make eyepoint move in a circle that spirals in with time */ shared->view.xyz[PF_X] = c*4.0/(1.0f+time/maxTime); shared->view.xyz[PF_Y] = s*4.0/(1.0f+time/maxTime); #else /* make eyepoint move in a circle */ shared->view.xyz[PF_X] = c*4.0; shared->view.xyz[PF_Y] = s*4.0; #endif followTerrain(); pfSetVec3(view.xyz, shared->view.xyz[PF_X], shared->view.xyz[PF_Y], shared->view.xyz[PF_Z]); pfSetVec3(view.hpr, angle, 0.0f, 0.0f);
pfChanView (shared->chan, view.xyz, view.hpr); /* spin each model */ for ( i = 0; i < shared->modelCount; i++ ) { pfDCSRot( dcs[i], time*10.0f, 0.0f, 0.0f ); }
/* Initiate cull/draw for this frame. */ pfFrame(); } pfExit(); exit(0); }
/* * intialize() initializes and configures Performer, * creates a graphics pipe and a channel, and calls * buildScene() to load a scene */ void initialize( int argc, char *argv[] ) { int i; pfPipe *pipe; pfGroup *root; pfEarthSky *eSky; pfSphere sceneBSphere; void *arena; /* check usage */ if (argc < 2) { fprintf(stderr, "Usage: %s terrain_file [model_file...]\n", argv[0]); exit (0); }
printHelp( argv[0] ); pfInit(); /* Initialize Performer */
arena = pfGetSharedArena();
/* Malloc storage in shared memory region for shared data, * must be done between pfInit() and pfConfig(), since pfConfig() * may fork processes for cull and draw */ shared = (SharedData *) pfMalloc(sizeof(SharedData),arena);
/* If debugging, force multiprocessing mode even if on single processor */ #ifdef DEBUG pfMultiprocess(PFMP_APP_CULL_DRAW); #endif
/* Else use default multiprocessing mode based on number of processors. */ pfConfig(); /* Configure */
pipe = pfGetPipe(0); shared->chan = pfNewChan(pipe);
/* Create a scene! */ shared->scene = pfNewScene(); root = buildScene( argc, argv ); pfAddChild( shared->scene, root );
/* initialize graphics pipeline and call openPipeline when ready */ pfInitPipe(pipe, openPipeline); /* specify scene to be viewed by channel */ pfChanScene(shared->chan, shared->scene);
/* Get the scene's extents. */ pfGetNodeBSphere(shared->scene, &sceneBSphere); printf("Scene bounds - center: %f %f %f, radius: %f\n", sceneBSphere.center[0], sceneBSphere.center[1], sceneBSphere.center[2], sceneBSphere.radius);
pfChanNearFar( shared->chan, 0.05f, 2.5f*sceneBSphere.radius ); /* Add an earth/sky effect */ eSky = pfNewESky(); pfESkyMode(eSky, PFES_BUFFER_CLEAR, PFES_SKY_GRND); pfESkyAttr(eSky, PFES_GRND_HT, -1.0f); pfESkyColor(eSky, PFES_GRND_NEAR, 0.0f, 0.3f, 0.8f, 1.0f); pfESkyColor(eSky, PFES_GRND_FAR, 0.0f, 0.0f, 0.4f, 1.0f); pfChanESky(shared->chan, eSky);
/* set initial view position */ shared->view.xyz[PF_X] = 0.0f; shared->view.xyz[PF_Y] = -12.0f; shared->view.xyz[PF_Z] = 2.0f;
/* set up intersection segment, pointing down for terrain following */ segset.activeMask = 0x1; 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; }
void printHelp( char *programName ) { fprintf(stdout, "\n\ %s loads terrain and model_files specified and puts each model under an SCS\n\n\ Escape key - exit the program\n\ \n", programName ); }
pfGroup *buildScene( int argc, char *argv[] ) { pfSCS *circleTrans; pfMatrix matrix; pfGeoState *gst1; pfMaterial *mt1, *mt2; pfNode *models[MAX_MODELS]; pfSCS *circleSCS[MAX_MODELS]; pfSCS *scaleSCS[MAX_MODELS]; pfSphere bounding_sphere; float unitScaler; pfGroup *root; int i; void *arena; root = pfNewGroup(); terrainSCS = loadTerrain( argc, argv ); pfAddChild( root, terrainSCS );
arena = pfGetSharedArena(); /* Create 1st geostate */ gst1 = pfNewGState(arena); mt1 = pfNewMtl(arena); pfMtlColor(mt1, PFMTL_DIFFUSE, 0.4f, 0.2f, 1.0f); pfGStateAttr(gst1, PFSTATE_FRONTMTL, mt1);
shared->modelCount = argc - 2; if (shared->modelCount > MAX_MODELS) shared->modelCount = MAX_MODELS;
/* read in all model files specifed as command line args */ for ( i = 0; i < shared->modelCount; i++ ) { if ( (models[i] = LoadFile( argv[i+2], gst1 ) ) == NULL ) { fprintf( stderr, "Model file %s not found, exiting %s\n", argv[i+1], argv[0] ); pfExit(); exit(-1); } else { fprintf( stdout, "Loading Model file %s\n", argv[i+1] );
/* Get the model's extents */ pfGetNodeBSphere(models[i], &bounding_sphere); /* create a matrix used to place all models on a circle of radius 10 */
/* rotate to a different, evenly spaced, angle for each model */ pfMakeRotMat( matrix, (float) i*( 360.0f/(float) shared->modelCount ), 0.0f, 0.0f, 1.0f ); /* translate out to radius 5 and up by 1.0 */ pfPreTransMat( matrix, 5.0f, 0.0f, 1.0f, matrix );
/* create an SCS using matrix to place all models * on a circle of radius 5 */ circleSCS[i] = pfNewSCS( matrix ); pfAddChild( root, circleSCS[i] ); dcs[i] = pfNewDCS();
pfAddChild( circleSCS[i], dcs[i] );
/* scale each model to unit size by scaling the SCS matrix */ unitScaler = 1.0f/bounding_sphere.radius; pfMakeScaleMat( matrix, unitScaler, unitScaler, unitScaler ); scaleSCS[i] = pfNewSCS( matrix ); pfAddChild( dcs[i], scaleSCS[i] ); pfAddChild( scaleSCS[i], models[i] ); } } return ( root ); }
/* * OpenPipeline() -- create a GL window: set up the * window system, IRIS GL, and IRIS Performer. This * procedure is executed in the draw process (when * there is a separate draw process). */ static void openPipeline (pfPipe *p) { static int texture = 1; static int fog = 1; void *arena; /* Open graphics window. */ foreground(); prefposition(100, 500, 100, 500); winopen("IRIS Performer"); winconstraints();
/* Configure window with reasonable defaults. */ pfInitGfx(p);
arena = pfGetSharedArena(); /* Create and apply a default material for those models * without one. */ pfApplyMtl(pfNewMtl( arena ));
/* Create a default lighting model. */ pfApplyLModel(pfNewLModel( arena ));
/* Turn on lighting */ pfEnable(PFEN_LIGHTING); pfLightOn(pfNewLight(arena));
if (texture) { /* Initialize IRIS Performer utility library. */ pfuInitUtil();
/* Prebind textures to be used in simulation */ shared->texList = pfuMakeTexList((pfNode *)shared->scene); pfuDownloadTexList(shared->texList, PFUTEX_SHOW); pfEnable(PFEN_TEXTURE); /* create a default texture environment */ pfApplyTEnv(pfNewTEnv( arena )); pfuExitUtil(); } if (fog) fogScene(); }
pfSCS *loadTerrain( int argc, char *argv[] ) { pfNode *terrain; pfSCS *terrainSCS; pfMatrix matrix; pfSphere bounding_sphere; float unitScaler; int i; /* load terrain model */ if ( (terrain = LoadFile( argv[1], NULL ) ) == NULL ) { fprintf( stderr, "Model file %s not found, exiting %s\n", argv[1], argv[0] ); pfExit(); exit(-1); } else { fprintf( stdout, "Loading Model file %s\n", argv[1] );
/* Get the model's extents */ pfGetNodeBSphere(terrain, &bounding_sphere);
printf("bounding_sphere.center = %f, %f, %f, radius = %f\n", bounding_sphere.center[0], bounding_sphere.center[1], bounding_sphere.center[2], bounding_sphere.radius ); /* scale model to 30*unit size by scaling the SCS matrix */ unitScaler = 30.0f/bounding_sphere.radius; pfMakeScaleMat( terrainSCSmatrix, unitScaler, unitScaler, unitScaler ); /* center terrain at the origin by translating * by the negative of the center of bounding sphere */ pfPreTransMat(terrainSCSmatrix, -bounding_sphere.center[0], -bounding_sphere.center[1], -bounding_sphere.center[2], terrainSCSmatrix);
terrainSCS = pfNewSCS (terrainSCSmatrix); pfAddChild( terrainSCS, terrain ); /* set up terrain for intersections */ pfNodeTravMask (terrainSCS, PFTRAV_ISECT, 1, PFTRAV_DESCEND, PF_SET); return ( terrainSCS ); } }
void followTerrain( void ) { pfHit **hits[100]; long isect;
/* update location of intersection segment */ pfSetVec3(segset.segs[0].pos, shared->view.xyz[PF_X], shared->view.xyz[PF_Y], shared->view.xyz[PF_Z]);
/* do an intersection test against the terrain scene graph */ isect = pfSegsIsectNode(terrainSCS, &segset, hits);
/* if successful, set our height to that of the point of contact, plus a small offset */ if (isect) { pfVec3 pnt, xformed_pnt; pfQueryHit (*hits[0], PFQHIT_POINT, &pnt); pfXformPt3( xformed_pnt, pnt, terrainSCSmatrix ); shared->view.xyz[PF_Z] = xformed_pnt[PF_Z] + 0.5; #ifdef DEBUG printf("hit view.xyz[PF_Z] = %f\n", shared->view.xyz[PF_Z] - 0.5); #endif } }
void fogScene( void ) { pfFog *fog; fog = pfNewFog(pfGetSharedArena()); pfFogType (fog, PFFOG_VTX_EXP); pfFogColor (fog, 0.8, 0.8, 0.8); pfFogRange (fog, 0.0f, 25.0f); pfApplyFog (fog); pfEnable (PFEN_FOG); pfOverride(PFSTATE_FOG | PFSTATE_ENFOG, PF_ON); }
This archive was generated by hypermail 2.0b2 on Mon Aug 10 1998 - 17:51:32 PDT