Rob Jenkins (robj++at++barney.reading.sgi.com)
Tue, 4 Jul 1995 10:05:21 +0100
find attached some example code form the Performer course labs - it includes a
'solar system' using DCSs which should point you in the right direction.
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,
/* * Module 2, Lab 1, Part 3: * Add lighting to sim.c * Note: formatted with pp, // comments for new code. * Module 2, Lab 1, Part 5: * Add texture and prebinding using pfUtil utilities * Note: need to make scene global, ie shared->scene. * Module 2, Lab 2, Part 1 & 2: * Add an earth/sky model. * Module 3, Lab 1, Part 1: * Add DCS above main model, make it spin. (Stop viewpoint rotation). * Module 3, Lab 1, Part 2: * Add another model in fixed location under DCS, spinning. * Note: changed view to be down -y axis. * Module 3, Lab 1, Part 3: * Add an array of objects under SCS modes. * Added myLoadFile to simplify file loading. * Module 3, Lab 1, Part 4: * Make the cow stand up. Just add 90 degrees of pitch to its DCS. * Module 3, Lab 2, Part 1: * Add a "solar system" of orbiting models. * * G Edwards, SG UK, Nov 94 * */
#include <X11/Xlib.h>
#include <math.h> #include <stdlib.h>
#include "pf.h" #include "pfsgi.h" #include "pfutil.h"
/* function prototypes */ void initialize(int argc, char *argv[]); pfNode *buildScene(int argc, char * argv[]); static void openPipeline(pfPipe *p); void printHelp(char *programName); pfNode *myLoadFile(char * filename);
typedef struct SharedData { pfChannel *chan; pfCoord view; float eyeRadius; pfScene *scene; pfDCS *mainDCS, *dcs2, *planetDCS, *moonDCS; } SharedData;
/* Global Variables */ SharedData *shared;
/* * Main program */
int main(int argc, char *argv[]) { pfCoord view; float time; float maxTime = 20.0; float eyeAngle, spinAngle;
initialize(argc, argv);
pfInitClock(0.0f);
/* Simulate for maxTime seconds. */ /* main loop */ while (time < maxTime) { float sin, cos;
/* Go to sleep until next frame time. */ pfSync();
time = pfGetTime();
// View position and direction now static, down -y axis
pfSinCos(eyeAngle, &sin, &cos); pfSetVec3(view.xyz, 0.0f, -shared->eyeRadius * 1.5, shared->eyeRadius * 0.4f); pfSetVec3(view.hpr, 0.0f, -10.0f, 0.0f); pfChanView(shared->chan, view.xyz, view.hpr);
// // Spin main DCS // spinAngle = 45.0f * time; pfDCSRot(shared->mainDCS, spinAngle, spinAngle / 2.0, 0.0f);
// // Spin 2nd DCS // pfDCSRot(shared->dcs2, 0.0f, 90.0f, spinAngle / 4.0f);
// // Spin earth and moon DCS's for solar system // Note: pfDCSRot uses heading, pitch, roll. //
pfDCSRot(shared->planetDCS, spinAngle/2.0, 0.0, 0.0 ); pfDCSRot(shared->moonDCS, spinAngle, 0.0, 0.0);
/* Initiate cull/draw for this frame. */ pfFrame(); } pfuExitUtil(); 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; pfNode *root; pfScene *scene; pfSphere sceneBSphere; pfEarthSky *eSky; void *arena;
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 */
pfConfig(); /* configure */
/* Initialize IRIS Performer utility library. */ pfuInitUtil();
pipe = pfGetPipe(0); /* create graphics pipeline */ shared->chan = pfNewChan(pipe); /* create a view into the pipe */
/* Create a scene! */ shared->scene = scene = pfNewScene(); root = buildScene(argc, argv); pfAddChild(scene, root);
/* initialize graphics pipeline and call openPipeline when ready */ pfInitPipe(pipe, openPipeline);
/* specify scene to be viewed by channel */ pfChanScene(shared->chan, scene);
/* Get the scene's extents. */ pfGetNodeBSphere(scene, &sceneBSphere); printf("Scene bounds - center: %f %f %f, radius: %f\n", sceneBSphere. center[0], sceneBSphere.center[1], sceneBSphere.center[2], sceneBSphere.radius); shared->eyeRadius = 1.5f * sceneBSphere.radius;
// // Add an earth/sky model //
eSky = pfNewESky(); // Specify what gets cleared & drawn pfESkyMode(eSky, PFES_BUFFER_CLEAR, PFES_SKY_GRND); // Ground height, a little below most models pfESkyAttr(eSky, PFES_GRND_HT, -1.0f); // Horizon glow band width & colour pfESkyAttr(eSky, PFES_HORIZ_ANGLE, 5.0f); pfESkyColor(eSky, PFES_HORIZ, 0.5f, 0.1f, 0.0f, 1.0f); // Top/bottom sky colours pfESkyColor(eSky, PFES_SKY_TOP, 0.0f, 0.0f, 0.0f, 1.0f); pfESkyColor(eSky, PFES_SKY_BOT, 0.05f, 0.0f, 0.6f, 1.0f); // Near/far ground colours pfESkyColor(eSky, PFES_GRND_NEAR, 0.0f, 0.3f, 0.0f, 1.0f); pfESkyColor(eSky, PFES_GRND_FAR, 0.0f, 0.0f, 0.0f, 1.0f); // Tell chan to draw this each frame pfChanESky(shared->chan, eSky); }
/* * buildScene() loads model file specified in command line * args (or a default) and returns a node containing the model */
pfNode *buildScene(int argc, char * argv[]) { pfNode *model1, *model2, *model3; pfGroup *group; pfMatrix matrix; pfSCS *scs[4][4], *planetSCS, *moonSCS; char *file1, *file2, *file3; char *default1 = "esprit.flt", *default2 = "cow.obj", *default3 = "icosahedron.ascii"; int i, j;
file1 = (argc < 2)? default1: argv[1]; file2 = (argc < 3)? default2: argv[2]; file3 = (argc < 4)? default3: argv[3];
// // Read in model files //
model1 = myLoadFile(file1); model2 = myLoadFile(file2); model3 = myLoadFile(file3);
// // Add a DCS above the main model. Needs to be global to update it from // APP process in main. //
shared->mainDCS = pfNewDCS(); pfAddChild(shared->mainDCS, model1);
// // Add another DCS above a 2nd model. DCS has fixed translation to // position model, and variable rotation to spin it. // And some scaling to get model right size. //
shared->dcs2 = pfNewDCS(); pfDCSTrans(shared->dcs2, 4.0, 0.0, 0.0); pfDCSScale(shared->dcs2, 0.20); pfAddChild(shared->dcs2, model2);
// // Add an array of models under SCS nodes. //
group = pfNewGroup();
for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { pfMakeTransMat(matrix, -(float) i - 1, -(float) j - 1, 0.0); pfPreScaleMat(matrix, 0.4, 0.4, 0.4, matrix); scs[i][j] = pfNewSCS(matrix); pfAddChild(scs[i][j], model3); pfAddChild(group, scs[i][j]); } }
// // Add a "solar system" of orbiting models. //
shared->planetDCS = pfNewDCS(); // earth orbit rot shared->moonDCS = pfNewDCS(); // moon orbit rot pfMakeTransMat(matrix, 5.0, 0.0, 2.0); // earth orbit trans planetSCS = pfNewSCS(matrix); pfMakeTransMat(matrix, 2.0, 0.0, 0.0); // moon orbit trans pfPreScaleMat(matrix, 0.5, 0.5, 0.5, matrix); moonSCS = pfNewSCS(matrix); // Compose the hierarchy pfAddChild(shared->planetDCS, planetSCS); pfAddChild(planetSCS, model3); // just instance model3 some more pfAddChild(planetSCS, shared->moonDCS); pfAddChild(shared->moonDCS, moonSCS); pfAddChild(moonSCS, model3);
// // Put all top level nodes under a group and return it. //
pfAddChild(group, shared->mainDCS); pfAddChild(group, shared->dcs2); pfAddChild(group, shared->planetDCS); return((pfNode *) group); }
/* * openPipeline() creates a GL window and sets 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 *pipe) { pfuGLXWindow *win; Display *XDpy; void *arena; pfList *texList;
XDpy = (Display *) pfuOpenXDisplay(0); if (!(win = pfuGLXWinopen((pfuXDisplay *) XDpy, pipe, "sim", 100, 900, 100, 900))) { pfNotify(PFNFY_FATAL, PFNFY_RESOURCE, "OpenXPipeline: Could not create GLX Window.\n"); }
/* initialize Performer for GLX rendering */ pfInitGLXGfx(pipe, (void *) XDpy, win->xWin, win->glWin, win->overWin, PFGLX_AUTO_RESIZE);
// // Turn on lighting //
arena = pfGetSharedArena();
// Create and apply default material (light grey) pfApplyMtl(pfNewMtl(arena));
// Create and apply default lighting model pfApplyLModel(pfNewLModel(arena));
// Create and apply one default light (white light looking down -y axis) pfLightOn(pfNewLight(arena));
// Enable lighting (this is defaulted on anyway) pfEnable(PFEN_LIGHTING);
// // Turn on texturing //
// Enable textuuring pfEnable(PFEN_TEXTURE);
// Create default texture environment pfApplyTEnv(pfNewTEnv(arena));
// Prebind (ie. read and download to gfx hardware) textures in scene. // This also gives the nice texture slideshow. pfuInitUtil(); texList = pfuMakeTexList((pfNode *) shared->scene); pfuDownloadTexList(texList, PFUTEX_SHOW); }
/* * Read model file, exit if not found. */
pfNode *myLoadFile(char * filename) { pfNode *model;
fprintf(stdout, "Loading Model file %s\n", filename); if ((model = LoadFile(filename, NULL)) == NULL) { fprintf(stderr, "Model file %s not found, exiting\n", filename); pfuExitUtil(); pfExit(); system("rm /usr/tmp/pfUtil*"); exit(-1); }
return(model); }
/* * Help routine */
void printHelp(char *programName) { fprintf(stdout, "Usage: %s [model1] [model2] [model3]\n\n", programName); fprintf(stdout, // "Loads model file specified (or a default model)\n" // "and loops around model\n" // "and turns on lighting\n" // "and turns on texturing\n" // "and adds an earth/sky model\n" // "and adds a DCS above main model\n" // "and adds another model in fixed location under a DCS, spinning\n" // "\n", // programName); }
This archive was generated by hypermail 2.0b2 on Mon Aug 10 1998 - 17:51:39 PDT