/***********************************************************************/        /***********************************************************************/
/* 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();
}                                                                                }