#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <Performer/pf/pfChannel.h>
#include <Performer/pf/pfLightSource.h>
#include <Performer/pf/pfDCS.h>
#include <Performer/pf/pfTraverser.h>
#include <Performer/pfdu.h>
#include <pfcave.h>

#include "pfVidAv.h"


static void createScene(pfChannel *chan);
static void loadObjects(pfGroup *parent);
static int navigate(pfTraverser *trav,void *data);


/** the following ogl_ functions are used to perform OpenGL calls  ***/
/** which are all done in either the pfCAVEPreDrawFunc() or        ***/
/** pfCAVEPostDrawFunc() ***/
 
void ogl_update_fn(void);
void ogl_draw_fn(void);
void ogl_init_fn(void);
void ogl_POSTframe(pfChannel * trav, void * data);
void ogl_PREframe(pfChannel * trav, void * data);

pfDCS *OBJdcs;
 
/* main() - this is identical to the skeleton main of outline.c++ */
int main(int argc,char **argv)
{
 pfInit();

 va_PrePreInit();  /*** does avatar initialization, must   ****/
		   /*** be called after pfInit() and       ****/
		   /*** before pfCAVEConfig();             ****/
		   
 pfCAVEConfig(&argc,argv,NULL);
 
 va_PreInit();	/*** sets up CAVE callbacks, must be   ****/
		/*** called after pfCAVEConfig() and   ****/
		/*** before pfConfig();                ****/

 
 pfMultiprocess(PFMP_APP_CULL_DRAW);
 
 
 pfConfig();
 
 pfCAVEInitChannels();
 if (CAVEConfig->Simulator)
	pfCAVEMasterChan()->getFStats()->setClass(
			PFSTATS_ALL^PFSTATSHW_ENGFXPIPE_FILL, PFSTATS_ON);
 else
	pfCAVEMasterChan()->getFStats()->setClass(PFSTATS_ALL, PFSTATS_OFF);

 createScene(pfCAVEMasterChan());
 
 pfCAVEPreDrawFunc( (pfChanFuncType) ogl_PREframe);
 pfCAVEPostDrawFunc( (pfChanFuncType) ogl_POSTframe);
 
 
 while (!CAVEgetbutton(CAVE_ESCKEY))
	{
	pfSync();
	pfCAVEPreFrame();
	pfFrame();
	pfCAVEPostFrame();
	}
 CAVEHalt();
 pfExit();
 return 0;
}



static void createScene(pfChannel *chan)
{
 pfScene *scene;
 pfGeoState *gstate;
 pfDCS *dcs;
 
 scene = new pfScene;
 gstate = new pfGeoState;				/* Set up a base geostate for the scene */
 gstate->setMode(PFSTATE_ENLIGHTING, PF_ON);
 gstate->setMode(PFSTATE_CULLFACE, PFCF_OFF);
 scene->setGState(gstate);
 scene->addChild(new pfLightSource);			/* Add a default light */
 dcs = new pfDCS;					/* Create a DCS for navigation */
 scene->addChild(dcs);
 dcs->setTravFuncs(PFTRAV_APP,navigate,NULL);
 loadObjects(dcs);
 chan->setScene(scene);					/* Assign the scene to the channels */
}


/* loadObjects() - loads and positions floor. 
*/

static void loadObjects(pfGroup *parent)
{
 pfNode *obj;
 
    OBJdcs = new pfDCS;
    
    obj = pfdLoadFile("floor.iv");	/* Load the object */
    if (obj)
    {					/* If it succeeded, add the object to the graph */
	OBJdcs->addChild(obj);
	parent->addChild(OBJdcs);
	
	OBJdcs->setScale( 80.0, 1.0, 80.0 );
	OBJdcs->setRot( 0.0, 90.0, 0.0 );
    }
    else
    {
	pfExit();
    }

}


static int navigate(pfTraverser *trav,void *)
{
#define SPEED 2.0f
 pfDCS *navDcs = (pfDCS *) trav->getNode();		/* Get a pointer to the DCS node itself */
 float jx=CAVE_JOYSTICK_X,jy=CAVE_JOYSTICK_Y;
 if (fabs(jx) > 0.125)					/* Rotate if the joystick is pushed left or right */
	CAVENavRot(-1.0f*jx,'z');
 if (fabs(jy) > 0.125)					/* Translate if the joystick is pushed forward or back */
	{
	float w[3];
	CAVEGetVector(CAVE_WAND_FRONT,w);
	CAVENavTranslate(w[0]*jy*SPEED,w[1]*jy*SPEED,w[2]*jy*SPEED);
	}
 if ((CAVEBUTTON1) && (CAVEBUTTON3))			/* Reset navigation on secret handshake */
	CAVENavLoadIdentity();
 pfCAVEDCSNavTransform(navDcs);				/* Load the DCS with the latest navigation matrix */
 return PFTRAV_CONT;					/* Tell Performer to continue traversing */
}


/***************************                    *************************/
/****************************** avatar stuff ****************************/
/***************************                    *************************/


void ogl_init_fn()
{
    
    glClearColor(0.0, 0.0, 0.0, 0.0);
  
  /***  va_InitTex initializes avatar's texture mapping  ***/
   
  va_InitTex();
  
}

void  ogl_draw_fn(void)
{
  
  glPushMatrix();

    CAVENavTransform();
    va_DrawAllAvatars();  /*** draws all enabled avatars ***/
	  
  glPopMatrix(); 
  

}


void ogl_update_fn(void)
{
    static int OnFlag=1;
    static Button1Val, Button2Val;
    static float RemoteAvatarScale=1.0;
    
   if (CAVEBUTTON1 && (CAVEBUTTON1!=Button1Val)) printf("Remote avatars are Enabled: %d\n", va_RemoteAvatarsAreEnabled());
   
   if (CAVEBUTTON2 && (CAVEBUTTON2!=Button2Val)) 
    {
	OnFlag=(OnFlag+1)%2;
	printf("OnFlag: %d\n", OnFlag);
	if (OnFlag) va_EnableRemoteAvatars();
	else va_DisableRemoteAvatars();
    }
    
    
    Button1Val=CAVEBUTTON1;
    Button2Val=CAVEBUTTON2;
    
    if (CAVEgetbutton(CAVE_NINEKEY)) 
    {
	RemoteAvatarScale-=.1;
	if (RemoteAvatarScale<0.0) RemoteAvatarScale=0.0;
	va_SetRemoteAvatarScale(RemoteAvatarScale);
    }
    
    if (CAVEgetbutton(CAVE_ZEROKEY)) 
    {
	RemoteAvatarScale+=.1;
	va_SetRemoteAvatarScale(RemoteAvatarScale);
    }

    /*** va_UpdateAllAvatars updates all avatars appropriately ***/
    
    va_UpdateAllAvatars();
    
}


void ogl_PREframe(pfChannel * trav, void * )
{
    static int first=1;
    
    trav->clear();
    
    if(first)
    {
        ogl_init_fn();  /** initialize OpenGL stuff only once **/
	first=0;
    }
}

void ogl_POSTframe(pfChannel * , void * )
{
   
    ogl_update_fn();
    ogl_draw_fn();

}



Back to VideoAvatar