/***********************************************************************/ /***********************************************************************/ /* FreeVR OpenGL tutorial example 2: ex2_static.c */ /* FreeVR OpenGL tutorial example 3: ex3_dynamic.c */ /* Last tested with: FreeVR version 0.6a */ /* Last tested with: FreeVR version 0.6a */ /* Last Modified: March 23, 2004 */ /* Last Modified: March 23, 2004 */ /* URL: http://freevr.org */ /* URL: http://freevr.org */ /***********************************************************************/ /***********************************************************************/ /* This example code demonstrates a VR application program that */ /* This example code demonstrates a VR application program that */ /* initializes the VR library routines, and renders a blue cube and */ /* renders a dynamic, albeit simple, world. The blue cube and */ /* a red pyramid on the floor near the front wall, but in a more */ /* red pyramid fly in a circle about a stationary green pyramid. */ /* civilized fashion than before. */ /* Lighting is improved to enhance the look of the world. */ /* */ /* */ /* */ /* */ /* The new features of this example include: */ /* The new features of this example include: */ /* - FreeVR Library functions, variables, and macros: */ /* - FreeVR Library functions, variables, and macros: */ /* * vrConfigure() */ /* * vrShmemAlloc0() */ /* * vrFunctionSetCallback(VRFUNC_DISPLAY_INIT, ...) */ /* * vrFunctionSetCallback(VRFUNC_DISPLAY_INIT, ...) [revisited] */ /* * vrFrame() */ /* * vrCurrentSimTime() */ /* * vrGet2switchValue() */ /* * type vrTime (a remapping of type 'double') */ /* * vrSystemSetName() */ /* - Database of the World */ /* * vrSystemSetAuthors() */ /* * vrSystemSetExtraInfo() */ /* * vrSystemSetStatusDescription() */ /* * vrInputSet2switchDescription() */ /* - Internally specifies the basic user interface */ /* - Creates a separate "World simulation" routine/file */ /* - Creates a separate graphics initialization routine (init_gfx) */ /* - VR housekeeping is done in vrFrame() */ /* - Exits the application when the 'Escape' key is pressed */ /* - Cleans up even when an interrupt signal is received */ /* */ /* */ /* */ /* */ /* Considerations: */ /* Considerations: */ /* - Doesn't do anything more interesting, other than wait for user */ /* - World simulation dynamics belong in the main process */ /* to terminate. */ /* - Callback arguments are used to pass Information about the world */ /* - update_world() routine highlights the fact that the simulation */ /* via shared memory */ /* should be separate from the rendering. */ /* - OpenGL lighting is now used to enhance the shading. Proper */ /* - NOTE: the Keypad-9 key toggles the help display on the screen */ /* implementation of lighting requires that the light's location */ /* with the input focus. */ /* be set after the perspective matrix, thus inside the rendering*/ /* routine. */ /* */ /* */ /* This application uses the files: */ /* This application uses the files: */ /* - shapes.c (Bill Sherman's simple OpenGL shapes) */ /* - shapes.c (Bill Sherman's simple OpenGL shapes) */ /* */ /* */ /* Copyright 2010, William R. Sherman, All Rights Reserved. */ /* Copyright 2010, William R. Sherman, All Rights Reserved. */ /* In particular, the right to republish this file in whole or in */ /* In particular, the right to republish this file in whole or in */ /* part, in any form (including electronic forms) is prohibited */ /* part, in any form (including electronic forms) is prohibited */ /* without written consent of the copyright holder. */ /* without written consent of the copyright holder. */ /***********************************************************************/ /***********************************************************************/ #include <stdio.h> /* needed for printf(), etc. */ #include <stdio.h> /* needed for printf(), etc. */ #include <stdlib.h> /* needed for exit() */ #include <stdlib.h> /* needed for exit() */ #include <signal.h> /* needed for signal() and its arguments */ #include <signal.h> /* needed for signal() and its arguments */ #include <unistd.h> /* not sure why/whether this is needed */ #include <math.h> /* needed for sin() & cos() */ #include <GL/gl.h> /* needed for all OpenGL functions & values */ #include <GL/gl.h> /* needed for all OpenGL functions & values */ #include "freevr.h" /* needed for FreeVR functions & values */ #include "freevr.h" /* needed for FreeVR functions & values */ /* Define a structure for holding a database of the virtual world. */ typedef struct { float obj1_x, obj1_y, obj1_z; /* location o float obj2_x, obj2_y, obj2_z; /* location o } WorldDataType; /**************************************************************************** /**************************************************************************** /* These function declarations are very important -- they will be used as arg /* These function declarations are very important -- they will be used as arg void exit_application(int signal); /* cleanly close down operati void exit_application(int signal); /* cleanly close down operati void init_gfx(void); /* initialize the graphics void init_gfx(void); /* initialize the graphics void draw_world(void); /* graphically render the wor void draw_world(WorldDataType *wd); /* graphically render the wor void update_world(void); /* perform the world simulati void init_world(WorldDataType *wd); /* initialize the world param void update_world(WorldDataType *wd); /* perform the world simulati /***********************************************************************/ /***********************************************************************/ main(int argc, char* argv[]) main(int argc, char* argv[]) { { WorldDataType *wd; /**********************************/ /**********************************/ /*** initialize FreeVR routines ***/ /*** initialize FreeVR routines ***/ /**********************************/ /**********************************/ signal(SIGINT, SIG_IGN); signal(SIGINT, SIG_IGN); vrConfigure(&argc, argv, NULL); /* allow CLAs to affect confi vrConfigure(&argc, argv, NULL); /* allow CLAs to affect confi vrStart(); vrStart(); signal(SIGINT, exit_application); signal(SIGINT, exit_application); /********************/ /* create the world */ wd = (WorldDataType *)vrShmemAlloc0(sizeof(WorldDataType)); init_world(wd); /***************************************/ /***************************************/ /* set up the FreeVR library functions */ /* set up the FreeVR library functions */ vrFunctionSetCallback(VRFUNC_DISPLAY_INIT, vrCallbackCreate(init_gfx, vrFunctionSetCallback(VRFUNC_DISPLAY_INIT, vrCallbackCreate(init_gfx, vrFunctionSetCallback(VRFUNC_DISPLAY, vrCallbackCreate(draw_world, 0) vrFunctionSetCallback(VRFUNC_DISPLAY, vrCallbackCreate(draw_world, 1, /********************************************************/ /********************************************************/ /* define the application name, authors, controls, etc. */ /* define the application name, authors, controls, etc. */ vrSystemSetName("FreeVR tutorial: example 2 -- static"); vrSystemSetName("FreeVR tutorial: example 3 -- dynamic"); vrSystemSetAuthors("Bill Sherman"); vrSystemSetAuthors("Bill Sherman"); vrSystemSetExtraInfo("An example to show a basic static world"); vrSystemSetExtraInfo("An example to show a basic dynamic world"); vrSystemSetStatusDescription("Application running fine"); vrSystemSetStatusDescription("Application running fine"); vrInputSet2switchDescription(0, "Terminate the application"); vrInputSet2switchDescription(0, "Terminate the application"); /***************************/ /***************************/ /*** do world simulation ***/ /*** do world simulation ***/ /***************************/ /***************************/ /* run until terminate key is pressed (Escape by default) */ /* run until terminate key is pressed (Escape by default) */ while(!vrGet2switchValue(0)) { while(!vrGet2switchValue(0)) { vrFrame(); vrFrame(); update_world(); update_world(wd); } } /*********************/ /*********************/ /*** close up shop ***/ /*** close up shop ***/ /*********************/ /*********************/ exit_application(0); exit_application(0); } } /********************************************************************/ /********************************************************************/ /* exit_application(): clean up anything started by the application */ /* exit_application(): clean up anything started by the application */ /* (forked processes, open files, open sockets, etc.) */ /* (forked processes, open files, open sockets, etc.) */ /********************************************************************/ /********************************************************************/ void exit_application(int signal) void exit_application(int signal) { { vrExit(); vrExit(); exit(0); exit(0); } } /* ----------------8<-----------------8<-----------------8<----------------*/ /* ----------------8<-----------------8<-----------------8<----------------*/ /* In a non-example applicatation, the following would be a separate file. */ /* In a non-example applicatation, the following would be a separate file. */ /**********************************/ /**********************************/ /**********************************/ /**********************************/ /** The World Simulation section **/ /** The World Simulation section **/ /**********************************/ /**********************************/ /**********************************/ /**********************************/ /********************************************************************/ /* update_world(): Do absolutely nothing. The short sleep allows */ /**************************************************************/ /* multiprocessing systems a good place to switch to other */ /* init_world(): create the initial conditions of the dynamic */ /* processing threads/forks -- something that can greatly improve */ /* simulation. */ /* the rendering frame rate. */ /**************************************************************/ /* Conceptually, this is the place where the "world physics" or the */ void init_world(WorldDataType *wd) /* world simulation should be, along with user interface */ /* processing, as will be exemplified in forthcoming examples. */ /* NOTE: it is very important that the simulation calculations be */ /* separate from the rendering of the virtual world. */ /********************************************************************/ void update_world(void) { { /* Nothing happens -- this is a static world. */ /* initial location of object 1 - a blue cube */ wd->obj1_x = -2.0; wd->obj1_y = 5.0; wd->obj1_z = -5.0; /* initial location of object 2 - a red pyramid */ wd->obj2_x = 2.0; wd->obj2_y = 5.0; wd->obj2_z = -5.0; } /*********************************************************************/ /* update_world(): This version now has a little action. However, */ /* although dynamic, it is not interactive. */ /*********************************************************************/ void update_world(WorldDataType *wd) { vrTime sim_time = vrCurrentSimTime(); /* the current time o /****************************************/ /* Move the objects with constant speed */ /* object 1 travels in a horizontal circle at a fixed speed */ wd->obj1_x = 3*sin(sim_time * 2.0); wd->obj1_z = 3*cos(sim_time * 2.0) - 5.0; /* object 2 travels in a verticle circle at a fixed speed */ wd->obj2_x = 3*cos(sim_time * 2.0); wd->obj2_y = 3*sin(sim_time * 2.0) + 5.0; /****************************************************/ /****************************************************/ /* yield to allow other processes access to the CPU */ /* yield to allow other processes access to the CPU */ vrSleep(10); vrSleep(0); } } /* ----------------8<-----------------8<-----------------8<----------------*/ /* ----------------8<-----------------8<-----------------8<----------------*/ /* In a non-example applicatation, the following would be a separate file. */ /* In a non-example applicatation, the following would be a separate file. */ /**************************/ /**************************/ /**************************/ /**************************/ /** The Graphics section **/ /** The Graphics section **/ /**************************/ /**************************/ /**************************/ /**************************/ /* functions from shapes.c */ /* functions from shapes.c */ void draw_cube(); void draw_cube(); void draw_pyramid(); void draw_pyramid(); /*********************************************************************/ /*********************************************************************/ /* init_gfx(): initialize general graphics properties (eg. lighting) */ /* init_gfx(): initialize general graphics properties (eg. lighting) */ /*********************************************************************/ /*********************************************************************/ void init_gfx(void) void init_gfx(void) { { GLfloat location_0[4] = { 0.0, 10.0, 10.0, 1.0 /* 0 = directional, 1 ambient_0[4] = { 0.2, 0.2, 0.2, 1.0 }, diffuse_0[4] = { 0.8, 0.8, 0.8, 1.0 }, specular_0[4] = { 0.2, 0.2, 0.2, 1.0 }; /****************************************/ /****************************************/ /* set the render initialization values */ /* set the render initialization values */ glClearColor(0.0, 0.0, 0.0, 0.0); glClearColor(0.0, 0.0, 0.0, 0.0); glClearDepth(1.0); glClearDepth(1.0); /**************************************/ /********************************************************/ /* set the polygon shading parameters */ /* set the polygon shading/lighting/material parameters */ glShadeModel(GL_SMOOTH); glShadeModel(GL_SMOOTH); glEnable(GL_LIGHTING); glLightfv(GL_LIGHT0, GL_POSITION, location_0); glLightfv(GL_LIGHT0, GL_AMBIENT, ambient_0); glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse_0); glLightfv(GL_LIGHT0, GL_SPECULAR, specular_0); glEnable(GL_LIGHT0); /* These two lines cause the vertex colors to be used (otherwise all glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); glEnable(GL_COLOR_MATERIAL); glEnable(GL_NORMALIZE); /* this is required when calling glScalef() w } } /*************************************************************/ /*************************************************************/ /* draw_world(): Render the two objects in the world -- the */ /* draw_world(): Render the three objects in the world. */ /* blue cube, and red pyramid -- such that they are on the */ /* Note that two of the objects (the blue cube, and red */ /* XZ plane (typically the floor), and 6 feet forward */ /* pyramid) get their locations from the world database */ /* (typically on the other side of a CAVE's front screen). */ /*************************************************************/ /*************************************************************/ void draw_world(void) void draw_world(WorldDataType *wd) { { static GLfloat location_0[4] = { 0.0, 10.0, 0.0, 1.0 /* 0 = directio /**************************************/ /**************************************/ /* clear the screen -- very important */ /* clear the screen -- very important */ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /******************************************************************** /* update the light's location -- must be done independently for each glLightfv(GL_LIGHT0, GL_POSITION, location_0); /************************/ /************************/ /* draw all the objects */ /* draw all the objects */ /* a blue cube */ /* a blue cube */ glColor3ub(100, 100, 255); glColor3ub(100, 100, 255); glTranslatef(-2.0, 1.0, -6.0); glPushMatrix(); draw_cube(); glTranslatef(wd->obj1_x, wd->obj1_y, wd->obj1_z); draw_cube(); glPopMatrix(); /* a red pyramid */ /* a red pyramid */ glColor3ub(255, 100, 100); glColor3ub(255, 100, 100); glTranslatef(4.0, 0.0, 0.0); glPushMatrix(); glTranslatef(wd->obj2_x, wd->obj2_y, wd->obj2_z); draw_pyramid(); glPopMatrix(); /* draw a _fixed_ green upside-down pyramid */ glColor3ub(100, 255, 100); glTranslatef(0.0, 4.0, -5.0); glScalef(1.0, -1.0, 1.0); draw_pyramid(); draw_pyramid(); } }